Merge branch 'develop' into connection-cleanup-tests

This commit is contained in:
FKSRipple
2020-01-10 16:15:16 -08:00
committed by GitHub
30 changed files with 1571 additions and 963 deletions

View File

@@ -1,5 +1,25 @@
# ripple-lib Release History
## 1.6.0 (2020-01-06)
* Add support for AccountDelete (#1120)
* Improve error type given on rejected message _send to be DisconnectedError (#1098)
* Internal
* Add unit test for unhandled promise rejection warning on message _send (#1098)
* Dependencies
* Update @types/node, @typescript-eslint/parser
## 1.5.1 (2019-12-28)
* Fix support for CDNs (#1142)
* Internal
* Clean up connection trace logic (#1114)
* Clean up the connection config (#1115)
* Run prettier format (#1116)
* Update eslint command (#1118)
* Dependencies
* Update webpack-cli, webpack, ts-node, @types/lodash, @types/ws, @types/node, @typescript-eslint/parser, @typescript-eslint/eslint-plugin, https-proxy-agent, mocha, eventemitter2
## 1.5.0 (2019-12-14)
* Add support for `WalletLocator` (#1083)

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>`
@@ -4511,7 +4479,7 @@ Prepare a transaction. The prepared transaction must subsequently be [signed](#s
This method works with any of [the transaction types supported by rippled](https://developers.ripple.com/transaction-types.html).
Notably, this is the preferred method for preparing a `DepositPreauth` transaction (added in rippled 1.1.0).
Notably, this is the preferred method for preparing `DepositPreauth` or `AccountDelete` transactions.
### Parameters
@@ -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,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.* 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 +5638,6 @@ return api.generateAddress();
}
```
## generateAddress
`generateAddress(options?: object): {address: string, secret: string}`
@@ -5703,7 +5652,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 +5683,6 @@ return api.generateAddress();
}
```
## isValidAddress
`isValidAddress(address: string): boolean`
@@ -5754,7 +5702,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 +5721,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 +5742,6 @@ var keypair = api.deriveKeypair(seed)
var public_key = keypair.publicKey;
var private_key = keypair.privateKey;
```
## deriveAddress
`deriveAddress(publicKey: string): string`
@@ -5816,7 +5761,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 +5799,6 @@ return api.signPaymentChannelClaim(channel, amount, privateKey);
"3045022100B5C54654221F154347679B97AE7791CBEF5E6772A3F894F9C781B8F1B400F89F022021E466D29DC5AEB5DFAFC76E8A88D2E388EBD25A84143B6AC3B647F479CB89B7"
```
## verifyPaymentChannelClaim
`verifyPaymentChannelClaim(channel: string, amount: string, signature: string, publicKey: string): boolean`
@@ -5894,7 +5837,6 @@ return api.verifyPaymentChannelClaim(channel, amount, signature, publicKey);
```json
true
```
## computeLedgerHash
`computeLedgerHash(ledger: object): string`
@@ -5950,7 +5892,6 @@ return api.computeLedgerHash(ledger);
```json
"F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349"
```
## xrpToDrops
`xrpToDrops(xrp: string | BigNumber): string`
@@ -5998,7 +5939,6 @@ return api.dropsToXrp('1');
```json
'0.000001'
```
## iso8601ToRippleTime
`iso8601ToRippleTime(iso8601: string): number`
@@ -6026,7 +5966,6 @@ api.iso8601ToRippleTime('2017-02-17T15:04:57Z');
```json
540659097
```
## rippleTimeToISO8601
`rippleTimeToISO8601(rippleTime: number): string`
@@ -6054,7 +5993,6 @@ api.rippleTimeToISO8601(540659097);
```json
'2017-02-17T15:04:57.000Z'
```
## txFlags
`txFlags.TRANSACTION_TYPE.FLAG`
@@ -6136,7 +6074,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 +6109,6 @@ RippleAPI.schemaValidator.schemaValidate('sign', {
```
[ValidationError(instance.id does not match pattern "^[A-F0-9]{64}$")]
```
# API Events
## ledger
@@ -6277,4 +6213,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

@@ -6,7 +6,7 @@ Prepare a transaction. The prepared transaction must subsequently be [signed](#s
This method works with any of [the transaction types supported by rippled](https://developers.ripple.com/transaction-types.html).
Notably, this is the preferred method for preparing a `DepositPreauth` transaction (added in rippled 1.1.0).
Notably, this is the preferred method for preparing `DepositPreauth` or `AccountDelete` transactions.
### Parameters

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,13 +1,16 @@
{
"name": "ripple-lib",
"version": "1.5.0",
"version": "1.6.0",
"license": "ISC",
"description": "A TypeScript/JavaScript API for interacting with the XRP Ledger in Node.js and the browser",
"files": [
"dist/npm/*",
"build/ripple-latest-min.js"
"build/ripple-latest-min.js",
"build/ripple-latest.js"
],
"main": "dist/npm/",
"unpkg": "build/ripple-latest-min.js",
"jsdelivr": "build/ripple-latest-min.js",
"types": "dist/npm/index.d.ts",
"browser": {
"ws": "./dist/npm/common/wswrapper.js",
@@ -20,30 +23,30 @@
"@types/lodash": "^4.14.136",
"@types/ws": "^6.0.3",
"bignumber.js": "^9.0.0",
"https-proxy-agent": "^3.0.0",
"https-proxy-agent": "^4.0.0",
"jsonschema": "1.2.2",
"lodash": "^4.17.4",
"lodash.isequal": "^4.5.0",
"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": {
"@types/mocha": "^5.2.7",
"@types/node": "^12.12.5",
"@types/node": "^13.1.1",
"@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": "^5.0.1",
"eventemitter2": "^6.0.0",
"json-schema-to-markdown-table": "^0.4.0",
"mocha": "6.2.0",
"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

@@ -62,6 +62,8 @@ function loadSchemas() {
require('./schemas/specifications/check-cash.json'),
require('./schemas/specifications/check-cancel.json'),
require('./schemas/specifications/trustline.json'),
require('./schemas/specifications/deposit-preauth.json'),
require('./schemas/specifications/account-delete.json'),
require('./schemas/output/sign.json'),
require('./schemas/output/submit.json'),
require('./schemas/output/get-account-info.json'),

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",

View File

@@ -18,6 +18,8 @@
"paymentChannelClaim",
"checkCreate",
"checkCancel",
"checkCash"
"checkCash",
"depositPreauth",
"accountDelete"
]
}

View File

@@ -208,6 +208,30 @@
"$ref": "paymentChannelClaim"
}
}
},
{
"properties": {
"type": {
"enum": [
"depositPreauth"
]
},
"specification": {
"$ref": "depositPreauth"
}
}
},
{
"properties": {
"type": {
"enum": [
"accountDelete"
]
},
"specification": {
"$ref": "accountDelete"
}
}
}
]
}

View File

@@ -0,0 +1,29 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "accountDelete",
"link": "account-delete",
"type": "object",
"properties": {
"destination": {
"$ref": "address",
"description": "Address of an account to receive any leftover XRP after deleting the sending account. Must be a funded account in the ledger, and must not be the sending account."
},
"destinationTag": {
"$ref": "tag",
"description": "(Optional) Arbitrary destination tag that identifies a hosted recipient or other information for the recipient of the deleted account's leftover XRP."
},
"destinationXAddress": {
"$ref": "address",
"description": "X-address of an account to receive any leftover XRP after deleting the sending account. Must be a funded account in the ledger, and must not be the sending account."
}
},
"anyOf": [
{
"required": ["destination"]
},
{
"required": ["destinationXAddress"]
}
],
"additionalProperties": false
}

View File

@@ -0,0 +1,21 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "depositPreauth",
"link": "deposit-preauth",
"type": "object",
"properties": {
"authorize": {
"$ref": "address",
"description": "Address of the account that can cash the check."
},
"unauthorize": {
"$ref": "address",
"description": "Address of the account that can cash the check."
}
},
"oneOf": [
{"required": ["authorize"]},
{"required": ["unauthorize"]}
],
"additionalProperties": false
}

View File

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

View File

@@ -0,0 +1,34 @@
import * as assert from 'assert'
import {removeUndefined} from '../../common'
import {classicAddressToXAddress} from 'ripple-address-codec'
export type FormattedAccountDelete = {
// account (address) of an account to receive any leftover XRP after deleting the sending account.
// Must be a funded account in the ledger, and must not be the sending account.
destination: string
// (Optional) Arbitrary destination tag that identifies a hosted recipient or other information
// for the recipient of the deleted account's leftover XRP. NB: Ensure that the hosted recipient is
// able to account for AccountDelete transactions; if not, your balance may not be properly credited.
destinationTag?: number
// X-address of an account to receive any leftover XRP after deleting the sending account.
// Must be a funded account in the ledger, and must not be the sending account.
destinationXAddress: string
}
function parseAccountDelete(tx: any): FormattedAccountDelete {
assert.ok(tx.TransactionType === 'AccountDelete')
return removeUndefined({
destination: tx.Destination,
destinationTag: tx.DestinationTag,
destinationXAddress: classicAddressToXAddress(
tx.Destination,
tx.DestinationTag === undefined ? false : tx.DestinationTag,
false
)
})
}
export default parseAccountDelete

View File

@@ -1,27 +1,31 @@
import {parseOutcome} from './utils'
import {removeUndefined} from '../../common'
import parsePayment from './payment'
import parseTrustline from './trustline'
import parseOrder from './order'
import parseOrderCancellation from './cancellation'
import parseSettings from './settings'
import parseAccountDelete from './account-delete'
import parseCheckCancel from './check-cancel'
import parseCheckCash from './check-cash'
import parseCheckCreate from './check-create'
import parseDepositPreauth from './deposit-preauth'
import parseEscrowCancellation from './escrow-cancellation'
import parseEscrowCreation from './escrow-creation'
import parseEscrowExecution from './escrow-execution'
import parseEscrowCancellation from './escrow-cancellation'
import parseCheckCreate from './check-create'
import parseCheckCash from './check-cash'
import parseCheckCancel from './check-cancel'
import parseDepositPreauth from './deposit-preauth'
import parseOrderCancellation from './cancellation'
import parseOrder from './order'
import parsePayment from './payment'
import parsePaymentChannelClaim from './payment-channel-claim'
import parsePaymentChannelCreate from './payment-channel-create'
import parsePaymentChannelFund from './payment-channel-fund'
import parsePaymentChannelClaim from './payment-channel-claim'
import parseFeeUpdate from './fee-update'
import parseAmendment from './amendment'
import parseTrustline from './trustline'
import parseAmendment from './amendment' // pseudo-transaction
import parseFeeUpdate from './fee-update' // pseudo-transaction
function parseTransactionType(type) {
// Ordering matches https://developers.ripple.com/transaction-types.html
const mapping = {
AccountSet: 'settings',
AccountDelete: 'accountDelete',
CheckCancel: 'checkCancel',
CheckCash: 'checkCash',
CheckCreate: 'checkCreate',
@@ -49,23 +53,25 @@ function parseTransactionType(type) {
function parseTransaction(tx: any, includeRawTransaction: boolean): any {
const type = parseTransactionType(tx.TransactionType)
const mapping = {
payment: parsePayment,
trustline: parseTrustline,
order: parseOrder,
orderCancellation: parseOrderCancellation,
settings: parseSettings,
accountDelete: parseAccountDelete,
checkCancel: parseCheckCancel,
checkCash: parseCheckCash,
checkCreate: parseCheckCreate,
depositPreauth: parseDepositPreauth,
escrowCancellation: parseEscrowCancellation,
escrowCreation: parseEscrowCreation,
escrowExecution: parseEscrowExecution,
escrowCancellation: parseEscrowCancellation,
checkCreate: parseCheckCreate,
checkCash: parseCheckCash,
checkCancel: parseCheckCancel,
depositPreauth: parseDepositPreauth,
orderCancellation: parseOrderCancellation,
order: parseOrder,
payment: parsePayment,
paymentChannelClaim: parsePaymentChannelClaim,
paymentChannelCreate: parsePaymentChannelCreate,
paymentChannelFund: parsePaymentChannelFund,
paymentChannelClaim: parsePaymentChannelClaim,
feeUpdate: parseFeeUpdate,
amendment: parseAmendment
trustline: parseTrustline,
amendment: parseAmendment, // pseudo-transaction
feeUpdate: parseFeeUpdate // pseudo-transaction
}
const parser: Function = mapping[type]

View File

@@ -354,6 +354,16 @@ export default <TestSuite>{
)
},
'AccountDelete': async (api, address) => {
const hash = 'EC2AB14028DC84DE525470AB4DAAA46358B50A8662C63804BFF38244731C0CB9'
const response = await api.getTransaction(hash)
assertResultMatch(
response,
RESPONSE_FIXTURES.accountDelete,
'getTransaction'
)
},
'no Meta': async (api, address) => {
const hash =
'AFB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA1B'

View File

@@ -745,6 +745,33 @@ export default <TestSuite>{
return assertResultMatch(response, expected, 'prepare')
},
'AccountDelete': async (api, address) => {
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '5.0' // 5 XRP fee for AccountDelete
}
const txJSON = {
TransactionType: 'AccountDelete',
Account: address,
Destination: 'rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe'
}
const response = await api.prepareTransaction(txJSON, localInstructions)
const expected = {
txJSON:
'{"TransactionType":"AccountDelete","Account":"' +
address +
'","Destination":"rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}',
instructions: {
fee: '0.000012',
sequence: 23,
maxLedgerVersion: 8820051
}
}
return assertResultMatch(response, expected, 'prepare')
},
// prepareTransaction - Payment
'Payment - normal': async (api, address) => {
const localInstructions = {

View File

@@ -212,7 +212,7 @@ export default <TestSuite>{
) => {
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
const request = {
// TODO: This fails when address is X-Address
// TODO: This fails when address is X-address
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"726970706C652E636F6D","LastLedgerSequence":8820051,"Fee":"1.2","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
instructions: {
fee: '0.0000012',
@@ -232,7 +232,7 @@ export default <TestSuite>{
) => {
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
const request = {
// TODO: This fails when address is X-Address
// TODO: This fails when address is X-address
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"726970706C652E636F6D","LastLedgerSequence":8820051,"Fee":"1123456.7","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
instructions: {
fee: '1.1234567',
@@ -289,7 +289,7 @@ export default <TestSuite>{
api._maxFeeXRP = '2.1'
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
const request = {
// TODO: This fails when address is X-Address
// TODO: This fails when address is X-address
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"726970706C652E636F6D","LastLedgerSequence":8820051,"Fee":"2010000","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
instructions: {
fee: '2.01',

View File

@@ -220,6 +220,30 @@ describe('Connection', function() {
})
})
it('DisconnectedError on initial _onOpen send', async function() {
// _onOpen previously could throw PromiseRejectionHandledWarning: Promise rejection was handled asynchronously
// do not rely on the api.setup hook to test this as it bypasses the case, disconnect api connection first
await this.api.disconnect();
// stub _onOpen to only run logic relevant to test case
this.api.connection._onOpen = () => {
// overload websocket send on open when _ws exists
this.api.connection._ws.send = function(data, options, cb) {
// recent ws throws this error instead of calling back
throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
}
const request = {command: 'subscribe', streams: ['ledger']};
return this.api.connection.request(request);
}
try {
await this.api.connect();
} catch (error) {
assert(error instanceof this.api.errors.DisconnectedError);
assert.strictEqual(error.message, 'WebSocket is not open: readyState 0 (CONNECTING)');
}
});
it('ResponseFormatError', function() {
return this.api
.request('test_command', {data: {unrecognizedResponse: true}})

View File

@@ -0,0 +1,32 @@
{
"type": "accountDelete",
"address": "rM5qup5BYDLMXaR5KU1hiC9HhFMuBVrnKv",
"sequence": 3227049,
"id": "EC2AB14028DC84DE525470AB4DAAA46358B50A8662C63804BFF38244731C0CB9",
"specification": {
"destination": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
"destinationXAddress": "XV5kHfQmzDQjbFNv4jX3FX9Y7ig5QhpKGEFCq4mdLfhdxMq"
},
"outcome": {
"result": "tesSUCCESS",
"timestamp": "2019-12-17T09:16:51.000Z",
"fee": "5",
"balanceChanges": {
"rM5qup5BYDLMXaR5KU1hiC9HhFMuBVrnKv": [
{
"currency": "XRP",
"value": "-10000"
}
],
"rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe": [
{
"currency": "XRP",
"value": "9995"
}
]
},
"orderbookChanges": {},
"ledgerVersion": 3232071,
"indexInLedger": 0
}
}

View File

@@ -67,7 +67,8 @@ module.exports = {
paymentChannelClaim:
require('./get-transaction-payment-channel-claim.json'),
amendment: require('./get-transaction-amendment.json'),
feeUpdate: require('./get-transaction-fee-update.json')
feeUpdate: require('./get-transaction-fee-update.json'),
accountDelete: require('./get-transaction-account-delete.json')
},
getTransactions: {
normal: require('./get-transactions.json'),

View File

@@ -99,6 +99,7 @@ module.exports = {
NoMeta: require('./tx/no-meta.json'),
LedgerZero: require('./tx/ledger-zero.json'),
Amendment: require('./tx/amendment.json'),
SetFee: require('./tx/set-fee.json')
SetFee: require('./tx/set-fee.json'),
AccountDelete: require('./tx/account-delete.json')
}
};

View File

@@ -0,0 +1,66 @@
{
"id": 0,
"result": {
"Account": "rM5qup5BYDLMXaR5KU1hiC9HhFMuBVrnKv",
"Destination": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
"Fee": "5000000",
"Flags": 2147483648,
"LastLedgerSequence": 3232818,
"Sequence": 3227049,
"SigningPubKey": "022E0DBF14BC4CFF96BC839557EE6F12F6DA45DCD917376F805E65D1B1C60A8CE6",
"TransactionType": "AccountDelete",
"TxnSignature": "304402207BDBE1B71C8BD00363905817C9373880CE9E8F0080623D457495E2B760BBBEE402202EDEB977D1ED865C1EAB88FE28581E3F8A672097B8BB0956E977C6EC87CA668C",
"date": 629889411,
"hash": "EC2AB14028DC84DE525470AB4DAAA46358B50A8662C63804BFF38244731C0CB9",
"inLedger": 3232071,
"ledger_index": 3232071,
"meta": {
"AffectedNodes": [
{
"DeletedNode": {
"FinalFields": {
"Account": "rM5qup5BYDLMXaR5KU1hiC9HhFMuBVrnKv",
"Balance": "0",
"Flags": 0,
"OwnerCount": 0,
"PreviousTxnID": "2737BEDDDA1D7FB523CFB84B891216331CC4CC999349828D81C6C727A1115A44",
"PreviousTxnLgrSeq": 3227049,
"Sequence": 3227050
},
"LedgerEntryType": "AccountRoot",
"LedgerIndex": "08EBF94D7BB527442E0B51F533B902DDCFBD423D8E95FAE752BE7876A29E875B",
"PreviousFields": {
"Balance": "10000000000",
"Sequence": 3227049
}
}
},
{
"ModifiedNode": {
"FinalFields": {
"Account": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
"Balance": "99991026734967448",
"Flags": 0,
"OwnerCount": 0,
"Sequence": 2978
},
"LedgerEntryType": "AccountRoot",
"LedgerIndex": "31CCE9D28412FF973E9AB6D0FA219BACF19687D9A2456A0C2ABC3280E9D47E37",
"PreviousFields": {
"Balance": "99991016739967448"
},
"PreviousTxnID": "2737BEDDDA1D7FB523CFB84B891216331CC4CC999349828D81C6C727A1115A44",
"PreviousTxnLgrSeq": 3227049
}
}
],
"DeliveredAmount": "9995000000",
"TransactionIndex": 0,
"TransactionResult": "tesSUCCESS",
"delivered_amount": "9995000000"
},
"validated": true
},
"status": "success",
"type": "response"
}

View File

@@ -553,6 +553,11 @@ export function createMockRippled(port) {
'81B9ECAE7195EB6E8034AEDF44D8415A7A803E14513FDBB34FA984AB37D59563'
) {
conn.send(createResponse(request, fixtures.tx.PaymentChannelClaim))
} else if (
request.transaction ===
'EC2AB14028DC84DE525470AB4DAAA46358B50A8662C63804BFF38244731C0CB9'
) {
conn.send(createResponse(request, fixtures.tx.AccountDelete))
} else if (
request.transaction ===
'AFB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA11'

View File

@@ -42,7 +42,7 @@ describe('RippleAPI [Test Runner]', function() {
})
// Run each test with the newer, x-address style.
if (!config.skipXAddress) {
describe(`[X-Address]`, () => {
describe(`[X-address]`, () => {
for (const [testName, fn] of tests) {
it(testName, function() {
return fn(this.api, addresses.ACCOUNT_X)

View File

@@ -33,7 +33,7 @@ interface LoadedTestSuite {
name: string
tests: [string, TestFn][]
config: {
/** Set to true to skip re-running tests with an X-Address. */
/** Set to true to skip re-running tests with an X-address. */
skipXAddress?: boolean
}
}

View File

@@ -41,7 +41,7 @@ module.exports = [
function(env, argv) {
const config = getDefaultConfiguration();
config.mode = 'production';
config.output.filename = `ripple-latest.min.js`;
config.output.filename = `ripple-latest-min.js`;
if (process.argv.includes('--analyze')) {
config.plugins.push(new BundleAnalyzerPlugin());
}

1918
yarn.lock

File diff suppressed because it is too large Load Diff