Compare commits

...

122 Commits

Author SHA1 Message Date
Elliot Lee
cabe029861 Release 0.17.9 2017-11-14 13:45:55 -08:00
Elliot Lee
1ac4ad2076 Update HISTORY.md for 0.17.9 2017-11-14 13:41:53 -08:00
Fred K. Schott
44119ddf2d remove unneccessary double-polyfills from runtime 2017-11-12 23:40:29 -08:00
Fred K. Schott
567036f382 fix lint errors and configure eslintrc to automatically work /w tooling 2017-11-12 12:46:50 -08:00
Elliot Lee
27aa0247e7 yarn.lock: Update ripple-keypairs to 0.10.1 2017-11-10 15:22:54 -08:00
Elliot Lee
0fc10b302f Update ripple-keypairs to 0.10.1 (#805) 2017-11-10 15:21:57 -08:00
Elliot Lee
0bc51a869d Merge pull request #786 from ripple/escrow-execution-ValidationError
escrow-execution - Add reference to ValidationError
2017-11-10 14:57:38 -08:00
Elliot Lee
a3dff0dcf7 Update HISTORY.md 2017-11-08 22:51:53 -08:00
Elliot Lee
048fc7ce71 Merge branch 'bsclifton-develop' into develop 2017-11-08 22:49:58 -08:00
Elliot Lee
6265e81afb Update yarn.lock for ws 3.3.1 2017-11-08 22:49:01 -08:00
Brian Clifton
38ca96a938 Update ws dependency >= 3.3.1 per https://nodesecurity.io/advisories/550 2017-11-08 21:42:23 -07:00
wilsonianb
8ed5f764fa Add missing condition or fulfillment test 2017-11-06 13:49:38 -06:00
Elliot Lee
227ea82a29 escrow-execution - Add reference to ValidationError 2017-11-06 11:08:06 -08:00
Elliot Lee
0e2a5e36c6 Add 0.17.8 release date 2017-11-06 10:13:23 -08:00
Elliot Lee
332b656860 Merge pull request #802 from ripple/update-bignumber
Update bignumber.js, ripple-hashes, ripple-lib-transactionparser
2017-11-06 08:58:27 -08:00
Elliot Lee
0230b963c1 Update HISTORY.md 2017-11-06 08:54:49 -08:00
Waldir Pimenta
48e2ea9ff2 LICENSE: add title (#803) 2017-11-04 18:18:55 -07:00
Elliot Lee
b6f1394c61 Update HISTORY.md 2017-11-03 23:44:17 -07:00
Elliot Lee
560e43b1a6 Update scripts/ci.sh to use yarn 2017-11-03 23:43:33 -07:00
Elliot Lee
cc1ab7ae97 Update references of npm to yarn 2017-11-03 15:30:41 -07:00
Elliot Lee
4886561f7d Add yarn lockfile
Use yarn to ensure that we always get the same dependencies each time
2017-11-03 14:20:00 -07:00
Elliot Lee
658d8a182e Update bignumber.js, ripple-hashes, ripple-lib-transactionparser 2017-11-03 14:20:00 -07:00
wilsonianb
2a90f9b134 Include signers in getSettings 2017-10-10 19:10:26 -05:00
Elliot Lee
f42dafd304 Merge branch 'update-lodash' into develop 2017-09-27 15:47:51 -07:00
Elliot Lee
ec2100094a Docs: Specify Node 6.11.3
- Add .nvmrc and update HISTORY.md
2017-09-27 15:45:50 -07:00
Elliot Lee
ecd6347859 Update to lodash 4
- Update ripple-lib-transactionparser
2017-09-27 10:25:53 -07:00
Elliot Lee
ab17b19ff0 Update for CircleCI
- circle.yml - use node 6
- Fix eslint errors
- Update coveralls and add path to babel
2017-09-27 10:25:08 -07:00
Elliot Lee
a9e5ac6290 Fix typos
Thanks @seelabs
2017-09-06 23:53:20 -07:00
Elliot Lee
4974f73f26 Clean up release history
- Fix some typos
- Improve consistency of formatting
2017-09-06 00:55:26 -07:00
Rome Reginelli
e6d71471e2 Merge pull request #791 from ripple/rr-xrp-ledger-rebranding
Fix case-sensitive broken link for preparePaymentChannelClaim
2017-09-01 15:16:58 -07:00
mDuo13
50db68dff7 Fix case-sensitive broken link for preparePaymentChannelClaim 2017-09-01 15:12:58 -07:00
Rome Reginelli
c8eb5b6a70 Merge pull request #790 from ripple/rr-xrp-ledger-rebranding
Fix 'Paymment' typo
2017-09-01 15:06:11 -07:00
mDuo13
c61a15e4f3 Fix 'Paymment' typo 2017-09-01 14:50:02 -07:00
Rome Reginelli
c151ff2d66 Merge pull request #788 from ripple/rr-xrp-ledger-rebranding
Docs: fix broken links
2017-09-01 14:45:56 -07:00
mDuo13
393b2f9d78 Docs: fix broken links 2017-09-01 12:45:03 -07:00
Rome Reginelli
bf36cf03d6 Merge pull request #785 from ripple/rr-xrp-ledger-rebranding
Rebrand 'Ripple Consensus Ledger' to 'XRP Ledger'
2017-08-31 14:47:52 -07:00
mDuo13
d3332e0db9 README updates for rebranding 2017-07-31 17:17:30 -07:00
mDuo13
ed62b20645 Rebrand 'Ripple Consensus Ledger' to 'XRP Ledger' 2017-07-31 14:05:40 -07:00
Rome Reginelli
5f2c5e27f1 Merge pull request #771 from xasos/develop
Fix readme syntax
2017-07-31 11:53:20 -07:00
Abraham Tom
ff702b85e2 Merge pull request #760 from mDuo13/doc_nodever_update
Docs: Require Node 6.9.0, update boilerplate to avoid destructuring assign
2017-07-28 12:04:23 -07:00
Niraj Pant
f91eb68556 Fix readme syntax 2017-06-09 11:12:42 -07:00
mDuo13
469fefee92 Docs: Require Node 6.9.0, update boilerplate to avoid destructuring assign 2017-05-09 15:51:45 -07:00
Matthew Fettig
de47263087 0.17.7 2017-05-08 15:10:26 -07:00
Matthew Fettig
3b9679a673 Merge pull request #759 from bachase/jsonschema
Switch to jsonschema
2017-05-08 15:09:04 -07:00
Brad Chase
f175966816 Make http server dev only 2017-05-05 14:59:15 -04:00
Brad Chase
f1f5364d07 Switch to jsonschema 2017-05-03 20:34:24 -04:00
Matthew Fettig
1b8b0c76ac Merge pull request #757 from ripple/fix-condition
Fix escrow condition and fulfillment descriptions
2017-04-13 19:39:27 -07:00
Matthew Fettig
1a8096ab18 Merge pull request #756 from ripple/sign-claim
Payment channel lookup and claim signing & verification
2017-04-13 19:38:45 -07:00
wilsonianb
f177771c67 Update ripple-binary-codec version 2017-04-13 17:39:27 -07:00
wilsonianb
081fcbfa32 Fix escrow condition and fulfillment descriptions 2017-04-12 15:16:01 -07:00
wilsonianb
0a5e4e2155 Update docs for escrow and paychan activation 2017-04-07 13:04:32 -07:00
wilsonianb
19eb88a00e Add getPaymentChannel 2017-04-07 13:04:21 -07:00
wilsonianb
c8f2967de0 Sign and verify payment channel claim 2017-04-07 13:01:58 -07:00
Matthew Fettig
b5564330f6 Merge pull request #755 from ripple/develop
0.17.6
2017-03-30 21:49:59 -07:00
Matthew Fettig
43ccb83f73 0.17.6 2017-03-30 21:33:09 -07:00
Brandon Wilson
e2d92126c0 Merge pull request #745 from ripple/feat/bs-paychan
Add transactions for payment channels
2017-03-30 21:26:13 -07:00
Ben Sharafian
8c8eef45d5 Add docs for payment channels 2017-03-30 21:19:31 -07:00
Ben Sharafian
a574e1158a Add transactions for payment channels 2017-03-30 21:19:31 -07:00
Matthew Fettig
af687a6aed Merge pull request #754 from ripple/escrowcreate
Simplify EscrowCreate parameters
2017-03-30 21:18:33 -07:00
wilsonianb
016e82ab5d Simplify EscrowCreate parameters 2017-03-30 19:01:58 -07:00
Matthew Fettig
f300a412d7 Merge pull request #753 from ripple/feature/dependancy-update
update ripple-hashes and ripple-binary-codec
2017-03-30 15:21:27 -07:00
Matthew Fettig
75e2249cf3 update ripple-hashes and ripple-binary-codec 2017-03-30 15:12:09 -07:00
Matthew Fettig
1942bcb971 Merge pull request #752 from ripple/rm-escrow-iou
Disallow escrow of IOU
2017-03-30 14:53:29 -07:00
wilsonianb
9393adf66f Disallow escrow of IOU 2017-03-30 10:10:00 -07:00
Matthew Fettig
917aae9bf3 Merge pull request #751 from ripple/feature/escrow
Replace suspended payments with escrow
2017-03-29 17:38:32 -07:00
wilsonianb
da36457d5c Update condition and fulfillment for escrow
Calculate escrowFinish fulfillment fee
2017-03-29 10:27:34 -07:00
wilsonianb
15a0ededc8 Replace suspended payments with escrow 2017-03-24 12:35:22 -07:00
wilsonianb
68d7864f93 Rename suspended payment files as escrow 2017-03-24 12:32:17 -07:00
Matthew Fettig
1eddbf995f 0.17.5 2017-03-24 12:31:10 -07:00
Matthew Fettig
592385ac73 Merge pull request #750 from ripple/feature/dependancy-update
update ripple-binary-codec to version 0.1.8
2017-03-24 12:26:35 -07:00
Matthew Fettig
56d626f5b1 Merge pull request #744 from choiip/develop
Added .json in missing require()
2017-03-24 10:53:42 -07:00
Matthew Fettig
7a14300409 update ripple-binary-codec to version 0.1.8 2017-03-24 10:40:19 -07:00
alex.choi
30fa8d658e Added .json in missing require() 2017-02-15 18:51:49 +08:00
Chris Clark
c0101cb5e7 Merge pull request #740 from wilsonianb/shamapv2
Check SHAMapV2 ledger close flag
2016-12-02 12:31:46 -08:00
wilsonianb
fd640cd65e Check SHAMapV2 ledger close flag 2016-12-02 12:25:32 -08:00
Chris Clark
11528eff92 Merge pull request #741 from wilsonianb/fix-lint-errors
Fix eslint errors
2016-12-02 11:55:21 -08:00
wilsonianb
3c9175459d Fix eslint errors 2016-12-02 08:16:16 -08:00
Chris Clark
bd4e0e01e2 Merge pull request #739 from clark800/develop
Update ripple-binary-codec and ripple-hashes dependencies
2016-11-30 14:59:52 -08:00
Chris Clark
cfcf6e473c Update ripple-binary-codec and ripple-hashes dependencies 2016-11-30 14:49:40 -08:00
Chris Clark
50c6af3158 Merge pull request #734 from clark800/bump-codec
Bump version to 0.17.3 and bump ripple-binary-codec to 0.1.4
2016-09-29 11:24:04 -07:00
Chris Clark
1d4310cd3a Disable flow type checking in CircleCI 2016-09-29 11:19:46 -07:00
Chris Clark
2191596e68 Bump version to 0.17.3 and bump ripple-binary-codec to 0.1.4 2016-09-29 11:19:32 -07:00
Chris Clark
acf8f87a88 Merge pull request #727 from clark800/order-seq
Add orderToReplace option
2016-08-01 14:34:27 -07:00
Chris Clark
cfac146620 Add orderToReplace option 2016-08-01 14:27:08 -07:00
Chris Clark
f3234ad853 Merge pull request #726 from clark800/doc-typos
Fix typos in docs
2016-08-01 14:24:22 -07:00
Chris Clark
b65fee3d85 Merge pull request #725 from shekenahglory/develop
update parseDeliveredAmount for cases where delivered_amount is not p…
2016-08-01 14:21:43 -07:00
Chris Clark
82b294bc7d Update flow 2016-08-01 14:13:00 -07:00
Chris Clark
2a58573823 Fix typos in docs 2016-08-01 11:53:46 -07:00
Matthew Fettig
a96f71b7fd fix missing deliveredAmount data from getLedger requests 2016-07-19 21:29:50 -07:00
Chris Clark
077f4a4c79 Merge pull request #723 from clark800/fix-coverage
Fix code coverage tool
2016-07-08 15:04:38 -07:00
Chris Clark
9a495467fb Disable sauce tests because they usually timeout 2016-07-08 11:45:27 -07:00
Chris Clark
db2e62b219 Fix code coverage tool 2016-07-08 11:28:10 -07:00
Alan Cohen
2fafa493a2 Version 0.17.2 2016-06-24 10:59:04 -07:00
Alan Cohen
7617c3005c Merge pull request #721 from mDuo13/fix_transferrate_docs
[DOC] fix transferRate description
2016-06-22 11:13:14 -07:00
mDuo13
5cdbb71277 [DOC] fix transferRate description 2016-06-16 15:11:08 -07:00
Chris Clark
f9339c36bf Merge pull request #720 from clark800/update-binary-codec
0.17.1
2016-05-11 18:20:29 -07:00
Chris Clark
67dc57e9d0 Disable PhantomJS tests due to issue downloading from bitbucket 2016-05-11 17:49:57 -07:00
Chris Clark
757f3190d1 0.17.1 2016-05-11 17:49:54 -07:00
Chris Clark
0d94a15ee7 0.17.0 2016-05-05 18:35:13 -07:00
Chris Clark
7f1c80da1b Merge pull request #718 from clark800/pseudo
Add support for parsing SetFee and EnableAmendment pseudo-transactions
2016-05-05 16:15:32 -07:00
Chris Clark
f74e11bce0 Add support for parsing SetFee and EnableAmendment pseudo-transactions 2016-05-05 15:37:23 -07:00
Chris Clark
d4c843e8e3 Merge pull request #714 from darkdarkdragon/remove_tej
[FIX] remove check for `tej` class of errors.
2016-04-05 15:15:42 -07:00
Ivan Tivonenko
bae190b282 [FIX] remove check for tej class of errors. 2016-04-05 23:50:41 +03:00
Chris Clark
d2cbd70da8 Merge pull request #712 from darkdarkdragon/reconnect_fix_browser
[FIX] on reconnect wait for server to be synced
2016-03-30 15:50:58 -07:00
Ivan Tivonenko
5da78ce583 [FIX] handle websocket errors in browsers
emit not RippledNotInitializedError if server doesn't have any
completed ledgers on connect
2016-03-31 00:46:00 +03:00
Chris Clark
14bbe3e30b Merge pull request #680 from ripple/sublimator-patch-1
Fix typo in docs
2016-03-29 10:27:34 -07:00
Nicholas Dudfield
e52e2bbc68 Fix IOU Amount precision related typo in docs 2016-03-29 13:51:30 +07:00
Alan Cohen
b56752e45b 0.16.10 2016-03-24 14:52:36 -07:00
Chris Clark
4632f511ab Merge pull request #711 from darkdarkdragon/reconnect_fix2
[FIX] on connect return error if server doesn't have validated ledgers
2016-03-24 14:27:50 -07:00
Ivan Tivonenko
e17b6f172d [FIX] on connect return error if server doesn't have validated ledgers 2016-03-24 22:26:33 +02:00
Alan Cohen
eb04e878ba 0.16.9 2016-03-22 18:39:33 -07:00
Chris Clark
c71febd116 Merge pull request #709 from darkdarkdragon/reconnect_fix
Reconnection fix
2016-03-22 18:12:28 -07:00
Ivan Tivonenko
69c1ccbb6b [TASK] emit connected and disconnected events from api 2016-03-23 02:05:07 +02:00
Ivan Tivonenko
499b8c8d8b [FIX] fix multiple reconnections issue 2016-03-23 01:18:08 +02:00
Chris Clark
ea009f9a84 Merge pull request #708 from clark800/fix-maker-exchange-rate
Fix makerExchangeRate for getOrders when rippled provides quality
2016-03-22 14:14:23 -07:00
Chris Clark
dc784d4567 Fix makerExchangeRate for getOrders when rippled provides quality 2016-03-22 13:21:26 -07:00
Alan Cohen
9ffc8a2c0b Merge pull request #707 from ripple/fix/filter-source-amount
FIX: Filtering source_amount pathfind correctly
2016-03-21 14:48:37 -07:00
Alan Cohen
5b20fe573e FIX: Filtering source_amount pathfind correctly
Bug:

```js
api.connect().then(() => {
  const pathfind = {
    source: {
      address: USDCold,
      amount: {
        currency: 'USD',
        value: '1.00' // <<<< Rippled response has "1" not "1.00"
      }
    },
    destination: {
      address: EURCold,
      amount: {currency: 'EUR'}
    }
  };
  return api.getPaths(pathfind).then(paths => {
    console.log('PATHS: \n', JSON.stringify(paths, null, 2));
  });
}).catch(console.log);

```
2016-03-21 11:44:55 -07:00
Chris Clark
7e466bb80f Merge pull request #705 from darkdarkdragon/code_comment
[FIX] add small code comment
2016-03-15 12:14:05 -07:00
Ivan Tivonenko
1f8418b447 [FIX] add small code comment 2016-03-15 20:58:22 +02:00
Alan Cohen
ccfc57fc62 Merge pull request #704 from darkdarkdragon/fix_edge_test
[FIX] fix test hang in microsoft edge
2016-03-15 10:27:01 -07:00
Ivan Tivonenko
1d31fccd72 [FIX] fix test hang in microsoft edge 2016-03-15 05:04:47 +02:00
246 changed files with 11223 additions and 2998 deletions

2
.gitignore vendored
View File

@@ -60,4 +60,4 @@ out/
# Ignore perf test cache
scripts/cache
eslintrc
.eslintrc

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
v6

View File

@@ -1,59 +1,82 @@
##0.16.5
**Changes**
# ripple-lib Release History
## 0.17.9 (2017-11-14)
+ [Update ws dependency to 3.3.1](https://github.com/ripple/ripple-lib/pull/804)
+ [Remove unnecessary polyfills](https://github.com/ripple/ripple-lib/pull/807)
+ Fix lint errors ([#786](https://github.com/ripple/ripple-lib/pull/786), [#808](https://github.com/ripple/ripple-lib/pull/808))
+ [Update ripple-keypairs dependency to 0.10.1](https://github.com/ripple/ripple-lib/pull/805)
## 0.17.8 (2017-11-06)
+ Fix: Freezing in Safari 10.1 (updated bignumber.js) (closes #762)
+ [Fix: `getSettings` should include signers](https://github.com/ripple/ripple-lib/commit/2a90f9b134e168937dceb7da283d63734eac9e7c)
+ Update for Node 6
+ Update lodash dependency
+ Migrate to yarn
## 0.17.7 (2017-05-08)
+ Replace AJV with jsonschema
## 0.16.5 (2016-01-21)
+ [Filter insufficient source funds paths from pathfind results](https://github.com/ripple/ripple-lib/pull/688)
##0.16.4
**Changes**
+ [Update ws to 1.0.1](https://github.com/ripple/ripple-lib/pull/682)
## 0.16.4
##0.16.2
**Changes**
+ [Bump ripple-binary-codec dependency version to 0.1.1 to fix issue with computeLedgerHash for transactions with DeliverMin]
+ [Update `ws` to 1.0.1](https://github.com/ripple/ripple-lib/pull/682)
## 0.16.2
+ Bump `ripple-binary-codec` dependency version to 0.1.1 to fix issue with `computeLedgerHash` for transactions with `DeliverMin`
## 0.16.1
##0.16.1
**Changes**
+ [FIX: Use assert not assert-diff](https://github.com/ripple/ripple-lib/commit/f6ebe325193e7208c5ee8d8e84a7504714f0009e)
##0.16.0
**Breaking Changes**
+ [Fix types of XRP values in getServerInfo response](https://github.com/ripple/ripple-lib/commit/99d08065e4bda3dda6ae1f183adbd11abc70a9b7)
+ [Change error event format and fix crash due to error event on webscocket](https://github.com/ripple/ripple-lib/commit/9cd72595f0efc062d77b9d625695d6030c524cc6)
## 0.16.0
**Changes**
+ [Fix generateAddress docs and add error event listener to boilerplate](https://github.com/ripple/ripple-lib/commit/809d981987a2890fac3a73a40a05c598b9040334)
+ [Allow setting maxLedgerVersion to null to specify no maximum](https://github.com/ripple/ripple-lib/commit/82613e7e8b360d1ae1552eab4559ab4763c06d7e)
__BREAKING CHANGES__
+ [Fix types of XRP values in `getServerInfo` response](https://github.com/ripple/ripple-lib/commit/99d08065e4bda3dda6ae1f183adbd11abc70a9b7)
+ [Change error event format and fix crash due to error event on websocket](https://github.com/ripple/ripple-lib/commit/9cd72595f0efc062d77b9d625695d6030c524cc6)
__OTHER CHANGES__
+ [Fix `generateAddress` docs and add error event listener to boilerplate](https://github.com/ripple/ripple-lib/commit/809d981987a2890fac3a73a40a05c598b9040334)
+ [Allow setting `maxLedgerVersion` to `null` to specify no maximum](https://github.com/ripple/ripple-lib/commit/82613e7e8b360d1ae1552eab4559ab4763c06d7e)
+ [Add support for client certificates](https://github.com/ripple/ripple-lib/commit/5f5e48e4140345d166b8c1a3ee0847b0d9e2d893)
+ [getFee returns a string not float](https://github.com/ripple/ripple-lib/commit/7bf2da6014c87e164542e69356efeaabb575a157)
+ [Fix parsing of quality for getTrustlines](https://github.com/ripple/ripple-lib/commit/86ff315ef2a39dfdc2ce97e0e1c4aa73f04e363b)
+ [Fix DeliverMin value when specifying minAmount](Fix DeliverMin value when specifying minAmount)
+ [`getFee` returns a string not a float](https://github.com/ripple/ripple-lib/commit/7bf2da6014c87e164542e69356efeaabb575a157)
+ [Fix parsing of quality for `getTrustlines`](https://github.com/ripple/ripple-lib/commit/86ff315ef2a39dfdc2ce97e0e1c4aa73f04e363b)
+ Fix `DeliverMin` value when specifying `minAmount`
+ [http server example](https://github.com/ripple/ripple-lib/commit/76866ab901ea46a2dd73181605e0f7f4220043d4)
## 0.15.2
##0.15.2
**Changes**
+ [Fix support for proxy credentials in proxy URL and fix error when there are more than 10 outstanding requests](https://github.com/ripple/ripple-lib/commit/0990ad4a6f1d59ca9d2cb859b4e2d71693f3fc4b)
##0.15.1
**Changes**
+ [Fix babel-polyfill require](https://github.com/ripple/ripple-lib/commit/062148674c3b1293ab82c28e25615ddd530339fa)
+ [Fix samples](https://github.com/ripple/ripple-lib/commit/5d5cf868a2ddb1b1cd40e4a4f0a782d0066c2055)
+ [add unit tests for RippleAPIBroadcast](https://github.com/ripple/ripple-lib/commit/ddf8fe5b1a9c750490dca98fb9ffaaf8017f87e0)
## 0.15.1
##0.15.0
**Breaking Changes**
+ [Fix `babel-polyfill` require](https://github.com/ripple/ripple-lib/commit/062148674c3b1293ab82c28e25615ddd530339fa)
+ [Fix samples](https://github.com/ripple/ripple-lib/commit/5d5cf868a2ddb1b1cd40e4a4f0a782d0066c2055)
+ [Add unit tests for `RippleAPIBroadcast`](https://github.com/ripple/ripple-lib/commit/ddf8fe5b1a9c750490dca98fb9ffaaf8017f87e0)
## 0.15.0
__BREAKING CHANGES__
+ ["servers" parameter changed to single "server"](https://github.com/ripple/ripple-lib/commit/7061e9afe46f0682254d098adeff3dd7157521a1)
**Changes**
+ [fix handling memos in prepareSettings](https://github.com/ripple/ripple-lib/commit/c9704137b7b538e8dbf31c483bcdcf2dcfd7cd75)
__OTHER CHANGES__
+ [Fix handling memos in `prepareSettings`](https://github.com/ripple/ripple-lib/commit/c9704137b7b538e8dbf31c483bcdcf2dcfd7cd75)
+ [Docs: SusPay warnings, offline mode, and other tweaks](https://github.com/ripple/ripple-lib/commit/4b4fc36ebd93f1360781a65f2869bd2c4f0a5093)
+ [Fix prepareOrderCancellation documentation](https://github.com/ripple/ripple-lib/commit/5e720891f579fd73d43c64e5ec519d9121023c10)
##0.14.0
**Breaking Changes**
+ [prepareOrderCancellation now takes orderCancellation specification](https://github.com/ripple/ripple-lib/commit/7f33d8a71e56289e5a5e0ead1c74f75ebcde72bc)
## 0.14.0
__BREAKING CHANGES__
+ [`prepareOrderCancellation` now takes orderCancellation specification](https://github.com/ripple/ripple-lib/commit/7f33d8a71e56289e5a5e0ead1c74f75ebcde72bc)
+ [Rename "ledgerClosed" event to "ledger" and change format](https://github.com/ripple/ripple-lib/commit/8a3d4a64db5fbf560ebf87dc62e0212513c5e18a)
**Changes**
__OTHER CHANGES__
+ [Fix proxy support and add support for proxy authorization](https://github.com/ripple/ripple-lib/commit/14b840f3feca758e0384b746c94e36d8bf59b8c2)
+ [Fix trace option](https://github.com/ripple/ripple-lib/commit/af620755c53556c55eed12de4b0013ef5a349ce2)
+ [Allow memos on all transaction types](https://github.com/ripple/ripple-lib/commit/b5081344da8e66fbd3a5113cc3313325ef72a494)
@@ -62,26 +85,24 @@
+ [Docs: revised introductory material](https://github.com/ripple/ripple-lib/commit/ef2515507dbd3c6a426ab5b31332a1bdf72d5b2d)
+ [boost coverage to almost 100%](https://github.com/ripple/ripple-lib/commit/995606b1e6f3643af34d9fd442ccd31f320b03eb)
##0.13.2
## 0.13.2
**Changes**
+ [Fix: Specify send_max when pathfinding with a source amount](https://github.com/ripple/ripple-lib/commit/75142139184625c8b9fcc480b1825d9985337813)
##0.13.1
+ [Add documentation for API events](https://github.com/ripple/ripple-lib/commit/25d1ac0c5f95cad32ea4ceebb))
## 0.13.1
**Changes**
+ [Add documentation for API events](https://github.com/ripple/ripple-lib/commit/25d1ac0c5f95cad32ea4ceebb)
+ [Fix: Add babel-polyfill](https://github.com/ripple/ripple-lib/commit/8a53abc32f6ec6c7d50cd182492d6fb511b86704)
+ [Fix: Bump version on ripple-hashes](https://github.com/ripple/ripple-lib/commit/12e5765c64aea31b3c2fb65ff989cf01e6368f58)
##0.13.0
## 0.13.0
**Breaking Changes**
__BREAKING CHANGES__
+ Add new RippleAPI interface and delete old API
- [RippleAPI README and samples](https://github.com/ripple/ripple-lib/tree/develop/docs/samples)
- [Method documentation](https://rawgit.com/ripple/ripple-lib/develop/docs/api.html)
**Changes**
__OTHER CHANGES__
+ [Removed timeout method of Request and added default timeout](https://github.com/ripple/ripple-lib/commit/634fe5683a9082e57682ff7d5c4fb9483b4af818)
+ [Add Remote.closeCurrentPathFind function, so current pathfind can be properly closed](https://github.com/ripple/ripple-lib/commit/e99010f363fc7cbe7fd547d3ca5b32ea083c44e6)
+ [Implement Balance Sheet API](https://github.com/ripple/ripple-lib/pull/579)
@@ -89,125 +110,85 @@
+ [Fix crash due to rippled slowDown error](https://github.com/ripple/ripple-lib/commit/84838b2e9f6969b593b8462a62a6b8f516ada937)
+ [Fix: Emit error events and return error on pathfind](https://github.com/ripple/ripple-lib/commit/1ccbaf677631a1944eb05d90f7afc5f3690a03dd)
+ [Deprecate core and remove snake case method copying](https://github.com/ripple/ripple-lib/commit/fb8dc44ec1d49bb05cd0cdbe6dd4ab211195868a)
+ [Fix RangeSet for validated_ledger as single ledger](https://github.com/ripple/ripple-lib/commit/9f9e76f8b933201651af59307135f67cfa7d60e8)
+ [Fix bug where the paths would be set with an empty array](https://github.com/ripple/ripple-lib/commit/83874ec0962da311b76f2385623e51c68bc39035)
+ [Fix reserve calculation](https://github.com/ripple/ripple-lib/commit/52879febb92d876f01f2e4d70871baa07af631fb)
##0.12.9
## 0.12.9
+ [OrderBook performance optimizations](https://github.com/ripple/ripple-lib/commit/3e17d91edf36745f6b6c09b0ad88971b7775f6ab)
##0.12.7 and 0.12.8
## 0.12.7 and 0.12.8
+ [Improve performance of orderbook](https://github.com/ripple/ripple-lib/commit/c745faaaf0956ca98448a754b4fe97fb50574fc7)
+ [Remove Firefox warning about prototype overwrite](https://github.com/ripple/ripple-lib/commit/0c62fa21123b220b066871e1c41a3b4fe6f51885)
+ [Fix compare bug in `Amount` class](https://github.com/ripple/ripple-lib/commit/806547dd154e1b0bf252e8a74ad3ac6aa8a97660)
+ [Fix compare bug in Amount class](https://github.com/ripple/ripple-lib/commit/806547dd154e1b0bf252e8a74ad3ac6aa8a97660)
##0.12.6
## 0.12.6
+ [Fix webpack require failure due to "./" notation](https://github.com/ripple/ripple-lib/commit/8d9746d7b10be203ee613df523c2522012ff1baf)
##0.12.15
## 0.12.15
+ [Add offer autobridging](https://github.com/ripple/ripple-lib/commit/c7bbce83719c1e8c6a4fae5ca850e7515db1a4a5)
+ [Prevent crash when listening for "model" events on the OrderBook class](https://github.com/ripple/ripple-lib/commit/5824c3cb7cb6bd834d6e037f69943aebf3d83351)
+ [Fix empty order edgecase](https://github.com/ripple/ripple-lib/commit/64809d9ae23dc24f47accd4b4788b48f49880d3e)
+ [Fix AutobridgeCalculator (RT-3445)](https://github.com/ripple/ripple-lib/commit/1fff5ea6dcbcee856536df26f3b9cf1aec3c3b55)
+ [Update sjcl and delete custom ripemd160, montgomery, and jacobi](https://github.com/ripple/ripple-lib/commit/50cda426eb83599c38c0b725e1524a01fc415da2)
+ [Fix transaction summary for transactions that fail with remoteError](https://github.com/ripple/ripple-lib/commit/5e714f6143464d7912f42537acaa553b88eaf6dc)
+ [Fix serializedobject append for excessively large bytes length](https://github.com/ripple/ripple-lib/commit/e93f1ab6f4aaad347450aee75a169af0faa2121c)
+ [Switch to sjcl npm module](https://github.com/ripple/ripple-lib/commit/9a502580fd89ec6a9aa55f4e5847f6a4a2cb5bba)
+ [Add babel transpiler](https://github.com/ripple/ripple-lib/commit/398f8d001f758bf575b959537a17e79e4042d17b)
+ [Remove unused float.js and wallet.js](https://github.com/ripple/ripple-lib/commit/d4a4b5f4fbbf09677a59ce81bace35c6426a2fda)
+ [Remove config singleton to reduce global state](https://github.com/ripple/ripple-lib/commit/c655c2a20ee5d150a4b5a1b6717b9fb81f636025)
##0.12.4
## 0.12.4
+ [Improve entropy security](https://github.com/ripple/ripple-lib/commit/c7ba822320880037796f57876d1abb4e525648ed)
+ [Remove unused crypt.js file](https://github.com/ripple/ripple-lib/commit/1f68eba1461bca03a4d22872450d15ae5a185334)
##0.12.3
## 0.12.3
+ [Add getLedgerSequence to Remote](https://github.com/ripple/ripple-lib/commit/d09548d04d3238fca653d482ec1d5faa7254559a)
+ [Improve randomness when generating ECDSA signatures](https://github.com/ripple/ripple-lib/commit/fe7e30b737ead6e71adfa466f5835ba546feab31)
+ [Improve SerializedObject.append performance](https://github.com/ripple/ripple-lib/commit/f7c35b118ebba549a64bcaa1a0629385ec6dbf6f)
+ [Add `Amount.scale`. Multiply an amounts value by a scale factor](https://github.com/ripple/ripple-lib/commit/74dac97b368493056474468520f05671f458a69f)
##0.12.2
## 0.12.2
+ [Check that stack trace is available, fixes logging in browser](https://github.com/ripple/ripple-lib/commit/53cae3a66d48e88e8a6bbb96d6489ce7b9e22975)
## 0.12.1
##0.12.1
**Breaking Changes**
__BREAKING CHANGES__
+ [Removed support for parsing native amounts in floating point format](https://github.com/ripple/ripple-lib/commit/e80cd1ff55deae9cd5b0ae85be957f86856b887e)
**Changes**
__OTHER CHANGES__
+ [Fix taker pays funded calculation](https://github.com/ripple/ripple-lib/commit/5af824f5cf46c7b9caa58ee0a757bf854d26c8dc)
+ [Fix order funded amount calculation](https://github.com/ripple/ripple-lib/commit/b2cdb1a6aed968b1f306e8dadbd4b7ca37e5aa03)
+ [Fix handling of quality in order book](https://github.com/ripple/ripple-lib/commit/2a5a8b498da60df738ba18d5c265f34771e8a1af)
+ [Fix currency parsing of non-alphanumeric and no-currency currencies](https://github.com/ripple/ripple-lib/commit/2166bb2e88eae8d5f1aba77338f69e8a9edf6a6f)
+ [Add Amount.strict_mode for toggling range validation](https://github.com/ripple/ripple-lib/commit/b5ed8f59a7dab1a17491618b8d9193646c314fb4)
+ [Add filename and line number to log, use log.warn() for deprecations](https://github.com/ripple/ripple-lib/commit/90329d3d73f1a76675063655b407513e32dc048b)
+ [Add GlobalFreeze and NoFreeze flags](https://github.com/ripple/ripple-lib/commit/e2ed2bdbf6f01c7d4d690c2cf0b83fba94558dd7)
+ [Fix handling of falsy parameters in requestLedger](https://github.com/ripple/ripple-lib/commit/6023efed41b7812b3bab660a1c0dc9f0a21000b9)
+ [Fix Base:decode](https://github.com/ripple/ripple-lib/commit/719f39c01c6941d9a650aa94f95617793dd53ea0)
+ [Fix Amount: clone in ratio_human, product_human](https://github.com/ripple/ripple-lib/commit/19e17a8431550cf156b1ad669a19dedfe4e28e4a)
+ [Fix Amount.to_human for very small numbers](https://github.com/ripple/ripple-lib/commit/6abfa759aa09d68074ac558d96c4b126a7cd1719)
+ [Refactor base conversion](https://github.com/ripple/ripple-lib/commit/f2b63fa4a80663eb29472bc6bb1aea8159f1f205)
+ [Update binary transaction format](https://github.com/ripple/ripple-lib/commit/8e134918fb4c22983320a3102f955e4568bb1dfb)
+ [Add DefaultRipple account flag](https://github.com/ripple/ripple-lib/commit/3e249902c4cf25b4da5e75048c84ae391be83b10)
+ [Remove `Features` field requirement in `SetFee` transaction format](https://github.com/ripple/ripple-lib/commit/a20a649013646710c078d4ce1e210f87c7fe74fe)
+ [Remove `RegularKey` field requirement in `SetRegularKey` transaction format](https://github.com/ripple/ripple-lib/commit/c275174f27877ba8f389eb4efe969feb514d6e46)
## 0.12.0
##0.12.0
**Breaking Changes**
__BREAKING CHANGES__
+ REMOVED Remote storage interface
+ REMOVED Remote `ping` configuration
+ REMOVED Old/deprecated Remote server configuration (websocket_ip, websocket_port)
+ REMOVED browser `online` reconnect listener
- [Cleanup, deprecations - 2833a7b6](https://github.com/ripple/ripple-lib/commit/2833a7b66e696dab427464625077f9b93092d0d5)
+ Remove `jsbn` and use `bignumber.js` instead for big number math
+ The `allow_nan` flag has been removed. Results for invalid amounts will always be `NaN`
- [Refactor to use bignumber.js - d025b4a0](https://github.com/ripple/ripple-lib/commit/d025b4a0c3a98a6de27a1bee9573c85347bcd66b)
@@ -215,109 +196,76 @@
- [Check for null in isNumber - b86790c8](https://github.com/ripple/ripple-lib/commit/b86790c8543c239a532fd7697d4652829019d385)
- [Cleanup amount.js - d0fb291c](https://github.com/ripple/ripple-lib/commit/d0fb291c4e330193a244902156f1d74730da357d)
**Changes**
__OTHER CHANGES__
+ [Add deprecation warnings to request constructors. The first argument to request constructor functions should be an object containing request properties](https://github.com/ripple/ripple-lib/commit/35d76b3520934285f80059c1badd6c522539104c)
+ [Fix taker_gets_funded exceeding offer.TakerGets](https://github.com/ripple/ripple-lib/commit/b19ecb4482b589d575382b7a5d0480b963383bb1)
+ [Fix unsymmetric memo serializing](https://github.com/ripple/ripple-lib/commit/1ed36fabdbd54f4d31078c2b0eaa3becc0fe2821)
+ [Fix IOU value passed to `Amount.from_json()`](https://github.com/ripple/ripple-lib/commit/fd1b64393dffb3d1819cd40b8d43df43a4db042d)
+ [Update transaction binary parsing to account for XRP delivered amounts](https://github.com/ripple/ripple-lib/commit/35a346a674e6ee1e1e495db93700d55984efc7dd)
+ [Bumped dependencies](https://github.com/ripple/ripple-lib/commit/f9bc7cc746b44b24b61bbe260ae2e9d9617286da)
##0.11.0
## 0.11.0
+ [Track the funded status of an order based on cumulative account orders](https://github.com/ripple/ripple-lib/commit/67d39737a4d5e0fcd9d9b47b9083ee00e5a9e652) and [67d3973](https://github.com/ripple/ripple-lib/commit/b6b99dde022e1e14c4797e454b1d7fca50e49482)
+ Remove blobvault client from ripple-lib, use the [`ripple-vault-client`](https://github.com/ripple/ripple-vault-client) instead [9b3d62b7](https://github.com/ripple/ripple-lib/commit/9b3d62b765c4c25beae6eb0fa57ef3a07f2581b1)
+ [Add support for `ledger` option in requestBookOffers](https://github.com/ripple/ripple-lib/commit/34c0677c453c409ef0a5b351959abdc176d3bacb)
+ [Add support for `limit` option in requestBookOffers](https://github.com/ripple/ripple-lib/commit/d1d4452217c878d0b377d24830b4cd8b3162f6e0)
+ [Add `ledgerSelect` request constructor in `Remote`](https://github.com/ripple/ripple-lib/commit/98f40abfc3aa74dec5067a2d90002756cc8acd01)
+ [Default to binary data for commands that accept the binary flag](https://github.com/ripple/ripple-lib/commit/7cb113fcbcfc1e3e9830a999148b3e78df3387cc)
+ [Fix metadata account check](https://github.com/ripple/ripple-lib/commit/3f61598d6c87e3cc877af60e2d515f9eff73dfe1)
+ [Double check `tes` code before emitting `success`](https://github.com/ripple/ripple-lib/commit/97a8c874903eb7309d8f755955ac80872f670582)
+ [Decrease redundancy in binary account_tx parsing](https://github.com/ripple/ripple-lib/commit/0aba638e6e7f4f6e22cb6424eed3897ebad90a5a)
+ [Abort server connection on unrecoverable TLS error](https://github.com/ripple/ripple-lib/commit/000a2ea00c57157044aeca0fb3f24b37669b163c)
+ [Fix complete ledgers check on subscription that is not initial](https://github.com/ripple/ripple-lib/commit/89de91301e682a46dc60aaacc7ae152e8fe1b7c7)
##0.10.0
## 0.10.0
+ [Transaction changes](https://github.com/ripple/ripple-lib/pull/221)
+ **Important** `tef*` and `tel*` and errors will no longer be presented as
final. Rather than considering these errors final, ripple-lib will wait until
the `LastLedgerSequence` specified in the transaction is exceeded. This makes
failures more definitive, and ensures that no transaction will resubmit
indefinitely.
+ A new, final tej-class error is introduced to account for transactions that
are locally determined to have expired: `tejMaxLedger`.
+ [Allow per transaction fees to be set, `transaction.setFixedFee()`](https://github.com/ripple/ripple-lib/commit/9b22f279bcbe60ee6bcf4b7fa60a48e9c197a828)
+ [Improve memo support](https://github.com/ripple/ripple-lib/commit/1704ac4ae144c0ce54afad86f644c75a632080b1)
- Add `MemoFormat` property for memo
- Enforce `MemoFormat` and `MemoType` to be valid ASCII
- Support `text` and `json` MemoFormat
+ [Update jscl library](https://github.com/ripple/ripple-lib/commit/3204998fcb6f31d6c90532a737a4adb8a1e420f6)
+ [Update sjcl library](https://github.com/ripple/ripple-lib/commit/3204998fcb6f31d6c90532a737a4adb8a1e420f6)
- Improved entropy by taking advantage of platform crypto
- Use jscl's k256 curve instead of altering the c256 curve with k256 configuration
- **deprecated:** the c256 curve is linked to the k256 curve to provide backwards compatibility, this link will be removed in the future
- **Deprecated:** The c256 curve is linked to the k256 curve to provide backwards compatibility, this link will be removed in the future
+ [Fix empty queue check on reconnect](https://github.com/ripple/ripple-lib/commit/3c21994adcf72d1fbd87d453ceb917f9ad6df4ec)
##0.9.4
## 0.9.4
+ [Normalize offers from book_offers and transaction stream](https://github.com/ripple/ripple-lib/commit/86ed24b94cf7c8929c87db3a63e9bbea7f767e9c)
+ [Fix: Amount.to_human() precision rounding](https://github.com/ripple/ripple-lib/commit/e371cc2c3ceccb3c1cfdf18b98d80093147dd8b2)
+ [Fix: fractional drops in funded taker_pays setter](https://github.com/ripple/ripple-lib/commit/0d7fc0a573a144caac15dd13798b23eeb1f95fb4)
##0.9.3
## 0.9.3
+ [Change `presubmit` to emit immediately before transaction submit](https://github.com/ripple/ripple-lib/commit/7a1feaa89701bf861ab31ebd8ffdc8d8d1474e29)
+ [Add a "core" browser build of ripple-lib which has a subset of features and smaller file size](https://github.com/ripple/ripple-lib/pull/205)
+ [Update binformat with missing fields from rippled](https://github.com/ripple/ripple-lib/commit/cae980788efb00191bfd0988ed836d60cdf7a9a2)
+ [Wait for transaction validation before returning `tec` error](https://github.com/ripple/ripple-lib/commit/6bdd4b2670906588852fc4dda457607b4aac08e4)
+ [Change default `max_fee` on `Remote` to `1 XRP`](https://github.com/ripple/ripple-lib/commit/d6b1728c23ff85c3cc791bed6982a750641fd95f)
+ [Fix: Request ledger_accept should return the Remote](https://github.com/ripple/ripple-lib/pull/209)
##0.9.2
## 0.9.2
+ [**Breaking change**: Change accountRequest method signature](https://github.com/ripple/ripple-lib/commit/6f5d1104aa3eb440c518ec4f39e264fdce15fa15)
__BREAKING CHANGES__
+ [Change accountRequest method signature](https://github.com/ripple/ripple-lib/commit/6f5d1104aa3eb440c518ec4f39e264fdce15fa15)
__OTHER CHANGES__
+ [Add paging behavior for account requests, `account_lines` and `account_offers`](https://github.com/ripple/ripple-lib/commit/722f4e175dbbf378e51b49142d0285f87acb22d7)
+ [Add max_fee setter to transactions to set max fee the submitter is willing to pay] (https://github.com/ripple/ripple-lib/commit/24587fab9c8ad3840d7aa345a7037b48839e09d7)
+ [Fix: cap IOU Amounts to their max and min value] (https://github.com/ripple/ripple-lib/commit/f05941fbc46fdb7c6fe7ad72927af02d527ffeed)
+ [Add max_fee setter to transactions to set max fee the submitter is willing to pay](https://github.com/ripple/ripple-lib/commit/24587fab9c8ad3840d7aa345a7037b48839e09d7)
+ [Fix: cap IOU Amounts to their max and min value](https://github.com/ripple/ripple-lib/commit/f05941fbc46fdb7c6fe7ad72927af02d527ffeed)
Example on how to use paging with `account_offers`:
```
```js
// A valid `ledger_index` or `ledger_hash` is required to provide a reliable result.
// Results can change between ledger closes, so the provided ledger will be used as base.
var options = {
@@ -337,110 +285,70 @@ var request = remote.requestAccountOffers(options);
[Full working example](https://github.com/geertweening/ripple-lib-scripts/blob/master/account_offers_paging.js)
##0.9.1
## 0.9.1
+ Switch account requests to use ledgerSelect rather than ledgerChoose ([278df90](https://github.com/ripple/ripple-lib/commit/278df9025a20228de22379a53c76ca12d40fa591))
+ **Deprecated** setting `ident` and `account_index` on account requests ([278df90](https://github.com/ripple/ripple-lib/commit/278df9025a20228de22379a53c76ca12d40fa591))
+ Change initial account transaction sequence to 1 ([a3c1d06](https://github.com/ripple/ripple-lib/commit/a3c1d06eba883dc84fe2bfe700e4309795c84cac))
+ Fix: instance transaction withoute remote ([d3b6b81](https://github.com/ripple/ripple-lib/commit/d3b6b8127c7b01e416b400c25abf1719bdd008ca))
+ Fix: instance transaction without remote ([d3b6b81](https://github.com/ripple/ripple-lib/commit/d3b6b8127c7b01e416b400c25abf1719bdd008ca))
+ Fix: account root request ledger argument ([bc1f9f8](https://github.com/ripple/ripple-lib/commit/bc1f9f8a286b187d36ebaf552694e31e73742293))
+ Fix: rsign.js local signing and example ([d3b6b81](https://github.com/ripple/ripple-lib/commit/d3b6b8127c7b01e416b400c25abf1719bdd008ca) and [f1004c6](https://github.com/ripple/ripple-lib/commit/f1004c6db2a0ce59bbabbb8f2b355a9fd9995fd8))
## 0.9.0
##0.9.0
__BREAKING CHANGES__
+ Make maxLoops in seed.get_key optional. [Example use in tests](https://github.com/ripple/ripple-lib/blob/23e473b6886c457781949c825b3ff48b3984e51f/test/seed-test.js) ([23e473b](https://github.com/ripple/ripple-lib/commit/23e473b6886c457781949c825b3ff48b3984e51f))
__OTHER CHANGES__
+ Add routes to the vault client for KYC attestations ([ed2da574](https://github.com/ripple/ripple-lib/commit/ed2da57475acf5e9d2cf3373858f4274832bd83f))
+ Currency: add `show_interest` flag to show or hide interest in `Currency.to_human()` and `Currency.to_json()` [Example use in tests](https://github.com/ripple/ripple-lib/blob/947ec3edc2e7c8f1ef097e496bf552c74366e749/test/currency-test.js#L123)
+ Configurable maxAttempts for transaction submission ([d107092](https://github.com/ripple/ripple-lib/commit/d10709254061e9e4416d2cb78b5cac1ec0d7ffa5))
+ Binformat: added missing TransactionResult options ([6abed8d](https://github.com/ripple/ripple-lib/commit/6abed8dd5311765b2eb70505dadbdf5121439ca8))
+ **Breaking change:** make maxLoops in seed.get_key optional. [Example use in tests](https://github.com/ripple/ripple-lib/blob/23e473b6886c457781949c825b3ff48b3984e51f/test/seed-test.js) ([23e473b](https://github.com/ripple/ripple-lib/commit/23e473b6886c457781949c825b3ff48b3984e51f))
+ Shrinkwrap packages for dependency locking ([2dcd5f9](2dcd5f94fbc71200eb08a5044c76ef94f7971913))
+ Fix: Amount.to_human() precision bugs ([4be209e](https://github.com/ripple/ripple-lib/commit/4be209e286b5b209bec7bcd1212098985e15ff2f) and [7708c64](https://github.com/ripple/ripple-lib/commit/7708c64576e70ce3ac190442daceb30e4446aab7))
+ Fix: change handling of requestLedger options ([57b7030](https://github.com/ripple/ripple-lib/commit/57b70300f5f0c7534ede118ddbb5d8762668a4f8))
##0.8.2
## 0.8.2
+ Currency: Allow mixed letters and numbers in currencies
+ Deprecate account_tx map/reduce/filterg
+ Fix: correct requestLedger arguments
+ Fix: missing subscription on error events for some server methods
+ Fix: orderbook reset on reconnect
+ Fix: ripple-lib crashing. Add potential missing error handlers
##0.8.1
## 0.8.1
+ Wallet: Add Wallet class that generates wallets
+ Make npm test runnable in Windows.
+ Fix several stability issues, see merged PR's for details
+ Fix bug in Amount.to_human_full()
+ Fix undefined fee states when connecting to a rippled that is syncing
##0.8.0
## 0.8.0
+ Orderbook: Added tracking of offer funds for determining when offers are not funded
+ Orderbook: Added tests
+ Orderbook: Update owner funds
+ Transactions: If transaction errs with `tefALREADY`, wait until all possible submissions err with the same before emitting `error`. Fixes a client "Transaction malformed" bug.
+ Transactions: Track submissions, don't bother submitting to unconnected servers
+ Request: `request.request()` now accepts an array of servers as first argument. Servers can be represented with URL, or the server object itself.
+ Request: `request.broadcast()` now returns the number of servers request was sent to
+ Server: Acquire host information from server without additional request
+ Amount: Add a constant for the maximum canonical value that can be expressed as a Ripple value
+ Amount: Make Constants static fields on the class, instead of a separate export
+ Amount: Make Constants static fields on the class, instead of a seperate export
##0.7.39
## 0.7.39
+ Improvements to multi-server support. Fixed an issue where a server's score was not reset and connections would keep dropping after being connected for a significant amount of time.
+ Improvements in order book support. Added support for currency pairs with interest bearing currencies. You can request an order book with hex, ISO code or full name for the currency.
+ Fix value parsing for amount/currency order pairs, e.g. `Amount.from_human("XAU 12345.6789")`
+ Improved Amount parsing from human readable string given a hex currency, e.g. `Amount.from_human("10 015841551A748AD2C1F76FF6ECB0CCCD00000000")`
+ Improvements to username normalization in the vault client
+ Add 2-factor authentication support for vault client
+ Removed vestiges of Grunt, switched to Gulp
##0.7.37
## 0.7.37
+ **Deprecations**
@@ -451,11 +359,8 @@ var request = remote.requestAccountOffers(options);
5. Removed `transaction.transactionManager` getter.
+ Improved multi-server support. Servers are now ranked dynamically, and transactions are broadcasted to all connected servers.
+ Automatically ping connected servers. Client configuration now should contain `ping: <seconds>` to specify the ping interval.
+ Added `transaction.lastLedger` to specify `LastLedgerSequence`. Setting it this way also ensures that the sequence is not bumped on subsequent requests.
+ Added optional `remote.accountTx` binary parsing.
```js
{
@@ -464,28 +369,19 @@ var request = remote.requestAccountOffers(options);
}
```
+ Added full currency name support, e.g. `Currency.from_json('XRP').to_human({full_name:'Ripples'})` will return `XRP - Ripples`
+ Improved interest bearing currency support, e.g. `Currency.from_human('USD - US Dollar (2.5%pa)')`
+ Improve test coverage
+ Added blob vault client. The vault client facilitates interaction with ripple's namespace and blob vault or 3rd party blob vaults using ripple's blob vault software (https://github.com/ripple/ripple-blobvault). A list of the available functions can be found at [docs/VAULTCLIENT.md](docs/VAULTCLIENT.md)
##0.7.35
## 0.7.35
+ `LastLedgerSequence` is set by default on outgoing transactions. This refers to the last valid ledger index (AKA sequence) for a transaction. By default, this index is set to the current index (at submission time) plus 8. In theory, this allows ripple-lib to deterministically fail a transaction whose submission request timed out, but whose associated server continues to emit ledger_closed events.
+ Transactions that err with `telINSUF_FEE_P` will be automatically resubmitted. This error indicates that the `Fee` supplied in the transaction submission request was inadquate. Ideally, the `Fee` is tracked by ripple-lib in real-time, and the resubmitted transaction will most likely succeed.
+ Transactions that err with `telINSUF_FEE_P` will be automatically resubmitted. This error indicates that the `Fee` supplied in the transaction submission request was inadequate. Ideally, the `Fee` is tracked by ripple-lib in real-time, and the resubmitted transaction will most likely succeed.
+ Added Transaction.iff(function(callback) { }). Callback expects first argument to be an Error or null, second argument is a boolean which indicates whether or not to proceed with the transaction submission. If an `iff` function is specified, it will be executed prior to every submission of the transaction (including resubmissions).
+ Transactions will now emit `presubmit` and `postsubmit` events. They will be emitted before and after a transaction is submitted, respectively.
+ Added Transaction.summary(). Returns a summary of a transaction in semi-human-readable form. JSON-stringifiable.
+ Remote.requestAccountTx() with `binary: true` will automatically parse transactions.
+ Added Remote.requestAccountTx filter, map, and reduce.
```js
@@ -513,6 +409,4 @@ var request = remote.requestAccountOffers(options);
```
+ Added persistence hooks.
+ General performance improvements, especially for long-running processes.

View File

@@ -1,3 +1,5 @@
ISC License
Copyright (c) 2012-2015 Ripple Labs Inc.
Permission to use, copy, modify, and distribute this software for any

View File

@@ -1,37 +1,45 @@
#ripple-lib
# ripple-lib
A JavaScript API for interacting with Ripple in Node.js
A JavaScript API for interacting with the XRP Ledger
[![Circle CI](https://circleci.com/gh/ripple/ripple-lib/tree/develop.svg?style=svg)](https://circleci.com/gh/ripple/ripple-lib/tree/develop) [![Coverage Status](https://coveralls.io/repos/ripple/ripple-lib/badge.png?branch=develop)](https://coveralls.io/r/ripple/ripple-lib?branch=develop)
[![NPM](https://nodei.co/npm/ripple-lib.png)](https://www.npmjs.org/package/ripple-lib)
###Features
### Features
+ Connect to a rippled server in Node.js
+ Connect to a `rippled` server from Node.js or a web browser
+ Issue [rippled API](https://ripple.com/build/rippled-apis/) requests
+ Listen to events on the Ripple network (transaction, ledger, etc.)
+ Sign and submit transactions to the Ripple network
+ Listen to events on the XRP Ledger (transaction, ledger, etc.)
+ Sign and submit transactions to the XRP Ledger
##Getting Started
## Getting Started
Install `ripple-lib` using npm:
See also: [RippleAPI Beginners Guide](https://ripple.com/build/rippleapi-beginners-guide/)
You can use `npm`, but we recommend using `yarn` for the added assurance provided by `yarn.lock`.
+ [Yarn Installation Instructions](https://yarnpkg.com/en/docs/install)
Install `ripple-lib`:
```
$ npm install ripple-lib
$ yarn install ripple-lib
```
Then see the [documentation](https://github.com/ripple/ripple-lib/blob/develop/docs/index.md) and [code samples](https://github.com/ripple/ripple-lib/tree/develop/docs/samples)
##Running tests
## Running tests
1. Clone the repository
2. `cd` into the repository and install dependencies with `npm install`
3. `npm test` or `npm test --coverage` (`istanbul` will create coverage reports in coverage/lcov-report/`)
2. `cd` into the repository and install dependencies with `yarn install`
3. `yarn test` or `yarn test --coverage` (`istanbul` will create coverage reports in `coverage/lcov-report/`)
##Generating Documentation
## Generating Documentation
The continuous integration tests require that the documentation stays up-to-date. If you make changes the the JSON schemas, fixtures, or documentation sources, you must update the documentation by running `npm run docgen`.
The continuous integration tests require that the documentation stays up-to-date. If you make changes to the JSON schemas, fixtures, or documentation sources, you must update the documentation by running `yarn run docgen`.
##More Information
`npm` may be used instead of `yarn` in the commands above.
+ [Ripple Dev Portal](https://ripple.com/build/)
## More Information
+ [Ripple Developer Center](https://ripple.com/build/)

View File

@@ -1,6 +1,6 @@
machine:
node:
version: 0.12.0
version: 6.11.3
hosts:
testripple.circleci.com: 127.0.0.1
dependencies:

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,27 @@
# Basic Types
## Ripple Address
## Address
```json
"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59"
```
Every Ripple account has an *address*, which is a base58-encoding of a hash of the account's public key. Ripple addresses always start with the lowercase letter `r`.
Every XRP Ledger account has an *address*, which is a base58-encoding of a hash of the account's public key. XRP Ledger addresses always start with the lowercase letter `r`.
## Account Sequence Number
Every Ripple account has a *sequence number* that is used to keep transactions in order. Every transaction must have a sequence number. A transaction can only be executed if it has the next sequence number in order, of the account sending it. This prevents one transaction from executing twice and transactions executing out of order. The sequence number starts at `1` and increments for each transaction that the account makes.
Every XRP Ledger account has a *sequence number* that is used to keep transactions in order. Every transaction must have a sequence number. A transaction can only be executed if it has the next sequence number in order, of the account sending it. This prevents one transaction from executing twice and transactions executing out of order. The sequence number starts at `1` and increments for each transaction that the account makes.
## Currency
Currencies are represented as either 3-character currency codes or 40-character uppercase hexadecimal strings. We recommend using uppercase [ISO 4217 Currency Codes](http://www.xe.com/iso4217.php) only. The string "XRP" is disallowed on trustlines because it is reserved for the Ripple native currency. The following characters are permitted: all uppercase and lowercase letters, digits, as well as the symbols `?`, `!`, `@`, `#`, `$`, `%`, `^`, `&`, `*`, `<`, `>`, `(`, `)`, `{`, `}`, `[`, `]`, and `|`.
Currencies are represented as either 3-character currency codes or 40-character uppercase hexadecimal strings. We recommend using uppercase [ISO 4217 Currency Codes](http://www.xe.com/iso4217.php) only. The string "XRP" is disallowed on trustlines because it is reserved for the XRP Ledger's native currency. The following characters are permitted: all uppercase and lowercase letters, digits, as well as the symbols `?`, `!`, `@`, `#`, `$`, `%`, `^`, `&`, `*`, `<`, `>`, `(`, `)`, `{`, `}`, `[`, `]`, and `|`.
## Value
A *value* is a quantity of a currency represented as a decimal string. Be careful: JavaScript's native number format does not have sufficient precision to represent all values. XRP has different precision from other currencies.
**XRP** has 6 significant digits past the decimal point. In other words, XRP cannot be divided into positive values smaller than `0.000001` (1e-6). XRP has a maximum value of `100000000000` (1e11).
**Non-XRP values** have 15 decimal digits of precision, with a maximum value of `9999999999999999e80`. The smallest positive non-XRP value is `1e-81`.
**Non-XRP values** have 16 decimal digits of precision, with a maximum value of `9999999999999999e80`. The smallest positive non-XRP value is `1e-81`.
## Amount

View File

@@ -3,7 +3,7 @@
Use the following [boilerplate code](https://en.wikipedia.org/wiki/Boilerplate_code) to wrap your custom code using RippleAPI.
```javascript
const {RippleAPI} = require('ripple-lib');
const RippleAPI = require('ripple-lib').RippleAPI;
const api = new RippleAPI({
server: 'wss://s1.ripple.com' // Public rippled server hosted by Ripple, Inc.
@@ -11,6 +11,14 @@ const api = new RippleAPI({
api.on('error', (errorCode, errorMessage) => {
console.log(errorCode + ': ' + errorMessage);
});
api.on('connected', () => {
console.log('connected');
});
api.on('disconnected', (code) => {
// code - [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) sent by the server
// will be 1000 if this was normal closure
console.log('disconnected, code:', code);
});
api.connect().then(() => {
/* insert code here */
}).then(() => {
@@ -18,9 +26,9 @@ api.connect().then(() => {
}).catch(console.error);
```
RippleAPI is designed to work in [NodeJS](https://nodejs.org) (version `0.12.0` or greater) using [Babel](https://babeljs.io/) for [ECMAScript 6](https://babeljs.io/docs/learn-es2015/) support.
RippleAPI is designed to work in [Node.js](https://nodejs.org) version **6.11.3**. RippleAPI may work on older Node.js versions if you use [Babel](https://babeljs.io/) for [ECMAScript 6](https://babeljs.io/docs/learn-es2015/) support.
The code samples in this documentation are written in ES6, but `RippleAPI` will work with ES5 also. Regardless of whether you use ES5 or ES6, the methods that return promises will return [ES6-style promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
The code samples in this documentation are written with ECMAScript 6 (ES6) features, but `RippleAPI` also works with ECMAScript 5 (ES5). Regardless of whether you use ES5 or ES6, the methods that return Promises return [ES6-style promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
<aside class="notice">
All the code snippets in this documentation assume that you have surrounded them with this boilerplate.
@@ -45,16 +53,10 @@ If you omit the `server` parameter, RippleAPI operates [offline](#offline-functi
### Installation ###
1. Install [NodeJS](https://nodejs.org) and the Node Package Manager (npm). Most Linux distros have a package for NodeJS, but make sure you have version `0.12.0` or higher.
2. Use npm to install [Babel](https://babeljs.io/) globally:
`npm install -g babel-cli`
3. Use npm to install RippleAPI:
`npm install ripple-lib`
1. Install [Node.js](https://nodejs.org) and [Yarn](https://yarnpkg.com/en/docs/install). Most Linux distros have a package for Node.js; check that it's the version you want.
2. Use yarn to install RippleAPI:
`yarn install ripple-lib`
After you have installed ripple-lib, you can create scripts using the [boilerplate](#boilerplate) and run them using babel-node:
`babel-node script.js`
<aside class="notice">
Instead of using babel-node in production, we recommend using Babel to transpile to ECMAScript 5 first.
</aside>
After you have installed ripple-lib, you can create scripts using the [boilerplate](#boilerplate) and run them using the Node.js executable, typically named `node`:
`node script.js`

View File

@@ -47,3 +47,35 @@ api.on('error', (errorCode, errorMessage, data) => {
```
tooBusy: The server is too busy to help you now.
```
## connected
This event is emitted after connection successfully opened.
### Example
```javascript
api.on('connected', () => {
console.log('Connection is open now.');
});
```
## disconnected
This event is emitted when connection is closed.
### Return Value
The only parameter is a number containing the [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) send by the server.
### Example
```javascript
api.on('disconnected', (code) => {
if (code !== 1000) {
console.log('Connection is closed due to error.');
} else {
console.log('Connection is closed normally.');
}
});
```

View File

@@ -2,7 +2,7 @@
`generateAddress(): {address: string, secret: string}`
Generate a new Ripple address and corresponding secret.
Generate a new XRP Ledger address and corresponding secret.
### Parameters

View File

@@ -10,7 +10,7 @@ Returns aggregate balances by currency plus a breakdown of assets and obligation
### Return Value
This method returns a promise that resolves with an array of objects with the following structure:
This method returns a promise that resolves with an object with the following structure:
<%- renderSchema('output/get-balance-sheet.json') %>

View File

@@ -0,0 +1,26 @@
## getPaymentChannel
`getPaymentChannel(id: string): Promise<Object>`
Returns specified payment channel.
### Parameters
<%- renderSchema('input/get-payment-channel.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<%- renderSchema('output/get-payment-channel.json') %>
### Example
```javascript
const channelId =
'E30E709CF009A1F26E0E5C48F7AA1BFB79393764F15FB108BDC6E06D3CBD8415';
return api.getPaymentChannel(channelId).then(channel =>
{/* ... */});
```
<%- renderFixture('responses/get-payment-channel.json') %>

View File

@@ -21,18 +21,24 @@
<% include getOrderbook.md.ejs %>
<% include getSettings.md.ejs %>
<% include getAccountInfo.md.ejs %>
<% include getPaymentChannel.md.ejs %>
<% include getLedger.md.ejs %>
<% include preparePayment.md.ejs %>
<% include prepareTrustline.md.ejs %>
<% include prepareOrder.md.ejs %>
<% include prepareOrderCancellation.md.ejs %>
<% include prepareSettings.md.ejs %>
<% include prepareSuspendedPaymentCreation.md.ejs %>
<% include prepareSuspendedPaymentCancellation.md.ejs %>
<% include prepareSuspendedPaymentExecution.md.ejs %>
<% include prepareEscrowCreation.md.ejs %>
<% include prepareEscrowCancellation.md.ejs %>
<% include prepareEscrowExecution.md.ejs %>
<% include preparePaymentChannelCreate.md.ejs %>
<% include preparePaymentChannelClaim.md.ejs %>
<% include preparePaymentChannelFund.md.ejs %>
<% include sign.md.ejs %>
<% include combine.md.ejs %>
<% include submit.md.ejs %>
<% include generateAddress.md.ejs %>
<% include signPaymentChannelClaim.md.ejs %>
<% include verifyPaymentChannelClaim.md.ejs %>
<% include computeLedgerHash.md.ejs %>
<% include events.md.ejs %>

View File

@@ -1,12 +1,12 @@
# Introduction
RippleAPI is the official client library to the Ripple Consensus Ledger. Currently, RippleAPI is only available in JavaScript.
RippleAPI is the official client library to the XRP Ledger. Currently, RippleAPI is only available in JavaScript.
Using RippleAPI, you can:
* [Query transactions from the network](#gettransaction)
* [Query transactions from the XRP Ledger history](#gettransaction)
* [Sign](#sign) transactions securely without connecting to any server
* [Submit](#submit) transactions to the Ripple Consensus Ledger, including [Payments](#payment), [Orders](#order), [Settings changes](#settings), and [other types](#transaction-types)
* [Generate a new Ripple Address](#generateaddress)
* [Submit](#submit) transactions to the XRP Ledger, including [Payments](#payment), [Orders](#order), [Settings changes](#settings), and [other types](#transaction-types)
* [Generate a new XRP Ledger Address](#generateaddress)
* ... and [much more](#api-methods).
RippleAPI only provides access to *validated*, *immutable* transaction data.

View File

@@ -5,23 +5,22 @@ RippleAPI can also function without internet connectivity. This can be useful in
To instantiate RippleAPI in offline mode, use the following boilerplate code:
```javascript
const {RippleAPI} = require('ripple-lib');
const RippleAPI = require('ripple-lib').RippleAPI;
const api = new RippleAPI();
/* insert code here */
```
Methods that depend on the state of the Ripple Consensus Ledger are unavailable in offline mode. To prepare transactions offline, you **must** specify the `fee`, `sequence`, and `maxLedgerVersion` parameters in the [transaction instructions](#transaction-instructions). The following methods should work offline:
Methods that depend on the state of the XRP Ledger are unavailable in offline mode. To prepare transactions offline, you **must** specify the `fee`, `sequence`, and `maxLedgerVersion` parameters in the [transaction instructions](#transaction-instructions). You can use the following methods while offline:
* [preparePayment](#preparepayment)
* [prepareTrustline](#preparetrustline)
* [prepareOrder](#prepareorder)
* [prepareOrderCancellation](#prepareordercancellation)
* [prepareSettings](#preparesettings)
* [prepareSuspendedPaymentCreation](#preparesuspendedpaymentcreation)
* [prepareSuspendedPaymentCancellation](#preparesuspendedpaymentcancellation)
* [prepareSuspendedPaymentExecution](#preparesuspendedpaymentexecution)
* [prepareEscrowCreation](#prepareescrowcreation)
* [prepareEscrowCancellation](#prepareescrowcancellation)
* [prepareEscrowExecution](#prepareescrowexecution)
* [sign](#sign)
* [generateAddress](#generateaddress)
* [computeLedgerHash](#computeledgerhash)

View File

@@ -0,0 +1,30 @@
## prepareEscrowCancellation
`prepareEscrowCancellation(address: string, escrowCancellation: Object, instructions: Object): Promise<Object>`
Prepare an escrow cancellation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
### Parameters
<%- renderSchema('input/prepare-escrow-cancellation.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const escrowCancellation = <%- importFile('test/fixtures/requests/prepare-escrow-cancellation.json') %>;
return api.prepareEscrowCancellation(address, escrowCancellation).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-escrow-cancellation.json') %>

View File

@@ -0,0 +1,30 @@
## prepareEscrowCreation
`prepareEscrowCreation(address: string, escrowCreation: Object, instructions: Object): Promise<Object>`
Prepare an escrow creation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
### Parameters
<%- renderSchema('input/prepare-escrow-creation.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const escrowCreation = <%- importFile('test/fixtures/requests/prepare-escrow-creation.json') %>;
return api.prepareEscrowCreation(address, escrowCreation).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-escrow-creation.json') %>

View File

@@ -0,0 +1,30 @@
## prepareEscrowExecution
`prepareEscrowExecution(address: string, escrowExecution: Object, instructions: Object): Promise<Object>`
Prepare an escrow execution transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
### Parameters
<%- renderSchema('input/prepare-escrow-execution.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const escrowExecution = <%- importFile('test/fixtures/requests/prepare-escrow-execution.json') %>;
return api.prepareEscrowExecution(address, escrowExecution).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-escrow-execution.json') %>

View File

@@ -23,7 +23,7 @@ All "prepare*" methods have the same return type.
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const orderCancellation = {orderSequence: 123};
return api.prepareOrderCancellation(address, sequence)
return api.prepareOrderCancellation(address, orderCancellation)
.then(prepared => {/* ... */});
```

View File

@@ -0,0 +1,30 @@
## preparePaymentChannelClaim
`preparePaymentChannelClaim(address: string, paymentChannelClaim: Object, instructions: Object): Promise<Object>`
Prepare a payment channel claim transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
### Parameters
<%- renderSchema('input/prepare-payment-channel-claim.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const paymentChannelClaim = <%- importFile('test/fixtures/requests/prepare-payment-channel-claim.json') %>;
return api.preparePaymentChannelClaim(address, paymentChannelClaim).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-payment-channel-claim.json') %>

View File

@@ -0,0 +1,30 @@
## preparePaymentChannelCreate
`preparePaymentChannelCreate(address: string, paymentChannelCreate: Object, instructions: Object): Promise<Object>`
Prepare a payment channel creation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
### Parameters
<%- renderSchema('input/prepare-payment-channel-create.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const paymentChannelCreate = <%- importFile('test/fixtures/requests/prepare-payment-channel-create.json') %>;
return api.preparePaymentChannelCreate(address, paymentChannelCreate).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-payment-channel-create.json') %>

View File

@@ -0,0 +1,30 @@
## preparePaymentChannelFund
`preparePaymentChannelFund(address: string, paymentChannelFund: Object, instructions: Object): Promise<Object>`
Prepare a payment channel fund transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
### Parameters
<%- renderSchema('input/prepare-payment-channel-fund.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const paymentChannelFund = <%- importFile('test/fixtures/requests/prepare-payment-channel-fund.json') %>;
return api.preparePaymentChannelFund(address, paymentChannelFund).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-payment-channel-fund.json') %>

View File

@@ -1,32 +0,0 @@
## prepareSuspendedPaymentCancellation
`prepareSuspendedPaymentCancellation(address: string, suspendedPaymentCancellation: Object, instructions: Object): Promise<Object>`
Prepare a suspended payment cancellation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
**Caution:** Suspended Payments are currently available on the [Ripple Test Net](https://ripple.com/build/ripple-test-net/) only.
### Parameters
<%- renderSchema('input/prepare-suspended-payment-cancellation.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const suspendedPaymentCancellation = <%- importFile('test/fixtures/requests/prepare-suspended-payment-cancellation.json') %>;
return api.prepareSuspendedPaymentCancellation(address, suspendedPaymentCancellation).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-suspended-payment-cancellation.json') %>

View File

@@ -1,32 +0,0 @@
## prepareSuspendedPaymentCreation
`prepareSuspendedPaymentCreation(address: string, suspendedPaymentCreation: Object, instructions: Object): Promise<Object>`
Prepare a suspended payment creation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
**Caution:** Suspended Payments are currently available on the [Ripple Test Net](https://ripple.com/build/ripple-test-net/) only.
### Parameters
<%- renderSchema('input/prepare-suspended-payment-creation.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const suspendedPaymentCreation = <%- importFile('test/fixtures/requests/prepare-suspended-payment-creation.json') %>;
return api.prepareSuspendedPaymentCreation(address, suspendedPaymentCreation).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-suspended-payment-creation.json') %>

View File

@@ -1,32 +0,0 @@
## prepareSuspendedPaymentExecution
`prepareSuspendedPaymentExecution(address: string, suspendedPaymentExecution: Object, instructions: Object): Promise<Object>`
Prepare a suspended payment execution transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
**Caution:** Suspended Payments are currently available on the [Ripple Test Net](https://ripple.com/build/ripple-test-net/) only.
### Parameters
<%- renderSchema('input/prepare-suspended-payment-execution.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const suspendedPaymentExecution = <%- importFile('test/fixtures/requests/prepare-suspended-payment-execution.json') %>;
return api.prepareSuspendedPaymentExecution(address, suspendedPaymentExecution).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-suspended-payment-execution.json') %>

View File

@@ -0,0 +1,28 @@
## signPaymentChannelClaim
`signPaymentChannelClaim(channel: string, amount: string, privateKey: string): string`
Sign a payment channel claim. The signature can be submitted in a subsequent [PaymentChannelClaim](#preparepaymentchannelclaim) transaction.
### Parameters
<%- renderSchema("input/sign-payment-channel-claim.json") %>
### Return Value
This method returns a signature string:
<%- renderSchema("output/sign-payment-channel-claim.json") %>
### Example
```javascript
const channel =
'3E18C05AD40319B809520F1A136370C4075321B285217323396D6FD9EE1E9037';
const amount = '.00001';
const privateKey =
'ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A';
return api.signPaymentChannelClaim(channel, amount, privateKey);
```
<%- renderFixture("responses/sign-payment-channel-claim.json") %>

View File

@@ -52,32 +52,62 @@ See [Transaction Types](#transaction-types) for a description.
<%- renderFixture('requests/prepare-settings.json') %>
## Suspended Payment Creation
## Escrow Creation
See [Transaction Types](#transaction-types) for a description.
<%- renderSchema('specifications/suspended-payment-creation.json') %>
<%- renderSchema('specifications/escrow-creation.json') %>
### Example
<%- renderFixture('requests/prepare-suspended-payment-creation.json') %>
<%- renderFixture('requests/prepare-escrow-creation.json') %>
## Suspended Payment Cancellation
## Escrow Cancellation
See [Transaction Types](#transaction-types) for a description.
<%- renderSchema('specifications/suspended-payment-cancellation.json') %>
<%- renderSchema('specifications/escrow-cancellation.json') %>
### Example
<%- renderFixture('requests/prepare-suspended-payment-cancellation.json') %>
<%- renderFixture('requests/prepare-escrow-cancellation.json') %>
## Suspended Payment Execution
## Escrow Execution
See [Transaction Types](#transaction-types) for a description.
<%- renderSchema('specifications/suspended-payment-execution.json') %>
<%- renderSchema('specifications/escrow-execution.json') %>
### Example
<%- renderFixture('requests/prepare-suspended-payment-execution.json') %>
<%- renderFixture('requests/prepare-escrow-execution.json') %>
## Payment Channel Create
See [Transaction Types](#transaction-types) for a description.
<%- renderSchema('specifications/payment-channel-create.json') %>
### Example
<%- renderFixture('requests/prepare-payment-channel-create.json') %>
## Payment Channel Fund
See [Transaction Types](#transaction-types) for a description.
<%- renderSchema('specifications/payment-channel-fund.json') %>
### Example
<%- renderFixture('requests/prepare-payment-channel-fund.json') %>
## Payment Channel Claim
See [Transaction Types](#transaction-types) for a description.
<%- renderSchema('specifications/payment-channel-claim.json') %>
### Example
<%- renderFixture('requests/prepare-payment-channel-claim.json') %>

View File

@@ -7,15 +7,13 @@ A transaction type is specified by the strings in the first column in the table
Type | Description
---- | -----------
[payment](#payment) | A `payment` transaction represents a transfer of value from one account to another. Depending on the [path](https://ripple.com/build/paths/) taken, additional exchanges of value may occur atomically to facilitate the payment.
[order](#order) | An `order` transaction creates a limit order. It defines an intent to exchange currencies, and creates an order in the Ripple Consensus Ledger's order book if not completely fulfilled when placed. Orders can be partially fulfilled.
[orderCancellation](#order-cancellation) | An `orderCancellation` transaction cancels an order in the Ripple Consensus Ledger's order book.
[order](#order) | An `order` transaction creates a limit order. It defines an intent to exchange currencies, and creates an order in the XRP Ledger's order book if not completely fulfilled when placed. Orders can be partially fulfilled.
[orderCancellation](#order-cancellation) | An `orderCancellation` transaction cancels an order in the XRP Ledger's order book.
[trustline](#trustline) | A `trustline` transactions creates or modifies a trust line between two accounts.
[settings](#settings) | A `settings` transaction modifies the settings of an account in the Ripple Consensus Ledger.
[suspendedPaymentCreation](#suspended-payment-creation) | A `suspendedPaymentCreation` transaction creates a suspended payment on the ledger, which locks XRP until a cryptographic condition is met or it expires. It is like an escrow service where the Ripple network acts as the escrow agent.
[suspendedPaymentCancellation](#suspended-payment-cancellation) | A `suspendedPaymentCancellation` transaction unlocks the funds in a suspended payment and sends them back to the creator of the suspended payment, but it will only work after the suspended payment expires.
[suspendedPaymentExecution](#suspended-payment-execution) | A `suspendedPaymentExecution` transaction unlocks the funds in a suspended payment and sends them to the destination of the suspended payment, but it will only work if the cryptographic condition is provided.
The three "suspended payment" transaction types are not supported by the production Ripple peer-to-peer network at this time. They are available for testing purposes if you [configure RippleAPI](#boilerplate) to connect to the [Ripple Test Net](https://ripple.com/build/ripple-test-net/) instead.
[settings](#settings) | A `settings` transaction modifies the settings of an account in the XRP Ledger.
[escrowCreation](#escrow-creation) | An `escrowCreation` transaction creates an escrow on the ledger, which locks XRP until a cryptographic condition is met or it expires. It is like an escrow service where the XRP Ledger acts as the escrow agent.
[escrowCancellation](#escrow-cancellation) | An `escrowCancellation` transaction unlocks the funds in an escrow and sends them back to the creator of the escrow, but it will only work after the escrow expires.
[escrowExecution](#escrow-execution) | An `escrowExecution` transaction unlocks the funds in an escrow and sends them to the destination of the escrow, but it will only work if the cryptographic condition is provided.
## Transaction Flow
@@ -27,16 +25,16 @@ Executing a transaction with `RippleAPI` requires the following four steps:
* [prepareOrder](#prepareorder)
* [prepareOrderCancellation](#prepareordercancellation)
* [prepareSettings](#preparesettings)
* [prepareSuspendedPaymentCreation](#preparesuspendedpaymentcreation)
* [prepareSuspendedPaymentCancellation](#preparesuspendedpaymentcancellation)
* [prepareSuspendedPaymentExecution](#preparesuspendedpaymentexecution)
* [prepareEscrowCreation](#prepareescrowcreation)
* [prepareEscrowCancellation](#prepareescrowcancellation)
* [prepareEscrowExecution](#prepareescrowexecution)
2. [Sign](#sign) - Cryptographically sign the transaction locally and save the [transaction ID](#transaction-id). Signing is how the owner of an account authorizes a transaction to take place. For multisignature transactions, the `signedTransaction` fields returned by `sign` must be collected and passed to the [combine](#combine) method.
3. [Submit](#submit) - Submit the transaction to the connected server.
4. Verify - Verify that the transaction got validated by querying with [getTransaction](#gettransaction). This is necessary because transactions may fail even if they were successfully submitted.
## Transaction Fees
Every transaction must destroy a small amount of XRP as a cost to send the transaction. This is also called a *transaction fee*. The transaction cost is designed to increase along with the load on the Ripple network, making it very expensive to deliberately or inadvertently overload the network.
Every transaction must destroy a small amount of XRP as a cost to send the transaction. This is also called a *transaction fee*. The transaction cost is designed to increase along with the load on the XRP Ledger, making it very expensive to deliberately or inadvertently overload the peer-to-peer network that powers the XRP Ledger.
You can choose the size of the fee you want to pay or let a default be used. You can get an estimate of the fee required to be included in the next ledger closing with the [getFee](#getfee) method.
@@ -46,7 +44,7 @@ Transaction instructions indicate how to execute a transaction, complementary wi
<%- renderSchema("objects/instructions.json") %>
We recommended that you specify a `maxLedgerVersion` so that you can quickly determine that a failed transaction will never succeeed in the future. It is impossible for a transaction to succeed after the network ledger version exceeds the transaction's `maxLedgerVersion`. If you omit `maxLedgerVersion`, the "prepare*" method automatically supplies a `maxLedgerVersion` equal to the current ledger plus 3, which it includes in the return value from the "prepare*" method.
We recommended that you specify a `maxLedgerVersion` so that you can quickly determine that a failed transaction will never succeeed in the future. It is impossible for a transaction to succeed after the XRP Ledger's consensus-validated ledger version exceeds the transaction's `maxLedgerVersion`. If you omit `maxLedgerVersion`, the "prepare*" method automatically supplies a `maxLedgerVersion` equal to the current ledger plus 3, which it includes in the return value from the "prepare*" method.
## Transaction ID

View File

@@ -0,0 +1,31 @@
## verifyPaymentChannelClaim
`verifyPaymentChannelClaim(channel: string, amount: string, signature: string, publicKey: string): boolean`
Verify a payment channel claim signature.
### Parameters
<%- renderSchema("input/verify-payment-channel-claim.json") %>
### Return Value
This method returns `true` if the claim signature is valid.
<%- renderSchema("output/verify-payment-channel-claim.json") %>
### Example
```javascript
const channel =
'3E18C05AD40319B809520F1A136370C4075321B285217323396D6FD9EE1E9037';
const amount = '.00001';
const signature = <%- importFile("test/fixtures/responses/sign-payment-channel-claim.json") %>;
const publicKey =
'02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8';
return api.verifyPaymentChannelClaim(channel, amount, signature, publicKey);
```
```json
true
```

352
npm-shrinkwrap.json generated
View File

@@ -1,352 +0,0 @@
{
"name": "ripple-lib",
"version": "0.16.8",
"dependencies": {
"ajv": {
"version": "1.4.10",
"from": "https://registry.npmjs.org/ajv/-/ajv-1.4.10.tgz",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-1.4.10.tgz",
"dependencies": {
"json-stable-stringify": {
"version": "1.0.0",
"from": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.0.tgz",
"dependencies": {
"jsonify": {
"version": "0.0.0",
"from": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz"
}
}
}
}
},
"ajv-i18n": {
"version": "0.1.1",
"from": "https://registry.npmjs.org/ajv-i18n/-/ajv-i18n-0.1.1.tgz",
"resolved": "https://registry.npmjs.org/ajv-i18n/-/ajv-i18n-0.1.1.tgz"
},
"babel-polyfill": {
"version": "6.3.14",
"from": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.3.14.tgz",
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.3.14.tgz",
"dependencies": {
"core-js": {
"version": "1.2.6",
"from": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz"
},
"babel-regenerator-runtime": {
"version": "6.3.13",
"from": "https://registry.npmjs.org/babel-regenerator-runtime/-/babel-regenerator-runtime-6.3.13.tgz",
"resolved": "https://registry.npmjs.org/babel-regenerator-runtime/-/babel-regenerator-runtime-6.3.13.tgz"
},
"babel-runtime": {
"version": "5.8.34",
"from": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.34.tgz",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.34.tgz"
}
}
},
"babel-runtime": {
"version": "6.3.19",
"from": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.3.19.tgz",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.3.19.tgz",
"dependencies": {
"core-js": {
"version": "1.2.6",
"from": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz"
}
}
},
"bignumber.js": {
"version": "2.1.2",
"from": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.1.2.tgz",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.1.2.tgz"
},
"https-proxy-agent": {
"version": "1.0.0",
"from": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz",
"dependencies": {
"agent-base": {
"version": "2.0.1",
"from": "https://registry.npmjs.org/agent-base/-/agent-base-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.0.1.tgz",
"dependencies": {
"semver": {
"version": "5.0.3",
"from": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz"
}
}
},
"debug": {
"version": "2.2.0",
"from": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"dependencies": {
"ms": {
"version": "0.7.1",
"from": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
}
}
},
"extend": {
"version": "3.0.0",
"from": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz"
}
}
},
"jayson": {
"version": "1.2.2",
"from": "https://registry.npmjs.org/jayson/-/jayson-1.2.2.tgz",
"resolved": "https://registry.npmjs.org/jayson/-/jayson-1.2.2.tgz",
"dependencies": {
"JSONStream": {
"version": "1.0.3",
"from": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.0.3.tgz",
"dependencies": {
"jsonparse": {
"version": "1.0.0",
"from": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.0.0.tgz"
},
"through": {
"version": "2.3.8",
"from": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
}
}
},
"commander": {
"version": "1.3.2",
"from": "https://registry.npmjs.org/commander/-/commander-1.3.2.tgz",
"resolved": "https://registry.npmjs.org/commander/-/commander-1.3.2.tgz",
"dependencies": {
"keypress": {
"version": "0.1.0",
"from": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz",
"resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz"
}
}
},
"eyes": {
"version": "0.1.8",
"from": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz"
},
"lodash": {
"version": "3.6.0",
"from": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz"
}
}
},
"lodash": {
"version": "3.10.1",
"from": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz"
},
"ripple-address-codec": {
"version": "2.0.1",
"from": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-2.0.1.tgz",
"dependencies": {
"hash.js": {
"version": "1.0.3",
"from": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz",
"dependencies": {
"inherits": {
"version": "2.0.1",
"from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
}
}
},
"x-address-codec": {
"version": "0.7.2",
"from": "https://registry.npmjs.org/x-address-codec/-/x-address-codec-0.7.2.tgz",
"resolved": "https://registry.npmjs.org/x-address-codec/-/x-address-codec-0.7.2.tgz",
"dependencies": {
"base-x": {
"version": "1.0.1",
"from": "https://registry.npmjs.org/base-x/-/base-x-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/base-x/-/base-x-1.0.1.tgz"
}
}
}
}
},
"ripple-binary-codec": {
"version": "0.1.2",
"from": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-0.1.2.tgz",
"resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-0.1.2.tgz",
"dependencies": {
"babel-runtime": {
"version": "5.8.34",
"from": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.34.tgz",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.34.tgz",
"dependencies": {
"core-js": {
"version": "1.2.6",
"from": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz"
}
}
},
"bn.js": {
"version": "3.3.0",
"from": "https://registry.npmjs.org/bn.js/-/bn.js-3.3.0.tgz",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-3.3.0.tgz"
},
"create-hash": {
"version": "1.1.2",
"from": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz",
"dependencies": {
"cipher-base": {
"version": "1.0.2",
"from": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.2.tgz"
},
"ripemd160": {
"version": "1.0.1",
"from": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.1.tgz"
},
"sha.js": {
"version": "2.4.4",
"from": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.4.tgz",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.4.tgz"
}
}
},
"decimal.js": {
"version": "4.0.3",
"from": "https://registry.npmjs.org/decimal.js/-/decimal.js-4.0.3.tgz",
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-4.0.3.tgz"
},
"inherits": {
"version": "2.0.1",
"from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
}
}
},
"ripple-hashes": {
"version": "0.1.0",
"from": "https://registry.npmjs.org/ripple-hashes/-/ripple-hashes-0.1.0.tgz",
"resolved": "https://registry.npmjs.org/ripple-hashes/-/ripple-hashes-0.1.0.tgz",
"dependencies": {
"create-hash": {
"version": "1.1.2",
"from": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz",
"dependencies": {
"cipher-base": {
"version": "1.0.2",
"from": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.2.tgz"
},
"inherits": {
"version": "2.0.1",
"from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"ripemd160": {
"version": "1.0.1",
"from": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.1.tgz"
},
"sha.js": {
"version": "2.4.4",
"from": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.4.tgz",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.4.tgz"
}
}
}
}
},
"ripple-keypairs": {
"version": "0.10.0",
"from": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-0.10.0.tgz",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-0.10.0.tgz",
"dependencies": {
"babel-runtime": {
"version": "5.8.34",
"from": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.34.tgz",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.34.tgz",
"dependencies": {
"core-js": {
"version": "1.2.6",
"from": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz"
}
}
},
"bn.js": {
"version": "3.3.0",
"from": "https://registry.npmjs.org/bn.js/-/bn.js-3.3.0.tgz",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-3.3.0.tgz"
},
"brorand": {
"version": "1.0.5",
"from": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz"
},
"elliptic": {
"version": "5.2.1",
"from": "https://registry.npmjs.org/elliptic/-/elliptic-5.2.1.tgz",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-5.2.1.tgz",
"dependencies": {
"inherits": {
"version": "2.0.1",
"from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
}
}
},
"hash.js": {
"version": "1.0.3",
"from": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz",
"dependencies": {
"inherits": {
"version": "2.0.1",
"from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
}
}
}
}
},
"ripple-lib-transactionparser": {
"version": "0.6.0",
"from": "https://registry.npmjs.org/ripple-lib-transactionparser/-/ripple-lib-transactionparser-0.6.0.tgz",
"resolved": "https://registry.npmjs.org/ripple-lib-transactionparser/-/ripple-lib-transactionparser-0.6.0.tgz"
},
"ws": {
"version": "1.0.1",
"from": "https://registry.npmjs.org/ws/-/ws-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/ws/-/ws-1.0.1.tgz",
"dependencies": {
"options": {
"version": "0.0.6",
"from": "https://registry.npmjs.org/options/-/options-0.0.6.tgz",
"resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz"
},
"ultron": {
"version": "1.0.2",
"from": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz"
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "ripple-lib",
"version": "0.16.8",
"version": "0.17.9",
"license": "ISC",
"description": "A JavaScript API for interacting with Ripple in Node.js and the browser",
"files": [
@@ -15,49 +15,45 @@
"test": "test"
},
"dependencies": {
"ajv": "^1.4.8",
"babel-polyfill": "^6.3.14",
"babel-runtime": "^6.3.19",
"bignumber.js": "^2.0.3",
"bignumber.js": "^4.1.0",
"https-proxy-agent": "^1.0.0",
"jayson": "^1.2.2",
"lodash": "^3.1.0",
"jsonschema": "^1.1.1",
"lodash": "^4.17.4",
"ripple-address-codec": "^2.0.1",
"ripple-binary-codec": "^0.1.2",
"ripple-hashes": "^0.1.0",
"ripple-keypairs": "^0.10.0",
"ripple-lib-transactionparser": "^0.6.0",
"ws": "^1.0.1"
"ripple-binary-codec": "^0.1.10",
"ripple-hashes": "^0.3.1",
"ripple-keypairs": "^0.10.1",
"ripple-lib-transactionparser": "^0.6.2",
"ws": "^3.3.1"
},
"devDependencies": {
"assert-diff": "^1.0.1",
"babel-cli": "^6.4.0",
"babel-core": "^6.4.0",
"babel-eslint": "^4.1.6",
"babel-eslint": "^6.0.4",
"babel-loader": "^6.2.1",
"babel-plugin-syntax-flow": "^6.3.13",
"babel-plugin-transform-flow-strip-types": "^6.4.0",
"babel-preset-es2015": "^6.3.13",
"babel-preset-stage-1": "^6.3.13",
"babel-register": "^6.3.13",
"coveralls": "^2.10.0",
"coveralls": "^2.13.1",
"doctoc": "^0.15.0",
"ejs": "^2.3.4",
"eslint": "^2.1.0",
"eslint": "^2.9.0",
"eventemitter2": "^0.4.14",
"flow-bin": "^0.14",
"gulp": "^3.8.10",
"gulp-bump": "^0.1.13",
"gulp-rename": "^1.2.0",
"gulp-uglify": "^1.1.0",
"http-server": "^0.8.5",
"isparta": "^4.0.0",
"istanbul": "^1.1.0-alpha.1",
"jayson": "^1.2.2",
"json-loader": "^0.5.2",
"json-schema-to-markdown-table": "^0.4.0",
"mocha": "^2.1.0",
"mocha-junit-reporter": "^1.9.1",
"mocha-phantomjs": "^4.0.1",
"mocha-in-sauce": "^0.0.1",
"mocha-junit-reporter": "^1.9.1",
"null-loader": "^0.1.1",
"webpack": "^1.5.3",
"yargs": "^1.3.1"
@@ -72,9 +68,9 @@
"watch": "babel -w -D --optional runtime -d dist/npm/ src/",
"compile-with-source-maps": "babel -D --optional runtime -s -t -d dist/npm/ src/",
"prepublish": "npm run clean && npm run compile",
"test": "babel-node node_modules/isparta/lib/cli cover ./node_modules/mocha/bin/_mocha",
"test": "babel-node ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha",
"coveralls": "cat ./coverage/lcov.info | coveralls",
"lint": "if ! [ -f eslintrc ]; then curl -o eslintrc 'https://raw.githubusercontent.com/ripple/javascript-style-guide/es6/eslintrc'; echo 'parser: babel-eslint' >> eslintrc; fi; eslint -c eslintrc src/",
"lint": "if ! [ -f .eslintrc ]; then curl -o .eslintrc 'https://raw.githubusercontent.com/ripple/javascript-style-guide/es6/eslintrc'; echo 'parser: babel-eslint' >> .eslintrc; fi; eslint -c .eslintrc src/",
"perf": "./scripts/perf_test.sh",
"start": "babel-node scripts/http.js",
"sauce": "babel-node scripts/sauce-runner.js"

View File

@@ -8,48 +8,48 @@ function checkEOL {
}
typecheck() {
npm install -g flow-bin
yarn install -g flow-bin
flow --version
npm run typecheck
yarn run typecheck
}
lint() {
echo "eslint $(node_modules/.bin/eslint --version)"
npm list babel-eslint
yarn list babel-eslint
REPO_URL="https://raw.githubusercontent.com/ripple/javascript-style-guide"
curl "$REPO_URL/es6/eslintrc" > ./eslintrc
echo "parser: babel-eslint" >> ./eslintrc
node_modules/.bin/eslint -c ./eslintrc $(git --no-pager diff --name-only -M100% --diff-filter=AM --relative $(git merge-base FETCH_HEAD origin/HEAD) FETCH_HEAD | grep "\.js$")
curl "$REPO_URL/es6/eslintrc" > .eslintrc
echo "parser: babel-eslint" >> .eslintrc
node_modules/.bin/eslint -c .eslintrc $(git --no-pager diff --name-only -M100% --diff-filter=AM --relative $(git merge-base FETCH_HEAD origin/HEAD) FETCH_HEAD | grep "\.js$")
}
unittest() {
# test "src"
mocha test --reporter mocha-junit-reporter --reporter-options mochaFile=$CIRCLE_TEST_REPORTS/test-results.xml
npm test --coverage
npm run coveralls
yarn test --coverage
yarn run coveralls
# test compiled version in "dist/npm"
babel -D --optional runtime --ignore "**/node_modules/**" -d test-compiled/ test/
$(npm bin)/babel -D --optional runtime --ignore "**/node_modules/**" -d test-compiled/ test/
echo "--reporter spec --timeout 5000 --slow 500" > test-compiled/mocha.opts
mkdir -p test-compiled/node_modules
ln -nfs ../../dist/npm test-compiled/node_modules/ripple-api
mocha --opts test-compiled/mocha.opts test-compiled
# compile tests for browser testing
gulp build-min build-tests
node --harmony test-compiled/mocked-server.js > /dev/null &
#compile tests for browser testing
#gulp build-min build-tests
#node --harmony test-compiled/mocked-server.js > /dev/null &
echo "Running tests in PhantomJS"
mocha-phantomjs test/localrunner.html
echo "Running tests using minified version in PhantomJS"
mocha-phantomjs test/localrunnermin.html
#echo "Running tests in PhantomJS"
#mocha-phantomjs test/localrunner.html
#echo "Running tests using minified version in PhantomJS"
#mocha-phantomjs test/localrunnermin.html
echo "Running tests in SauceLabs"
http-server &
npm run sauce
#echo "Running tests in SauceLabs"
#http-server &
#yarn run sauce
pkill -f mocked-server.js
pkill -f http-server
#pkill -f mocked-server.js
#pkill -f http-server
rm -rf test-compiled
}
@@ -58,14 +58,14 @@ integrationtest() {
mocha test/integration/http-integration-test.js
# run integration tests in PhantomJS
gulp build-tests build-min
echo "Running integragtion tests in PhantomJS"
mocha-phantomjs test/localintegrationrunner.html
#gulp build-tests build-min
#echo "Running integragtion tests in PhantomJS"
#mocha-phantomjs test/localintegrationrunner.html
}
doctest() {
mv docs/index.md docs/index.md.save
npm run docgen
yarn run docgen
mv docs/index.md docs/index.md.test
mv docs/index.md.save docs/index.md
cmp docs/index.md docs/index.md.test
@@ -76,7 +76,6 @@ oneNode() {
checkEOL
doctest
lint
typecheck
unittest
integrationtest
}
@@ -84,7 +83,7 @@ oneNode() {
twoNodes() {
case "$NODE_INDEX" in
0) doctest; lint; integrationtest;;
1) checkEOL; typecheck; unittest;;
1) checkEOL; unittest;;
*) echo "ERROR: invalid usage"; exit 2;;
esac
}
@@ -92,7 +91,7 @@ twoNodes() {
threeNodes() {
case "$NODE_INDEX" in
0) doctest; lint; integrationtest;;
1) checkEOL; typecheck;;
1) checkEOL;;
2) unittest;;
*) echo "ERROR: invalid usage"; exit 2;;
esac

View File

@@ -1,6 +1,6 @@
'use strict';
const createHTTPServer = require('../src/index').createHTTPServer;
'use strict';
const createHTTPServer = require('../src/http').createHTTPServer;
const port = 5990;
const serverUrl = 'wss://s1.ripple.com';

View File

@@ -7,12 +7,12 @@ function exit_on_error {
rm -rf build
npm install
yarn install
gulp
npm test
yarn test
exit_on_error
echo ""
echo "publish to npm"
npm publish
yarn publish
exit_on_error

View File

@@ -7,12 +7,12 @@ function exit_on_error {
rm -rf build
npm install
yarn install
gulp
npm test
yarn test
exit_on_error
echo ""
echo "publish rc to npm"
npm publish --tag beta
yarn publish --tag beta
exit_on_error

View File

@@ -1,4 +1,3 @@
'use strict';
const _ = require('lodash');
const MochaSauce = require('mocha-in-sauce');
@@ -18,7 +17,6 @@ function main() {
maxDuration: 180000,
// the current build name (optional)
build: Date.now(),
seleniumVersion: '2.50.1',
url: testUrl,
runSauceConnect: true
};
@@ -42,6 +40,10 @@ function main() {
version: '43'});
sauce.browser({browserName: 'safari', platform: 'OS X 10.11',
version: '9'});
sauce.browser({browserName: 'safari', platform: 'OS X 10.10',
version: '8'});
sauce.browser({browserName: 'safari', platform: 'OS X 10.9',
version: '7'});
sauce.browser({browserName: 'chrome', platform: 'OS X 10.11',
version: '47'});
sauce.browser({browserName: 'chrome', platform: 'Linux',

View File

@@ -1,56 +1,56 @@
/* @flow */
'use strict';
'use strict' // eslint-disable-line strict
/* eslint-disable max-len */
// Enable core-js polyfills. This allows use of ES6/7 extensions listed here:
// https://github.com/zloirock/core-js/blob/fb0890f32dabe8d4d88a4350d1b268446127132e/shim.js#L1-L103
/* eslint-enable max-len */
// In node.js env, polyfill might be already loaded (from any npm package),
// that's why we do this check.
if (!global._babelPolyfill) {
require('babel-polyfill');
}
const _ = require('lodash');
const EventEmitter = require('events').EventEmitter;
const common = require('./common');
const server = require('./server/server');
const connect = server.connect;
const disconnect = server.disconnect;
const getServerInfo = server.getServerInfo;
const getFee = server.getFee;
const isConnected = server.isConnected;
const getLedgerVersion = server.getLedgerVersion;
const getTransaction = require('./ledger/transaction');
const getTransactions = require('./ledger/transactions');
const getTrustlines = require('./ledger/trustlines');
const getBalances = require('./ledger/balances');
const getBalanceSheet = require('./ledger/balance-sheet');
const getPaths = require('./ledger/pathfind');
const getOrders = require('./ledger/orders');
const getOrderbook = require('./ledger/orderbook');
const getSettings = require('./ledger/settings');
const getAccountInfo = require('./ledger/accountinfo');
const preparePayment = require('./transaction/payment');
const prepareTrustline = require('./transaction/trustline');
const prepareOrder = require('./transaction/order');
const prepareOrderCancellation = require('./transaction/ordercancellation');
const prepareSuspendedPaymentCreation =
require('./transaction/suspended-payment-creation');
const prepareSuspendedPaymentExecution =
require('./transaction/suspended-payment-execution');
const prepareSuspendedPaymentCancellation =
require('./transaction/suspended-payment-cancellation');
const prepareSettings = require('./transaction/settings');
const sign = require('./transaction/sign');
const combine = require('./transaction/combine');
const submit = require('./transaction/submit');
const errors = require('./common').errors;
const _ = require('lodash')
const EventEmitter = require('events').EventEmitter
const common = require('./common')
const server = require('./server/server')
const connect = server.connect
const disconnect = server.disconnect
const getServerInfo = server.getServerInfo
const getFee = server.getFee
const isConnected = server.isConnected
const getLedgerVersion = server.getLedgerVersion
const getTransaction = require('./ledger/transaction')
const getTransactions = require('./ledger/transactions')
const getTrustlines = require('./ledger/trustlines')
const getBalances = require('./ledger/balances')
const getBalanceSheet = require('./ledger/balance-sheet')
const getPaths = require('./ledger/pathfind')
const getOrders = require('./ledger/orders')
const getOrderbook = require('./ledger/orderbook')
const getSettings = require('./ledger/settings')
const getAccountInfo = require('./ledger/accountinfo')
const getPaymentChannel = require('./ledger/payment-channel')
const preparePayment = require('./transaction/payment')
const prepareTrustline = require('./transaction/trustline')
const prepareOrder = require('./transaction/order')
const prepareOrderCancellation = require('./transaction/ordercancellation')
const prepareEscrowCreation =
require('./transaction/escrow-creation')
const prepareEscrowExecution =
require('./transaction/escrow-execution')
const prepareEscrowCancellation =
require('./transaction/escrow-cancellation')
const preparePaymentChannelCreate =
require('./transaction/payment-channel-create')
const preparePaymentChannelFund =
require('./transaction/payment-channel-fund')
const preparePaymentChannelClaim =
require('./transaction/payment-channel-claim')
const prepareSettings = require('./transaction/settings')
const sign = require('./transaction/sign')
const combine = require('./transaction/combine')
const submit = require('./transaction/submit')
const errors = require('./common').errors
const generateAddress =
require('./offline/generate-address').generateAddressAPI;
const computeLedgerHash = require('./offline/ledgerhash');
const getLedger = require('./ledger/ledger');
require('./offline/generate-address').generateAddressAPI
const computeLedgerHash = require('./offline/ledgerhash')
const signPaymentChannelClaim =
require('./offline/sign-payment-channel-claim')
const verifyPaymentChannelClaim =
require('./offline/verify-payment-channel-claim')
const getLedger = require('./ledger/ledger')
type APIOptions = {
server?: string,
@@ -63,36 +63,42 @@ type APIOptions = {
// prevent access to non-validated ledger versions
class RestrictedConnection extends common.Connection {
request(request, timeout) {
const ledger_index = request.ledger_index;
const ledger_index = request.ledger_index
if (ledger_index !== undefined && ledger_index !== 'validated') {
if (!_.isNumber(ledger_index) || ledger_index > this._ledgerVersion) {
return Promise.reject(new errors.LedgerVersionError(
`ledgerVersion ${ledger_index} is greater than server\'s ` +
`most recent validated ledger: ${this._ledgerVersion}`));
`most recent validated ledger: ${this._ledgerVersion}`))
}
}
return super.request(request, timeout);
return super.request(request, timeout)
}
}
class RippleAPI extends EventEmitter {
constructor(options: APIOptions = {}) {
common.validate.apiOptions(options);
super();
this._feeCushion = options.feeCushion || 1.2;
const serverURL = options.server;
common.validate.apiOptions(options)
super()
this._feeCushion = options.feeCushion || 1.2
const serverURL = options.server
if (serverURL !== undefined) {
this.connection = new RestrictedConnection(serverURL, options);
this.connection = new RestrictedConnection(serverURL, options)
this.connection.on('ledgerClosed', message => {
this.emit('ledger', server.formatLedgerClose(message));
});
this.emit('ledger', server.formatLedgerClose(message))
})
this.connection.on('error', (errorCode, errorMessage, data) => {
this.emit('error', errorCode, errorMessage, data);
});
this.emit('error', errorCode, errorMessage, data)
})
this.connection.on('connected', () => {
this.emit('connected')
})
this.connection.on('disconnected', code => {
this.emit('disconnected', code)
})
} else {
// use null object pattern to provide better error message if user
// tries to call a method that requires a connection
this.connection = new RestrictedConnection(null, options);
this.connection = new RestrictedConnection(null, options)
}
}
}
@@ -115,15 +121,19 @@ _.assign(RippleAPI.prototype, {
getOrderbook,
getSettings,
getAccountInfo,
getPaymentChannel,
getLedger,
preparePayment,
prepareTrustline,
prepareOrder,
prepareOrderCancellation,
prepareSuspendedPaymentCreation,
prepareSuspendedPaymentExecution,
prepareSuspendedPaymentCancellation,
prepareEscrowCreation,
prepareEscrowExecution,
prepareEscrowCancellation,
preparePaymentChannelCreate,
preparePaymentChannelFund,
preparePaymentChannelClaim,
prepareSettings,
sign,
combine,
@@ -131,8 +141,10 @@ _.assign(RippleAPI.prototype, {
generateAddress,
computeLedgerHash,
signPaymentChannelClaim,
verifyPaymentChannelClaim,
errors
});
})
// these are exposed only for use by unit tests; they are not part of the API
RippleAPI._PRIVATE = {
@@ -140,8 +152,8 @@ RippleAPI._PRIVATE = {
RangeSet: require('./common/rangeset').RangeSet,
ledgerUtils: require('./ledger/utils'),
schemaValidator: require('./common/schema-validator')
};
}
module.exports = {
RippleAPI
};
}

View File

@@ -1,70 +1,70 @@
'use strict';
const _ = require('lodash');
const RippleAPI = require('./api').RippleAPI;
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const RippleAPI = require('./api').RippleAPI
class RippleAPIBroadcast extends RippleAPI {
constructor(servers, options) {
super(options);
this.ledgerVersion = 0;
super(options)
this.ledgerVersion = 0
const apis = servers.map(server => new RippleAPI(
_.assign({}, options, {server})
));
))
// exposed for testing
this._apis = apis;
this._apis = apis
this.getMethodNames().forEach(name => {
this[name] = function() { // eslint-disable-line no-loop-func
return Promise.race(apis.map(api => api[name].apply(api, arguments)));
};
});
return Promise.race(apis.map(api => api[name](...arguments)))
}
})
// connection methods must be overridden to apply to all api instances
this.connect = function() {
return Promise.all(apis.map(api => api.connect()));
};
return Promise.all(apis.map(api => api.connect()))
}
this.disconnect = function() {
return Promise.all(apis.map(api => api.disconnect()));
};
return Promise.all(apis.map(api => api.disconnect()))
}
this.isConnected = function() {
return _.every(apis.map(api => api.isConnected()));
};
return _.every(apis.map(api => api.isConnected()))
}
// synchronous methods are all passed directly to the first api instance
const defaultAPI = apis[0];
const syncMethods = ['sign', 'generateAddress', 'computeLedgerHash'];
const defaultAPI = apis[0]
const syncMethods = ['sign', 'generateAddress', 'computeLedgerHash']
syncMethods.forEach(name => {
this[name] = defaultAPI[name].bind(defaultAPI);
});
this[name] = defaultAPI[name].bind(defaultAPI)
})
apis.forEach(api => {
api.on('ledger', this.onLedgerEvent.bind(this));
api.on('ledger', this.onLedgerEvent.bind(this))
api.on('error', (errorCode, errorMessage, data) =>
this.emit('error', errorCode, errorMessage, data));
});
this.emit('error', errorCode, errorMessage, data))
})
}
onLedgerEvent(ledger) {
if (ledger.ledgerVersion > this.ledgerVersion) {
this.ledgerVersion = ledger.ledgerVersion;
this.emit('ledger', ledger);
this.ledgerVersion = ledger.ledgerVersion
this.emit('ledger', ledger)
}
}
getMethodNames() {
const methodNames = [];
const methodNames = []
for (const name in RippleAPI.prototype) {
if (RippleAPI.prototype.hasOwnProperty(name)) {
if (typeof RippleAPI.prototype[name] === 'function') {
methodNames.push(name);
methodNames.push(name)
}
}
}
return methodNames;
return methodNames
}
}
module.exports = {
RippleAPIBroadcast
};
}

View File

@@ -1,4 +1,4 @@
'use strict';
'use strict' // eslint-disable-line strict
function setPrototypeOf(object, prototype) {
// Object.setPrototypeOf not supported on Internet Explorer 9
@@ -12,10 +12,10 @@ function getConstructorName(object) {
// hack for internet explorer
return process.browser ?
object.constructor.toString().match(/^function\s+([^(]*)/)[1] :
object.constructor.name;
object.constructor.name
}
module.exports = {
getConstructorName,
setPrototypeOf
};
}

View File

@@ -1,141 +1,234 @@
const _ = require('lodash');
const {EventEmitter} = require('events');
const WebSocket = require('ws');
const parseURL = require('url').parse;
const RangeSet = require('./rangeset').RangeSet;
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const {EventEmitter} = require('events')
const WebSocket = require('ws')
const parseURL = require('url').parse
const RangeSet = require('./rangeset').RangeSet
const {RippledError, DisconnectedError, NotConnectedError,
TimeoutError, ResponseFormatError, ConnectionError} = require('./errors');
TimeoutError, ResponseFormatError, ConnectionError,
RippledNotInitializedError} = require('./errors')
function isStreamMessageType(type) {
return type === 'ledgerClosed' ||
type === 'transaction' ||
type === 'path_find';
type === 'path_find'
}
class Connection extends EventEmitter {
constructor(url, options = {}) {
super();
this.setMaxListeners(Infinity);
this._url = url;
this._trace = options.trace;
super()
this.setMaxListeners(Infinity)
this._url = url
this._trace = options.trace
if (this._trace) {
// for easier unit testing
this._console = console;
this._console = console
}
this._proxyURL = options.proxy;
this._proxyAuthorization = options.proxyAuthorization;
this._authorization = options.authorization;
this._trustedCertificates = options.trustedCertificates;
this._key = options.key;
this._passphrase = options.passphrase;
this._certificate = options.certificate;
this._timeout = options.timeout || (20 * 1000);
this._isReady = false;
this._ws = null;
this._ledgerVersion = null;
this._availableLedgerVersions = new RangeSet();
this._nextRequestID = 1;
this._proxyURL = options.proxy
this._proxyAuthorization = options.proxyAuthorization
this._authorization = options.authorization
this._trustedCertificates = options.trustedCertificates
this._key = options.key
this._passphrase = options.passphrase
this._certificate = options.certificate
this._timeout = options.timeout || (20 * 1000)
this._isReady = false
this._ws = null
this._ledgerVersion = null
this._availableLedgerVersions = new RangeSet()
this._nextRequestID = 1
this._retry = 0
this._retryTimer = null
this._onOpenErrorBound = null
this._onUnexpectedCloseBound = null
this._fee_base = null
this._fee_ref = null
}
_updateLedgerVersions(data) {
this._ledgerVersion = Number(data.ledger_index);
this._ledgerVersion = Number(data.ledger_index)
if (data.validated_ledgers) {
this._availableLedgerVersions.reset();
this._availableLedgerVersions.reset()
this._availableLedgerVersions.parseAndAddRanges(
data.validated_ledgers);
data.validated_ledgers)
} else {
this._availableLedgerVersions.addValue(this._ledgerVersion);
this._availableLedgerVersions.addValue(this._ledgerVersion)
}
}
_updateFees(data) {
this._fee_base = Number(data.fee_base)
this._fee_ref = Number(data.fee_ref)
}
// return value is array of arguments to Connection.emit
_parseMessage(message) {
const data = JSON.parse(message);
const data = JSON.parse(message)
if (data.type === 'response') {
if (!(Number.isInteger(data.id) && data.id >= 0)) {
throw new ResponseFormatError('valid id not found in response');
throw new ResponseFormatError('valid id not found in response')
}
return [data.id.toString(), data];
return [data.id.toString(), data]
} else if (isStreamMessageType(data.type)) {
if (data.type === 'ledgerClosed') {
this._updateLedgerVersions(data);
this._updateLedgerVersions(data)
this._updateFees(data)
}
return [data.type, data];
return [data.type, data]
} else if (data.type === undefined && data.error) {
return ['error', data.error, data.error_message, data]; // e.g. slowDown
return ['error', data.error, data.error_message, data] // e.g. slowDown
}
throw new ResponseFormatError('unrecognized message type: ' + data.type);
throw new ResponseFormatError('unrecognized message type: ' + data.type)
}
_onMessage(message) {
let parameters;
let parameters
if (this._trace) {
this._console.log(message);
this._console.log(message)
}
try {
parameters = this._parseMessage(message);
parameters = this._parseMessage(message)
} catch (error) {
this.emit('error', 'badMessage', error.message, message);
return;
this.emit('error', 'badMessage', error.message, message)
return
}
// we don't want this inside the try/catch or exceptions in listener
// will be caught
this.emit(...parameters);
this.emit(...parameters)
}
get _state() {
return this._ws ? this._ws.readyState : WebSocket.CLOSED;
return this._ws ? this._ws.readyState : WebSocket.CLOSED
}
get _shouldBeConnected() {
return this._ws !== null;
return this._ws !== null
}
isConnected() {
return this._state === WebSocket.OPEN && this._isReady;
return this._state === WebSocket.OPEN && this._isReady
}
_onUnexpectedClose(resolve = function() {}, reject = function() {}) {
_onUnexpectedClose(beforeOpen, resolve, reject, code) {
if (this._onOpenErrorBound) {
this._ws.removeListener('error', this._onOpenErrorBound);
this._onOpenErrorBound = null;
this._ws.removeListener('error', this._onOpenErrorBound)
this._onOpenErrorBound = null
}
this._ws = null;
this._isReady = false;
this.connect().then(resolve, reject);
// just in case
this._ws.removeAllListeners('open')
this._ws = null
this._isReady = false
if (beforeOpen) {
// connection was closed before it was properly opened, so we must return
// error to connect's caller
this.connect().then(resolve, reject)
} else {
// if first parameter ws lib sends close code,
// but sometimes it forgots about it, so default to 1006 - CLOSE_ABNORMAL
this.emit('disconnected', code || 1006)
this._retryConnect()
}
}
_calculateTimeout(retriesCount) {
return (retriesCount < 40)
// First, for 2 seconds: 20 times per second
? (1000 / 20)
: (retriesCount < 40 + 60)
// Then, for 1 minute: once per second
? (1000)
: (retriesCount < 40 + 60 + 60)
// Then, for 10 minutes: once every 10 seconds
? (10 * 1000)
// Then: once every 30 seconds
: (30 * 1000)
}
_retryConnect() {
this._retry += 1
const retryTimeout = this._calculateTimeout(this._retry)
this._retryTimer = setTimeout(() => {
this.emit('reconnecting', this._retry)
this.connect().catch(this._retryConnect.bind(this))
}, retryTimeout)
}
_clearReconnectTimer() {
clearTimeout(this._retryTimer)
this._retryTimer = null
}
_onOpen() {
this._ws.removeListener('close', this._onUnexpectedCloseBound);
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this);
this._ws.once('close', this._onUnexpectedCloseBound);
this._ws.removeListener('error', this._onOpenErrorBound);
this._onOpenErrorBound = null;
this._ws.on('error', error =>
this.emit('error', 'websocket', error.message, error));
if (!this._ws) {
return Promise.reject(new DisconnectedError())
}
if (this._onOpenErrorBound) {
this._ws.removeListener('error', this._onOpenErrorBound)
this._onOpenErrorBound = null
}
const request = {
command: 'subscribe',
streams: ['ledger']
};
}
return this.request(request).then(data => {
this._updateLedgerVersions(data);
this._isReady = true;
this.emit('connected');
});
if (_.isEmpty(data) || !data.ledger_index) {
// rippled instance doesn't have validated ledgers
return this._disconnect(false).then(() => {
throw new RippledNotInitializedError('Rippled not initialized')
})
}
this._updateLedgerVersions(data)
this._updateFees(data)
this._rebindOnUnxpectedClose()
this._retry = 0
this._ws.on('error', error => {
if (process.browser && error && error.type === 'error') {
// we are in browser, ignore error - `close` event will be fired
// after error
return
}
this.emit('error', 'websocket', error.message, error)
})
this._isReady = true
this.emit('connected')
return undefined
})
}
_rebindOnUnxpectedClose() {
if (this._onUnexpectedCloseBound) {
this._ws.removeListener('close', this._onUnexpectedCloseBound)
}
this._onUnexpectedCloseBound =
this._onUnexpectedClose.bind(this, false, null, null)
this._ws.once('close', this._onUnexpectedCloseBound)
}
_unbindOnUnxpectedClose() {
if (this._onUnexpectedCloseBound) {
this._ws.removeListener('close', this._onUnexpectedCloseBound)
}
this._onUnexpectedCloseBound = null
}
_onOpenError(reject, error) {
reject(new NotConnectedError(error && error.message));
this._onOpenErrorBound = null
this._unbindOnUnxpectedClose()
reject(new NotConnectedError(error && error.message))
}
_createWebSocket() {
const options = {};
const options = {}
if (this._proxyURL !== undefined) {
const parsedURL = parseURL(this._url);
const parsedProxyURL = parseURL(this._proxyURL);
const proxyOverrides = _.omit({
const parsedURL = parseURL(this._url)
const parsedProxyURL = parseURL(this._proxyURL)
const proxyOverrides = _.omitBy({
secureEndpoint: (parsedURL.protocol === 'wss:'),
secureProxy: (parsedProxyURL.protocol === 'https:'),
auth: this._proxyAuthorization,
@@ -143,48 +236,49 @@ class Connection extends EventEmitter {
key: this._key,
passphrase: this._passphrase,
cert: this._certificate
}, _.isUndefined);
const proxyOptions = _.assign({}, parsedProxyURL, proxyOverrides);
let HttpsProxyAgent;
}, _.isUndefined)
const proxyOptions = _.assign({}, parsedProxyURL, proxyOverrides)
let HttpsProxyAgent
try {
HttpsProxyAgent = require('https-proxy-agent');
HttpsProxyAgent = require('https-proxy-agent')
} catch (error) {
throw new Error('"proxy" option is not supported in the browser');
throw new Error('"proxy" option is not supported in the browser')
}
options.agent = new HttpsProxyAgent(proxyOptions);
options.agent = new HttpsProxyAgent(proxyOptions)
}
if (this._authorization !== undefined) {
const base64 = new Buffer(this._authorization).toString('base64');
options.headers = {Authorization: `Basic ${base64}`};
const base64 = new Buffer(this._authorization).toString('base64')
options.headers = {Authorization: `Basic ${base64}`}
}
const optionsOverrides = _.omit({
const optionsOverrides = _.omitBy({
ca: this._trustedCertificates,
key: this._key,
passphrase: this._passphrase,
cert: this._certificate
}, _.isUndefined);
const websocketOptions = _.assign({}, options, optionsOverrides);
const websocket = new WebSocket(this._url, null, websocketOptions);
}, _.isUndefined)
const websocketOptions = _.assign({}, options, optionsOverrides)
const websocket = new WebSocket(this._url, null, websocketOptions)
// we will have a listener for each outstanding request,
// so we have to raise the limit (the default is 10)
if (typeof websocket.setMaxListeners === 'function') {
websocket.setMaxListeners(Infinity);
websocket.setMaxListeners(Infinity)
}
return websocket;
return websocket
}
connect() {
this._clearReconnectTimer()
return new Promise((resolve, reject) => {
if (!this._url) {
reject(new ConnectionError(
'Cannot connect because no server was specified'));
'Cannot connect because no server was specified'))
}
if (this._state === WebSocket.OPEN) {
resolve();
resolve()
} else if (this._state === WebSocket.CONNECTING) {
this._ws.once('open', resolve);
this._ws.once('open', resolve)
} else {
this._ws = this._createWebSocket();
this._ws = this._createWebSocket()
// when an error causes the connection to close, the close event
// should still be emitted; the "ws" documentation says: "The close
// event is also emitted when then underlying net.Socket closes the
@@ -192,142 +286,164 @@ class Connection extends EventEmitter {
// In case if there is connection error (say, server is not responding)
// we must return this error to connection's caller. After successful
// opening, we will forward all errors to main api object.
this._onOpenErrorBound = this._onOpenError.bind(this, reject);
this._ws.once('error', this._onOpenErrorBound);
this._ws.on('message', this._onMessage.bind(this));
this._onOpenErrorBound = this._onOpenError.bind(this, reject)
this._ws.once('error', this._onOpenErrorBound)
this._ws.on('message', this._onMessage.bind(this))
// in browser close event can came before open event, so we must
// resolve connect's promise after reconnect in that case.
// after open event we will rebound _onUnexpectedCloseBound
// without resolve and reject functions
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this,
resolve, reject);
this._ws.once('close', this._onUnexpectedCloseBound);
this._ws.once('open', () => this._onOpen().then(resolve, reject));
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this, true,
resolve, reject)
this._ws.once('close', this._onUnexpectedCloseBound)
this._ws.once('open', () => this._onOpen().then(resolve, reject))
}
});
})
}
disconnect() {
return this._disconnect(true)
}
_disconnect(calledByUser) {
if (calledByUser) {
this._clearReconnectTimer()
this._retry = 0
}
return new Promise(resolve => {
if (this._state === WebSocket.CLOSED) {
resolve();
resolve()
} else if (this._state === WebSocket.CLOSING) {
this._ws.once('close', resolve);
this._ws.once('close', resolve)
} else {
this._ws.removeListener('close', this._onUnexpectedCloseBound);
this._ws.once('close', () => {
this._ws = null;
this._isReady = false;
resolve();
});
this._ws.close();
if (this._onUnexpectedCloseBound) {
this._ws.removeListener('close', this._onUnexpectedCloseBound)
this._onUnexpectedCloseBound = null
}
this._ws.once('close', code => {
this._ws = null
this._isReady = false
if (calledByUser) {
this.emit('disconnected', code || 1000) // 1000 - CLOSE_NORMAL
}
resolve()
})
this._ws.close()
}
});
})
}
reconnect() {
return this.disconnect().then(() => this.connect());
return this.disconnect().then(() => this.connect())
}
_whenReady(promise) {
return new Promise((resolve, reject) => {
if (!this._shouldBeConnected) {
reject(new NotConnectedError());
reject(new NotConnectedError())
} else if (this._state === WebSocket.OPEN && this._isReady) {
promise.then(resolve, reject);
promise.then(resolve, reject)
} else {
this.once('connected', () => promise.then(resolve, reject));
this.once('connected', () => promise.then(resolve, reject))
}
});
})
}
getLedgerVersion() {
return this._whenReady(Promise.resolve(this._ledgerVersion));
return this._whenReady(Promise.resolve(this._ledgerVersion))
}
hasLedgerVersions(lowLedgerVersion, highLedgerVersion) {
return this._whenReady(Promise.resolve(
this._availableLedgerVersions.containsRange(
lowLedgerVersion, highLedgerVersion || this._ledgerVersion)));
lowLedgerVersion, highLedgerVersion || this._ledgerVersion)))
}
hasLedgerVersion(ledgerVersion) {
return this.hasLedgerVersions(ledgerVersion, ledgerVersion);
return this.hasLedgerVersions(ledgerVersion, ledgerVersion)
}
getFeeBase() {
return this._whenReady(Promise.resolve(Number(this._fee_base)))
}
getFeeRef() {
return this._whenReady(Promise.resolve(Number(this._fee_ref)))
}
_send(message) {
if (this._trace) {
this._console.log(message);
this._console.log(message)
}
return new Promise((resolve, reject) => {
this._ws.send(message, undefined, (error, result) => {
if (error) {
reject(new DisconnectedError(error.message));
reject(new DisconnectedError(error.message))
} else {
resolve(result);
resolve(result)
}
});
});
})
})
}
request(request, timeout) {
return new Promise((resolve, reject) => {
if (!this._shouldBeConnected) {
reject(new NotConnectedError());
reject(new NotConnectedError())
}
let timer = null;
const self = this;
const id = this._nextRequestID;
this._nextRequestID += 1;
const eventName = id.toString();
let timer = null
const self = this
const id = this._nextRequestID
this._nextRequestID += 1
const eventName = id.toString()
function onDisconnect() {
clearTimeout(timer);
self.removeAllListeners(eventName);
reject(new DisconnectedError());
clearTimeout(timer)
self.removeAllListeners(eventName)
reject(new DisconnectedError())
}
function cleanup() {
clearTimeout(timer);
self.removeAllListeners(eventName);
clearTimeout(timer)
self.removeAllListeners(eventName)
if (self._ws !== null) {
self._ws.removeListener('close', onDisconnect);
self._ws.removeListener('close', onDisconnect)
}
}
function _resolve(response) {
cleanup();
resolve(response);
cleanup()
resolve(response)
}
function _reject(error) {
cleanup();
reject(error);
cleanup()
reject(error)
}
this.once(eventName, response => {
if (response.status === 'error') {
_reject(new RippledError(response.error));
_reject(new RippledError(response.error))
} else if (response.status === 'success') {
_resolve(response.result);
_resolve(response.result)
} else {
_reject(new ResponseFormatError(
'unrecognized status: ' + response.status));
'unrecognized status: ' + response.status))
}
});
})
this._ws.once('close', onDisconnect);
this._ws.once('close', onDisconnect)
// JSON.stringify automatically removes keys with value of 'undefined'
const message = JSON.stringify(Object.assign({}, request, {id}));
const message = JSON.stringify(Object.assign({}, request, {id}))
this._whenReady(this._send(message)).then(() => {
const delay = timeout || this._timeout;
timer = setTimeout(() => _reject(new TimeoutError()), delay);
}).catch(_reject);
});
const delay = timeout || this._timeout
timer = setTimeout(() => _reject(new TimeoutError()), delay)
}).catch(_reject)
})
}
}
module.exports = Connection;
module.exports = Connection

View File

@@ -1,5 +1,5 @@
'use strict';
const flagIndices = require('./txflags').txFlagIndices.AccountSet;
'use strict' // eslint-disable-line strict
const flagIndices = require('./txflags').txFlagIndices.AccountSet
const accountRootFlags = {
PasswordSpent: 0x00010000, // password set fee is spent
@@ -10,7 +10,7 @@ const accountRootFlags = {
NoFreeze: 0x00200000, // permanently disallowed freezing trustlines
GlobalFreeze: 0x00400000, // trustlines globally frozen
DefaultRipple: 0x00800000
};
}
const AccountFlags = {
passwordSpent: accountRootFlags.PasswordSpent,
@@ -21,7 +21,7 @@ const AccountFlags = {
noFreeze: accountRootFlags.NoFreeze,
globalFreeze: accountRootFlags.GlobalFreeze,
defaultRipple: accountRootFlags.DefaultRipple
};
}
const AccountFlagIndices = {
requireDestinationTag: flagIndices.asfRequireDest,
@@ -32,7 +32,7 @@ const AccountFlagIndices = {
noFreeze: flagIndices.asfNoFreeze,
globalFreeze: flagIndices.asfGlobalFreeze,
defaultRipple: flagIndices.asfDefaultRipple
};
}
const AccountFields = {
EmailHash: {name: 'emailHash', encoding: 'hex',
@@ -40,10 +40,10 @@ const AccountFields = {
MessageKey: {name: 'messageKey'},
Domain: {name: 'domain', encoding: 'hex'},
TransferRate: {name: 'transferRate', defaults: 0, shift: 9}
};
}
module.exports = {
AccountFields,
AccountFlagIndices,
AccountFlags
};
}

View File

@@ -1,43 +1,43 @@
'use strict';
const util = require('util');
const browserHacks = require('./browser-hacks');
'use strict' // eslint-disable-line strict
const util = require('util')
const browserHacks = require('./browser-hacks')
// this is needed because extending builtins doesn't work in babel 6.x
function extendableBuiltin(cls) {
function ExtendableBuiltin() {
cls.apply(this, arguments);
cls.apply(this, arguments)
}
ExtendableBuiltin.prototype = Object.create(cls.prototype);
browserHacks.setPrototypeOf(ExtendableBuiltin, cls);
return ExtendableBuiltin;
ExtendableBuiltin.prototype = Object.create(cls.prototype)
browserHacks.setPrototypeOf(ExtendableBuiltin, cls)
return ExtendableBuiltin
}
class RippleError extends extendableBuiltin(Error) {
constructor(message, data) {
super(message);
super(message)
this.name = browserHacks.getConstructorName(this);
this.message = message;
this.data = data;
this.name = browserHacks.getConstructorName(this)
this.message = message
this.data = data
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor.name);
Error.captureStackTrace(this, this.constructor.name)
}
}
toString() {
let result = '[' + this.name + '(' + this.message;
let result = '[' + this.name + '(' + this.message
if (this.data) {
result += ', ' + util.inspect(this.data);
result += ', ' + util.inspect(this.data)
}
result += ')]';
return result;
result += ')]'
return result
}
/* console.log in node uses util.inspect on object, and util.inspect allows
us to cutomize its output:
https://nodejs.org/api/util.html#util_custom_inspect_function_on_objects */
inspect() {
return this.toString();
return this.toString()
}
}
@@ -53,6 +53,8 @@ class NotConnectedError extends ConnectionError {}
class DisconnectedError extends ConnectionError {}
class RippledNotInitializedError extends ConnectionError {}
class TimeoutError extends ConnectionError {}
class ResponseFormatError extends ConnectionError {}
@@ -61,20 +63,20 @@ class ValidationError extends RippleError {}
class NotFoundError extends RippleError {
constructor(message) {
super(message || 'Not found');
super(message || 'Not found')
}
}
class MissingLedgerHistoryError extends RippleError {
constructor(message) {
super(message || 'Server is missing ledger history in the specified range');
super(message || 'Server is missing ledger history in the specified range')
}
}
class PendingLedgerVersionError extends RippleError {
constructor(message) {
super(message || 'maxLedgerVersion is greater than server\'s'
+ ' most recent validated ledger');
+ ' most recent validated ledger')
}
}
@@ -85,6 +87,7 @@ module.exports = {
RippledError,
NotConnectedError,
DisconnectedError,
RippledNotInitializedError,
TimeoutError,
ResponseFormatError,
ValidationError,
@@ -92,4 +95,4 @@ module.exports = {
PendingLedgerVersionError,
MissingLedgerHistoryError,
LedgerVersionError
};
}

View File

@@ -1,5 +1,5 @@
'use strict';
const utils = require('./utils');
'use strict' // eslint-disable-line strict
const utils = require('./utils')
module.exports = {
Connection: require('./connection'),
@@ -19,4 +19,4 @@ module.exports = {
iso8601ToRippleTime: utils.iso8601ToRippleTime,
rippleTimeToISO8601: utils.rippleTimeToISO8601,
isValidSecret: utils.isValidSecret
};
}

View File

@@ -1,61 +1,61 @@
/* @flow */
'use strict';
const _ = require('lodash');
const assert = require('assert');
const ranges = Symbol();
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const assert = require('assert')
const ranges = Symbol()
function mergeIntervals(intervals: Array<[number, number]>) {
const stack = [[-Infinity, -Infinity]];
const stack = [[-Infinity, -Infinity]]
_.forEach(_.sortBy(intervals, x => x[0]), interval => {
const lastInterval = stack.pop();
const lastInterval = stack.pop()
if (interval[0] <= lastInterval[1] + 1) {
stack.push([lastInterval[0], Math.max(interval[1], lastInterval[1])]);
stack.push([lastInterval[0], Math.max(interval[1], lastInterval[1])])
} else {
stack.push(lastInterval);
stack.push(interval);
stack.push(lastInterval)
stack.push(interval)
}
});
return stack.slice(1);
})
return stack.slice(1)
}
class RangeSet {
constructor() {
this.reset();
this.reset()
}
reset() {
this[ranges] = [];
this[ranges] = []
}
serialize() {
return this[ranges].map(range =>
range[0].toString() + '-' + range[1].toString()).join(',');
range[0].toString() + '-' + range[1].toString()).join(',')
}
addRange(start: number, end: number) {
assert(start <= end, 'invalid range');
this[ranges] = mergeIntervals(this[ranges].concat([[start, end]]));
assert(start <= end, 'invalid range')
this[ranges] = mergeIntervals(this[ranges].concat([[start, end]]))
}
addValue(value: number) {
this.addRange(value, value);
this.addRange(value, value)
}
parseAndAddRanges(rangesString: string) {
const rangeStrings = rangesString.split(',');
const rangeStrings = rangesString.split(',')
_.forEach(rangeStrings, rangeString => {
const range = rangeString.split('-').map(Number);
this.addRange(range[0], range.length === 1 ? range[0] : range[1]);
});
const range = rangeString.split('-').map(Number)
this.addRange(range[0], range.length === 1 ? range[0] : range[1])
})
}
containsRange(start: number, end: number) {
return _.some(this[ranges], range => range[0] <= start && range[1] >= end);
return _.some(this[ranges], range => range[0] <= start && range[1] >= end)
}
containsValue(value: number) {
return this.containsRange(value, value);
return this.containsRange(value, value)
}
}
module.exports.RangeSet = RangeSet;
module.exports.RangeSet = RangeSet

View File

@@ -1,12 +1,12 @@
// flow is disabled for this file until support for requiring json is added:
// https://github.com/facebook/flow/issues/167
'use strict';
const _ = require('lodash');
const assert = require('assert');
const Ajv = require('ajv');
const ValidationError = require('./errors').ValidationError;
const {isValidAddress} = require('ripple-address-codec');
const {isValidSecret} = require('./utils');
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const assert = require('assert')
const Validator = require('jsonschema').Validator
const ValidationError = require('./errors').ValidationError
const {isValidAddress} = require('ripple-address-codec')
const {isValidSecret} = require('./utils')
function loadSchemas() {
// listed explicitly for webpack (instead of scanning schemas directory)
@@ -16,11 +16,13 @@ function loadSchemas() {
require('./schemas/objects/hash128.json'),
require('./schemas/objects/hash256.json'),
require('./schemas/objects/sequence.json'),
require('./schemas/objects/signature.json'),
require('./schemas/objects/issue.json'),
require('./schemas/objects/ledgerversion.json'),
require('./schemas/objects/max-adjustment.json'),
require('./schemas/objects/memo.json'),
require('./schemas/objects/memos.json'),
require('./schemas/objects/public-key.json'),
require('./schemas/objects/uint32.json'),
require('./schemas/objects/value.json'),
require('./schemas/objects/source-adjustment.json'),
@@ -46,21 +48,25 @@ function loadSchemas() {
require('./schemas/objects/settings.json'),
require('./schemas/specifications/settings.json'),
require('./schemas/specifications/payment.json'),
require('./schemas/specifications/suspended-payment-cancellation.json'),
require('./schemas/specifications/escrow-cancellation.json'),
require('./schemas/specifications/order-cancellation.json'),
require('./schemas/specifications/order.json'),
require('./schemas/specifications/suspended-payment-execution.json'),
require('./schemas/specifications/suspended-payment-creation.json'),
require('./schemas/specifications/escrow-execution.json'),
require('./schemas/specifications/escrow-creation.json'),
require('./schemas/specifications/payment-channel-create.json'),
require('./schemas/specifications/payment-channel-fund.json'),
require('./schemas/specifications/payment-channel-claim.json'),
require('./schemas/specifications/trustline.json'),
require('./schemas/output/sign.json'),
require('./schemas/output/submit.json'),
require('./schemas/output/get-account-info.json'),
require('./schemas/output/get-balances.json'),
require('./schemas/output/get-balance-sheet'),
require('./schemas/output/get-balance-sheet.json'),
require('./schemas/output/get-ledger.json'),
require('./schemas/output/get-orderbook.json'),
require('./schemas/output/get-orders.json'),
require('./schemas/output/order-change.json'),
require('./schemas/output/get-payment-channel.json'),
require('./schemas/output/prepare.json'),
require('./schemas/output/ledger-event.json'),
require('./schemas/output/get-paths.json'),
@@ -71,12 +77,15 @@ function loadSchemas() {
require('./schemas/output/get-transaction.json'),
require('./schemas/output/get-transactions.json'),
require('./schemas/output/get-trustlines.json'),
require('./schemas/output/sign-payment-channel-claim.json'),
require('./schemas/output/verify-payment-channel-claim.json'),
require('./schemas/input/get-balances.json'),
require('./schemas/input/get-balance-sheet.json'),
require('./schemas/input/get-ledger.json'),
require('./schemas/input/get-orders.json'),
require('./schemas/input/get-orderbook.json'),
require('./schemas/input/get-paths.json'),
require('./schemas/input/get-payment-channel.json'),
require('./schemas/input/api-options.json'),
require('./schemas/input/get-settings.json'),
require('./schemas/input/get-account-info.json'),
@@ -88,35 +97,60 @@ function loadSchemas() {
require('./schemas/input/prepare-trustline.json'),
require('./schemas/input/prepare-order-cancellation.json'),
require('./schemas/input/prepare-settings.json'),
require('./schemas/input/prepare-suspended-payment-creation.json'),
require('./schemas/input/prepare-suspended-payment-cancellation.json'),
require('./schemas/input/prepare-suspended-payment-execution.json'),
require('./schemas/input/compute-ledger-hash'),
require('./schemas/input/prepare-escrow-creation.json'),
require('./schemas/input/prepare-escrow-cancellation.json'),
require('./schemas/input/prepare-escrow-execution.json'),
require('./schemas/input/prepare-payment-channel-create.json'),
require('./schemas/input/prepare-payment-channel-fund.json'),
require('./schemas/input/prepare-payment-channel-claim.json'),
require('./schemas/input/compute-ledger-hash.json'),
require('./schemas/input/sign.json'),
require('./schemas/input/submit.json'),
require('./schemas/input/generate-address.json'),
require('./schemas/input/sign-payment-channel-claim.json'),
require('./schemas/input/verify-payment-channel-claim.json'),
require('./schemas/input/combine.json')
];
const titles = _.map(schemas, schema => schema.title);
const duplicates = _.keys(_.pick(_.countBy(titles), count => count > 1));
assert(duplicates.length === 0, 'Duplicate schemas for: ' + duplicates);
const ajv = new Ajv();
_.forEach(schemas, schema => ajv.addSchema(schema, schema.title));
ajv.addFormat('address', isValidAddress);
ajv.addFormat('secret', isValidSecret);
return ajv;
]
const titles = _.map(schemas, schema => schema.title)
const duplicates = _.keys(_.pick(_.countBy(titles), count => count > 1))
assert(duplicates.length === 0, 'Duplicate schemas for: ' + duplicates)
const v = new Validator()
// Register custom format validators that ignore undefined instances
// since jsonschema will still call the format validator on a missing
// (optional) property
v.customFormats.address = function(instance) {
if (instance === undefined) {
return true
}
return isValidAddress(instance)
}
v.customFormats.secret = function(instance) {
if (instance === undefined) {
return true
}
return isValidSecret(instance)
}
// Register under the root URI '/'
_.forEach(schemas, schema => v.addSchema(schema, '/' + schema.title))
return v
}
const ajv = loadSchemas();
const v = loadSchemas()
function schemaValidate(schemaName: string, object: any): void {
const isValid = ajv.validate(schemaName, object);
if (!isValid) {
throw new ValidationError(ajv.errorsText());
// Lookup under the root URI '/'
const schema = v.getSchema('/' + schemaName)
if (schema === undefined) {
throw new ValidationError('no schema for ' + schemaName)
}
const result = v.validate(object, schema)
if (!result.valid) {
throw new ValidationError(result.errors.join())
}
}
module.exports = {
schemaValidate,
isValidSecret
};
}

View File

@@ -0,0 +1,14 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "getPaymentChannelParameters",
"description": "Parameters for getPaymentChannel",
"type": "object",
"properties": {
"id": {
"$ref": "hash256",
"description": "256-bit hexadecimal channel identifier."
}
},
"additionalProperties": false,
"required": ["id"]
}

View File

@@ -1,18 +1,18 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "prepareSuspendedPaymentCreationParameters",
"title": "prepareEscrowCancellationParameters",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address of the account that is creating the transaction."
},
"suspendedPaymentCreation": {
"$ref": "suspendedPaymentCreation",
"description": "The specification of the suspended payment creation to prepare."
"escrowCancellation": {
"$ref": "escrowCancellation",
"description": "The specification of the escrow cancellation to prepare."
},
"instructions": {"$ref": "instructions"}
},
"additionalProperties": false,
"required": ["address", "suspendedPaymentCreation"]
"required": ["address", "escrowCancellation"]
}

View File

@@ -1,18 +1,18 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "prepareSuspendedPaymentExecutionParameters",
"title": "prepareEscrowCreationParameters",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address of the account that is creating the transaction."
},
"suspendedPaymentExecution": {
"$ref": "suspendedPaymentExecution",
"description": "The specification of the suspended payment execution to prepare."
"escrowCreation": {
"$ref": "escrowCreation",
"description": "The specification of the escrow creation to prepare."
},
"instructions": {"$ref": "instructions"}
},
"additionalProperties": false,
"required": ["address", "suspendedPaymentExecution"]
"required": ["address", "escrowCreation"]
}

View File

@@ -1,18 +1,18 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "prepareSuspendedPaymentCancellationParameters",
"title": "prepareEscrowExecutionParameters",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address of the account that is creating the transaction."
},
"suspendedPaymentCancellation": {
"$ref": "suspendedPaymentCancellation",
"description": "The specification of the suspended payment cancellation to prepare."
"escrowExecution": {
"$ref": "escrowExecution",
"description": "The specification of the escrow execution to prepare."
},
"instructions": {"$ref": "instructions"}
},
"additionalProperties": false,
"required": ["address", "suspendedPaymentCancellation"]
"required": ["address", "escrowExecution"]
}

View File

@@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "preparePaymentChannelClaimParameters",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address of the account that is creating the transaction."
},
"paymentChannelClaim": {
"$ref": "paymentChannelClaim",
"description": "Details of the channel and claim."
},
"instructions": {"$ref": "instructions"}
},
"additionalProperties": false,
"required": ["address", "paymentChannelClaim"]
}

View File

@@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "preparePaymentChannelCreateParameters",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address of the account that is creating the transaction."
},
"paymentChannelCreate": {
"$ref": "paymentChannelCreate",
"description": "The specification of the payment channel to create."
},
"instructions": {"$ref": "instructions"}
},
"additionalProperties": false,
"required": ["address", "paymentChannelCreate"]
}

View File

@@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "preparePaymentChannelFundParameters",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address of the account that is creating the transaction."
},
"paymentChannelFund": {
"$ref": "paymentChannelFund",
"description": "The channel to fund, and the details of how to fund it."
},
"instructions": {"$ref": "instructions"}
},
"additionalProperties": false,
"required": ["address", "paymentChannelFund"]
}

View File

@@ -0,0 +1,21 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "signPaymentChannelClaimParameters",
"type": "object",
"properties": {
"channel": {
"$ref": "hash256",
"description": "256-bit hexadecimal channel identifier."
},
"amount": {
"$ref": "value",
"description": "Amount of XRP authorized by the claim."
},
"privateKey": {
"$ref": "publicKey",
"description": "The private key to sign the payment channel claim."
}
},
"additionalProperties": false,
"required": ["channel", "amount", "privateKey"]
}

View File

@@ -0,0 +1,25 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "verifyPaymentChannelClaimParameters",
"type": "object",
"properties": {
"channel": {
"$ref": "hash256",
"description": "256-bit hexadecimal channel identifier."
},
"amount": {
"$ref": "value",
"description": "Amount of XRP authorized by the claim."
},
"signature": {
"$ref": "signature",
"description": "Signature of this claim."
},
"publicKey": {
"$ref": "publicKey",
"description": "Public key of the channel's sender"
}
},
"additionalProperties": false,
"required": ["channel", "amount", "signature", "publicKey"]
}

View File

@@ -4,6 +4,6 @@
"description": "A Ripple account address",
"type": "string",
"format": "address",
"link": "ripple-address",
"link": "address",
"pattern": "^r[1-9A-HJ-NP-Za-km-z]{25,34}$"
}

View File

@@ -0,0 +1,7 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "publicKey",
"description": "The hexadecimal representation of a secp256k1 or Ed25519 public key.",
"type": "string",
"pattern": "^[A-F0-9]+$"
}

View File

@@ -55,7 +55,7 @@
"description": " The domain that owns this account, as a hexadecimal string representing the ASCII for the domain in lowercase."
},
"transferRate": {
"description": " The fee to charge when users transfer this accounts issuances, represented as billionths of a unit. Use `null` to set no fee.",
"description": " The fee to charge when users transfer this accounts issuances, as the decimal amount that must be sent to deliver 1 unit. Has precision up to 9 digits beyond the decimal point. Use `null` to set no fee.",
"oneOf": [
{"type": "null"},
{"type": "number", "minimum": 1, "maximum": 4.294967295}

View File

@@ -0,0 +1,7 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "signature",
"description": "The hexadecimal representation of a signature.",
"type": "string",
"pattern": "^[A-F0-9]+$"
}

View File

@@ -5,6 +5,7 @@
"description": "The type of the transaction.",
"type": "string",
"enum": ["payment", "order", "orderCancellation", "trustline", "settings",
"suspendedPaymentCreation", "suspendedPaymentCancellation",
"suspendedPaymentExecution"]
"escrowCreation", "escrowCancellation",
"escrowExecution", "paymentChannelCreate",
"paymentChannelFund", "paymentChannelClaim"]
}

View File

@@ -0,0 +1,67 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "getPaymentChannel",
"type": "object",
"properties": {
"account": {
"$ref": "address",
"description": "Address that created the payment channel."
},
"destination": {
"$ref": "address",
"description": "Address to receive XRP claims against this channel."
},
"amount": {
"$ref": "value",
"description": "The total amount of XRP funded in this channel."
},
"balance": {
"$ref": "value",
"description": "The total amount of XRP delivered by this channel."
},
"settleDelay": {
"type": "number",
"description": "Amount of seconds the source address must wait before closing the channel if it has unclaimed XRP."
},
"expiration": {
"type": "string",
"format": "date-time",
"description": "Time when this channel expires."
},
"publicKey": {
"$ref": "publicKey",
"description": "Public key of the key pair the source will use to sign claims against this channel."
},
"cancelAfter": {
"type": "string",
"format": "date-time",
"description": "Time when this channel expires as specified at creation."
},
"sourceTag": {
"$ref": "tag",
"description": "Source tag."
},
"destinationTag": {
"$ref": "tag",
"description": "Destination tag."
},
"previousAffectingTransactionID": {
"$ref": "hash256",
"description": "Hash value representing the most recent transaction that affected this payment channel."
},
"previousAffectingTransactionLedgerVersion": {
"$ref": "ledgerVersion",
"description": "The ledger version that the transaction identified by the `previousAffectingTransactionID` was validated in."
}
},
"required": [
"account",
"destination",
"amount",
"balance",
"settleDelay",
"previousAffectingTransactionID",
"previousAffectingTransactionLedgerVersion"
],
"additionalProperties": false
}

View File

@@ -59,20 +59,38 @@
},
{
"properties": {
"type": {"enum": ["suspendedPaymentCreation"]},
"specification": {"$ref": "suspendedPaymentCreation"}
"type": {"enum": ["escrowCreation"]},
"specification": {"$ref": "escrowCreation"}
}
},
{
"properties": {
"type": {"enum": ["suspendedPaymentCancellation"]},
"specification": {"$ref": "suspendedPaymentCancellation"}
"type": {"enum": ["escrowCancellation"]},
"specification": {"$ref": "escrowCancellation"}
}
},
{
"properties": {
"type": {"enum": ["suspendedPaymentExecution"]},
"specification": {"$ref": "suspendedPaymentExecution"}
"type": {"enum": ["escrowExecution"]},
"specification": {"$ref": "escrowExecution"}
}
},
{
"properties": {
"type": {"enum": ["paymentChannelCreate"]},
"specification": {"$ref": "paymentChannelCreate"}
}
},
{
"properties": {
"type": {"enum": ["paymentChannelFund"]},
"specification": {"$ref": "paymentChannelFund"}
}
},
{
"properties": {
"type": {"enum": ["paymentChannelClaim"]},
"specification": {"$ref": "paymentChannelClaim"}
}
}
]

View File

@@ -0,0 +1,7 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "signPaymentChannelClaim",
"type": "string",
"$ref": "signature",
"additionalProperties": false
}

View File

@@ -0,0 +1,6 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "verifyPaymentChannelClaim",
"type": "boolean",
"additionalProperties": false
}

View File

@@ -0,0 +1,19 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "escrowCancellation",
"link": "escrow-cancellation",
"type": "object",
"properties": {
"memos": {"$ref": "memos"},
"owner": {
"$ref": "address",
"description": "The address of the owner of the escrow to cancel."
},
"escrowSequence": {
"$ref": "sequence",
"description": "The [account sequence number](#account-sequence-number) of the [Escrow Creation](#escrow-creation) transaction for the escrow to cancel."
}
},
"required": ["owner", "escrowSequence"],
"additionalProperties": false
}

View File

@@ -0,0 +1,42 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "escrowCreation",
"link": "escrow-creation",
"type": "object",
"properties": {
"amount": {
"$ref": "value",
"description": "Amount of XRP for sender to escrow."
},
"destination": {
"$ref": "address",
"description": "Address to receive escrowed XRP."
},
"memos": {"$ref": "memos"},
"condition": {
"type": "string",
"description": "A hex value representing a [PREIMAGE-SHA-256 crypto-condition](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1). If present, `fulfillment` is required upon execution.",
"pattern": "^[A-F0-9]{0,256}$"
},
"allowCancelAfter": {
"type": "string",
"format": "date-time",
"description": "If present, the escrow may be cancelled after this time."
},
"allowExecuteAfter": {
"type": "string",
"format": "date-time",
"description": "If present, the escrow can not be executed before this time."
},
"sourceTag": {
"$ref": "tag",
"description": "Source tag."
},
"destinationTag": {
"$ref": "tag",
"description": "Destination tag."
}
},
"required": ["amount", "destination"],
"additionalProperties": false
}

View File

@@ -0,0 +1,29 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "escrowExecution",
"link": "escrow-execution",
"type": "object",
"properties": {
"memos": {"$ref": "memos"},
"owner": {
"$ref": "address",
"description": "The address of the owner of the escrow to execute."
},
"escrowSequence": {
"$ref": "sequence",
"description": "The [account sequence number](#account-sequence-number) of the [Escrow Creation](#escrow-creation) transaction for the escrow to execute."
},
"condition": {
"type": "string",
"description": "A hex value representing a [PREIMAGE-SHA-256 crypto-condition](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1). This must match the original `condition` from the escrow creation transaction.",
"pattern": "^[A-F0-9]{0,256}$"
},
"fulfillment": {
"type": "string",
"description": "A hex value representing the [PREIMAGE-SHA-256 crypto-condition](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1) fulfillment for `condition`.",
"pattern": "^[A-F0-9]+$"
}
},
"required": ["owner", "escrowSequence"],
"additionalProperties": false
}

View File

@@ -34,6 +34,10 @@
"format": "date-time",
"description": "Time after which the offer is no longer active, as an [ISO 8601 date-time](https://en.wikipedia.org/wiki/ISO_8601)."
},
"orderToReplace": {
"$ref": "sequence",
"description": "The [account sequence number](#account-sequence-number) of an order to cancel before the new order is created, effectively replacing the old order."
},
"memos": {"$ref": "memos"}
},
"required": ["direction", "quantity", "totalPrice"],

View File

@@ -0,0 +1,38 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "paymentChannelClaim",
"link": "payment-channel-claim",
"type": "object",
"properties": {
"channel": {
"$ref": "hash256",
"description": "256-bit hexadecimal channel identifier."
},
"amount": {
"$ref": "value",
"description": "XRP balance of this channel after claim is processed."
},
"balance": {
"$ref": "value",
"description": "Amount of XRP authorized by signature."
},
"signature": {
"$ref": "signature",
"description": "Signature of this claim."
},
"publicKey": {
"$ref": "publicKey",
"description": "Public key of the channel's sender"
},
"renew": {
"type": "boolean",
"description": "Clear the channel's expiration time."
},
"close": {
"type": "boolean",
"description": "Request to close the channel."
}
},
"required": ["channel"],
"additionalProperties": false
}

View File

@@ -0,0 +1,39 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "paymentChannelCreate",
"link": "payment-channel-create",
"type": "object",
"properties": {
"amount": {
"$ref": "value",
"description": "Amount of XRP for sender to set aside in this channel."
},
"destination": {
"$ref": "address",
"description": "Address to receive XRP claims against this channel."
},
"settleDelay": {
"type": "number",
"description": "Amount of seconds the source address must wait before closing the channel if it has unclaimed XRP."
},
"publicKey": {
"$ref": "publicKey",
"description": "Public key of the key pair the source will use to sign claims against this channel."
},
"cancelAfter": {
"type": "string",
"format": "date-time",
"description": "Time when this channel expires."
},
"sourceTag": {
"$ref": "tag",
"description": "Source tag."
},
"destinationTag": {
"$ref": "tag",
"description": "Destination tag."
}
},
"required": ["amount", "destination", "settleDelay", "publicKey"],
"additionalProperties": false
}

View File

@@ -0,0 +1,23 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "paymentChannelFund",
"link": "payment-channel-fund",
"type": "object",
"properties": {
"amount": {
"$ref": "value",
"description": "Amount of XRP to fund the channel with."
},
"channel": {
"$ref": "hash256",
"description": "256-bit hexadecimal channel identifier."
},
"expiration": {
"type": "string",
"format": "date-time",
"description": "New expiration for this channel."
}
},
"required": ["amount", "channel"],
"additionalProperties": false
}

View File

@@ -1,19 +0,0 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "suspendedPaymentCancellation",
"link": "suspended-payment-cancellation",
"type": "object",
"properties": {
"memos": {"$ref": "memos"},
"owner": {
"$ref": "address",
"description": "The address of the owner of the suspended payment to cancel."
},
"suspensionSequence": {
"$ref": "sequence",
"description": "The [account sequence number](#account-sequence-number) of the [Suspended Payment Creation](#suspended-payment-creation) transaction for the suspended payment to cancel."
}
},
"required": ["owner", "suspensionSequence"],
"additionalProperties": false
}

View File

@@ -1,33 +0,0 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "suspendedPaymentCreation",
"link": "suspended-payment-creation",
"type": "object",
"properties": {
"source": {
"$ref": "maxAdjustment",
"description": "Fields pertaining to the source of the payment."
},
"destination": {
"$ref": "destinationExactAdjustment",
"description": "Fields pertaining to the destination of the payment."
},
"memos": {"$ref": "memos"},
"digest": {
"$ref": "hash256",
"description": "If present, proof is required upon execution."
},
"allowCancelAfter": {
"type": "string",
"format": "date-time",
"description": "If present, the suspended payment may be cancelled after this time."
},
"allowExecuteAfter": {
"type": "string",
"format": "date-time",
"description": "If present, the suspended payment can not be executed before this time."
}
},
"required": ["source", "destination"],
"additionalProperties": false
}

View File

@@ -1,34 +0,0 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "suspendedPaymentExecution",
"link": "suspended-payment-execution",
"type": "object",
"properties": {
"memos": {"$ref": "memos"},
"owner": {
"$ref": "address",
"description": "The address of the owner of the suspended payment to execute."
},
"suspensionSequence": {
"$ref": "sequence",
"description": "The [account sequence number](#account-sequence-number) of the [Suspended Payment Creation](#suspended-payment-creation) transaction for the suspended payment to execute."
},
"method": {
"type": "integer",
"minimum": 0,
"maximum": 255,
"description": "The method for verifying the proof; only method `1` is supported."
},
"digest": {
"$ref": "hash256",
"description": "The original `digest` from the suspended payment creation transaction. This is sha256 hash of `proof` string. It is replicated here so that the relatively expensive hashing operation can be delegated to a server without ledger history and the server with ledger history only has to do a quick comparison of the old digest with the new digest."
},
"proof": {
"type": "string",
"description": "A value that produces the digest when hashed. It must be 32 charaters long and contain only 8-bit characters.",
"pattern": "^[\\x00-\\xFF]{32}$"
}
},
"required": ["owner", "suspensionSequence"],
"additionalProperties": false
}

View File

@@ -1,7 +1,7 @@
'use strict';
const _ = require('lodash');
const {convertKeysFromSnakeCaseToCamelCase} = require('./utils');
import type {Connection} from './connection';
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const {convertKeysFromSnakeCaseToCamelCase} = require('./utils')
import type {Connection} from './connection'
export type GetServerInfoResponse = {
buildVersion: string,
@@ -34,44 +34,46 @@ export type GetServerInfoResponse = {
function renameKeys(object, mapping) {
_.forEach(mapping, (to, from) => {
object[to] = object[from];
delete object[from];
});
object[to] = object[from]
delete object[from]
})
}
function getServerInfo(connection: Connection): Promise<GetServerInfoResponse> {
return connection.request({command: 'server_info'}).then(response => {
const info = convertKeysFromSnakeCaseToCamelCase(response.info);
renameKeys(info, {hostid: 'hostID'});
renameKeys(info.validatedLedger, {
baseFeeXrp: 'baseFeeXRP',
reserveBaseXrp: 'reserveBaseXRP',
reserveIncXrp: 'reserveIncrementXRP',
seq: 'ledgerVersion'
});
info.validatedLedger.baseFeeXRP =
info.validatedLedger.baseFeeXRP.toString();
info.validatedLedger.reserveBaseXRP =
info.validatedLedger.reserveBaseXRP.toString();
info.validatedLedger.reserveIncrementXRP =
info.validatedLedger.reserveIncrementXRP.toString();
return info;
});
const info = convertKeysFromSnakeCaseToCamelCase(response.info)
renameKeys(info, {hostid: 'hostID'})
if (info.validatedLedger) {
renameKeys(info.validatedLedger, {
baseFeeXrp: 'baseFeeXRP',
reserveBaseXrp: 'reserveBaseXRP',
reserveIncXrp: 'reserveIncrementXRP',
seq: 'ledgerVersion'
})
info.validatedLedger.baseFeeXRP =
info.validatedLedger.baseFeeXRP.toString()
info.validatedLedger.reserveBaseXRP =
info.validatedLedger.reserveBaseXRP.toString()
info.validatedLedger.reserveIncrementXRP =
info.validatedLedger.reserveIncrementXRP.toString()
}
return info
})
}
function computeFeeFromServerInfo(cushion: number,
serverInfo: GetServerInfoResponse
): number {
return (Number(serverInfo.validatedLedger.baseFeeXRP)
* Number(serverInfo.loadFactor) * cushion).toString();
* Number(serverInfo.loadFactor) * cushion).toString()
}
function getFee(connection: Connection, cushion: number) {
return getServerInfo(connection).then(
_.partial(computeFeeFromServerInfo, cushion));
_.partial(computeFeeFromServerInfo, cushion))
}
module.exports = {
getServerInfo,
getFee
};
}

View File

@@ -1,4 +1,4 @@
'use strict';
'use strict' // eslint-disable-line strict
const txFlags = {
// Universal flags can apply to any transaction type
@@ -35,8 +35,13 @@ const txFlags = {
NoRippleDirect: 0x00010000,
PartialPayment: 0x00020000,
LimitQuality: 0x00040000
},
PaymentChannelClaim: {
Renew: 0x00010000,
Close: 0x00020000
}
};
}
// The following are integer (as opposed to bit) flags
// that can be set for particular transactions in the
@@ -52,9 +57,9 @@ const txFlagIndices = {
asfGlobalFreeze: 7,
asfDefaultRipple: 8
}
};
}
module.exports = {
txFlags,
txFlagIndices
};
}

View File

@@ -1,5 +1,5 @@
/* @flow */
'use strict';
'use strict' // eslint-disable-line strict
export type RippledAmountIOU = {
currency: string,

View File

@@ -1,59 +1,59 @@
/* @flow */
'use strict';
const _ = require('lodash');
const BigNumber = require('bignumber.js');
const {deriveKeypair} = require('ripple-keypairs');
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const BigNumber = require('bignumber.js')
const {deriveKeypair} = require('ripple-keypairs')
import type {Amount, RippledAmount} from './types.js';
import type {Amount, RippledAmount} from './types.js'
function isValidSecret(secret: string): boolean {
try {
deriveKeypair(secret);
return true;
deriveKeypair(secret)
return true
} catch (err) {
return false;
return false
}
}
function dropsToXrp(drops: string): string {
return (new BigNumber(drops)).dividedBy(1000000.0).toString();
return (new BigNumber(drops)).dividedBy(1000000.0).toString()
}
function xrpToDrops(xrp: string): string {
return (new BigNumber(xrp)).times(1000000.0).floor().toString();
return (new BigNumber(xrp)).times(1000000.0).floor().toString()
}
function toRippledAmount(amount: Amount): RippledAmount {
if (amount.currency === 'XRP') {
return xrpToDrops(amount.value);
return xrpToDrops(amount.value)
}
return {
currency: amount.currency,
issuer: amount.counterparty ? amount.counterparty :
(amount.issuer ? amount.issuer : undefined),
value: amount.value
};
}
}
function convertKeysFromSnakeCaseToCamelCase(obj: any): any {
if (typeof obj === 'object') {
let newKey;
let newKey
return _.reduce(obj, (result, value, key) => {
newKey = key;
newKey = key
// taking this out of function leads to error in PhantomJS
const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g;
const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g
if (FINDSNAKE.test(key)) {
newKey = key.replace(FINDSNAKE, r => r[0] + r[2].toUpperCase());
newKey = key.replace(FINDSNAKE, r => r[0] + r[2].toUpperCase())
}
result[newKey] = convertKeysFromSnakeCaseToCamelCase(value);
return result;
}, {});
result[newKey] = convertKeysFromSnakeCaseToCamelCase(value)
return result
}, {})
}
return obj;
return obj
}
function removeUndefined(obj: Object): Object {
return _.omit(obj, _.isUndefined);
return _.omitBy(obj, _.isUndefined)
}
/**
@@ -62,7 +62,7 @@ function removeUndefined(obj: Object): Object {
*
*/
function rippleToUnixTimestamp(rpepoch: number): number {
return (rpepoch + 0x386D4380) * 1000;
return (rpepoch + 0x386D4380) * 1000
}
/**
@@ -70,15 +70,15 @@ function rippleToUnixTimestamp(rpepoch: number): number {
* @return {Number} seconds since ripple epoch ( 1/1/2000 GMT)
*/
function unixToRippleTimestamp(timestamp: number): number {
return Math.round(timestamp / 1000) - 0x386D4380;
return Math.round(timestamp / 1000) - 0x386D4380
}
function rippleTimeToISO8601(rippleTime: number): string {
return new Date(rippleToUnixTimestamp(rippleTime)).toISOString();
return new Date(rippleToUnixTimestamp(rippleTime)).toISOString()
}
function iso8601ToRippleTime(iso8601: string): number {
return unixToRippleTimestamp(Date.parse(iso8601));
return unixToRippleTimestamp(Date.parse(iso8601))
}
module.exports = {
@@ -90,4 +90,4 @@ module.exports = {
rippleTimeToISO8601,
iso8601ToRippleTime,
isValidSecret
};
}

View File

@@ -1,25 +1,25 @@
/* @flow */
'use strict';
const _ = require('lodash');
const ValidationError = require('./errors').ValidationError;
const schemaValidate = require('./schema-validator').schemaValidate;
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const ValidationError = require('./errors').ValidationError
const schemaValidate = require('./schema-validator').schemaValidate
function error(text) {
return new ValidationError(text);
return new ValidationError(text)
}
function validateLedgerRange(options) {
if (!_.isUndefined(options) && !_.isUndefined(options.minLedgerVersion)
&& !_.isUndefined(options.maxLedgerVersion)) {
if (Number(options.minLedgerVersion) > Number(options.maxLedgerVersion)) {
throw error('minLedgerVersion must not be greater than maxLedgerVersion');
throw error('minLedgerVersion must not be greater than maxLedgerVersion')
}
}
}
function validateOptions(schema, instance) {
schemaValidate(schema, instance);
validateLedgerRange(instance.options);
schemaValidate(schema, instance)
validateLedgerRange(instance.options)
}
module.exports = {
@@ -33,6 +33,7 @@ module.exports = {
getOrders: _.partial(validateOptions, 'getOrdersParameters'),
getOrderbook: _.partial(validateOptions, 'getOrderbookParameters'),
getTransaction: _.partial(validateOptions, 'getTransactionParameters'),
getPaymentChannel: _.partial(validateOptions, 'getPaymentChannelParameters'),
getLedger: _.partial(validateOptions, 'getLedgerParameters'),
preparePayment: _.partial(schemaValidate, 'preparePaymentParameters'),
prepareOrder: _.partial(schemaValidate, 'prepareOrderParameters'),
@@ -40,17 +41,27 @@ module.exports = {
_.partial(schemaValidate, 'prepareOrderCancellationParameters'),
prepareTrustline: _.partial(schemaValidate, 'prepareTrustlineParameters'),
prepareSettings: _.partial(schemaValidate, 'prepareSettingsParameters'),
prepareSuspendedPaymentCreation: _.partial(schemaValidate,
'prepareSuspendedPaymentCreationParameters'),
prepareSuspendedPaymentCancellation: _.partial(schemaValidate,
'prepareSuspendedPaymentCancellationParameters'),
prepareSuspendedPaymentExecution: _.partial(schemaValidate,
'prepareSuspendedPaymentExecutionParameters'),
prepareEscrowCreation: _.partial(schemaValidate,
'prepareEscrowCreationParameters'),
prepareEscrowCancellation: _.partial(schemaValidate,
'prepareEscrowCancellationParameters'),
prepareEscrowExecution: _.partial(schemaValidate,
'prepareEscrowExecutionParameters'),
preparePaymentChannelCreate: _.partial(schemaValidate,
'preparePaymentChannelCreateParameters'),
preparePaymentChannelFund: _.partial(schemaValidate,
'preparePaymentChannelFundParameters'),
preparePaymentChannelClaim: _.partial(schemaValidate,
'preparePaymentChannelClaimParameters'),
sign: _.partial(schemaValidate, 'signParameters'),
combine: _.partial(schemaValidate, 'combineParameters'),
submit: _.partial(schemaValidate, 'submitParameters'),
computeLedgerHash: _.partial(schemaValidate, 'computeLedgerHashParameters'),
generateAddress: _.partial(schemaValidate, 'generateAddressParameters'),
signPaymentChannelClaim: _.partial(schemaValidate,
'signPaymentChannelClaimParameters'),
verifyPaymentChannelClaim: _.partial(schemaValidate,
'verifyPaymentChannelClaimParameters'),
apiOptions: _.partial(schemaValidate, 'api-options'),
instructions: _.partial(schemaValidate, 'instructions')
};
}

View File

@@ -1,6 +1,6 @@
'use strict';
'use strict' // eslint-disable-line strict
const {EventEmitter} = require('events');
const {EventEmitter} = require('events')
function unsused() {}
@@ -10,50 +10,50 @@ function unsused() {}
*/
class WSWrapper extends EventEmitter {
constructor(url, protocols = null, websocketOptions = {}) {
super();
unsused(protocols);
unsused(websocketOptions);
this.setMaxListeners(Infinity);
super()
unsused(protocols)
unsused(websocketOptions)
this.setMaxListeners(Infinity)
this._ws = new WebSocket(url);
this._ws = new WebSocket(url)
this._ws.onclose = () => {
this.emit('close');
};
this.emit('close')
}
this._ws.onopen = () => {
this.emit('open');
};
this.emit('open')
}
this._ws.onerror = error => {
this.emit('error', error);
};
this.emit('error', error)
}
this._ws.onmessage = message => {
this.emit('message', message.data);
};
this.emit('message', message.data)
}
}
close() {
if (this.readyState === 1) {
this._ws.close();
this._ws.close()
}
}
send(message) {
this._ws.send(message);
this._ws.send(message)
}
get readyState() {
return this._ws.readyState;
return this._ws.readyState
}
}
WSWrapper.CONNECTING = 0;
WSWrapper.OPEN = 1;
WSWrapper.CLOSING = 2;
WSWrapper.CLOSED = 3;
WSWrapper.CONNECTING = 0
WSWrapper.OPEN = 1
WSWrapper.CLOSING = 2
WSWrapper.CLOSED = 3
module.exports = WSWrapper;
module.exports = WSWrapper

View File

@@ -1,86 +1,86 @@
/* eslint-disable new-cap */
'use strict';
'use strict' // eslint-disable-line strict
const assert = require('assert');
const _ = require('lodash');
const jayson = require('jayson');
const assert = require('assert')
const _ = require('lodash')
const jayson = require('jayson')
const RippleAPI = require('./api').RippleAPI;
const RippleAPI = require('./api').RippleAPI
/* istanbul ignore next */
function createHTTPServer(options, httpPort) {
const rippleAPI = new RippleAPI(options);
const rippleAPI = new RippleAPI(options)
const methodNames = _.filter(_.keys(RippleAPI.prototype), k => {
return typeof RippleAPI.prototype[k] === 'function'
&& k !== 'connect'
&& k !== 'disconnect'
&& k !== 'constructor'
&& k !== 'RippleAPI';
});
&& k !== 'RippleAPI'
})
function applyPromiseWithCallback(fnName, callback, args_) {
try {
let args = args_;
let args = args_
if (!_.isArray(args_)) {
const fnParameters = jayson.Utils.getParameterNames(rippleAPI[fnName]);
args = fnParameters.map(name => args_[name]);
const defaultArgs = _.omit(args_, fnParameters);
const fnParameters = jayson.Utils.getParameterNames(rippleAPI[fnName])
args = fnParameters.map(name => args_[name])
const defaultArgs = _.omit(args_, fnParameters)
assert(_.size(defaultArgs) <= 1,
'Function must have no more than one default argument');
'Function must have no more than one default argument')
if (_.size(defaultArgs) > 0) {
args.push(defaultArgs[_.keys(defaultArgs)[0]]);
args.push(defaultArgs[_.keys(defaultArgs)[0]])
}
}
Promise.resolve(rippleAPI[fnName].apply(rippleAPI, args))
Promise.resolve(rippleAPI[fnName](...args))
.then(res => callback(null, res))
.catch(err => {
callback({code: 99, message: err.message, data: {name: err.name}});
});
callback({code: 99, message: err.message, data: {name: err.name}})
})
} catch (err) {
callback({code: 99, message: err.message, data: {name: err.name}});
callback({code: 99, message: err.message, data: {name: err.name}})
}
}
const methods = {};
const methods = {}
_.forEach(methodNames, fn => {
methods[fn] = jayson.Method((args, cb) => {
applyPromiseWithCallback(fn, cb, args);
}, {collect: true});
});
applyPromiseWithCallback(fn, cb, args)
}, {collect: true})
})
const server = jayson.server(methods);
let httpServer = null;
const server = jayson.server(methods)
let httpServer = null
return {
server: server,
start: function() {
if (httpServer !== null) {
return Promise.reject('Already started');
return Promise.reject('Already started')
}
return new Promise((resolve) => {
return new Promise(resolve => {
rippleAPI.connect().then(() => {
httpServer = server.http();
httpServer.listen(httpPort, resolve);
});
});
httpServer = server.http()
httpServer.listen(httpPort, resolve)
})
})
},
stop: function() {
if (httpServer === null) {
return Promise.reject('Not started');
return Promise.reject('Not started')
}
return new Promise((resolve) => {
rippleAPI.disconnect();
return new Promise(resolve => {
rippleAPI.disconnect()
httpServer.close(() => {
httpServer = null;
resolve();
});
});
httpServer = null
resolve()
})
})
}
};
}
}
module.exports = {
createHTTPServer
};
}

View File

@@ -1,9 +1,7 @@
'use strict';
'use strict' // eslint-disable-line strict
module.exports = {
RippleAPI: require('./api').RippleAPI,
// Broadcast api is experimental
RippleAPIBroadcast: require('./broadcast').RippleAPIBroadcast,
// HTTP server is experimental
createHTTPServer: require('./http').createHTTPServer
};
RippleAPIBroadcast: require('./broadcast').RippleAPIBroadcast
}

View File

@@ -1,8 +1,8 @@
/* @flow */
'use strict';
const utils = require('./utils');
const {validate, removeUndefined} = utils.common;
'use strict' // eslint-disable-line strict
const utils = require('./utils')
const {validate, removeUndefined} = utils.common
type AccountData = {
Sequence: number,
@@ -39,7 +39,7 @@ type AccountInfoResponse = {
}
function formatAccountInfo(response: AccountDataResponse) {
const data = response.account_data;
const data = response.account_data
return removeUndefined({
sequence: data.Sequence,
xrpBalance: utils.common.dropsToXrp(data.Balance),
@@ -47,20 +47,20 @@ function formatAccountInfo(response: AccountDataResponse) {
previousInitiatedTransactionID: data.AccountTxnID,
previousAffectingTransactionID: data.PreviousTxnID,
previousAffectingTransactionLedgerVersion: data.PreviousTxnLgrSeq
});
})
}
function getAccountInfo(address: string, options: AccountInfoOptions = {}
): Promise<AccountInfoResponse> {
validate.getAccountInfo({address, options});
validate.getAccountInfo({address, options})
const request = {
command: 'account_info',
account: address,
ledger_index: options.ledgerVersion || 'validated'
};
}
return this.connection.request(request).then(formatAccountInfo);
return this.connection.request(request).then(formatAccountInfo)
}
module.exports = getAccountInfo;
module.exports = getAccountInfo

View File

@@ -1,10 +1,10 @@
/* @flow */
'use strict';
'use strict' // eslint-disable-line strict
const _ = require('lodash');
const utils = require('./utils');
const {validate} = utils.common;
import type {Amount} from '../common/types.js';
const _ = require('lodash')
const utils = require('./utils')
const {validate} = utils.common
import type {Amount} from '../common/types.js'
type BalanceSheetOptions = {
excludeAddresses?: Array<string>,
@@ -21,35 +21,35 @@ type GetBalanceSheet = {
}
function formatBalanceSheet(balanceSheet): GetBalanceSheet {
const result = {};
const result = {}
if (!_.isUndefined(balanceSheet.balances)) {
result.balances = [];
result.balances = []
_.forEach(balanceSheet.balances, (balances, counterparty) => {
_.forEach(balances, (balance) => {
result.balances.push(Object.assign({counterparty}, balance));
});
});
_.forEach(balances, balance => {
result.balances.push(Object.assign({counterparty}, balance))
})
})
}
if (!_.isUndefined(balanceSheet.assets)) {
result.assets = [];
result.assets = []
_.forEach(balanceSheet.assets, (assets, counterparty) => {
_.forEach(assets, (balance) => {
result.assets.push(Object.assign({counterparty}, balance));
});
});
_.forEach(assets, balance => {
result.assets.push(Object.assign({counterparty}, balance))
})
})
}
if (!_.isUndefined(balanceSheet.obligations)) {
result.obligations = _.map(balanceSheet.obligations, (value, currency) =>
({currency, value}));
({currency, value}))
}
return result;
return result
}
function getBalanceSheet(address: string, options: BalanceSheetOptions = {}
): Promise<GetBalanceSheet> {
validate.getBalanceSheet({address, options});
validate.getBalanceSheet({address, options})
return utils.ensureLedgerVersion.call(this, options).then(_options => {
const request = {
@@ -58,10 +58,10 @@ function getBalanceSheet(address: string, options: BalanceSheetOptions = {}
strict: true,
hotwallet: _options.excludeAddresses,
ledger_index: _options.ledgerVersion
};
}
return this.connection.request(request).then(formatBalanceSheet);
});
return this.connection.request(request).then(formatBalanceSheet)
})
}
module.exports = getBalanceSheet;
module.exports = getBalanceSheet

View File

@@ -1,9 +1,9 @@
/* @flow */
'use strict';
const utils = require('./utils');
const {validate} = utils.common;
import type {Connection} from '../common/connection.js';
import type {TrustlinesOptions, Trustline} from './trustlines-types.js';
'use strict' // eslint-disable-line strict
const utils = require('./utils')
const {validate} = utils.common
import type {Connection} from '../common/connection.js'
import type {TrustlinesOptions, Trustline} from './trustlines-types.js'
type Balance = {
@@ -19,38 +19,38 @@ function getTrustlineBalanceAmount(trustline: Trustline) {
currency: trustline.specification.currency,
counterparty: trustline.specification.counterparty,
value: trustline.state.balance
};
}
}
function formatBalances(options, balances) {
const result = balances.trustlines.map(getTrustlineBalanceAmount);
const result = balances.trustlines.map(getTrustlineBalanceAmount)
if (!(options.counterparty ||
(options.currency && options.currency !== 'XRP')
)) {
const xrpBalance = {
currency: 'XRP',
value: balances.xrp
};
result.unshift(xrpBalance);
}
result.unshift(xrpBalance)
}
if (options.limit && result.length > options.limit) {
const toRemove = result.length - options.limit;
result.splice(-toRemove, toRemove);
const toRemove = result.length - options.limit
result.splice(-toRemove, toRemove)
}
return result;
return result
}
function getLedgerVersionHelper(connection: Connection, optionValue?: number
): Promise<number> {
if (optionValue !== undefined && optionValue !== null) {
return Promise.resolve(optionValue);
return Promise.resolve(optionValue)
}
return connection.getLedgerVersion();
return connection.getLedgerVersion()
}
function getBalances(address: string, options: TrustlinesOptions = {}
): Promise<GetBalances> {
validate.getTrustlines({address, options});
validate.getTrustlines({address, options})
return Promise.all([
getLedgerVersionHelper(this.connection, options.ledgerVersion).then(
@@ -58,7 +58,7 @@ function getBalances(address: string, options: TrustlinesOptions = {}
utils.getXRPBalance(this.connection, address, ledgerVersion)),
this.getTrustlines(address, options)
]).then(results =>
formatBalances(options, {xrp: results[0], trustlines: results[1]}));
formatBalances(options, {xrp: results[0], trustlines: results[1]}))
}
module.exports = getBalances;
module.exports = getBalances

View File

@@ -1,9 +1,9 @@
/* @flow */
'use strict';
const utils = require('./utils');
const {validate} = utils.common;
const parseLedger = require('./parse/ledger');
import type {GetLedger} from './types.js';
'use strict' // eslint-disable-line strict
const utils = require('./utils')
const {validate} = utils.common
const parseLedger = require('./parse/ledger')
import type {GetLedger} from './types.js'
type LedgerOptions = {
ledgerVersion?: number,
@@ -14,7 +14,7 @@ type LedgerOptions = {
function getLedger(options: LedgerOptions = {}): Promise<GetLedger> {
validate.getLedger({options});
validate.getLedger({options})
const request = {
command: 'ledger',
@@ -22,10 +22,10 @@ function getLedger(options: LedgerOptions = {}): Promise<GetLedger> {
expand: options.includeAllData,
transactions: options.includeTransactions,
accounts: options.includeState
};
}
return this.connection.request(request).then(response =>
parseLedger(response.ledger));
parseLedger(response.ledger))
}
module.exports = getLedger;
module.exports = getLedger

View File

@@ -1,12 +1,12 @@
/* @flow */
'use strict';
const _ = require('lodash');
const utils = require('./utils');
const {validate} = utils.common;
const parseOrderbookOrder = require('./parse/orderbook-order');
import type {Connection} from '../common/connection.js';
import type {OrdersOptions, OrderSpecification} from './types.js';
import type {Amount, Issue} from '../common/types.js';
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const utils = require('./utils')
const {validate} = utils.common
const parseOrderbookOrder = require('./parse/orderbook-order')
import type {Connection} from '../common/connection.js'
import type {OrdersOptions, OrderSpecification} from './types.js'
import type {Amount, Issue} from '../common/types.js'
type Orderbook = {
base: Issue,
@@ -46,31 +46,31 @@ function getBookOffers(connection: Connection, account: string,
ledger_index: ledgerVersion || 'validated',
limit: limit,
taker: account
})).then(data => data.offers);
})).then(data => data.offers)
}
function isSameIssue(a: Amount, b: Amount) {
return a.currency === b.currency && a.counterparty === b.counterparty;
return a.currency === b.currency && a.counterparty === b.counterparty
}
function directionFilter(direction: string, order: OrderbookItem) {
return order.specification.direction === direction;
return order.specification.direction === direction
}
function flipOrder(order: OrderbookItem) {
const specification = order.specification;
const specification = order.specification
const flippedSpecification = {
quantity: specification.totalPrice,
totalPrice: specification.quantity,
direction: specification.direction === 'buy' ? 'sell' : 'buy'
};
const newSpecification = _.merge({}, specification, flippedSpecification);
return _.merge({}, order, {specification: newSpecification});
}
const newSpecification = _.merge({}, specification, flippedSpecification)
return _.merge({}, order, {specification: newSpecification})
}
function alignOrder(base: Amount, order: OrderbookItem) {
const quantity = order.specification.quantity;
return isSameIssue(quantity, base) ? order : flipOrder(order);
const quantity = order.specification.quantity
return isSameIssue(quantity, base) ? order : flipOrder(order)
}
function formatBidsAndAsks(orderbook: Orderbook, offers) {
@@ -84,24 +84,24 @@ function formatBidsAndAsks(orderbook: Orderbook, offers) {
// for asks: lowest quality => lowest totalPrice/quantity => lowest price
// for both bids and asks, lowest quality is closest to mid-market
// we sort the orders so that earlier orders are closer to mid-market
const orders = _.sortBy(offers, 'quality').map(parseOrderbookOrder);
const alignedOrders = orders.map(_.partial(alignOrder, orderbook.base));
const bids = alignedOrders.filter(_.partial(directionFilter, 'buy'));
const asks = alignedOrders.filter(_.partial(directionFilter, 'sell'));
return {bids, asks};
const orders = _.sortBy(offers, 'quality').map(parseOrderbookOrder)
const alignedOrders = orders.map(_.partial(alignOrder, orderbook.base))
const bids = alignedOrders.filter(_.partial(directionFilter, 'buy'))
const asks = alignedOrders.filter(_.partial(directionFilter, 'sell'))
return {bids, asks}
}
function getOrderbook(address: string, orderbook: Orderbook,
options: OrdersOptions = {}
): Promise<GetOrderbook> {
validate.getOrderbook({address, orderbook, options});
validate.getOrderbook({address, orderbook, options})
const getter = _.partial(getBookOffers, this.connection, address,
options.ledgerVersion, options.limit);
const getOffers = _.partial(getter, orderbook.base, orderbook.counter);
const getReverseOffers = _.partial(getter, orderbook.counter, orderbook.base);
options.ledgerVersion, options.limit)
const getOffers = _.partial(getter, orderbook.base, orderbook.counter)
const getReverseOffers = _.partial(getter, orderbook.counter, orderbook.base)
return Promise.all([getOffers(), getReverseOffers()]).then(data =>
formatBidsAndAsks(orderbook, _.flatten(data)));
formatBidsAndAsks(orderbook, _.flatten(data)))
}
module.exports = getOrderbook;
module.exports = getOrderbook

View File

@@ -1,11 +1,11 @@
/* @flow */
'use strict';
const _ = require('lodash');
const utils = require('./utils');
const {validate} = utils.common;
const parseAccountOrder = require('./parse/account-order');
import type {Connection} from '../common/connection.js';
import type {OrdersOptions, Order} from './types.js';
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const utils = require('./utils')
const {validate} = utils.common
const parseAccountOrder = require('./parse/account-order')
import type {Connection} from '../common/connection.js'
import type {OrdersOptions, Order} from './types.js'
type GetOrders = Array<Order>
@@ -22,20 +22,20 @@ function requestAccountOffers(connection: Connection, address: string,
return {
marker: data.marker,
results: data.offers.map(_.partial(parseAccountOrder, address))
};
});
}
})
}
function getOrders(address: string, options: OrdersOptions = {}
): Promise<GetOrders> {
validate.getOrders({address, options});
validate.getOrders({address, options})
return utils.ensureLedgerVersion.call(this, options).then(_options => {
const getter = _.partial(requestAccountOffers, this.connection, address,
_options.ledgerVersion);
_options.ledgerVersion)
return utils.getRecursive(getter, _options.limit).then(orders =>
_.sortBy(orders, (order) => order.properties.sequence));
});
_.sortBy(orders, order => order.properties.sequence))
})
}
module.exports = getOrders;
module.exports = getOrders

View File

@@ -1,24 +1,24 @@
/* @flow */
'use strict';
const utils = require('./utils');
const flags = require('./flags').orderFlags;
const parseAmount = require('./amount');
const BigNumber = require('bignumber.js');
'use strict' // eslint-disable-line strict
const utils = require('./utils')
const flags = require('./flags').orderFlags
const parseAmount = require('./amount')
const BigNumber = require('bignumber.js')
// TODO: remove this function once rippled provides quality directly
function computeQuality(takerGets, takerPays) {
const quotient = new BigNumber(takerPays.value).dividedBy(takerGets.value);
return quotient.toDigits(16, BigNumber.ROUND_HALF_UP).toString();
const quotient = new BigNumber(takerPays.value).dividedBy(takerGets.value)
return quotient.toDigits(16, BigNumber.ROUND_HALF_UP).toString()
}
// rippled 'account_offers' returns a different format for orders than 'tx'
// the flags are also different
function parseAccountOrder(address: string, order: Object): Object {
const direction = (order.flags & flags.Sell) === 0 ? 'buy' : 'sell';
const takerGetsAmount = parseAmount(order.taker_gets);
const takerPaysAmount = parseAmount(order.taker_pays);
const quantity = (direction === 'buy') ? takerPaysAmount : takerGetsAmount;
const totalPrice = (direction === 'buy') ? takerGetsAmount : takerPaysAmount;
const direction = (order.flags & flags.Sell) === 0 ? 'buy' : 'sell'
const takerGetsAmount = parseAmount(order.taker_gets)
const takerPaysAmount = parseAmount(order.taker_pays)
const quantity = (direction === 'buy') ? takerPaysAmount : takerGetsAmount
const totalPrice = (direction === 'buy') ? takerGetsAmount : takerPaysAmount
// note: immediateOrCancel and fillOrKill orders cannot enter the order book
// so we can omit those flags here
@@ -29,16 +29,19 @@ function parseAccountOrder(address: string, order: Object): Object {
passive: ((order.flags & flags.Passive) !== 0) || undefined,
// rippled currently does not provide "expiration" in account_offers
expirationTime: utils.parseTimestamp(order.expiration)
});
})
const makerExchangeRate = order.quality ?
utils.adjustQualityForXRP(order.quality.toString(),
takerGetsAmount.currency, takerPaysAmount.currency) :
computeQuality(takerGetsAmount, takerPaysAmount)
const properties = {
maker: address,
sequence: order.seq,
makerExchangeRate: order.quality ? order.quality.toString()
: computeQuality(takerGetsAmount, takerPaysAmount)
};
makerExchangeRate: makerExchangeRate
}
return {specification, properties};
return {specification, properties}
}
module.exports = parseAccountOrder;
module.exports = parseAccountOrder

View File

@@ -1,6 +1,6 @@
/* @flow */
'use strict';
const utils = require('./utils');
'use strict' // eslint-disable-line strict
const utils = require('./utils')
type Trustline = {
account: string, limit: number, currency: string, quality_in: ?number,
@@ -29,18 +29,18 @@ function parseAccountTrustline(trustline: Trustline): AccountTrustline {
ripplingDisabled: trustline.no_ripple || undefined,
frozen: trustline.freeze || undefined,
authorized: trustline.authorized || undefined
});
})
// rippled doesn't provide the counterparty's qualities
const counterparty = utils.removeUndefined({
limit: trustline.limit_peer,
ripplingDisabled: trustline.no_ripple_peer || undefined,
frozen: trustline.freeze_peer || undefined,
authorized: trustline.peer_authorized || undefined
});
})
const state = {
balance: trustline.balance
};
return {specification, counterparty, state};
}
return {specification, counterparty, state}
}
module.exports = parseAccountTrustline;
module.exports = parseAccountTrustline

View File

@@ -0,0 +1,9 @@
'use strict' // eslint-disable-line strict
function parseAmendment(tx: Object) {
return {
amendment: tx.Amendment
}
}
module.exports = parseAmendment

View File

@@ -1,7 +1,7 @@
/* @flow */
'use strict';
const utils = require('../utils');
import type {Amount, RippledAmount} from '../../common/types.js';
'use strict' // eslint-disable-line strict
const utils = require('../utils')
import type {Amount, RippledAmount} from '../../common/types.js'
function parseAmount(amount: RippledAmount): Amount {
@@ -9,13 +9,13 @@ function parseAmount(amount: RippledAmount): Amount {
return {
currency: 'XRP',
value: utils.common.dropsToXrp(amount)
};
}
}
return {
currency: amount.currency,
value: amount.value,
counterparty: amount.issuer
};
}
}
module.exports = parseAmount;
module.exports = parseAmount

View File

@@ -1,12 +1,12 @@
/* @flow */
'use strict';
const assert = require('assert');
'use strict' // eslint-disable-line strict
const assert = require('assert')
function parseOrderCancellation(tx: Object): Object {
assert(tx.TransactionType === 'OfferCancel');
assert(tx.TransactionType === 'OfferCancel')
return {
orderSequence: tx.OfferSequence
};
}
}
module.exports = parseOrderCancellation;
module.exports = parseOrderCancellation

View File

@@ -0,0 +1,16 @@
/* @flow */
'use strict' // eslint-disable-line strict
const assert = require('assert')
const utils = require('./utils')
function parseEscrowCancellation(tx: Object): Object {
assert(tx.TransactionType === 'EscrowCancel')
return utils.removeUndefined({
memos: utils.parseMemos(tx),
owner: tx.Owner,
escrowSequence: tx.OfferSequence
})
}
module.exports = parseEscrowCancellation

View File

@@ -0,0 +1,22 @@
/* @flow */
'use strict' // eslint-disable-line strict
const assert = require('assert')
const utils = require('./utils')
const parseAmount = require('./amount')
function parseEscrowCreation(tx: Object): Object {
assert(tx.TransactionType === 'EscrowCreate')
return utils.removeUndefined({
amount: parseAmount(tx.Amount).value,
destination: tx.Destination,
memos: utils.parseMemos(tx),
condition: tx.Condition,
allowCancelAfter: utils.parseTimestamp(tx.CancelAfter),
allowExecuteAfter: utils.parseTimestamp(tx.FinishAfter),
sourceTag: tx.SourceTag,
destinationTag: tx.DestinationTag
})
}
module.exports = parseEscrowCreation

View File

@@ -0,0 +1,18 @@
/* @flow */
'use strict' // eslint-disable-line strict
const assert = require('assert')
const utils = require('./utils')
function parseEscrowExecution(tx: Object): Object {
assert(tx.TransactionType === 'EscrowFinish')
return utils.removeUndefined({
memos: utils.parseMemos(tx),
owner: tx.Owner,
escrowSequence: tx.OfferSequence,
condition: tx.Condition,
fulfillment: tx.Fulfillment
})
}
module.exports = parseEscrowExecution

View File

@@ -0,0 +1,15 @@
'use strict' // eslint-disable-line strict
const BigNumber = require('bignumber.js')
const {dropsToXrp} = require('./utils')
function parseFeeUpdate(tx: Object) {
const baseFeeDrops = (new BigNumber(tx.BaseFee, 16)).toString()
return {
baseFeeXRP: dropsToXrp(baseFeeDrops),
referenceFeeUnits: tx.ReferenceFeeUnits,
reserveBaseXRP: dropsToXrp(tx.ReserveBase),
reserveIncrementXRP: dropsToXrp(tx.ReserveIncrement)
}
}
module.exports = parseFeeUpdate

View File

@@ -1,49 +1,52 @@
/* @flow */
'use strict';
const _ = require('lodash');
const BigNumber = require('bignumber.js');
const AccountFields = require('./utils').constants.AccountFields;
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const BigNumber = require('bignumber.js')
const AccountFields = require('./utils').constants.AccountFields
function parseField(info, value) {
if (info.encoding === 'hex' && !info.length) { // e.g. "domain"
return new Buffer(value, 'hex').toString('ascii');
return new Buffer(value, 'hex').toString('ascii')
}
if (info.shift) {
return (new BigNumber(value)).shift(-info.shift).toNumber();
return (new BigNumber(value)).shift(-info.shift).toNumber()
}
return value;
return value
}
function parseFields(data: Object): Object {
const settings = {};
const settings = {}
for (const fieldName in AccountFields) {
const fieldValue = data[fieldName];
const fieldValue = data[fieldName]
if (fieldValue !== undefined) {
const info = AccountFields[fieldName];
settings[info.name] = parseField(info, fieldValue);
const info = AccountFields[fieldName]
settings[info.name] = parseField(info, fieldValue)
}
}
if (data.RegularKey) {
settings.regularKey = data.RegularKey;
settings.regularKey = data.RegularKey
}
// TODO: this isn't implemented in rippled yet, may have to change this later
if (data.SignerQuorum || data.SignerEntries) {
settings.signers = {};
if (data.SignerQuorum) {
settings.signers.threshold = data.SignerQuorum;
// Since an account can own at most one SignerList,
// this array must have exactly one member if it is present.
if (data.signer_lists && data.signer_lists.length === 1) {
settings.signers = {}
if (data.signer_lists[0].SignerQuorum) {
settings.signers.threshold = data.signer_lists[0].SignerQuorum
}
if (data.SignerEntries) {
settings.signers.weights = _.map(data.SignerEntries, entry => {
return {
address: entry.SignerEntry.Account,
weight: entry.SignerEntry.SignerWeight
};
});
if (data.signer_lists[0].SignerEntries) {
settings.signers.weights = _.map(
data.signer_lists[0].SignerEntries,
entry => {
return {
address: entry.SignerEntry.Account,
weight: entry.SignerEntry.SignerWeight
}
})
}
}
return settings;
return settings
}
module.exports = parseFields;
module.exports = parseFields

View File

@@ -1,9 +1,9 @@
'use strict';
'use strict' // eslint-disable-line strict
const orderFlags = {
Passive: 0x00010000,
Sell: 0x00020000 // offer was placed as a sell
};
}
const trustlineFlags = {
LowReserve: 0x00010000, // entry counts toward reserve
@@ -14,9 +14,9 @@ const trustlineFlags = {
HighNoRipple: 0x00200000,
LowFreeze: 0x00400000,
HighFreeze: 0x00800000
};
}
module.exports = {
orderFlags,
trustlineFlags
};
}

View File

@@ -1,46 +1,48 @@
/* @flow */
'use strict';
const _ = require('lodash');
const {removeUndefined, rippleTimeToISO8601} = require('./utils');
const parseTransaction = require('./transaction');
import type {GetLedger} from '../types.js';
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const {removeUndefined, rippleTimeToISO8601} = require('./utils')
const parseTransaction = require('./transaction')
import type {GetLedger} from '../types.js'
function parseTransactionWrapper(ledgerVersion, tx) {
const transaction = _.assign({}, _.omit(tx, 'metaData'),
{meta: tx.metaData});
const result = parseTransaction(transaction);
const transaction = _.assign({}, _.omit(tx, 'metaData'), {
meta: tx.metaData,
ledger_index: ledgerVersion
})
const result = parseTransaction(transaction)
if (!result.outcome.ledgerVersion) {
result.outcome.ledgerVersion = ledgerVersion;
result.outcome.ledgerVersion = ledgerVersion
}
return result;
return result
}
function parseTransactions(transactions, ledgerVersion) {
if (_.isEmpty(transactions)) {
return {};
return {}
}
if (_.isString(transactions[0])) {
return {transactionHashes: transactions};
return {transactionHashes: transactions}
}
return {
transactions: _.map(transactions,
_.partial(parseTransactionWrapper, ledgerVersion)),
rawTransactions: JSON.stringify(transactions)
};
}
}
function parseState(state) {
if (_.isEmpty(state)) {
return {};
return {}
}
if (_.isString(state[0])) {
return {stateHashes: state};
return {stateHashes: state}
}
return {rawState: JSON.stringify(state)};
return {rawState: JSON.stringify(state)}
}
function parseLedger(ledger: Object): GetLedger {
const ledgerVersion = parseInt(ledger.ledger_index || ledger.seqNum, 10);
const ledgerVersion = parseInt(ledger.ledger_index || ledger.seqNum, 10)
return removeUndefined(_.assign({
stateHash: ledger.account_hash,
closeTime: rippleTimeToISO8601(ledger.close_time),
@@ -55,7 +57,7 @@ function parseLedger(ledger: Object): GetLedger {
},
parseTransactions(ledger.transactions, ledgerVersion),
parseState(ledger.accountState)
));
))
}
module.exports = parseLedger;
module.exports = parseLedger

Some files were not shown because too many files have changed in this diff Show More