Compare commits

...

43 Commits
1.6.0 ... 1.6.1

Author SHA1 Message Date
Elliot Lee
c234be0a8c Release 1.6.1 (#1170)
Update HISTORY and version number
2020-01-13 23:48:59 -08:00
Hans Bergren
7c6b8398cf Improve documentation for generateXAddress() (#1169)
It takes an optional property for including the classic address in the
return payload

Co-authored-by: Elliot Lee
2020-01-13 23:39:02 -08:00
Elliot Lee
7de677c953 Create SECURITY.md (#1164) 2020-01-13 23:27:05 -08:00
FKSRipple
aa23f44555 Merge pull request #1168 from ripple/dependabot/npm_and_yarn/mocha-junit-reporter-1.23.2
Bump mocha-junit-reporter from 1.23.1 to 1.23.2
2020-01-13 22:17:47 -08:00
dependabot-preview[bot]
901d75a1eb Bump mocha-junit-reporter from 1.23.1 to 1.23.2
Bumps [mocha-junit-reporter](https://github.com/michaelleeallen/mocha-junit-reporter) from 1.23.1 to 1.23.2.
- [Release notes](https://github.com/michaelleeallen/mocha-junit-reporter/releases)
- [Commits](https://github.com/michaelleeallen/mocha-junit-reporter/compare/v1.23.1...v1.23.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-13 13:27:35 +00:00
FKSRipple
aa95286810 Merge pull request #1140 from ripple/connection-cleanup-tests
Refactor tests to support the new connection logic
2020-01-10 17:24:52 -08:00
FKSRipple
f6b3f661d6 Merge branch 'develop' into connection-cleanup-tests 2020-01-10 16:15:16 -08:00
FKSRipple
0850d85791 Merge pull request #1141 from ripple/connection-cleanup-logic
Refactor the Connection class
2020-01-10 16:10:27 -08:00
FKSRipple
c564400ac4 Merge pull request #1119 from ripple/connection-cleanup-ledger
Add LedgerHistory to Connection
2020-01-10 16:07:08 -08:00
dependabot-preview[bot]
94ab545ffe Bump @types/node from 13.1.4 to 13.1.6 (#1163)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 13.1.4 to 13.1.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-10 11:57:41 -08:00
Hans Bergren
e10df203b7 Update documentation for functions that can be called offline (#1159)
You can also generate an X-Address without a connection to the ledger.
2020-01-09 10:33:12 -05:00
Hans Bergren
eea20a6eab Improve documentation for address generation (#1158)
The documentation previously just stated that any array of integers
was acceptable for providing as entropy, but it must be an array of
length 16 where the values are from 0-255 (uint8) to ensure we have
16 bytes of entropy.
2020-01-08 18:30:08 -05:00
Fred K. Schott
5f208801ee move backoff into codebase 2020-01-08 14:50:17 -08:00
Fred K. Schott
0a22697e5d Refactor the Connection 2020-01-08 12:21:37 -08:00
Fred K. Schott
30cf4f0b00 cleanup event listeners 2020-01-08 12:20:58 -08:00
Fred K. Schott
e4bb88a725 clarify comment 2020-01-08 12:20:58 -08:00
Fred K. Schott
e3822e6bc3 refactor tests for the new connection logic 2020-01-08 12:20:58 -08:00
Fred K. Schott
20d3be0d1d nevermind, regression wasn't actually a regression 2020-01-08 12:20:40 -08:00
Fred K. Schott
1785863686 update docs, fix a regression 2020-01-08 11:53:33 -08:00
FKSRipple
ea4ced3cc1 Merge pull request #1154 from ripple/dependabot/npm_and_yarn/types/node-13.1.4
Bump @types/node from 13.1.2 to 13.1.4
2020-01-08 11:35:01 -08:00
FKSRipple
149008d18b Merge pull request #1156 from ripple/dependabot/npm_and_yarn/ripple-binary-codec-0.2.6
Bump ripple-binary-codec from 0.2.5 to 0.2.6
2020-01-08 11:34:15 -08:00
FKSRipple
55a21d2eec Merge pull request #1157 from ripple/dependabot/npm_and_yarn/mocha-7.0.0
Bump mocha from 6.2.2 to 7.0.0
2020-01-08 11:32:45 -08:00
dependabot-preview[bot]
c7491e631a Bump mocha from 6.2.2 to 7.0.0
Bumps [mocha](https://github.com/mochajs/mocha) from 6.2.2 to 7.0.0.
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v6.2.2...v7.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-08 13:40:56 +00:00
dependabot-preview[bot]
468a205e36 Bump ripple-binary-codec from 0.2.5 to 0.2.6
Bumps [ripple-binary-codec](https://github.com/ripple/ripple-binary-codec) from 0.2.5 to 0.2.6.
- [Release notes](https://github.com/ripple/ripple-binary-codec/releases)
- [Changelog](https://github.com/ripple/ripple-binary-codec/blob/master/HISTORY.md)
- [Commits](https://github.com/ripple/ripple-binary-codec/compare/0.2.5...0.2.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-08 13:40:27 +00:00
dependabot-preview[bot]
bebe951a57 Bump @types/node from 13.1.2 to 13.1.4
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 13.1.2 to 13.1.4.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-08 13:39:39 +00:00
FKSRipple
85a8ab32ef update docs dependencies (#1153) 2020-01-07 15:30:29 -08:00
FKSRipple
34ddbe170c Merge pull request #1127 from you21979/fix-account-object
fix AccountObjectsResponse structure
2020-01-07 11:52:01 -08:00
FKSRipple
e9846eb249 Merge pull request #1145 from ripple/dependabot/npm_and_yarn/nyc-15.0.0
Bump nyc from 14.1.1 to 15.0.0
2020-01-07 11:51:39 -08:00
FKSRipple
7cc418ac93 Merge pull request #1131 from ripple/dependabot/npm_and_yarn/ws-7.2.1
Bump ws from 7.2.0 to 7.2.1
2020-01-07 11:50:43 -08:00
FKSRipple
69532a4f23 Merge pull request #1128 from ripple/dependabot/npm_and_yarn/typescript-3.7.4
Bump typescript from 3.6.4 to 3.7.4
2020-01-07 11:49:21 -08:00
FKSRipple
f59419d96f Update ledger_entries.ts 2020-01-07 11:44:14 -08:00
FKSRipple
7f288d0555 Update signers.ts 2020-01-07 11:43:37 -08:00
FKSRipple
53afa8c276 Merge pull request #1121 from r0bertz/develop
Document message type 'path_find' that connection can listen on
2020-01-07 11:34:57 -08:00
dependabot-preview[bot]
22f4dd2f75 Bump ws from 7.2.0 to 7.2.1
Bumps [ws](https://github.com/websockets/ws) from 7.2.0 to 7.2.1.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.2.0...7.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-07 19:29:37 +00:00
FKSRipple
0989152024 Merge pull request #1150 from ripple/dependabot/npm_and_yarn/ripple-lib-transactionparser-0.8.2
Bump ripple-lib-transactionparser from 0.8.1 to 0.8.2
2020-01-07 11:28:03 -08:00
dependabot-preview[bot]
f74809d361 Bump nyc from 14.1.1 to 15.0.0
Bumps [nyc](https://github.com/istanbuljs/nyc) from 14.1.1 to 15.0.0.
- [Release notes](https://github.com/istanbuljs/nyc/releases)
- [Changelog](https://github.com/istanbuljs/nyc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/istanbuljs/nyc/compare/v14.1.1...v15.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-07 19:27:39 +00:00
FKSRipple
9724cf7776 Merge pull request #1144 from ripple/dependabot/npm_and_yarn/eslint-6.8.0
Bump eslint from 6.5.1 to 6.8.0
2020-01-07 11:26:01 -08:00
dependabot-preview[bot]
909e5438a8 Bump typescript from 3.6.4 to 3.7.4
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.6.4 to 3.7.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 21:49:27 +00:00
dependabot-preview[bot]
4022a59705 Bump ripple-lib-transactionparser from 0.8.1 to 0.8.2
Bumps [ripple-lib-transactionparser](https://github.com/ripple/ripple-lib-extensions) from 0.8.1 to 0.8.2.
- [Release notes](https://github.com/ripple/ripple-lib-extensions/releases)
- [Commits](https://github.com/ripple/ripple-lib-extensions/compare/0.8.1...0.8.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 13:26:07 +00:00
dependabot-preview[bot]
d7d26a3ae1 Bump eslint from 6.5.1 to 6.8.0
Bumps [eslint](https://github.com/eslint/eslint) from 6.5.1 to 6.8.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v6.5.1...v6.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 03:56:35 +00:00
yuki akiyama
66db127245 fix AccountObjectsResponse: Does not match the structure returned by the API. 2019-12-23 13:21:26 +09:00
Robert Zhang
932be02e9e Document message type 'path_find' that connection can listen on 2019-12-21 20:01:00 -08:00
Fred K. Schott
fc524894c6 add ledger to connection 2019-12-18 11:35:47 -08:00
26 changed files with 1921 additions and 1310 deletions

View File

@@ -1,5 +1,20 @@
# ripple-lib Release History
## 1.6.1 (2020-01-14)
* Documentation
* Document message type 'path_find' (#1121) (thanks @r0bertz)
* Improve documentation for address generation; functions that can be called offline; generateXAddress() (#1158, #1159, #1169) (thanks @hbergren)
* Add [Security Policy](https://github.com/ripple/ripple-lib/blob/develop/SECURITY.md)
* Bug fixes
* Types: Fix AccountObjectsResponse structure (#1127) (thanks @you21979)
* In some cases, ripple-lib would fail to wait for the connection to be ready (#1119)
* Dependencies
* Update docs dependencies, ejs and doctoc (#1153)
* Update eslint, ripple-lib-transactionparser, typescript, nyc, ws, @types/node, ripple-binary-codec, mocha, mocha-junit-reporter
* Internal
* Add LedgerHistory to Connection (#1119): Moved ledger logic into its own Ledger class
## 1.6.0 (2020-01-06)
* Add support for AccountDelete (#1120)
@@ -447,7 +462,7 @@ f28921f57a133678dcb3cb54c497626bd76b1f953d22d61f3ddca31c8947d552 ripple-1.1.0-m
The SHA-256 checksums for the browser version of this release can be found
below.
```
% shasum -a 256 *
% shasum -a 256 *
2556fe17296e127ed44e7066e90a6175e2b164f00ca3c1aa7b1c554f31c688dd ripple-1.0.2-debug.js
e0342ea21eac32a1024c62034fba09c6f26dd3e7371b23ea1e153e03135cd590 ripple-1.0.2-min.js
c7286c517497d018d02d09257e81172b61d36c8b9885a077af68e8133c3b3b9b ripple-1.0.2.js

29
SECURITY.md Normal file
View File

@@ -0,0 +1,29 @@
# Security Policy
## Supported Versions
This table shows which versions of ripple-lib are currently supported with security updates:
| Version | Supported |
| ------- | ---------------------- |
| 1.x | :white_check_mark: Yes |
| 0.x | :x: No |
## Responsible disclosure security policy
The responsible disclosure of vulnerabilities helps to protect users of the project. Vulnerabilities are first triaged in a private manner, and only publicly disclosed after a reasonable time period that allows patching the vulnerability and provides an upgrade path for users.
When contacting us directly via email, we will do our best to respond in a reasonable time to resolve the issue. Do not disclose the vulnerability until it has been patched and users have been given time to upgrade.
We kindly ask you to refrain from malicious acts that put our users, the project, or any of the projects team members at risk.
## Reporting a security issue
Security is a top priority. But no matter how much effort we put into security, there can still be vulnerabilities present.
If you discover a security vulnerability, please use the following means of communications to report it to us:
- Report the security issue to bugs@ripple.com
- [Ripple Bug Bounty](https://ripple.com/bug-bounty/)
Your efforts to responsibly disclose your findings are sincerely appreciated and will be taken into account to acknowledge your contributions.

View File

@@ -119,7 +119,6 @@ Using RippleAPI, you can:
This page contains documentation for ripple-lib. To use ripple-lib with npm/yarn, begin with the [Getting Started](https://github.com/ripple/ripple-lib#getting-started) steps.
**What is ripple-lib used for?** Here's a [list of applications that use `ripple-lib`](https://github.com/ripple/ripple-lib/blob/develop/APPLICATIONS.md). Open a PR to add your app or project to the list!
## Boilerplate
Use the following [boilerplate code](https://en.wikipedia.org/wiki/Boilerplate_code) to wrap your custom code using RippleAPI.
@@ -195,7 +194,6 @@ If you omit the `server` parameter, RippleAPI operates [offline](#offline-functi
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`
## Offline functionality
RippleAPI can also function without internet connectivity. This can be useful in order to generate secrets and sign transactions from a secure, isolated machine.
@@ -221,8 +219,8 @@ Methods that depend on the state of the XRP Ledger are unavailable in offline mo
* [prepareEscrowExecution](#prepareescrowexecution)
* [sign](#sign)
* [generateAddress](#generateaddress)
* [generateXAddress](#generatexaddress)
* [computeLedgerHash](#computeledgerhash)
# Basic Types
## Address
@@ -294,7 +292,6 @@ Name | Type | Description
currency | [currency](#currency) | The three-character code or hexadecimal string used to denote currencies, or "drops" for the smallest unit of XRP.
counterparty | [address](#address) | *Optional* The XRP Ledger address of the account that owes or is owed the funds (omitted if `currency` is "XRP" or "drops")
value | [value](#value) | *Optional* The quantity of the currency, denoted as a string to retain floating point precision
# Transaction Overview
## Transaction Types
@@ -381,7 +378,6 @@ Name | Type | Description
data | string | *Optional* Arbitrary string, conventionally containing the content of the memo.
format | string | *Optional* Conventionally containing information on how the memo is encoded, for example as a [MIME type](http://www.iana.org/assignments/media-types/media-types.xhtml). Only characters allowed in URLs are permitted.
type | string | *Optional* Conventionally, a unique relation (according to [RFC 5988](http://tools.ietf.org/html/rfc5988#section-4)) that defines the format of this memo. Only characters allowed in URLs are permitted.
# Transaction Specifications
A *transaction specification* specifies what a transaction should do. Each [Transaction Type](#transaction-types) has its own type of specification.
@@ -792,7 +788,6 @@ signature | string | *Optional* Signed claim authorizing withdrawal of XRP from
}
```
# rippled APIs
ripple-lib relies on [rippled APIs](https://ripple.com/build/rippled-apis/) for online functionality. In addition to ripple-lib's own methods, you can also access rippled APIs through ripple-lib. Use the `request()`, `hasNextPage()`, and `requestNextPage()` methods:
@@ -834,6 +829,7 @@ Type | Description
`manifestReceived` | Sent by the `manifests` stream when the server receives a manifest.
`transaction` | Sent by many subscriptions including `transactions`, `transactions_proposed`, `accounts`, `accounts_proposed`, and `book` (Order Book). See [Transaction Streams](https://ripple.com/build/rippled-apis/#transaction-streams) for details.
`peerStatusChange` | (Admin-only) Reports a large amount of information on the activities of other `rippled` servers to which the server is connected.
`path_find` | Asynchronous follow-up response to the currently open path\_find request. See [rippled path\_find method](https://xrpl.org/path_find.html) for details.
To register your listener function, use `connection.on(type, handler)`.
@@ -864,7 +860,6 @@ api.connect().then(() => { // Omit this if you are already connected
The subscription ends when you unsubscribe or the WebSocket connection is closed.
For full details, see [rippled Subscriptions](https://ripple.com/build/rippled-apis/#subscriptions).
## request
`request(command: string, options: object): Promise<object>`
@@ -918,7 +913,6 @@ return api.request('ledger', {
}
```
## hasNextPage
`hasNextPage(currentResponse): boolean`
@@ -946,7 +940,6 @@ return api.request('ledger_data', {
}
}).catch(console.error);
```
## requestNextPage
`requestNextPage(command: string, params: object = {}, currentResponse: object): Promise<object>`
@@ -977,9 +970,7 @@ return api.request(command, params).then(response => {
}).catch(console.error);
```
# Static Methods
## renameCounterpartyToIssuer
`renameCounterpartyToIssuer(issue: {currency: string, counterparty: address}): {currency: string, issuer: address}`
@@ -1017,7 +1008,6 @@ console.log(RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter))
{ currency: 'USD', issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' }
{ currency: 'BTC', issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' }
```
## formatBidsAndAsks
`formatBidsAndAsks(orderbookInfo: {base: Issue, counter: Issue}, offers: BookOffer[]): orderbook`
@@ -1296,9 +1286,7 @@ return Promise.all(
}
```
# API Methods
## connect
`connect(): Promise<void>`
@@ -1316,7 +1304,6 @@ This method returns a promise that resolves with a void value when a connection
### Example
See [Boilerplate](#boilerplate) for code sample.
## disconnect
`disconnect(): Promise<void>`
@@ -1334,7 +1321,6 @@ This method returns a promise that resolves with a void value when a connection
### Example
See [Boilerplate](#boilerplate) for code sample
## isConnected
`isConnected(): boolean`
@@ -1358,7 +1344,6 @@ return api.isConnected();
```json
true
```
## getServerInfo
`getServerInfo(): Promise<object>`
@@ -1432,7 +1417,6 @@ return api.getServerInfo().then(info => {/* ... */});
}
```
## getFee
`getFee(): Promise<string>`
@@ -1460,7 +1444,6 @@ return api.getFee().then(fee => {/* ... */});
```json
"0.000012"
```
## getLedgerVersion
`getLedgerVersion(): Promise<number>`
@@ -1487,7 +1470,6 @@ return api.getLedgerVersion().then(ledgerVersion => {
16869039
```
## getTransaction
`getTransaction(id: string, options: object): Promise<object>`
@@ -1639,7 +1621,6 @@ return api.getTransaction(id).then(transaction => {
}
```
## getTransactions
`getTransactions(address: string, options: object): Promise<Array<object>>`
@@ -1873,7 +1854,6 @@ return api.getTransactions(address).then(transaction => {
]
```
## getTrustlines
`getTrustlines(address: string, options: object): Promise<Array<object>>`
@@ -2018,7 +1998,6 @@ return api.getTrustlines(address).then(trustlines =>
]
```
## getBalances
`getBalances(address: string, options: object): Promise<Array<object>>`
@@ -2185,7 +2164,6 @@ return api.getBalances(address).then(balances =>
]
```
## getBalanceSheet
`getBalanceSheet(address: string, options: object): Promise<object>`
@@ -2281,7 +2259,6 @@ return api.getBalanceSheet(address).then(balanceSheet =>
}
```
## getPaths
`getPaths(pathfind: object): Promise<Array<object>>`
@@ -2402,7 +2379,6 @@ return api.getPaths(pathfind)
]
```
## getOrders
`getOrders(address: string, options: object): Promise<Array<object>>`
@@ -2783,7 +2759,6 @@ return api.getOrders(address).then(orders =>
]
```
## getOrderbook
`getOrderbook(address: string, orderbook: object, options: object): Promise<object>`
@@ -3889,7 +3864,6 @@ return api.getOrderbook(address, orderbook)
}
```
## getSettings
`getSettings(address: string, options: object): Promise<object>`
@@ -3972,7 +3946,6 @@ return api.getSettings(address).then(settings =>
}
```
## getAccountInfo
`getAccountInfo(address: string, options: object): Promise<object>`
@@ -4021,7 +3994,6 @@ return api.getAccountInfo(address).then(info =>
}
```
## getAccountObjects
`getAccountObjects(address: string, options: object): Promise<AccountObjectsResponse>`
@@ -4346,7 +4318,6 @@ return api.getAccountObjects(address: address).then(objects =>
}
```
## getPaymentChannel
`getPaymentChannel(id: string): Promise<object>`
@@ -4402,7 +4373,6 @@ return api.getPaymentChannel(channelId).then(channel =>
}
```
## getLedger
`getLedger(options: object): Promise<object>`
@@ -4466,7 +4436,6 @@ return api.getLedger()
}
```
## parseAccountFlags
`parseAccountFlags(Flags: number): object`
@@ -4502,7 +4471,6 @@ console.log(JSON.stringify(flags, null, 2))
"defaultRipple": false
}
```
## prepareTransaction
`prepareTransaction(transaction: object, instructions: object): Promise<object>`
@@ -4560,7 +4528,6 @@ async function preparedPreauth() {
}
}
```
## preparePayment
`preparePayment(address: string, payment: object, instructions: object): Promise<object>`
@@ -4633,7 +4600,6 @@ return api.preparePayment(address, payment).then(prepared => {
}
```
## prepareTrustline
`prepareTrustline(address: string, trustline: object, instructions: object): Promise<object>`
@@ -4701,7 +4667,6 @@ return api.prepareTrustline(address, trustline).then(prepared =>
}
```
## prepareOrder
`prepareOrder(address: string, order: object, instructions: object): Promise<object>`
@@ -4769,7 +4734,6 @@ return api.prepareOrder(address, order)
}
```
## prepareOrderCancellation
`prepareOrderCancellation(address: string, orderCancellation: object, instructions: object): Promise<object>`
@@ -4822,7 +4786,6 @@ return api.prepareOrderCancellation(address, orderCancellation)
}
```
## prepareSettings
`prepareSettings(address: string, settings: object, instructions: object): Promise<object>`
@@ -4886,7 +4849,6 @@ return api.prepareSettings(address, settings)
}
```
## prepareEscrowCreation
`prepareEscrowCreation(address: string, escrowCreation: object, instructions: object): Promise<object>`
@@ -4950,7 +4912,6 @@ return api.prepareEscrowCreation(address, escrowCreation).then(prepared =>
}
```
## prepareEscrowCancellation
`prepareEscrowCancellation(address: string, escrowCancellation: object, instructions: object): Promise<object>`
@@ -5006,7 +4967,6 @@ return api.prepareEscrowCancellation(address, escrowCancellation).then(prepared
}
```
## prepareEscrowExecution
`prepareEscrowExecution(address: string, escrowExecution: object, instructions: object): Promise<object>`
@@ -5064,7 +5024,6 @@ return api.prepareEscrowExecution(address, escrowExecution).then(prepared =>
}
```
## preparePaymentChannelCreate
`preparePaymentChannelCreate(address: string, paymentChannelCreate: object, instructions: object): Promise<object>`
@@ -5122,7 +5081,6 @@ return api.preparePaymentChannelCreate(address, paymentChannelCreate).then(prepa
}
```
## preparePaymentChannelClaim
`preparePaymentChannelClaim(address: string, paymentChannelClaim: object, instructions: object): Promise<object>`
@@ -5177,7 +5135,6 @@ return api.preparePaymentChannelClaim(address, paymentChannelClaim).then(prepare
}
```
## preparePaymentChannelFund
`preparePaymentChannelFund(address: string, paymentChannelFund: object, instructions: object): Promise<object>`
@@ -5233,7 +5190,6 @@ return api.preparePaymentChannelFund(address, paymentChannelFund).then(prepared
}
```
## prepareCheckCreate
`prepareCheckCreate(address: string, checkCreate: object, instructions: object): Promise<object>`
@@ -5292,7 +5248,6 @@ return api.prepareCheckCreate(address, checkCreate).then(prepared =>
}
```
## prepareCheckCancel
`prepareCheckCancel(address: string, checkCancel: object, instructions: object): Promise<object>`
@@ -5347,7 +5302,6 @@ return api.prepareCheckCancel(address, checkCancel).then(prepared =>
}
```
## prepareCheckCash
`prepareCheckCash(address: string, checkCash: object, instructions: object): Promise<object>`
@@ -5406,7 +5360,6 @@ return api.prepareCheckCash(address, checkCash).then(prepared =>
}
```
## sign
```
@@ -5548,7 +5501,6 @@ If any of `{signAs: some_address}` options were missing the code will return a v
```
[ValidationError(txJSON is not the same for all signedTransactions)]
```
## combine
`combine(signedTransactions: Array<string>): {signedTransaction: string, id: string}`
@@ -5586,7 +5538,6 @@ return api.combine(signedTransactions);
}
```
## submit
`submit(signedTransaction: string): Promise<object>`
@@ -5649,7 +5600,6 @@ return api.submit(signedTransaction)
}
```
## generateXAddress
`generateXAddress(options?: object): {address: string, secret: string}`
@@ -5662,7 +5612,8 @@ Name | Type | Description
---- | ---- | -----------
options | object | *Optional* Options to control how the address and secret are generated.
*options.* algorithm | string | *Optional* The digital signature algorithm to generate an address for. Can be `ecdsa-secp256k1` (default) or `ed25519`.
*options.* entropy | array\<integer\> | *Optional* The entropy to use to generate the seed.
*options.* entropy | array\<integer\> | *Optional* The entropy to use to generate the seed. Must be an array of length 16 with values from 0-255 (16 bytes of entropy)
*options.* includeClassicAddress | boolean | *Optional* Specifies whether the classic address should also be included in the returned payload.
*options.* test | boolean | *Optional* Specifies whether the address is intended for use on a test network such as Testnet or Devnet. If `true`, the address should only be used for testing, and will start with `T`. If `false`, the address should only be used on mainnet, and will start with `X`.
### Return Value
@@ -5688,7 +5639,6 @@ return api.generateAddress();
}
```
## generateAddress
`generateAddress(options?: object): {address: string, secret: string}`
@@ -5703,7 +5653,7 @@ Name | Type | Description
---- | ---- | -----------
options | object | *Optional* Options to control how the address and secret are generated.
*options.* algorithm | string | *Optional* The digital signature algorithm to generate an address for. Can be `ecdsa-secp256k1` (default) or `ed25519`.
*options.* entropy | array\<integer\> | *Optional* The entropy to use to generate the seed.
*options.* entropy | array\<integer\> | *Optional* The entropy to use to generate the seed. Must be an array of length 16 with values from 0-255 (16 bytes of entropy)
*options.* includeClassicAddress | boolean | *Optional* If `true`, return the classic address, in addition to the X-address.
*options.* test | boolean | *Optional* Specifies whether the address is intended for use on a test network such as Testnet or Devnet. If `true`, the address should only be used for testing, and will start with `T`. If `false`, the address should only be used on mainnet, and will start with `X`.
@@ -5734,7 +5684,6 @@ return api.generateAddress();
}
```
## isValidAddress
`isValidAddress(address: string): boolean`
@@ -5754,7 +5703,6 @@ This method returns `true` if the address is valid and `false` if it is not.
```javascript
return api.isValidAddress("address")
```
## isValidSecret
`isValidSecret(secret: string): boolean`
@@ -5774,7 +5722,6 @@ This method returns `true` if the secret is valid and `false` if it is not.
```javascript
return api.isValidSecret("secret")
```
## deriveKeypair
`deriveKeypair(seed: string): {privateKey: string, publicKey: string}`
@@ -5796,7 +5743,6 @@ var keypair = api.deriveKeypair(seed)
var public_key = keypair.publicKey;
var private_key = keypair.privateKey;
```
## deriveAddress
`deriveAddress(publicKey: string): string`
@@ -5816,7 +5762,6 @@ This method returns a string corresponding to the address derived from the publi
```javascript
var address = api.deriveAddress(public_key);
```
## signPaymentChannelClaim
`signPaymentChannelClaim(channel: string, amount: string, privateKey: string): string`
@@ -5855,7 +5800,6 @@ return api.signPaymentChannelClaim(channel, amount, privateKey);
"3045022100B5C54654221F154347679B97AE7791CBEF5E6772A3F894F9C781B8F1B400F89F022021E466D29DC5AEB5DFAFC76E8A88D2E388EBD25A84143B6AC3B647F479CB89B7"
```
## verifyPaymentChannelClaim
`verifyPaymentChannelClaim(channel: string, amount: string, signature: string, publicKey: string): boolean`
@@ -5894,7 +5838,6 @@ return api.verifyPaymentChannelClaim(channel, amount, signature, publicKey);
```json
true
```
## computeLedgerHash
`computeLedgerHash(ledger: object): string`
@@ -5950,7 +5893,6 @@ return api.computeLedgerHash(ledger);
```json
"F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349"
```
## xrpToDrops
`xrpToDrops(xrp: string | BigNumber): string`
@@ -5998,7 +5940,6 @@ return api.dropsToXrp('1');
```json
'0.000001'
```
## iso8601ToRippleTime
`iso8601ToRippleTime(iso8601: string): number`
@@ -6026,7 +5967,6 @@ api.iso8601ToRippleTime('2017-02-17T15:04:57Z');
```json
540659097
```
## rippleTimeToISO8601
`rippleTimeToISO8601(rippleTime: number): string`
@@ -6054,7 +5994,6 @@ api.rippleTimeToISO8601(540659097);
```json
'2017-02-17T15:04:57.000Z'
```
## txFlags
`txFlags.TRANSACTION_TYPE.FLAG`
@@ -6136,7 +6075,6 @@ The remaining transaction types do not have any flags at this time.
* EscrowCancel
* PaymentChannelCreate
* PaymentChannelFund
## schemaValidator
Unlike the rest of the ripple-lib API, schemaValidator is a static object on RippleAPI. It provides utility methods that do not use a server.
@@ -6172,7 +6110,6 @@ RippleAPI.schemaValidator.schemaValidate('sign', {
```
[ValidationError(instance.id does not match pattern "^[A-F0-9]{64}$")]
```
# API Events
## ledger
@@ -6277,4 +6214,3 @@ api.on('disconnected', (code) => {
}
});
```

View File

@@ -1,69 +1,69 @@
<% include introduction.md.ejs %>
<% include boilerplate.md.ejs %>
<% include offline.md.ejs %>
<% include basictypes.md.ejs %>
<% include transactions.md.ejs %>
<% include specifications.md.ejs %>
<% include rippledAPIs.md.ejs %>
<% include request.md.ejs %>
<% include hasNextPage.md.ejs %>
<% include requestNextPage.md.ejs %>
<%- include('introduction.md.ejs') -%>
<%- include('boilerplate.md.ejs') -%>
<%- include('offline.md.ejs') -%>
<%- include('basictypes.md.ejs') -%>
<%- include('transactions.md.ejs') -%>
<%- include('specifications.md.ejs') -%>
<%- include('rippledAPIs.md.ejs') -%>
<%- include('request.md.ejs') -%>
<%- include('hasNextPage.md.ejs') -%>
<%- include('requestNextPage.md.ejs') -%>
<% include staticMethods.md.ejs %>
<% include renameCounterpartyToIssuer.md.ejs %>
<% include formatBidsAndAsks.md.ejs %>
<%- include('staticMethods.md.ejs') -%>
<%- include('renameCounterpartyToIssuer.md.ejs') -%>
<%- include('formatBidsAndAsks.md.ejs') -%>
<% include methods.md.ejs %>
<% include connect.md.ejs %>
<% include disconnect.md.ejs %>
<% include isConnected.md.ejs %>
<% include getServerInfo.md.ejs %>
<% include getFee.md.ejs %>
<% include getLedgerVersion.md.ejs %>
<% include getTransaction.md.ejs %>
<% include getTransactions.md.ejs %>
<% include getTrustlines.md.ejs %>
<% include getBalances.md.ejs %>
<% include getBalanceSheet.md.ejs %>
<% include getPaths.md.ejs %>
<% include getOrders.md.ejs %>
<% include getOrderbook.md.ejs %>
<% include getSettings.md.ejs %>
<% include getAccountInfo.md.ejs %>
<% include getAccountObjects.md.ejs %>
<% include getPaymentChannel.md.ejs %>
<% include getLedger.md.ejs %>
<% include parseAccountFlags.md.ejs %>
<% include prepareTransaction.md.ejs %>
<% include preparePayment.md.ejs %>
<% include prepareTrustline.md.ejs %>
<% include prepareOrder.md.ejs %>
<% include prepareOrderCancellation.md.ejs %>
<% include prepareSettings.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 prepareCheckCreate.md.ejs %>
<% include prepareCheckCancel.md.ejs %>
<% include prepareCheckCash.md.ejs %>
<% include sign.md.ejs %>
<% include combine.md.ejs %>
<% include submit.md.ejs %>
<% include generateXAddress.md.ejs %>
<% include generateAddress.md.ejs %>
<% include isValidAddress.md.ejs %>
<% include isValidSecret.md.ejs %>
<% include deriveKeypair.md.ejs %>
<% include deriveAddress.md.ejs %>
<% include signPaymentChannelClaim.md.ejs %>
<% include verifyPaymentChannelClaim.md.ejs %>
<% include computeLedgerHash.md.ejs %>
<% include xrpToDropsAndDropsToXrp.md.ejs %>
<% include iso8601ToRippleTime.md.ejs %>
<% include rippleTimeToISO8601.md.ejs %>
<% include txFlags.md.ejs %>
<% include schemaValidator.md.ejs %>
<% include events.md.ejs %>
<%- include('methods.md.ejs') -%>
<%- include('connect.md.ejs') -%>
<%- include('disconnect.md.ejs') -%>
<%- include('isConnected.md.ejs') -%>
<%- include('getServerInfo.md.ejs') -%>
<%- include('getFee.md.ejs') -%>
<%- include('getLedgerVersion.md.ejs') -%>
<%- include('getTransaction.md.ejs') -%>
<%- include('getTransactions.md.ejs') -%>
<%- include('getTrustlines.md.ejs') -%>
<%- include('getBalances.md.ejs') -%>
<%- include('getBalanceSheet.md.ejs') -%>
<%- include('getPaths.md.ejs') -%>
<%- include('getOrders.md.ejs') -%>
<%- include('getOrderbook.md.ejs') -%>
<%- include('getSettings.md.ejs') -%>
<%- include('getAccountInfo.md.ejs') -%>
<%- include('getAccountObjects.md.ejs') -%>
<%- include('getPaymentChannel.md.ejs') -%>
<%- include('getLedger.md.ejs') -%>
<%- include('parseAccountFlags.md.ejs') -%>
<%- include('prepareTransaction.md.ejs') -%>
<%- include('preparePayment.md.ejs') -%>
<%- include('prepareTrustline.md.ejs') -%>
<%- include('prepareOrder.md.ejs') -%>
<%- include('prepareOrderCancellation.md.ejs') -%>
<%- include('prepareSettings.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('prepareCheckCreate.md.ejs') -%>
<%- include('prepareCheckCancel.md.ejs') -%>
<%- include('prepareCheckCash.md.ejs') -%>
<%- include('sign.md.ejs') -%>
<%- include('combine.md.ejs') -%>
<%- include('submit.md.ejs') -%>
<%- include('generateXAddress.md.ejs') -%>
<%- include('generateAddress.md.ejs') -%>
<%- include('isValidAddress.md.ejs') -%>
<%- include('isValidSecret.md.ejs') -%>
<%- include('deriveKeypair.md.ejs') -%>
<%- include('deriveAddress.md.ejs') -%>
<%- include('signPaymentChannelClaim.md.ejs') -%>
<%- include('verifyPaymentChannelClaim.md.ejs') -%>
<%- include('computeLedgerHash.md.ejs') -%>
<%- include('xrpToDropsAndDropsToXrp.md.ejs') -%>
<%- include('iso8601ToRippleTime.md.ejs') -%>
<%- include('rippleTimeToISO8601.md.ejs') -%>
<%- include('txFlags.md.ejs') -%>
<%- include('schemaValidator.md.ejs') -%>
<%- include('events.md.ejs') -%>

View File

@@ -23,4 +23,5 @@ Methods that depend on the state of the XRP Ledger are unavailable in offline mo
* [prepareEscrowExecution](#prepareescrowexecution)
* [sign](#sign)
* [generateAddress](#generateaddress)
* [generateXAddress](#generatexaddress)
* [computeLedgerHash](#computeledgerhash)

View File

@@ -39,6 +39,7 @@ Type | Description
`manifestReceived` | Sent by the `manifests` stream when the server receives a manifest.
`transaction` | Sent by many subscriptions including `transactions`, `transactions_proposed`, `accounts`, `accounts_proposed`, and `book` (Order Book). See [Transaction Streams](https://ripple.com/build/rippled-apis/#transaction-streams) for details.
`peerStatusChange` | (Admin-only) Reports a large amount of information on the activities of other `rippled` servers to which the server is connected.
`path_find` | Asynchronous follow-up response to the currently open path\_find request. See [rippled path\_find method](https://xrpl.org/path_find.html) for details.
To register your listener function, use `connection.on(type, handler)`.

View File

@@ -1,6 +1,6 @@
{
"name": "ripple-lib",
"version": "1.6.0",
"version": "1.6.1",
"license": "ISC",
"description": "A TypeScript/JavaScript API for interacting with the XRP Ledger in Node.js and the browser",
"files": [
@@ -30,7 +30,7 @@
"ripple-address-codec": "^4.0.0",
"ripple-binary-codec": "^0.2.5",
"ripple-keypairs": "^0.11.0",
"ripple-lib-transactionparser": "0.8.1",
"ripple-lib-transactionparser": "0.8.2",
"ws": "^7.2.0"
},
"devDependencies": {
@@ -39,14 +39,14 @@
"@typescript-eslint/eslint-plugin": "^2.3.3",
"@typescript-eslint/parser": "^2.3.3",
"assert-diff": "^2.0.3",
"doctoc": "^0.15.0",
"ejs": "^2.3.4",
"doctoc": "^1.4.0",
"ejs": "^3.0.1",
"eslint": "^6.5.1",
"eventemitter2": "^6.0.0",
"json-schema-to-markdown-table": "^0.4.0",
"mocha": "6.2.2",
"mocha": "7.0.0",
"mocha-junit-reporter": "^1.9.1",
"nyc": "^14.1.1",
"nyc": "^15.0.0",
"prettier": "^1.19.1",
"ts-node": "^8.4.1",
"typescript": "^3.6.4",

View File

@@ -153,10 +153,10 @@ class RippleAPI extends EventEmitter {
})
this.connection.on('disconnected', code => {
let finalCode = code
// This is a backwards-compatible fix for this change in the ws library:
// https://github.com/websockets/ws/issues/1257
// 1005: This is a backwards-compatible fix for this change in the ws library: https://github.com/websockets/ws/issues/1257
// 4000: Connection uses a 4000 code internally to indicate a manual disconnect/close
// TODO: Remove in next major, breaking version
if (finalCode === 1005) {
if (finalCode === 1005 || finalCode === 4000) {
finalCode = 1000
}
this.emit('disconnected', finalCode)

44
src/common/backoff.ts Normal file
View File

@@ -0,0 +1,44 @@
/*
* Original code based on "backo" - https://github.com/segmentio/backo
* MIT License - Copyright 2014 Segment.io
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* A Back off strategy that increases exponentionally. Useful with repeated
* setTimeout calls over a network (where the destination may be down).
*/
export class ExponentialBackoff {
private readonly ms: number
private readonly max: number
private readonly factor: number = 2
private readonly jitter: number = 0
attempts: number = 0
constructor(opts: {min?: number; max?: number} = {}) {
this.ms = opts.min || 100
this.max = opts.max || 10000
}
/**
* Return the backoff duration.
*/
duration() {
var ms = this.ms * Math.pow(this.factor, this.attempts++)
if (this.jitter) {
var rand = Math.random()
var deviation = Math.floor(rand * this.jitter * ms)
ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation
}
return Math.min(ms, this.max) | 0
}
/**
* Reset the number of attempts.
*/
reset() {
this.attempts = 0
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -34,5 +34,5 @@ export {
iso8601ToRippleTime,
rippleTimeToISO8601
} from './utils'
export {default as Connection} from './connection'
export {Connection} from './connection'
export {txFlags} from './txflags'

View File

@@ -14,7 +14,7 @@
"minimum": 0,
"maximum": 255
},
"description": "The entropy to use to generate the seed."
"description": "The entropy to use to generate the seed. Must be an array of length 16 with values from 0-255 (16 bytes of entropy)"
},
"algorithm": {
"type": "string",

View File

@@ -14,7 +14,7 @@
"minimum": 0,
"maximum": 255
},
"description": "The entropy to use to generate the seed."
"description": "The entropy to use to generate the seed. Must be an array of length 16 with values from 0-255 (16 bytes of entropy)"
},
"algorithm": {
"type": "string",
@@ -24,6 +24,10 @@
"test": {
"type": "boolean",
"description": "Specifies whether the address is intended for use on a test network such as Testnet or Devnet. If `true`, the address should only be used for testing, and will start with `T`. If `false`, the address should only be used on mainnet, and will start with `X`."
},
"includeClassicAddress": {
"type": "boolean",
"description": "Specifies whether the classic address should also be included in the returned payload."
}
},
"additionalProperties": false

View File

@@ -1,4 +1,6 @@
export interface SignerEntry {
Account: string
SignerWeight: number
SignerEntry: {
Account: string
SignerWeight: number
}
}

View File

@@ -9,12 +9,14 @@ function getLedgerVersion(this: RippleAPI): Promise<number> {
return this.connection.getLedgerVersion()
}
function connect(this: RippleAPI): Promise<void> {
async function connect(this: RippleAPI): Promise<void> {
return this.connection.connect()
}
function disconnect(this: RippleAPI): Promise<void> {
return this.connection.disconnect()
async function disconnect(this: RippleAPI): Promise<void> {
// backwards compatibility: connection.disconnect() can return a number, but
// this method returns nothing. SO we await but don't return any result.
await this.connection.disconnect()
}
function formatLedgerClose(ledgerClose: any): object {

View File

@@ -19,12 +19,10 @@ export default <TestSuite>{
},
'getFee - high load_factor': async (api, address) => {
api.connection._send(
JSON.stringify({
command: 'config',
data: {highLoadFactor: true}
})
)
api.connection.request({
command: 'config',
data: {highLoadFactor: true}
})
const fee = await api.getFee()
assert.strictEqual(fee, '2')
},
@@ -33,12 +31,10 @@ export default <TestSuite>{
// Ensure that overriding with high maxFeeXRP of '51540' causes no errors.
// (fee will actually be 51539.607552)
api._maxFeeXRP = '51540'
api.connection._send(
JSON.stringify({
command: 'config',
data: {highLoadFactor: true}
})
)
api.connection.request({
command: 'config',
data: {highLoadFactor: true}
})
const fee = await api.getFee()
assert.strictEqual(fee, '51539.607552')
},

View File

@@ -14,12 +14,10 @@ export default <TestSuite>{
},
'error': async (api, address) => {
api.connection._send(
JSON.stringify({
command: 'config',
data: {returnErrorOnServerInfo: true}
})
)
api.connection.request({
command: 'config',
data: {returnErrorOnServerInfo: true}
})
try {
await api.getServerInfo()
throw new Error('Should throw NetworkError')
@@ -31,12 +29,10 @@ export default <TestSuite>{
},
'no validated ledger': async (api, address) => {
api.connection._send(
JSON.stringify({
command: 'config',
data: {serverInfoWithoutValidated: true}
})
)
api.connection.request({
command: 'config',
data: {serverInfoWithoutValidated: true}
})
const serverInfo = await api.getServerInfo()
assert.strictEqual(serverInfo.networkLedger, 'waiting')
},

View File

@@ -416,12 +416,10 @@ export default <TestSuite>{
api,
address
) => {
api.connection._send(
JSON.stringify({
command: 'config',
data: {loadFactor: 5407.96875}
})
)
api.connection.request({
command: 'config',
data: {loadFactor: 5407.96875}
})
const expectedResponse = {
txJSON:
'{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"64896","Sequence":23}',

View File

@@ -1050,12 +1050,10 @@ export default <TestSuite>{
api,
address
) => {
api.connection._send(
JSON.stringify({
command: 'config',
data: {loadFactor: 5407.96875}
})
)
api.connection.request({
command: 'config',
data: {loadFactor: 5407.96875}
})
const expectedResponse = {
txJSON:

37
test/backoff-test.ts Normal file
View File

@@ -0,0 +1,37 @@
import assert from 'assert-diff'
import {ExponentialBackoff} from '../src/common/backoff'
describe('ExponentialBackoff', function() {
it('duration() return value starts with the min value', function() {
// default: 100ms
assert(new ExponentialBackoff().duration(), 100)
assert(new ExponentialBackoff({min: 100}).duration(), 100)
assert(new ExponentialBackoff({min: 123}).duration(), 123)
})
it('duration() return value increases when called multiple times', function() {
const backoff = new ExponentialBackoff({min: 100, max: 1000})
assert.strictEqual(backoff.duration(), 100)
assert.strictEqual(backoff.duration(), 200)
assert.strictEqual(backoff.duration(), 400)
assert.strictEqual(backoff.duration(), 800)
})
it('duration() never returns greater than the max value', function() {
const backoff = new ExponentialBackoff({min: 300, max: 1000})
assert.strictEqual(backoff.duration(), 300)
assert.strictEqual(backoff.duration(), 600)
assert.strictEqual(backoff.duration(), 1000)
assert.strictEqual(backoff.duration(), 1000)
})
it('reset() will reset the duration() value', function() {
const backoff = new ExponentialBackoff({min: 100, max: 1000})
assert.strictEqual(backoff.duration(), 100)
assert.strictEqual(backoff.duration(), 200)
assert.strictEqual(backoff.duration(), 400)
backoff.reset()
assert.strictEqual(backoff.duration(), 100)
assert.strictEqual(backoff.duration(), 200)
})
})

View File

@@ -4,6 +4,7 @@ import setupAPI from './setup-api'
import responses from './fixtures/responses'
import ledgerClosed from './fixtures/rippled/ledger-close.json'
import {RippleAPI} from 'ripple-api'
import {ignoreWebSocketDisconnect} from './utils'
const schemaValidator = RippleAPI._PRIVATE.schemaValidator
const TIMEOUT = 20000
@@ -43,12 +44,12 @@ describe('RippleAPIBroadcast', function() {
ledgerNext.ledger_index++
this.api._apis.forEach(api =>
api.connection._send(
JSON.stringify({
api.connection
.request({
command: 'echo',
data: ledgerNext
})
)
.catch(ignoreWebSocketDisconnect)
)
setTimeout(() => {
@@ -63,11 +64,11 @@ describe('RippleAPIBroadcast', function() {
assert.strictEqual(info, 'info')
done()
})
this.api._apis[1].connection._send(
JSON.stringify({
this.api._apis[1].connection
.request({
command: 'echo',
data: {error: 'type', error_message: 'info'}
})
)
.catch(ignoreWebSocketDisconnect)
})
})

View File

@@ -4,6 +4,7 @@ import assert from 'assert-diff'
import setupAPI from './setup-api'
import {RippleAPI} from 'ripple-api'
import ledgerClose from './fixtures/rippled/ledger-close.json'
import {ignoreWebSocketDisconnect} from './utils'
const utils = RippleAPI._PRIVATE.ledgerUtils
const TIMEOUT = 200000 // how long before each test case times out
@@ -35,11 +36,12 @@ describe('Connection', function() {
})
describe('trace', () => {
const message1 = '{"type": "transaction"}'
const message2 = '{"type": "path_find"}'
const mockedRequestData = {mocked: 'request'}
const mockedResponse = JSON.stringify({mocked: 'response', id: 0})
const expectedMessages = [
['send', message1],
['receive', message2]
// We add the ID here, since it's not a part of the user-provided request.
['send', JSON.stringify({...mockedRequestData, id: 0})],
['receive', mockedResponse]
]
const originalConsoleLog = console.log
@@ -52,8 +54,8 @@ describe('Connection', function() {
console.log = (id, message) => messages.push([id, message])
const connection: any = new utils.common.Connection('url', {trace: false})
connection._ws = {send: function() {}}
connection._send(message1)
connection._onMessage(message2)
connection.request(mockedRequestData)
connection._onMessage(mockedResponse)
assert.deepEqual(messages, [])
})
@@ -62,8 +64,8 @@ describe('Connection', function() {
console.log = (id, message) => messages.push([id, message])
const connection: any = new utils.common.Connection('url', {trace: true})
connection._ws = {send: function() {}}
connection._send(message1)
connection._onMessage(message2)
connection.request(mockedRequestData)
connection._onMessage(mockedResponse)
assert.deepEqual(messages, expectedMessages)
})
@@ -73,12 +75,31 @@ describe('Connection', function() {
trace: (id, message) => messages.push([id, message])
})
connection._ws = {send: function() {}}
connection._send(message1)
connection._onMessage(message2)
connection.request(mockedRequestData)
connection._onMessage(mockedResponse)
assert.deepEqual(messages, expectedMessages)
})
})
it('ledger methods work as expected', async function() {
assert.strictEqual(await this.api.connection.getLedgerVersion(), 8819951)
assert.strictEqual(
await this.api.connection.hasLedgerVersion(8819951),
true
)
assert.strictEqual(
await this.api.connection.hasLedgerVersions(8819951, undefined),
true
)
// It would be nice to test a better range, but the mocked ledger only supports this single number
assert.strictEqual(
await this.api.connection.hasLedgerVersions(8819951, 8819951),
true
)
assert.strictEqual(await this.api.connection.getFeeBase(), 10)
assert.strictEqual(await this.api.connection.getFeeRef(), 10)
})
it('with proxy', function(done) {
if (isBrowser) {
done()
@@ -154,13 +175,11 @@ describe('Connection', function() {
})
})
it('DisconnectedError', function() {
this.api.connection._send(
JSON.stringify({
command: 'config',
data: {disconnectOnServerInfo: true}
})
)
it('DisconnectedError', async function() {
await this.api.connection.request({
command: 'config',
data: {disconnectOnServerInfo: true}
})
return this.api
.getServerInfo()
.then(() => {
@@ -172,12 +191,12 @@ describe('Connection', function() {
})
it('TimeoutError', function() {
this.api.connection._send = function() {
return Promise.resolve({})
this.api.connection._ws.send = function(message, options, callback) {
callback(null)
}
const request = {command: 'server_info'}
return this.api.connection
.request(request, 1)
.request(request, 10)
.then(() => {
assert(false, 'Should throw TimeoutError')
})
@@ -226,22 +245,8 @@ describe('Connection', function() {
});
it('ResponseFormatError', function() {
this.api.connection._send = function(message) {
const parsed = JSON.parse(message)
setTimeout(() => {
this._ws.emit(
'message',
JSON.stringify({
id: parsed.id,
type: 'response',
status: 'unrecognized'
})
)
}, 2)
return new Promise(() => {})
}
return this.api
.getServerInfo()
.request('test_command', {data: {unrecognizedResponse: true}})
.then(() => {
assert(false, 'Should throw ResponseFormatError')
})
@@ -250,34 +255,16 @@ describe('Connection', function() {
})
})
it('reconnect on unexpected close ', function(done) {
it('reconnect on unexpected close', function(done) {
this.api.connection.on('connected', () => {
done()
})
setTimeout(() => {
this.api.connection._ws.close()
}, 1)
})
describe('reconnection test', function() {
beforeEach(function() {
this.api.connection.__workingUrl = this.api.connection._url
this.api.connection.__doReturnBad = function() {
this._url = this.__badUrl
const self = this
function onReconnect(num) {
if (num >= 2) {
self._url = self.__workingUrl
self.removeListener('reconnecting', onReconnect)
}
}
this.on('reconnecting', onReconnect)
}
})
afterEach(function() {})
it('reconnect on several unexpected close', function(done) {
if (isBrowser) {
const phantomTest = /PhantomJS/
@@ -289,15 +276,13 @@ describe('Connection', function() {
}
this.timeout(70001)
const self = this
self.api.connection.__badUrl = 'ws://testripple.circleci.com:129'
function breakConnection() {
self.api.connection.__doReturnBad()
self.api.connection._send(
JSON.stringify({
self.api.connection
.request({
command: 'test_command',
data: {disconnectIn: 10}
})
)
.catch(ignoreWebSocketDisconnect)
}
let connectsCount = 0
@@ -328,11 +313,11 @@ describe('Connection', function() {
' instead)'
)
)
} else if (reconnectsCount !== num * 2) {
} else if (reconnectsCount !== num) {
done(
new Error(
'reconnectsCount must be equal to ' +
num * 2 +
num +
' (got ' +
reconnectsCount +
' instead)'
@@ -370,7 +355,9 @@ describe('Connection', function() {
// Hook up a listener for the reconnect event
this.api.connection.on('reconnect', () => done())
// Trigger a heartbeat
this.api.connection._heartbeat()
this.api.connection._heartbeat().catch(error => {
/* ignore - test expects heartbeat failure */
})
})
it('should emit disconnected event with code 1000 (CLOSE_NORMAL)', function(done) {
@@ -382,19 +369,19 @@ describe('Connection', function() {
})
it('should emit disconnected event with code 1006 (CLOSE_ABNORMAL)', function(done) {
this.api.once('error', error => {
this.api.connection.once('error', error => {
done(new Error('should not throw error, got ' + String(error)))
})
this.api.once('disconnected', code => {
this.api.connection.once('disconnected', code => {
assert.strictEqual(code, 1006)
done()
})
this.api.connection._send(
JSON.stringify({
this.api.connection
.request({
command: 'test_command',
data: {disconnectIn: 10}
})
)
.catch(ignoreWebSocketDisconnect)
})
it('should emit connected event on after reconnect', function(done) {
@@ -455,7 +442,8 @@ describe('Connection', function() {
this.api.connection.on('path_find', () => {
pathFindCount++
})
this.api.connection.on('1', () => {
this.api.connection.on('response', message => {
assert.strictEqual(message.id, 1)
assert.strictEqual(transactionCount, 1)
assert.strictEqual(pathFindCount, 1)
done()
@@ -550,15 +538,13 @@ describe('Connection', function() {
it(
'should throw RippledNotInitializedError if server does not have ' +
'validated ledgers',
function() {
async function() {
this.timeout(3000)
this.api.connection._send(
JSON.stringify({
command: 'global_config',
data: {returnEmptySubscribeRequest: 1}
})
)
await this.api.connection.request({
command: 'global_config',
data: {returnEmptySubscribeRequest: 1}
})
const api = new RippleAPI({server: this.api.connection._url})
return api.connect().then(
@@ -578,7 +564,6 @@ describe('Connection', function() {
it('should try to reconnect on empty subscribe response on reconnect', function(done) {
this.timeout(23000)
this.api.on('error', error => {
done(error || new Error('Should not emit error.'))
})
@@ -593,19 +578,9 @@ describe('Connection', function() {
this.api.on('disconnected', () => {
disconnectedCount++
})
this.api.connection._send(
JSON.stringify({
command: 'global_config',
data: {returnEmptySubscribeRequest: 3}
})
)
this.api.connection._send(
JSON.stringify({
command: 'test_command',
data: {disconnectIn: 10}
})
)
this.api.connection.request({
command: 'test_command',
data: {disconnectIn: 5}
})
})
})

View File

@@ -1,4 +1,4 @@
import Connection from '../../src/common/connection'
import {Connection} from '../../src/common/connection'
const request1 = {
command: 'server_info'

View File

@@ -119,12 +119,26 @@ export function createMockRippled(port) {
mock.on('request_config', function(request, conn) {
assert.strictEqual(request.command, 'config')
conn.config = _.assign(conn.config, request.data)
conn.send(
createResponse(request, {
status: 'success',
type: 'response',
result: {}
})
)
})
mock.on('request_test_command', function(request, conn) {
assert.strictEqual(request.command, 'test_command')
if (request.data.disconnectIn) {
setTimeout(conn.terminate.bind(conn), request.data.disconnectIn)
conn.send(
createResponse(request, {
status: 'success',
type: 'response',
result: {}
})
)
} else if (request.data.openOnOtherPort) {
getFreePort().then(newPort => {
createMockRippled(newPort)
@@ -145,12 +159,27 @@ export function createMockRippled(port) {
}, request.data.closeServerAndReopen)
})
}, 10)
} else if (request.data.unrecognizedResponse) {
conn.send(
createResponse(request, {
status: 'unrecognized',
type: 'response',
result: {}
})
)
}
})
mock.on('request_global_config', function(request, conn) {
assert.strictEqual(request.command, 'global_config')
mock.config = _.assign(conn.config, request.data)
conn.send(
createResponse(request, {
status: 'success',
type: 'response',
result: {}
})
)
})
mock.on('request_echo', function(request, conn) {

View File

@@ -139,3 +139,15 @@ export function loadTestSuites(): LoadedTestSuite[] {
})
.filter(Boolean)
}
/**
* Ignore WebSocket DisconnectErrors. Useful for making requests where we don't
* care about the response and plan to teardown the test before the response
* has come back.
*/
export function ignoreWebSocketDisconnect(error: Error): void {
if (error.message === 'websocket was closed') {
return
}
throw error
}

1613
yarn.lock

File diff suppressed because it is too large Load Diff