mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-11 16:25:48 +00:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c234be0a8c | ||
|
|
7c6b8398cf | ||
|
|
7de677c953 | ||
|
|
aa23f44555 | ||
|
|
901d75a1eb | ||
|
|
aa95286810 | ||
|
|
f6b3f661d6 | ||
|
|
0850d85791 | ||
|
|
c564400ac4 | ||
|
|
94ab545ffe | ||
|
|
e10df203b7 | ||
|
|
eea20a6eab | ||
|
|
5f208801ee | ||
|
|
0a22697e5d | ||
|
|
30cf4f0b00 | ||
|
|
e4bb88a725 | ||
|
|
e3822e6bc3 | ||
|
|
20d3be0d1d | ||
|
|
1785863686 | ||
|
|
ea4ced3cc1 | ||
|
|
149008d18b | ||
|
|
55a21d2eec | ||
|
|
c7491e631a | ||
|
|
468a205e36 | ||
|
|
bebe951a57 | ||
|
|
85a8ab32ef | ||
|
|
34ddbe170c | ||
|
|
e9846eb249 | ||
|
|
7cc418ac93 | ||
|
|
69532a4f23 | ||
|
|
f59419d96f | ||
|
|
7f288d0555 | ||
|
|
53afa8c276 | ||
|
|
22f4dd2f75 | ||
|
|
0989152024 | ||
|
|
f74809d361 | ||
|
|
9724cf7776 | ||
|
|
909e5438a8 | ||
|
|
4022a59705 | ||
|
|
d7d26a3ae1 | ||
|
|
66db127245 | ||
|
|
932be02e9e | ||
|
|
fc524894c6 |
17
HISTORY.md
17
HISTORY.md
@@ -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
29
SECURITY.md
Normal 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 project’s 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.
|
||||
@@ -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) => {
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
@@ -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') -%>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)`.
|
||||
|
||||
|
||||
12
package.json
12
package.json
@@ -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",
|
||||
|
||||
@@ -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
44
src/common/backoff.ts
Normal 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
@@ -34,5 +34,5 @@ export {
|
||||
iso8601ToRippleTime,
|
||||
rippleTimeToISO8601
|
||||
} from './utils'
|
||||
export {default as Connection} from './connection'
|
||||
export {Connection} from './connection'
|
||||
export {txFlags} from './txflags'
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export interface SignerEntry {
|
||||
Account: string
|
||||
SignerWeight: number
|
||||
SignerEntry: {
|
||||
Account: string
|
||||
SignerWeight: number
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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')
|
||||
},
|
||||
|
||||
@@ -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')
|
||||
},
|
||||
|
||||
@@ -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}',
|
||||
|
||||
@@ -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
37
test/backoff-test.ts
Normal 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)
|
||||
})
|
||||
})
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Connection from '../../src/common/connection'
|
||||
import {Connection} from '../../src/common/connection'
|
||||
|
||||
const request1 = {
|
||||
command: 'server_info'
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user