Compare commits

...

39 Commits

Author SHA1 Message Date
Elliot Lee
f785605db8 Release 1.0.1 2018-09-27 19:01:38 -07:00
Elliot Lee
01ad30ab07 Fix typos in ledger_entries.ts 2018-09-19 14:24:02 -07:00
Cory Perkins
e08d507462 Add remaining LedgerEntry types (#943)
* Replaced the union with 'any' in the LedgerEntry type
* Added DepositPreauthLedgerEntry (new in rippled 1.1.0)
2018-09-19 14:21:52 -07:00
wudanjs
4c23bd5ad3 Include memos when parsing trustlines (#949) 2018-09-19 14:17:38 -07:00
Scott M Sunarto
b15abd5376 Update server regex to accommodate UDS (#944) 2018-09-18 11:47:46 -07:00
Elliot Lee
79971f906b Update release notes 2018-09-11 18:45:52 -07:00
Elliot Lee
9eec98778f Expose validation methods (#932)
Merge branch 'movitto-expose_validation_methods' into develop
2018-09-11 18:33:55 -07:00
Elliot Lee
dcd0e14142 Add test of deriveKeypair with ed25519 secret 2018-09-11 18:33:07 -07:00
Elliot Lee
cfcbc9aab7 Update checksums for 1.0.0 2018-09-10 14:52:14 -07:00
Mo Morsi
a80de5658a Move deriveKeypair and deriveAddress to offline module 2018-09-09 09:39:25 -04:00
Mo Morsi
34215eb309 Add docs for newly exposed API methods 2018-09-09 09:39:25 -04:00
Mo Morsi
9458005d7f Add tests for newly exposed API methods 2018-09-09 09:39:25 -04:00
Mo Morsi
5f36df0172 Expose deriveKeypair, deriveAddress, isValidAddress, and isValidSecret to the public API 2018-09-09 09:39:25 -04:00
Elliot Lee
3ff4929a49 Fix PendingLedgerVersionError message and export FormattedTransactionType (#941) 2018-09-04 18:31:24 -07:00
Elliot Lee
4bea69d647 Release 1.0.0 2018-08-30 14:30:57 -07:00
Elliot Lee
09541dae86 docs: rippled APIs use issuer 2018-08-30 14:12:45 -07:00
Elliot Lee
bcbcc53c87 No `--coverage' option anymore with nyc
See https://github.com/istanbuljs/nyc
2018-08-30 13:41:52 -07:00
Elliot Lee
76f120bec9 Merge branch 'getLedger-includeRawTransaction-2' into develop 2018-08-30 13:30:18 -07:00
Elliot Lee
f8bf28876d if statements must be braced 2018-08-30 13:29:50 -07:00
wilsonianb
b03795df09 Add hidden computeTreeHashes option 2018-08-30 13:29:50 -07:00
Elliot Lee
dbe20d6574 getLedger: include raw transaction with each transaction
computeLedgerHash: support new getLedger response by using
rawTransaction

BREAKING CHANGES:

* Remove the `rawTransactions` field and replace it with a new `rawTransaction` field in each transaction.
* Rename the `metaData` field (in each raw transaction) to `meta` (for consistency with rippled's `tx` method).
* Add `ledger_index` to each raw transaction.
2018-08-30 13:28:52 -07:00
Elliot Lee
0550fab73e Update escrowCreation error message and docs (#934)
Fix #933
2018-08-29 19:03:33 -07:00
Elliot Lee
3f2d9d198e computeLedgerHash - add requireRawTransactions option 2018-08-28 17:31:12 -07:00
Elliot Lee
b9c953fce6 Fix getPaths (#930)
* getPaths:
  * Filter paths correctly
  * Use correct value when XRP is the destination currency
2018-08-23 17:37:02 -07:00
Elliot Lee
181cfd69de Prevent 'amount' from being misinterpreted (#924)
The 'amount' field should almost never be used.
With partial payments, the field can show an amount that is
significantly less than the amount that the transaction actually
delivered. This change sets amount to 0 XRP when it may be misleading.

This change omits the `amount` when parsing payment transactions.
See `HISTORY.md` for recommended alternatives.
2018-08-23 16:17:23 -07:00
Elliot Lee
569766b8f8 Rename json schemas (#931)
Rename files for consistency with their titles:

* Rename amount-base to amountbase
* Rename tx-hash to transaction-hash
* Rename id to transactionHash
* Rename objects/settings.json to objects/settings-plus-memos.json
* Rename ledgerversion to ledger-version
2018-08-22 14:41:41 -07:00
Elliot Lee
53a232ebdc Update docs 2018-08-14 20:05:50 -07:00
Elliot Lee
4c9a2ff538 Improve Order docs. Fix #776 2018-08-14 19:27:50 -07:00
Elliot Lee
dc623cd049 Release 1.0.0-beta.5 2018-08-11 01:38:36 -07:00
Elliot Lee
7cd517268b Fix error TS2307: Cannot find module 2018-08-11 01:35:47 -07:00
Elliot Lee
2438295e70 Release 1.0.0-beta.4 2018-08-10 14:58:19 -07:00
Elliot Lee
f5e1a4a588 Revert "Expose validation methods in public api"
This reverts commit 9e9a0a7d9b.

We should move methods like deriveKeypair and deriveAddress
off of the schemaValidator object.
2018-08-10 14:54:01 -07:00
Mo Morsi
9e9a0a7d9b Expose validation methods in public api
Updated to fix tests
2018-08-06 16:09:04 -07:00
Elliot Lee
1c68283d1e ES6: omit property value since it matches the variable name 2018-07-28 00:42:37 -07:00
Elliot Lee
28796d37cb Update TypeScript to 2.9.2 2018-07-28 00:18:58 -07:00
Elliot Lee
067bc48d4e Add prepareTransaction() (#898)
* Export iso8601ToRippleTime(), txFlags, convertStringToHex()

* Fix a bug that caused fees exceeding 999 to throw an error

e.g. '1,000' would not be recognized as a valid number.
To use 6 decimal places, toFixed should be used instead of toFormat.
2018-07-26 12:24:29 -07:00
Fred K. Schott
b94698df0b Update some API methods to use api.request() internally (#896)
* use any instead of object
2018-07-26 12:23:07 -07:00
Elliot Lee
4f40b5cb6d Update README.md - How to build ripple-lib (#837) 2018-07-25 12:09:55 -07:00
Elliot Lee
14704eee6b Add more tests of getFee (#897) 2018-07-25 01:53:27 -07:00
69 changed files with 2727 additions and 895 deletions

View File

@@ -1,5 +1,99 @@
# ripple-lib Release History
## 1.0.1 (2018-09-27)
+ Add address/secret/key validation and derivation methods ([#932](https://github.com/ripple/ripple-lib/pull/932))
+ `isValidAddress(address: string) : boolean`: Checks if the specified string contains a valid address.
+ `isValidSecret(secret: string): boolean`: Checks if the specified string contains a valid secret.
+ `deriveKeypair(seed: string): {privateKey: string, publicKey: string}`: Derive a public and private key from a seed.
+ `deriveAddress(publicKey: string): string`: Derive an XRP Ledger address from a public key.
+ To derive an address from a secret:
1. Derive the public key from the secret.
2. Derive the address from the public key.
+ Example: `const address = api.deriveAddress(api.deriveKeypair(secret).publicKey)`
+ Update server regex to accommodate UDS (#944)
+ Include memos when parsing trustlines (#949)
+ Add remaining LedgerEntry types (#943)
The SHA-256 checksums for the browser version of this release can be found
below.
```
% shasum -a 256 *
9b6408641ce83659afcd5765c256c35829a4fcb4c3244dc9ca6bf27c871a45c4 ripple-1.0.1-debug.js
7ab2b69fe59c2d4a74638116e2ba3b387155eb2d23e48a01bbf7beb72911f898 ripple-1.0.1-min.js
8bb4dcad9ce25a27003b1d73d71ddf41b8a5af02ece4ebbfeaff4aeb91f3b8c4 ripple-1.0.1.js
```
## 1.0.0 (2018-08-30)
We are pleased to announce the release of `ripple-lib` version 1.0.0.
This version features a range of changes and improvements that make the library
more capable and flexible. It includes new methods for accessing rippled APIs,
including subscriptions.
When using this version with `rippled` for online functionality, we recommend
using `rippled` version 1.0.1 or later.
Here is a summary of the changes since `ripple-lib` version 0.22.0, which was
the last non-beta version.
### New Features
+ [Add `request()`, `hasNextPage()`, and `requestNextPage()` for accessing `rippled`
APIs](https://github.com/ripple/ripple-lib/blob/09541dae86bc859bf5928ac65b2645dfaaf7f8b1/docs/index.md#rippled-apis).
+ Add `prepareTransaction()` for preparing raw `txJSON`.
+ XRP amounts can be specified in drops. Also, `xrpToDrops()` and `dropsToXrp()`
are available to make conversions.
+ `getTransaction` responses can include a new `channelChanges` property that
describes the details of a payment channel.
### Data Validation and Errors
+ [Amounts in drops and XRP are checked for
validity](https://github.com/ripple/ripple-lib/blob/develop/HISTORY.md#100-beta1-2018-05-24).
+ [A maximum fee is now
imposed](https://github.com/ripple/ripple-lib/blob/develop/HISTORY.md#100-beta2-2018-06-08). Exceeding it causes a `ValidationError` to be
thrown.
+ Errors are improved and more data validation was added.
+ Bug fix: `getPaths` now filters paths correctly and works correctly when the
destination currency is XRP.
### Breaking Changes
The following changes were introduced in 1.0.0.
+ `getTransaction()` and `getTransactions()`
+ The `specification.destination.amount` field has been removed from the parsed transaction response.
+ To determine the amount that a transaction delivered, use `outcome.deliveredAmount`.
+ If you require the provisional requested `Amount` from the original transaction:
+ Use `getTransaction`'s `includeRawTransaction` option, or
+ Use `getTransactions`'s `includeRawTransactions` option, or
+ Use the rippled APIs directly with `request`. For example, call the API methods `tx`, `account_tx`, etc.
+ `getLedger()` response object
+ The `rawTransactions` field has been removed (for consistency with `getTransaction()` and `getTransactions()`).
+ Instead, within each `transaction`, use the new `rawTransaction` JSON string.
+ The `metaData` field has been renamed to `meta` for consistency with rippled's `tx` method.
+ `ledger_index` has been added to each raw transaction.
The SHA-256 checksums for the browser version of this release can be found
below.
```
% shasum -a 256 *
06e5efcb6846ad45dedfd85cfa2ef4bdeb608b15ccbfb60b872c995d97342426 ripple-1.0.0-debug.js
cdb26b928a89ce228c727d1ff966df266eb46b2f76bd94f81cbeb0a9d75febf0 ripple-1.0.0-min.js
f74ee804e8a945a994e4e3901a0a3eb52292fbdcbff61ed30cefb8ffbcba50c3 ripple-1.0.0.js
```
## 1.0.0-beta.5 (2018-08-11)
+ [Fix a TypeScript error by importing the `Prepare` type](https://github.com/ripple/ripple-lib/commit/7cd517268bda5fe74b91dad02fedf8b51b7eae9b)
## 1.0.0-beta.4 (2018-08-10)
+ [Add `prepareTransaction()`](https://github.com/ripple/ripple-lib/pull/898)
+ Internal improvements and cleanup
## 1.0.0-beta.3 (2018-07-17)
+ For payment channel transactions, `getTransaction` includes a new

View File

@@ -28,7 +28,7 @@ $ yarn add ripple-lib
Then see the [documentation](https://github.com/ripple/ripple-lib/blob/develop/docs/index.md) and [code samples](https://github.com/ripple/ripple-lib/tree/develop/docs/samples).
### Mailing lists
### Mailing Lists
We have a low-traffic mailing list for announcements of new ripple-lib releases. (About 1 email per week)
@@ -38,11 +38,29 @@ If you're using the XRP Ledger in production, you should run a [rippled server](
+ [Subscribe to ripple-server](https://groups.google.com/forum/#!forum/ripple-server)
## Running tests
## Development
To build the library for Node.js:
```
$ yarn compile
```
The TypeScript compiler will [output](./tsconfig.json#L7) the resulting JS files in `./dist/npm/`.
To build the library for the browser:
```
$ yarn build
```
Gulp will [output](./Gulpfile.js) the resulting JS files in `./build/`.
For more details, see the `scripts` in `package.json`.
## Running Tests
1. Clone the repository
2. `cd` into the repository and install dependencies with `yarn install`
3. `yarn test` or `yarn test --coverage` (`istanbul` will create coverage reports in `coverage/lcov-report/`)
3. `yarn test`
## Generating Documentation

View File

@@ -76,6 +76,10 @@
- [combine](#combine)
- [submit](#submit)
- [generateAddress](#generateaddress)
- [isValidAddress](#isvalidaddress)
- [isValidSecret](#isvalidsecret)
- [deriveKeypair](#derivekeypair)
- [deriveAddress](#deriveaddress)
- [signPaymentChannelClaim](#signpaymentchannelclaim)
- [verifyPaymentChannelClaim](#verifypaymentchannelclaim)
- [computeLedgerHash](#computeledgerhash)
@@ -156,7 +160,7 @@ maxFeeXRP | string | *Optional* Maximum fee to use with transactions, in XRP. Mu
passphrase | string | *Optional* The passphrase for the private key of the client.
proxy | uri string | *Optional* URI for HTTP/HTTPS proxy to use to connect to the rippled server.
proxyAuthorization | string | *Optional* Username and password for HTTP basic authentication to the proxy in the format **username:password**.
server | uri string | *Optional* URI for rippled websocket port to connect to. Must start with `wss://` or `ws://`.
server | uri string | *Optional* URI for rippled websocket port to connect to. Must start with `wss://`, `ws://`, `wss+unix://`, or `ws+unix://`.
timeout | integer | *Optional* Timeout in milliseconds before considering a request to have failed.
trace | boolean | *Optional* If true, log rippled requests and responses to stdout.
trustedCertificates | array\<string\> | *Optional* Array of PEM-formatted SSL certificates to trust when connecting to a proxy. This is useful if you want to use a self-signed certificate on the proxy server. Note: Each element must contain a single certificate; concatenated certificates are not valid.
@@ -363,7 +367,7 @@ source | object | The source of the funds to be sent.
*source.* maxAmount | [laxAmount](#amount) | The maximum amount to send. (This field is exclusive with source.amount)
destination | object | The destination of the funds to be sent.
*destination.* address | [address](#address) | The address to receive at.
*destination.* amount | [laxAmount](#amount) | An exact amount to deliver to the recipient. If the counterparty is not specified, amounts with any counterparty may be used. (This field is exclusive with destination.minAmount).
*destination.* amount | [laxAmount](#amount) | An exact amount to deliver to the recipient. If the counterparty is not specified, amounts with any counterparty may be used. (This field cannot be used with `destination.minAmount`.)
*destination.* tag | integer | *Optional* An arbitrary unsigned 32-bit integer that identifies a reason for payment or a non-Ripple account.
*destination.* address | [address](#address) | The address to send to.
*destination.* minAmount | [laxAmount](#amount) | The minimum amount to be delivered. (This field is exclusive with destination.amount)
@@ -448,12 +452,14 @@ direction | string | Equal to "buy" for buy orders and "sell" for sell orders.
quantity | [amount](#amount) | The amount of currency to buy or sell.
totalPrice | [amount](#amount) | The total price to be paid for the `quantity` to be bought or sold.
expirationTime | date-time string | *Optional* Time after which the offer is no longer active, as an [ISO 8601 date-time](https://en.wikipedia.org/wiki/ISO_8601).
fillOrKill | boolean | *Optional* Treat the offer as a [Fill or Kill order](http://en.wikipedia.org/wiki/Fill_or_kill). Only attempt to match existing offers in the ledger, and only do so if the entire quantity can be exchanged.
immediateOrCancel | boolean | *Optional* Treat the offer as an [Immediate or Cancel order](http://en.wikipedia.org/wiki/Immediate_or_cancel). If enabled, the offer will never become a ledger node: it only attempts to match existing offers in the ledger.
fillOrKill | boolean | *Optional* Treat the offer as a [Fill or Kill order](http://en.wikipedia.org/wiki/Fill_or_kill). Only attempt to match existing offers in the ledger, and only do so if the entire quantity can be exchanged. This cannot be used with `immediateOrCancel`.
immediateOrCancel | boolean | *Optional* Treat the offer as an [Immediate or Cancel order](http://en.wikipedia.org/wiki/Immediate_or_cancel). If enabled, the offer will never become a ledger node: it only attempts to match existing offers in the ledger. This cannot be used with `fillOrKill`.
memos | [memos](#transaction-memos) | *Optional* Array of memos to attach to the transaction.
orderToReplace | [sequence](#account-sequence-number) | *Optional* The [account sequence number](#account-sequence-number) of an order to cancel before the new order is created, effectively replacing the old order.
passive | boolean | *Optional* If enabled, the offer will not consume offers that exactly match it, and instead becomes an Offer node in the ledger. It will still consume offers that cross it.
The following invalid flag combination causes a `ValidationError`: `immediateOrCancel` and `fillOrKill`. These fields are mutually exclusive, and cannot both be set at the same time.
### Example
@@ -761,11 +767,14 @@ ripple-lib relies on [rippled APIs](https://ripple.com/build/rippled-apis/) for
* Use `hasNextPage()` to determine whether a response has more pages. This is true when the response includes a [`marker` field](https://ripple.com/build/rippled-apis/#markers-and-pagination).
* Use `requestNextPage()` to request the next page of data.
When using rippled APIs, [specify XRP amounts in drops](https://ripple.com/build/rippled-apis/#specifying-currency-amounts). 1 XRP = 1000000 drops.
When using rippled APIs:
* [Specify XRP amounts in drops](https://developers.ripple.com/basic-data-types.html#specifying-currency-amounts).
* [Specify timestamps as the number of seconds since the "Ripple Epoch"](https://developers.ripple.com/basic-data-types.html#specifying-time).
* Instead of `counterparty`, use `issuer`.
## Listening to streams
The `rippled` server can push updates to your client when various events happen. Refer to [Subscriptions in the `rippled` API docs](https://ripple.com/build/rippled-apis/#subscriptions) for details.
The `rippled` server can push updates to your client when various events happen. Refer to [Subscriptions in the `rippled` API docs](https://developers.ripple.com/subscription-methods.html) for details.
Note that the `streams` parameter for generic streams takes an array. For example, to subscribe to the `validations` stream, use `{ streams: [ 'validations' ] }`.
@@ -1075,6 +1084,8 @@ return api.getServerInfo().then(info => {/* ... */});
Returns the estimated transaction fee for the rippled server the RippleAPI instance is connected to.
This will use the [feeCushion parameter](#parameters) provided to the RippleAPI constructor, or the default value of `1.2`.
### Parameters
Name | Type | Description
@@ -1083,7 +1094,7 @@ cushion | number | *Optional* The fee is the product of the base fee, the `load_
### Return Value
This method returns a promise that resolves with a string encoded floating point value representing the estimated fee to submit a transaction, expressed in XRP.
This method returns a promise that resolves with a string-encoded floating point value representing the estimated fee to submit a transaction, expressed in XRP.
### Example
@@ -1092,7 +1103,7 @@ return api.getFee().then(fee => {/* ... */});
```
```json
"0.012"
"0.000012"
```
## getLedgerVersion
@@ -1132,8 +1143,9 @@ Retrieves a transaction by its [Transaction ID](#transaction-id).
Name | Type | Description
---- | ---- | -----------
id | [id](#transaction-id) | A hash of a transaction used to identify the transaction, represented in hexadecimal.
options | object | *Optional* Options to limit the ledger versions to search.
id | [transactionHash](#transaction-id) | A hash of a transaction used to identify the transaction, represented in hexadecimal.
options | object | *Optional* Options to limit the ledger versions to search and/or to include raw transaction data.
*options.* includeRawTransaction | object | *Optional* Include raw transaction data. For advanced users; exercise caution when interpreting this data.
*options.* maxLedgerVersion | integer | *Optional* The highest ledger version to search
*options.* maxLedgerVersion | string | *Optional* The highest ledger version to search
*options.* minLedgerVersion | integer | *Optional* The lowest ledger version to search.
@@ -1145,11 +1157,11 @@ This method returns a promise that resolves with a transaction object containing
Name | Type | Description
---- | ---- | -----------
id | [id](#transaction-id) | A hash of the transaction that can be used to identify it.
id | [transactionHash](#transaction-id) | A hash of the transaction that can be used to identify it.
address | [address](#address) | The address of the account that initiated the transaction.
sequence | [sequence](#account-sequence-number) | The account sequence number of the transaction for the account that initiated it.
type | [transactionType](#transaction-types) | The type of the transaction.
specification | object | A specification that would produce the same outcome as this transaction. The structure of the specification depends on the value of the `type` field (see [Transaction Types](#transaction-types) for details). *Note:* This is **not** necessarily the same as the original specification.
specification | object | A specification that would produce the same outcome as this transaction. *Exception:* For payment transactions, this omits the `destination.amount` field, to prevent misunderstanding. The structure of the specification depends on the value of the `type` field (see [Transaction Types](#transaction-types) for details). *Note:* This is **not** necessarily the same as the original specification.
outcome | object | The outcome of the transaction (what effects it had).
*outcome.* result | string | Result code returned by rippled. See [Transaction Results](https://ripple.com/build/transactions/#full-transaction-response-list) for a complete list.
*outcome.* fee | [value](#value) | The XRP fee that was charged for the transaction.
@@ -1169,6 +1181,7 @@ outcome | object | The outcome of the transaction (what effects it had).
*outcome.* channelChanges | object | *Optional* Properties reflecting the details of the payment channel.
*outcome.* deliveredAmount | [amount](#amount) | *Optional* For payment transactions, it is impossible to reliably compute the actual delivered amount from the balanceChanges due to fixed precision. If the payment is not a partial payment and the transaction succeeded, the deliveredAmount should always be considered to be the amount specified in the transaction.
*outcome.* timestamp | date-time string | *Optional* The timestamp when the transaction was validated. (May be missing when requesting transactions in binary mode.)
rawTransaction | string | *Optional* The raw transaction data as a JSON string. For advanced users only; exercise caution when interpreting this data.
### Example
@@ -1195,11 +1208,7 @@ return api.getTransaction(id).then(transaction => {
}
},
"destination": {
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"amount": {
"currency": "USD",
"value": "0.001"
}
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"paths": "[[{\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"type\":48,\"type_hex\":\"0000000000000030\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"type\":49,\"type_hex\":\"0000000000000031\"}]]"
},
@@ -1292,6 +1301,7 @@ options | object | *Optional* Options to filter the resulting transactions.
*options.* counterparty | [address](#address) | *Optional* If provided, only return transactions with this account as a counterparty to the transaction.
*options.* earliestFirst | boolean | *Optional* If true, sort transactions so that the earliest ones come first. By default, the newest transactions will come first.
*options.* excludeFailures | boolean | *Optional* If true, the result will omit transactions that did not succeed.
*options.* includeRawTransactions | object | *Optional* Include raw transaction data. For advanced users; exercise caution when interpreting this data.
*options.* initiated | boolean | *Optional* If true, return only transactions initiated by the account specified by `address`. If false, return only transactions not initiated by the account specified by `address`.
*options.* limit | integer | *Optional* If specified, return at most this many transactions.
*options.* maxLedgerVersion | integer | *Optional* Return only transactions in this ledger version or lower.
@@ -1337,11 +1347,7 @@ return api.getTransactions(address).then(transaction => {
}
},
"destination": {
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"amount": {
"currency": "USD",
"value": "0.001"
}
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"paths": "[[{\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"}]]"
},
@@ -1434,11 +1440,7 @@ return api.getTransactions(address).then(transaction => {
}
},
"destination": {
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"amount": {
"currency": "USD",
"value": "0.001"
}
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"paths": "[[{\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"}]]"
},
@@ -1958,7 +1960,7 @@ source | object | Properties of the source of the payment.
*source.* maxAmount | [laxAmount](#amount) | The maximum amount to send. (This field is exclusive with source.amount)
destination | object | Properties of the destination of the payment.
*destination.* address | [address](#address) | The address to receive at.
*destination.* amount | [laxAmount](#amount) | An exact amount to deliver to the recipient. If the counterparty is not specified, amounts with any counterparty may be used. (This field is exclusive with destination.minAmount).
*destination.* amount | [laxAmount](#amount) | An exact amount to deliver to the recipient. If the counterparty is not specified, amounts with any counterparty may be used. (This field cannot be used with `destination.minAmount`.)
*destination.* tag | integer | *Optional* An arbitrary unsigned 32-bit integer that identifies a reason for payment or a non-Ripple account.
*destination.* address | [address](#address) | The address to send to.
*destination.* minAmount | [laxAmount](#amount) | The minimum amount to be delivered. (This field is exclusive with destination.amount)
@@ -4073,9 +4075,8 @@ parentCloseTime | date-time string | The time at which the previous ledger was c
totalDrops | [value](#value) | Total number of drops (1/1,000,000th of an XRP) in the network, as a quoted integer. (This decreases as transaction fees cause XRP to be destroyed.)
transactionHash | string | Hash of the transaction information included in this ledger.
rawState | string | *Optional* A JSON string containing all state data for this ledger in rippled JSON format.
rawTransactions | string | *Optional* A JSON string containing rippled format transaction JSON for all transactions that were validated in this ledger.
stateHashes | array\<string\> | *Optional* An array of hashes of all state data in this ledger.
transactionHashes | array\<[id](#transaction-id)\> | *Optional* An array of hashes of all transactions that were validated in this ledger.
transactionHashes | array\<[transactionHash](#transaction-id)\> | *Optional* An array of hashes of all transactions that were validated in this ledger.
transactions | array\<[getTransaction](#gettransaction)\> | *Optional* Array of all transactions that were validated in this ledger. Transactions are represented in the same format as the return value of [getTransaction](#gettransaction).
### Example
@@ -4439,6 +4440,12 @@ address | [address](#address) | The address of the account that is creating the
escrowCreation | [escrowCreation](#escrow-creation) | The specification of the escrow creation to prepare.
instructions | [instructions](#transaction-instructions) | *Optional* Instructions for executing the transaction
This is a convenience method for generating the EscrowCreate JSON used by rippled, so the same restrictions apply.
Field mapping: `allowCancelAfter` is equivalent to rippled's `CancelAfter`; `allowExecuteAfter` is equivalent to `FinishAfter`. At the `allowCancelAfter` time, the escrow is considered expired. This means that the funds can only be returned to the sender. At the `allowExecuteAfter` time, the escrow is permitted to be released to the recipient (if the `condition` is fulfilled).
Note that `allowCancelAfter` must be chronologically later than `allowExecuteAfter`.
### Return Value
This method returns a promise that resolves with an object with the following structure:
@@ -4967,7 +4974,7 @@ This method returns an object with the following structure:
Name | Type | Description
---- | ---- | -----------
signedTransaction | string | The signed transaction represented as an uppercase hexadecimal string.
id | [id](#transaction-id) | The [Transaction ID](#transaction-id) of the signed transaction.
id | [transactionHash](#transaction-id) | The [Transaction ID](#transaction-id) of the signed transaction.
### Example
@@ -5006,7 +5013,7 @@ This method returns an object with the following structure:
Name | Type | Description
---- | ---- | -----------
signedTransaction | string | The signed transaction represented as an uppercase hexadecimal string.
id | [id](#transaction-id) | The [Transaction ID](#transaction-id) of the signed transaction.
id | [transactionHash](#transaction-id) | The [Transaction ID](#transaction-id) of the signed transaction.
### Example
@@ -5101,6 +5108,88 @@ return api.generateAddress();
```
## isValidAddress
`isValidAddress(address: string): boolean`
Checks if the specified string contains a valid address.
### Parameters
This method takes one parameter, the address to validate.
### Return Value
This method returns `true` if the address is valid and `false` if it is not.
### Example
```javascript
return api.isValidAddress("address")
```
## isValidSecret
`isValidSecret(secret: string): boolean`
Checks if the specified string contains a valid secret.
### Parameters
This method takes one parameter, the secret which to validate.
### Return Value
This method returns `true` if the secret is valid and `false` if it is not.
### Example
```javascript
return api.isValidSecret("secret")
```
## deriveKeypair
`deriveKeypair(seed: string): {privateKey: string, publicKey: string}`
Derive a public and private key from a seed.
### Parameters
This method takes one parameter, the seed from which to derive the public and private key.
### Return Value
This method returns an object containing the public and private components of the keypair corresponding to the seed.
### Example
```javascript
var keypair = api.deriveKeypair(seed)
var public_key = keypair.publicKey;
var private_key = keypair.privateKey;
```
## deriveAddress
`deriveAddress(publicKey: string): string`
Derive an XRP Ledger address from a public key.
### Parameters
This method takes one parameter, the public key from which to derive the address.
### Return Value
This method returns a string corresponding to the address derived from the public key.
### Example
```javascript
var address = api.deriveAddress(public_key);
```
## signPaymentChannelClaim
`signPaymentChannelClaim(channel: string, amount: string, privateKey: string): string`
@@ -5206,9 +5295,8 @@ ledger | object | The ledger header to hash.
*ledger.* totalDrops | [value](#value) | Total number of drops (1/1,000,000th of an XRP) in the network, as a quoted integer. (This decreases as transaction fees cause XRP to be destroyed.)
*ledger.* transactionHash | string | Hash of the transaction information included in this ledger.
*ledger.* rawState | string | *Optional* A JSON string containing all state data for this ledger in rippled JSON format.
*ledger.* rawTransactions | string | *Optional* A JSON string containing rippled format transaction JSON for all transactions that were validated in this ledger.
*ledger.* stateHashes | array\<string\> | *Optional* An array of hashes of all state data in this ledger.
*ledger.* transactionHashes | array\<[id](#transaction-id)\> | *Optional* An array of hashes of all transactions that were validated in this ledger.
*ledger.* transactionHashes | array\<[transactionHash](#transaction-id)\> | *Optional* An array of hashes of all transactions that were validated in this ledger.
*ledger.* transactions | array\<[getTransaction](#gettransaction)\> | *Optional* Array of all transactions that were validated in this ledger. Transactions are represented in the same format as the return value of [getTransaction](#gettransaction).
### Return Value

View File

@@ -52,4 +52,4 @@ A *lax lax amount* allows either or both the counterparty and value to be omitte
A *balance* is an amount than can have a negative value.
<%- renderSchema('objects/amount-base.json') %>
<%- renderSchema('objects/amountbase.json') %>

View File

@@ -0,0 +1,19 @@
## deriveAddress
`deriveAddress(publicKey: string): string`
Derive an XRP Ledger address from a public key.
### Parameters
This method takes one parameter, the public key from which to derive the address.
### Return Value
This method returns a string corresponding to the address derived from the public key.
### Example
```javascript
var address = api.deriveAddress(public_key);
```

View File

@@ -0,0 +1,21 @@
## deriveKeypair
`deriveKeypair(seed: string): {privateKey: string, publicKey: string}`
Derive a public and private key from a seed.
### Parameters
This method takes one parameter, the seed from which to derive the public and private key.
### Return Value
This method returns an object containing the public and private components of the keypair corresponding to the seed.
### Example
```javascript
var keypair = api.deriveKeypair(seed)
var public_key = keypair.publicKey;
var private_key = keypair.privateKey;
```

View File

@@ -4,13 +4,15 @@
Returns the estimated transaction fee for the rippled server the RippleAPI instance is connected to.
This will use the [feeCushion parameter](#parameters) provided to the RippleAPI constructor, or the default value of `1.2`.
### Parameters
<%- renderSchema('input/get-fee.json') %>
### Return Value
This method returns a promise that resolves with a string encoded floating point value representing the estimated fee to submit a transaction, expressed in XRP.
This method returns a promise that resolves with a string-encoded floating point value representing the estimated fee to submit a transaction, expressed in XRP.
### Example
@@ -19,5 +21,5 @@ return api.getFee().then(fee => {/* ... */});
```
```json
"0.012"
"0.000012"
```

View File

@@ -46,6 +46,10 @@
<% include combine.md.ejs %>
<% include submit.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 %>

View File

@@ -0,0 +1,19 @@
## isValidAddress
`isValidAddress(address: string): boolean`
Checks if the specified string contains a valid address.
### Parameters
This method takes one parameter, the address to validate.
### Return Value
This method returns `true` if the address is valid and `false` if it is not.
### Example
```javascript
return api.isValidAddress("address")
```

View File

@@ -0,0 +1,19 @@
## isValidSecret
`isValidSecret(secret: string): boolean`
Checks if the specified string contains a valid secret.
### Parameters
This method takes one parameter, the secret which to validate.
### Return Value
This method returns `true` if the secret is valid and `false` if it is not.
### Example
```javascript
return api.isValidSecret("secret")
```

View File

@@ -8,6 +8,12 @@ Prepare an escrow creation transaction. The prepared transaction must subsequent
<%- renderSchema('input/prepare-escrow-creation.json') %>
This is a convenience method for generating the EscrowCreate JSON used by rippled, so the same restrictions apply.
Field mapping: `allowCancelAfter` is equivalent to rippled's `CancelAfter`; `allowExecuteAfter` is equivalent to `FinishAfter`. At the `allowCancelAfter` time, the escrow is considered expired. This means that the funds can only be returned to the sender. At the `allowExecuteAfter` time, the escrow is permitted to be released to the recipient (if the `condition` is fulfilled).
Note that `allowCancelAfter` must be chronologically later than `allowExecuteAfter`.
### Return Value
This method returns a promise that resolves with an object with the following structure:

View File

@@ -5,11 +5,14 @@ ripple-lib relies on [rippled APIs](https://ripple.com/build/rippled-apis/) for
* Use `hasNextPage()` to determine whether a response has more pages. This is true when the response includes a [`marker` field](https://ripple.com/build/rippled-apis/#markers-and-pagination).
* Use `requestNextPage()` to request the next page of data.
When using rippled APIs, [specify XRP amounts in drops](https://ripple.com/build/rippled-apis/#specifying-currency-amounts). 1 XRP = 1000000 drops.
When using rippled APIs:
* [Specify XRP amounts in drops](https://developers.ripple.com/basic-data-types.html#specifying-currency-amounts).
* [Specify timestamps as the number of seconds since the "Ripple Epoch"](https://developers.ripple.com/basic-data-types.html#specifying-time).
* Instead of `counterparty`, use `issuer`.
## Listening to streams
The `rippled` server can push updates to your client when various events happen. Refer to [Subscriptions in the `rippled` API docs](https://ripple.com/build/rippled-apis/#subscriptions) for details.
The `rippled` server can push updates to your client when various events happen. Refer to [Subscriptions in the `rippled` API docs](https://developers.ripple.com/subscription-methods.html) for details.
Note that the `streams` parameter for generic streams takes an array. For example, to subscribe to the `validations` stream, use `{ streams: [ 'validations' ] }`.

View File

@@ -28,6 +28,8 @@ See [Transaction Types](#transaction-types) for a description.
<%- renderSchema('specifications/order.json') %>
The following invalid flag combination causes a `ValidationError`: `immediateOrCancel` and `fillOrKill`. These fields are mutually exclusive, and cannot both be set at the same time.
### Example
<%- renderFixture('requests/prepare-order.json') %>

View File

@@ -1,6 +1,6 @@
{
"name": "ripple-lib",
"version": "1.0.0-beta.3",
"version": "1.0.1",
"license": "ISC",
"description": "A JavaScript API for interacting with Ripple in Node.js and the browser",
"files": [
@@ -53,7 +53,7 @@
"ts-node": "^3.3.0",
"tslint": "^5.8.0",
"tslint-eslint-rules": "^4.1.1",
"typescript": "^2.6.1",
"typescript": "2.9.2",
"uglifyjs-webpack-plugin": "^1.1.4",
"webpack": "^3.10.0",
"yargs": "^8.0.2"

View File

@@ -1,5 +1,13 @@
import {EventEmitter} from 'events'
import {Connection, errors, validate, xrpToDrops, dropsToXrp} from './common'
import {
Connection,
errors,
validate,
xrpToDrops,
dropsToXrp,
iso8601ToRippleTime,
txFlags
} from './common'
import {
connect,
disconnect,
@@ -37,6 +45,7 @@ import sign from './transaction/sign'
import combine from './transaction/combine'
import submit from './transaction/submit'
import {generateAddressAPI} from './offline/generate-address'
import {deriveKeypair, deriveAddress} from './offline/derive'
import computeLedgerHash from './offline/ledgerhash'
import signPaymentChannelClaim from './offline/sign-payment-channel-claim'
import verifyPaymentChannelClaim from './offline/verify-payment-channel-claim'
@@ -57,9 +66,11 @@ import {
import RangeSet from './common/rangeset'
import * as ledgerUtils from './ledger/utils'
import * as transactionUtils from './transaction/utils'
import * as schemaValidator from './common/schema-validator'
import {getServerInfo, getFee} from './common/serverinfo'
import {clamp} from './ledger/utils'
import {Instructions, Prepare} from './transaction/types'
export type APIOptions = {
server?: string,
@@ -97,7 +108,7 @@ class RippleAPI extends EventEmitter {
// these are exposed only for use by unit tests; they are not part of the API.
static _PRIVATE = {
validate: validate,
validate,
RangeSet,
ledgerUtils,
schemaValidator
@@ -131,19 +142,16 @@ class RippleAPI extends EventEmitter {
}
/**
* Makes a request to the API with the given command and
* additional request body parameters.
*/
async request(command: 'account_info', params: AccountInfoRequest):
Promise<AccountInfoResponse>
async request(command: 'account_lines', params: AccountLinesRequest):
Promise<AccountLinesResponse>
/**
* Returns objects owned by an account.
* For an account's trust lines and balances,
* see `getTrustlines` and `getBalances`.
*/
async request(command: 'account_objects', params: AccountObjectsRequest):
Promise<AccountObjectsResponse>
async request(command: 'account_offers', params: AccountOffersRequest):
Promise<AccountOffersResponse>
async request(command: 'book_offers', params: BookOffersRequest):
@@ -156,15 +164,9 @@ class RippleAPI extends EventEmitter {
Promise<LedgerEntryResponse>
async request(command: 'server_info', params?: ServerInfoRequest):
Promise<ServerInfoResponse>
async request(command: string, params: object):
Promise<object>
/**
* Makes a request to the API with the given command and
* additional request body parameters.
*/
async request(command: string, params: object = {}): Promise<object> {
async request(command: string, params: any):
Promise<any>
async request(command: string, params: any = {}): Promise<any> {
return this.connection.request({
...params,
command
@@ -199,6 +201,27 @@ class RippleAPI extends EventEmitter {
return this.request(command, nextPageParams)
}
/**
* Prepare a transaction.
*
* You can later submit the transaction with `submit()`.
*/
async prepareTransaction(txJSON: object, instructions: Instructions = {}):
Promise<Prepare> {
return transactionUtils.prepareTransaction(txJSON, this, instructions)
}
/**
* Convert a string to hex.
*
* This can be used to generate `MemoData`, `MemoType`, and `MemoFormat`.
*
* @param string string to convert to hex
*/
convertStringToHex(string: string): string {
return transactionUtils.convertStringToHex(string)
}
/**
* Makes multiple paged requests to the API to return a given number of
* resources. _requestAll() will make multiple requests until the `limit`
@@ -299,6 +322,8 @@ class RippleAPI extends EventEmitter {
submit = submit
generateAddress = generateAddressAPI
deriveKeypair = deriveKeypair
deriveAddress = deriveAddress
computeLedgerHash = computeLedgerHash
signPaymentChannelClaim = signPaymentChannelClaim
verifyPaymentChannelClaim = verifyPaymentChannelClaim
@@ -306,6 +331,11 @@ class RippleAPI extends EventEmitter {
xrpToDrops = xrpToDrops
dropsToXrp = dropsToXrp
iso8601ToRippleTime = iso8601ToRippleTime
txFlags = txFlags
isValidAddress = schemaValidator.isValidAddress
isValidSecret = schemaValidator.isValidSecret
}
export {

View File

@@ -70,7 +70,7 @@ class MissingLedgerHistoryError extends RippleError {
class PendingLedgerVersionError extends RippleError {
constructor(message?: string) {
super(message || 'maxLedgerVersion is greater than server\'s most recent ' +
super(message || 'maxLedgerVersion is greater than server\'s most recent' +
' validated ledger')
}
}

View File

@@ -9,13 +9,13 @@ function loadSchemas() {
// listed explicitly for webpack (instead of scanning schemas directory)
const schemas = [
require('./schemas/objects/tx-json.json'),
require('./schemas/objects/tx-type.json'),
require('./schemas/objects/transaction-type.json'),
require('./schemas/objects/hash128.json'),
require('./schemas/objects/hash256.json'),
require('./schemas/objects/sequence.json'),
require('./schemas/objects/signature.json'),
require('./schemas/objects/issue.json'),
require('./schemas/objects/ledgerversion.json'),
require('./schemas/objects/ledger-version.json'),
require('./schemas/objects/max-adjustment.json'),
require('./schemas/objects/memo.json'),
require('./schemas/objects/memos.json'),
@@ -31,21 +31,23 @@ function loadSchemas() {
require('./schemas/objects/min-adjustment.json'),
require('./schemas/objects/source-exact-adjustment.json'),
require('./schemas/objects/destination-exact-adjustment.json'),
require('./schemas/objects/tx-hash.json'),
require('./schemas/objects/destination-address-tag.json'),
require('./schemas/objects/transaction-hash.json'),
require('./schemas/objects/address.json'),
require('./schemas/objects/adjustment.json'),
require('./schemas/objects/quality.json'),
require('./schemas/objects/amount.json'),
require('./schemas/objects/amount-base.json'),
require('./schemas/objects/amountbase.json'),
require('./schemas/objects/balance.json'),
require('./schemas/objects/blob.json'),
require('./schemas/objects/currency.json'),
require('./schemas/objects/signed-value.json'),
require('./schemas/objects/orderbook.json'),
require('./schemas/objects/instructions.json'),
require('./schemas/objects/settings.json'),
require('./schemas/objects/settings-plus-memos.json'),
require('./schemas/specifications/settings.json'),
require('./schemas/specifications/payment.json'),
require('./schemas/specifications/get-payment.json'),
require('./schemas/specifications/escrow-cancellation.json'),
require('./schemas/specifications/order-cancellation.json'),
require('./schemas/specifications/order.json'),
@@ -158,5 +160,6 @@ function schemaValidate(schemaName: string, object: any): void {
export {
schemaValidate,
isValidSecret
isValidSecret,
isValidAddress
}

View File

@@ -18,9 +18,9 @@
},
"server": {
"type": "string",
"description": "URI for rippled websocket port to connect to. Must start with `wss://` or `ws://`.",
"description": "URI for rippled websocket port to connect to. Must start with `wss://`, `ws://`, `wss+unix://`, or `ws+unix://`.",
"format": "uri",
"pattern": "^wss?://"
"pattern": "^(wss?|wss?\\+unix)://"
},
"proxy": {
"format": "uri",

View File

@@ -4,9 +4,9 @@
"description": "Parameters for getTransaction",
"type": "object",
"properties": {
"id": {"$ref": "id"},
"id": {"$ref": "transactionHash"},
"options": {
"description": "Options to limit the ledger versions to search.",
"description": "Options to limit the ledger versions to search and/or to include raw transaction data.",
"properties": {
"minLedgerVersion": {
"$ref": "ledgerVersion",
@@ -15,6 +15,9 @@
"maxLedgerVersion": {
"$ref": "ledgerVersion",
"description": "The highest ledger version to search"
},
"includeRawTransaction": {
"description": "Include raw transaction data. For advanced users; exercise caution when interpreting this data. "
}
},
"additionalProperties": false

View File

@@ -49,6 +49,9 @@
"items": {"$ref": "transactionType"},
"description": "Only return transactions of the specified [Transaction Types](#transaction-types)."
},
"includeRawTransactions": {
"description": "Include raw transaction data. For advanced users; exercise caution when interpreting this data. "
},
"binary": {
"type": "boolean",
"description": "If true, the transactions will be sent from the server in a condensed binary format rather than JSON."

View File

@@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "amount",
"link": "amount",
"description": "An Amount on the Ripple Protocol",
"description": "An Amount on the XRP Ledger",
"allOf": [
{"$ref": "amountbase"},
{"required": ["value"]}

View File

@@ -0,0 +1,15 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "destinationAddressTag",
"description": "A destination address and optional tag, with no amount included. When parsing an incoming transaction, the original specification's amount is hidden to prevent misinterpretation. For the amount that the transaction delivered, see `outcome.deliveredAmount`.",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address to receive at."
},
"tag": {"$ref": "tag"}
},
"required": ["address"],
"additionalProperties": false
}

View File

@@ -9,7 +9,7 @@
},
"amount": {
"$ref": "laxAmount",
"description": "An exact amount to deliver to the recipient. If the counterparty is not specified, amounts with any counterparty may be used. (This field is exclusive with destination.minAmount)."
"description": "An exact amount to deliver to the recipient. If the counterparty is not specified, amounts with any counterparty may be used. (This field cannot be used with `destination.minAmount`.)"
},
"tag": {"$ref": "tag"}
},

View File

@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "id",
"title": "transactionHash",
"link": "transaction-id",
"description": "A hash of a transaction used to identify the transaction, represented in hexadecimal.",
"type": "string",

View File

@@ -55,15 +55,11 @@
"description": "A transaction in the same format as the return value of [getTransaction](#gettransaction)."
}
},
"rawTransactions": {
"type": "string",
"description": "A JSON string containing rippled format transaction JSON for all transactions that were validated in this ledger."
},
"transactionHashes": {
"description": "An array of hashes of all transactions that were validated in this ledger.",
"type": "array",
"items": {
"$ref": "id"
"$ref": "transactionHash"
}
},
"rawState": {

View File

@@ -1,20 +1,21 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "getTransaction",
"description": "getTransaction response",
"link": "gettransaction",
"properties": {
"type": {
"$ref": "transactionType"
},
"specification": {
"description": "A specification that would produce the same outcome as this transaction. The structure of the specification depends on the value of the `type` field (see [Transaction Types](#transaction-types) for details). *Note:* This is **not** necessarily the same as the original specification."
"description": "A specification that would produce the same outcome as this transaction. *Exception:* For payment transactions, this omits the `destination.amount` field, to prevent misunderstanding. The structure of the specification depends on the value of the `type` field (see [Transaction Types](#transaction-types) for details). *Note:* This is **not** necessarily the same as the original specification."
},
"outcome": {
"$ref": "outcome",
"description": "The outcome of the transaction (what effects it had)."
},
"id": {
"$ref": "id",
"$ref": "transactionHash",
"description": "A hash of the transaction that can be used to identify it."
},
"address": {
@@ -24,6 +25,10 @@
"sequence": {
"$ref": "sequence",
"description": "The account sequence number of the transaction for the account that initiated it."
},
"rawTransaction": {
"description": "The raw transaction data as a JSON string. For advanced users only; exercise caution when interpreting this data.",
"type": "string"
}
},
"required": [
@@ -44,7 +49,7 @@
]
},
"specification": {
"$ref": "payment"
"$ref": "getPayment"
}
}
},

View File

@@ -9,7 +9,7 @@
"description": "The signed transaction represented as an uppercase hexadecimal string."
},
"id": {
"$ref": "id",
"$ref": "transactionHash",
"description": "The [Transaction ID](#transaction-id) of the signed transaction."
}
},

View File

@@ -0,0 +1,39 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "getPayment",
"description": "A specification of a payment in a response for getTransaction or getTransactions.",
"type": "object",
"properties": {
"source": {
"$ref": "sourceAdjustment",
"description": "The source of the funds to be sent."
},
"destination": {
"$ref": "destinationAddressTag",
"description": "The destination of the funds to be sent. Since this is a payment response, the amount is not shown here. For the amount that the transaction delivered, see `outcome.deliveredAmount`."
},
"paths": {
"type": "string",
"description": "The paths of trustlines and orders to use in executing the payment."
},
"memos": {"$ref": "memos"},
"invoiceID": {
"description": "A 256-bit hash that can be used to identify a particular payment.",
"$ref": "hash256"
},
"allowPartialPayment": {
"description": "If true, this payment should proceed even if the whole amount cannot be delivered due to a lack of liquidity or a lack of funds in the source account.",
"type": "boolean"
},
"noDirectRipple": {
"description": "If true and paths are specified, the sender would like the XRP Ledger to disregard any direct paths from the source account to the destination account. This may be used to take advantage of an arbitrage opportunity or by gateways wishing to issue balances from a hot wallet to a user who has mistakenly set a trustline directly to the hot wallet.",
"type": "boolean"
},
"limitQuality": {
"description": "Only take paths where all the conversions have an input:output ratio that is equal or better than the ratio of destination.amount:source.maxAmount.",
"type": "boolean"
}
},
"required": ["source", "destination"],
"additionalProperties": false
}

View File

@@ -19,11 +19,11 @@
},
"immediateOrCancel": {
"type": "boolean",
"description": "Treat the offer as an [Immediate or Cancel order](http://en.wikipedia.org/wiki/Immediate_or_cancel). If enabled, the offer will never become a ledger node: it only attempts to match existing offers in the ledger."
"description": "Treat the offer as an [Immediate or Cancel order](http://en.wikipedia.org/wiki/Immediate_or_cancel). If enabled, the offer will never become a ledger node: it only attempts to match existing offers in the ledger. This cannot be used with `fillOrKill`."
},
"fillOrKill": {
"type": "boolean",
"description": "Treat the offer as a [Fill or Kill order](http://en.wikipedia.org/wiki/Fill_or_kill). Only attempt to match existing offers in the ledger, and only do so if the entire quantity can be exchanged."
"description": "Treat the offer as a [Fill or Kill order](http://en.wikipedia.org/wiki/Fill_or_kill). Only attempt to match existing offers in the ledger, and only do so if the entire quantity can be exchanged. This cannot be used with `immediateOrCancel`."
},
"passive": {
"description": "If enabled, the offer will not consume offers that exactly match it, and instead becomes an Offer node in the ledger. It will still consume offers that cross it.",

View File

@@ -61,6 +61,8 @@ function getServerInfo(this: RippleAPI): Promise<GetServerInfoResponse> {
})
}
// This is a public API that can be called directly.
// This is not used by the `prepare*` methods. See `src/transaction/utils.ts`
async function getFee(
this: RippleAPI,
cushion?: number
@@ -79,7 +81,7 @@ async function getFee(
// Cap fee to `this._maxFeeXRP`
fee = BigNumber.min(fee, this._maxFeeXRP)
// Round fee to 6 decimal places
return (new BigNumber(fee.toFormat(6))).toString(10)
return (new BigNumber(fee.toFixed(6))).toString(10)
}
export {

View File

@@ -1,4 +1,5 @@
import {SignerEntry} from './index'
import {Amount, RippledAmount} from './amounts'
export interface AccountRootLedgerEntry {
LedgerEntryType: 'AccountRoot',
@@ -44,6 +45,87 @@ export interface CheckLedgerEntry {
SourceTag: number
}
export interface DepositPreauthLedgerEntry {
LedgerEntryType: 'DepositPreauth',
Account: string,
Authorize: string,
OwnerNode: string,
PreviousTxnID: string,
PreviousTxnLgrSeq: number
}
export interface DirectoryNodeLedgerEntry {
LedgerEntryType: 'DirectoryNode',
Flags: number,
RootIndex: string,
Indexes: string[],
IndexNext?: number,
IndexPrevious?: number
}
export interface OfferDirectoryNodeLedgerEntry
extends DirectoryNodeLedgerEntry {
TakerPaysCurrency: string,
TakerPaysIssuer: string,
TakerGetsCurrency: string,
TakerGetsIssuer: string,
ExchangeRate?: number // DEPRECATED
}
export interface OwnerDirectoryNodeLedgerEntry
extends DirectoryNodeLedgerEntry {
Owner: string,
}
export interface EscrowLedgerEntry {
LedgerEntryType: 'Escrow',
Account: string,
Destination: string,
Amount: string,
Condition?: string,
CancelAfter?: number,
FinishAfter?: number,
Flags: number,
SourceTag?: number,
DestinationTag?: number,
OwnerNode: string,
DestinationNode?: string,
PreviousTxnID: string,
PreviousTxnLgrSeq: number
}
export interface FeeSettingsLedgerEntry {
LedgerEntryType: 'FeeSettings',
BaseFee: string,
ReferenceFeeUnits: number,
ReserveBase: number,
ReserveIncrement: number,
Flags: number
}
export interface LedgerHashesLedgerEntry {
LedgerEntryType: 'LedgerHashes',
Hashes: string[],
Flags: number,
FirstLedgerSequence?: number, // DEPRECATED
LastLedgerSequence?: number
}
export interface OfferLedgerEntry {
LedgerEntryType: 'Offer',
Flags: number,
Account: string,
Sequence: number,
TakerPays: RippledAmount,
TakerGets: RippledAmount,
BookDirectory: string,
BookNode: string,
OwnerNode: string,
PreviousTxnID: string,
PreviousTxnLgrSeq: number,
Expiration?: number
}
export interface PayChannelLedgerEntry {
LedgerEntryType: 'PayChannel',
Sequence: number,
@@ -63,6 +145,22 @@ export interface PayChannelLedgerEntry {
index: string
}
export interface RippleStateLedgerEntry {
LedgerEntryType: 'RippleState',
Flags: number,
Balance: Amount,
LowLimit: Amount,
HighLimit: Amount,
PreviousTxnID: string,
PreviousTxnLgrSeq: number,
LowNode?: string,
HighNode?: string,
LowQualityIn?: number,
LowQualityOut?: number,
HighQualityIn?: number,
HighQualityOut?: number
}
export interface SignerListLedgerEntry {
LedgerEntryType: 'SignerList',
OwnerNode: string,
@@ -73,11 +171,19 @@ export interface SignerListLedgerEntry {
PreviousTxnLgrSeq: number
}
// TODO: Add the other ledger entry types, then remove the `any` fallback
// see https://ripple.com/build/ledger-format/#ledger-object-types
export type LedgerEntry =
AccountRootLedgerEntry |
AmendmentsLedgerEntry |
CheckLedgerEntry |
DepositPreauthLedgerEntry |
DirectoryNodeLedgerEntry |
OfferDirectoryNodeLedgerEntry |
OwnerDirectoryNodeLedgerEntry |
EscrowLedgerEntry |
FeeSettingsLedgerEntry |
LedgerHashesLedgerEntry |
OfferLedgerEntry |
PayChannelLedgerEntry |
SignerListLedgerEntry |
any
RippleStateLedgerEntry |
SignerListLedgerEntry

View File

@@ -1,5 +1,8 @@
export {RippleAPI} from './api'
export {
FormattedTransactionType
} from './transaction/types'
// Broadcast api is experimental
export {RippleAPIBroadcast} from './broadcast'

View File

@@ -18,18 +18,18 @@ export type FormattedLedger = {
totalDrops: string,
transactionHash: string,
transactions?: Array<Object>,
rawTransactions?: string,
transactionHashes?: Array<string>,
rawState?: string,
stateHashes?: Array<string>
}
function parseTransactionWrapper(ledgerVersion, tx) {
// renames metaData to meta and adds ledger_index
const transaction = _.assign({}, _.omit(tx, 'metaData'), {
meta: tx.metaData,
ledger_index: ledgerVersion
})
const result = parseTransaction(transaction)
const result = parseTransaction(transaction, true)
if (!result.outcome.ledgerVersion) {
result.outcome.ledgerVersion = ledgerVersion
}
@@ -45,8 +45,7 @@ function parseTransactions(transactions, ledgerVersion) {
}
return {
transactions: _.map(transactions,
_.partial(parseTransactionWrapper, ledgerVersion)),
rawTransactions: JSON.stringify(transactions)
_.partial(parseTransactionWrapper, ledgerVersion))
}
}
@@ -62,19 +61,20 @@ function parseState(state) {
export function parseLedger(ledger: Ledger): FormattedLedger {
const ledgerVersion = parseInt(ledger.ledger_index || ledger.seqNum, 10)
return removeUndefined(Object.assign({
stateHash: ledger.account_hash,
closeTime: rippleTimeToISO8601(ledger.close_time),
closeTimeResolution: ledger.close_time_resolution,
closeFlags: ledger.close_flags,
ledgerHash: ledger.hash || ledger.ledger_hash,
ledgerVersion: ledgerVersion,
parentLedgerHash: ledger.parent_hash,
parentCloseTime: rippleTimeToISO8601(ledger.parent_close_time),
totalDrops: ledger.total_coins || ledger.totalCoins,
transactionHash: ledger.transaction_hash
},
parseTransactions(ledger.transactions, ledgerVersion),
parseState(ledger.accountState)
return removeUndefined(Object.assign(
{
stateHash: ledger.account_hash,
closeTime: rippleTimeToISO8601(ledger.close_time),
closeTimeResolution: ledger.close_time_resolution,
closeFlags: ledger.close_flags,
ledgerHash: ledger.hash || ledger.ledger_hash,
ledgerVersion: ledgerVersion,
parentLedgerHash: ledger.parent_hash,
parentCloseTime: rippleTimeToISO8601(ledger.parent_close_time),
totalDrops: ledger.total_coins || ledger.totalCoins,
transactionHash: ledger.transaction_hash
},
parseTransactions(ledger.transactions, ledgerVersion),
parseState(ledger.accountState)
))
}

View File

@@ -17,6 +17,7 @@ function removeGenericCounterparty(amount, address) {
_.omit(amount, 'counterparty') : amount
}
// Payment specification
function parsePayment(tx: any): Object {
assert(tx.TransactionType === 'Payment')
@@ -27,10 +28,13 @@ function parsePayment(tx: any): Object {
tag: tx.SourceTag
}
const destination = {
const destination: {
address: string,
tag: number | undefined
} = {
address: tx.Destination,
amount: removeGenericCounterparty(parseAmount(tx.Amount), tx.Destination),
tag: tx.DestinationTag
// Notice that `amount` is omitted to prevent misinterpretation
}
return removeUndefined({

View File

@@ -42,7 +42,7 @@ function parseTransactionType(type) {
return mapping[type] || null
}
function parseTransaction(tx: any): any {
function parseTransaction(tx: any, includeRawTransaction: boolean): any {
const type = parseTransactionType(tx.TransactionType)
const mapping = {
'payment': parsePayment,
@@ -72,7 +72,8 @@ function parseTransaction(tx: any): any {
sequence: tx.Sequence,
id: tx.hash,
specification: removeUndefined(specification),
outcome: outcome ? removeUndefined(outcome) : undefined
outcome: outcome ? removeUndefined(outcome) : undefined,
rawTransaction: includeRawTransaction ? JSON.stringify(tx) : undefined
})
}

View File

@@ -1,5 +1,5 @@
import * as assert from 'assert'
import {parseQuality} from './utils'
import {parseQuality, parseMemos} from './utils'
import {txFlags, removeUndefined} from '../../common'
const flags = txFlags.TrustSet
@@ -20,6 +20,7 @@ function parseTrustline(tx: any): Object {
limit: tx.LimitAmount.value,
currency: tx.LimitAmount.currency,
counterparty: tx.LimitAmount.issuer,
memos: parseMemos(tx),
qualityIn: parseQuality(tx.QualityIn),
qualityOut: parseQuality(tx.QualityOut),
ripplingDisabled: parseFlag(

View File

@@ -1,7 +1,13 @@
import * as _ from 'lodash'
import BigNumber from 'bignumber.js'
import {getXRPBalance, renameCounterpartyToIssuer} from './utils'
import {validate, toRippledAmount, errors} from '../common'
import {
validate,
toRippledAmount,
errors,
xrpToDrops,
dropsToXrp
} from '../common'
import {Connection} from '../common'
import parsePathfind from './parse/pathfind'
import {RippledAmount, Amount} from '../common/types/objects'
@@ -23,7 +29,11 @@ function addParams(request: PathFindRequest, result: RippledPathsResponse
function requestPathFind(connection: Connection, pathfind: PathFind
): Promise<RippledPathsResponse> {
const destinationAmount: Amount = _.assign(
{value: '-1'},
{
// This is converted back to drops by toRippledAmount()
value: pathfind.destination.amount.currency === 'XRP' ?
dropsToXrp('-1') : '-1'
},
pathfind.destination.amount
)
const request: PathFindRequest = {
@@ -95,13 +105,21 @@ function filterSourceFundsLowPaths(pathfind: PathFind,
): RippledPathsResponse {
if (pathfind.source.amount &&
pathfind.destination.amount.value === undefined && paths.alternatives) {
paths.alternatives = _.filter(paths.alternatives, alt =>
!!alt.source_amount &&
!!pathfind.source.amount &&
// TODO: Returns false when alt.source_amount is a string. Fix?
typeof alt.source_amount !== 'string' &&
new BigNumber(alt.source_amount.value).eq(pathfind.source.amount.value)
)
paths.alternatives = _.filter(paths.alternatives, alt => {
if (!alt.source_amount) {
return false
}
const pathfindSourceAmountValue = new BigNumber(
pathfind.source.amount.currency === 'XRP' ?
xrpToDrops(pathfind.source.amount.value) :
pathfind.source.amount.value)
const altSourceAmountValue = new BigNumber(
typeof alt.source_amount === 'string' ?
alt.source_amount :
alt.source_amount.value
)
return altSourceAmountValue.eq(pathfindSourceAmountValue)
})
}
return paths
}

View File

@@ -7,7 +7,8 @@ import {FormattedTransactionType} from '../transaction/types'
export type TransactionOptions = {
minLedgerVersion?: number,
maxLedgerVersion?: number
maxLedgerVersion?: number,
includeRawTransaction?: boolean
}
type TransactionResponse = FormattedTransactionType & {
hash: string,
@@ -18,7 +19,7 @@ type TransactionResponse = FormattedTransactionType & {
function attachTransactionDate(connection: Connection, tx: any
): Promise<FormattedTransactionType> {
): Promise<TransactionResponse> {
if (tx.date) {
return Promise.resolve(tx)
}
@@ -83,31 +84,25 @@ function convertError(connection: Connection, options: TransactionOptions,
function formatResponse(options: TransactionOptions, tx: TransactionResponse
): FormattedTransactionType {
if (tx.validated !== true || !isTransactionInRange(tx, options)) {
throw new errors.NotFoundError('Transaction not found')
throw new errors.NotFoundError('Transaction not found')
}
return parseTransaction(tx)
return parseTransaction(tx, options.includeRawTransaction)
}
function getTransaction(id: string, options: TransactionOptions = {}
async function getTransaction(id: string, options: TransactionOptions = {}
): Promise<FormattedTransactionType> {
validate.getTransaction({id, options})
const request = {
command: 'tx',
transaction: id,
binary: false
const _options = await utils.ensureLedgerVersion.call(this, options)
try {
const tx = await this.request('tx', {
transaction: id,
binary: false
})
const txWithDate = await attachTransactionDate(this.connection, tx)
return formatResponse(_options, txWithDate)
} catch (error) {
throw (await convertError(this.connection, _options, error))
}
return utils.ensureLedgerVersion.call(this, options).then(_options => {
return this.connection.request(request).then((tx: TransactionResponse) =>
attachTransactionDate(this.connection, tx)
).then(_.partial(formatResponse, _options))
.catch(error => {
return convertError(this.connection, _options, error).then(_error => {
throw _error
})
})
})
}
export default getTransaction

View File

@@ -18,6 +18,7 @@ export type TransactionsOptions = {
initiated?: boolean,
counterparty?: string,
types?: Array<string>,
includeRawTransactions?: boolean,
binary?: boolean,
startTx?: FormattedTransactionType
}
@@ -35,11 +36,11 @@ function parseBinaryTransaction(transaction) {
}
}
function parseAccountTxTransaction(tx) {
function parseAccountTxTransaction(tx, includeRawTransaction: boolean) {
const _tx = tx.tx_blob ? parseBinaryTransaction(tx) : tx
// rippled uses a different response format for 'account_tx' than 'tx'
return parseTransaction(_.assign({}, _tx.tx,
{meta: _tx.meta, validated: _tx.validated}))
{meta: _tx.meta, validated: _tx.validated}), includeRawTransaction)
}
function counterpartyFilter(filters, tx: FormattedTransactionType) {
@@ -87,11 +88,13 @@ function orderFilter(
function formatPartialResponse(address: string,
options: TransactionsOptions, data
) {
const parse = tx =>
parseAccountTxTransaction(tx, options.includeRawTransactions)
return {
marker: data.marker,
results: data.transactions
.filter(tx => tx.validated)
.map(parseAccountTxTransaction)
.map(parse)
.filter(_.partial(transactionFilter, address, options))
.filter(_.partial(orderFilter, options))
}

7
src/offline/derive.ts Normal file
View File

@@ -0,0 +1,7 @@
import {deriveKeypair, deriveAddress} from 'ripple-keypairs'
export {
deriveKeypair,
deriveAddress
}

View File

@@ -25,13 +25,33 @@ function hashLedgerHeader(ledgerHeader) {
return hashes.computeLedgerHash(header)
}
function computeTransactionHash(ledger, version) {
if (ledger.rawTransactions === undefined) {
function computeTransactionHash(ledger, version,
options: ComputeLedgerHashOptions) {
let transactions: any[]
if (ledger.rawTransactions) {
transactions = JSON.parse(ledger.rawTransactions)
} else if (ledger.transactions) {
try {
transactions = ledger.transactions.map(tx =>
JSON.parse(tx.rawTransaction))
} catch (e) {
if (e.toString() === 'SyntaxError: Unexpected' +
' token u in JSON at position 0') {
// one or more of the `tx.rawTransaction`s is undefined
throw new common.errors.ValidationError('ledger'
+ ' is missing raw transactions')
}
}
} else {
if (options.computeTreeHashes) {
throw new common.errors.ValidationError('transactions'
+ ' property is missing from the ledger')
}
return ledger.transactionHash
}
const transactions: any[] = JSON.parse(ledger.rawTransactions)
const txs = _.map(transactions, tx => {
const mergeTx = _.assign({}, _.omit(tx, 'tx'), tx.tx || {})
// rename `meta` back to `metaData`
const renameMeta = _.assign({}, _.omit(mergeTx, 'meta'),
tx.meta ? {metaData: tx.meta} : {})
return renameMeta
@@ -40,13 +60,21 @@ function computeTransactionHash(ledger, version) {
if (ledger.transactionHash !== undefined
&& ledger.transactionHash !== transactionHash) {
throw new common.errors.ValidationError('transactionHash in header'
+ ' does not match computed hash of transactions')
+ ' does not match computed hash of transactions', {
transactionHashInHeader: ledger.transactionHash,
computedHashOfTransactions: transactionHash
})
}
return transactionHash
}
function computeStateHash(ledger, version) {
function computeStateHash(ledger, version,
options: ComputeLedgerHashOptions) {
if (ledger.rawState === undefined) {
if (options.computeTreeHashes) {
throw new common.errors.ValidationError('rawState'
+ ' property is missing from the ledger')
}
return ledger.stateHash
}
const state = JSON.parse(ledger.rawState)
@@ -60,11 +88,16 @@ function computeStateHash(ledger, version) {
const sLCF_SHAMapV2 = 0x02
function computeLedgerHash(ledger: any): string {
export type ComputeLedgerHashOptions = {
computeTreeHashes?: boolean
}
function computeLedgerHash(ledger: any,
options: ComputeLedgerHashOptions = {}): string {
const version = ((ledger.closeFlags & sLCF_SHAMapV2) === 0) ? 1 : 2
const subhashes = {
transactionHash: computeTransactionHash(ledger, version),
stateHash: computeStateHash(ledger, version)
transactionHash: computeTransactionHash(ledger, version, options),
stateHash: computeStateHash(ledger, version, options)
}
return hashLedgerHeader(_.assign({}, ledger, subhashes))
}

View File

@@ -46,8 +46,8 @@ function createEscrowCreationTransaction(account: string,
}
if (Boolean(payment.allowCancelAfter) && Boolean(payment.allowExecuteAfter) &&
txJSON.CancelAfter <= txJSON.FinishAfter) {
throw new ValidationError('"CancelAfter" must be after "FinishAfter" for'
+ ' EscrowCreate')
throw new ValidationError('prepareEscrowCreation: ' +
'"allowCancelAfter" must be after "allowExecuteAfter"')
}
return txJSON
}

View File

@@ -7,6 +7,7 @@ const ValidationError = utils.common.errors.ValidationError
import {Instructions, Prepare} from './types'
import {Amount, Adjustment, MaxAdjustment,
MinAdjustment, Memo} from '../common/types/objects'
import {xrpToDrops} from '../common'
export interface Payment {
@@ -32,12 +33,12 @@ export interface Payment {
function isMaxAdjustment(
source: Adjustment | MaxAdjustment): source is MaxAdjustment {
return (source as MaxAdjustment).maxAmount !== undefined
return (source as MaxAdjustment).maxAmount !== undefined
}
function isMinAdjustment(
destination: Adjustment | MinAdjustment): destination is MinAdjustment {
return (destination as MinAdjustment).minAmount !== undefined
return (destination as MinAdjustment).minAmount !== undefined
}
function isXRPToXRPPayment(payment: Payment): boolean {
@@ -50,7 +51,7 @@ function isXRPToXRPPayment(payment: Payment): boolean {
}
function isIOUWithoutCounterparty(amount: Amount): boolean {
return amount && amount.currency !== 'XRP'
return amount && amount.currency !== 'XRP' && amount.currency !== 'drops'
&& amount.counterparty === undefined
}
@@ -72,7 +73,14 @@ function applyAnyCounterpartyEncoding(payment: Payment): void {
function createMaximalAmount(amount: Amount): Amount {
const maxXRPValue = '100000000000'
const maxIOUValue = '9999999999999999e80'
const maxValue = amount.currency === 'XRP' ? maxXRPValue : maxIOUValue
let maxValue
if (amount.currency === 'XRP') {
maxValue = maxXRPValue
} else if (amount.currency === 'drops') {
maxValue = xrpToDrops(maxXRPValue)
} else {
maxValue = maxIOUValue
}
return _.assign({}, amount, {value: maxValue})
}

View File

@@ -1,7 +1,12 @@
import * as _ from 'lodash'
import * as utils from './utils'
import {validate} from '../common'
import {Submit} from './types'
import {RippleAPI} from '..'
export interface FormattedSubmitResponse {
resultCode: string,
resultMessage: string
}
function isImmediateRejection(engineResult: string): boolean {
// note: "tel" errors mean the local server refused to process the
@@ -13,7 +18,7 @@ function isImmediateRejection(engineResult: string): boolean {
return _.startsWith(engineResult, 'tem')
}
function formatSubmitResponse(response) {
function formatSubmitResponse(response): FormattedSubmitResponse {
const data = {
resultCode: response.engine_result,
resultMessage: response.engine_result_message
@@ -24,14 +29,15 @@ function formatSubmitResponse(response) {
return data
}
function submit(signedTransaction: string): Promise<Submit> {
async function submit(
this: RippleAPI, signedTransaction: string
): Promise<FormattedSubmitResponse> {
// 1. Validate
validate.submit({signedTransaction})
const request = {
command: 'submit',
tx_blob: signedTransaction
}
return this.connection.request(request).then(formatSubmitResponse)
// 2. Make Request
const response = await this.request('submit', {tx_blob: signedTransaction})
// 3. Return Formatted Response
return formatSubmitResponse(response)
}
export default submit

View File

@@ -22,10 +22,10 @@ export type Instructions = {
export type Prepare = {
txJSON: string,
instructions: {
fee: string,
sequence: number,
maxLedgerVersion?: number
}
fee: string,
sequence: number,
maxLedgerVersion?: number
}
}
export type Submit = {

View File

@@ -94,19 +94,16 @@ function prepareTransaction(txJSON: any, api: RippleAPI,
})
}
function prepareSequence(): Promise<Object> {
async function prepareSequence(): Promise<Object> {
if (instructions.sequence !== undefined) {
txJSON.Sequence = instructions.sequence
return Promise.resolve(txJSON)
}
const request = {
command: 'account_info',
account: account
}
return api.connection.request(request).then(response => {
txJSON.Sequence = response.account_data.Sequence
return txJSON
const response = await api.request('account_info', {
account: account as string
})
txJSON.Sequence = response.account_data.Sequence
return txJSON
}
return Promise.all([

View File

@@ -270,6 +270,54 @@ describe('RippleAPI', function () {
}, /dropsToXrp:\ invalid\ value\ '\.\.\.'\,\ should\ be\ a\ number\ matching\ \(\^\-\?\[0\-9\]\*\.\?\[0\-9\]\*\$\)\./)
})
})
describe('isValidAddress', function () {
it('returns true for valid address', function () {
assert(this.api.isValidAddress('rLczgQHxPhWtjkaQqn3Q6UM8AbRbbRvs5K'));
})
it('returns false for invalid address', function () {
assert(!this.api.isValidAddress('foobar'));
})
})
describe('isValidSecret', function () {
it('returns true for valid secret', function () {
assert(this.api.isValidSecret('snsakdSrZSLkYpCXxfRkS4Sh96PMK'));
})
it('returns false for invalid secret', function () {
assert(!this.api.isValidSecret('foobar'));
})
})
describe('deriveKeypair', function () {
it('returns keypair for secret', function () {
var keypair = this.api.deriveKeypair('snsakdSrZSLkYpCXxfRkS4Sh96PMK');
assert.equal(keypair.privateKey, '008850736302221AFD59FF9CA1A29D4975F491D726249302EE48A3078A8934D335');
assert.equal(keypair.publicKey, '035332FBA71D705BD5D97014A833BE2BBB25BEFCD3506198E14AFEA241B98C2D06');
})
it('returns keypair for ed25519 secret', function () {
var keypair = this.api.deriveKeypair('sEdV9eHWbibBnTj7b1H5kHfPfv7gudx');
assert.equal(keypair.privateKey, 'ED5C2EF6C2E3200DFA6B72F47935C7F64D35453646EA34919192538F458C7BC30F');
assert.equal(keypair.publicKey, 'ED0805EC4E728DB87C0CA6C420751F296C57A5F42D02E9E6150CE60694A44593E5');
})
it('throws with an invalid secret', function (){
assert.throws(() => {
this.api.deriveKeypair('...');
}, /^Error\: Non\-base58 character$/)
})
})
describe('deriveAddress', function () {
it('returns address for public key', function () {
var address = this.api.deriveAddress('035332FBA71D705BD5D97014A833BE2BBB25BEFCD3506198E14AFEA241B98C2D06');
assert.equal(address, 'rLczgQHxPhWtjkaQqn3Q6UM8AbRbbRvs5K');
})
})
describe('pagination', function () {
describe('hasNextPage', function () {
@@ -404,6 +452,23 @@ describe('RippleAPI', function () {
}, /Fee of 2\.1 XRP exceeds max of 2 XRP\. To use this fee, increase `maxFeeXRP` in the RippleAPI constructor\./)
});
it('preparePayment - caps fee at 2 XRP by default', function () {
this.api._feeCushion = 1000000;
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\":\"2000000\",\"Sequence\":23}",
"instructions": {
"fee": "2",
"sequence": 23,
"maxLedgerVersion": 8820051
}
}
return this.api.preparePayment(
address, requests.preparePayment.normal, instructions).then(
_.partial(checkResult, expectedResponse, 'prepare'));
});
it('preparePayment - allows fee exceeding 2 XRP when maxFeeXRP is higher', function () {
this.api._maxFeeXRP = '2.2'
const localInstructions = _.defaults({
@@ -698,6 +763,384 @@ describe('RippleAPI', function () {
'prepare'));
});
describe('prepareTransaction - Payment', function () {
it('normal', function () {
const localInstructions = _.defaults({
maxFee: '0.000012'
}, instructions);
const txJSON = {
TransactionType: 'Payment',
Account: address,
Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo',
Amount: {
currency: 'USD',
issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM',
value: '0.01'
},
SendMax: {
currency: 'USD',
issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM',
value: '0.01'
},
Flags: 0
}
return this.api.prepareTransaction(txJSON, localInstructions).then(
_.partial(checkResult, responses.preparePayment.normal, 'prepare'));
});
// prepareTransaction - Payment
it('min amount xrp', function () {
const localInstructions = _.defaults({
maxFee: '0.000012'
}, instructions);
const txJSON = {
TransactionType: 'Payment',
Account: address,
Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo',
// Max amount to send. Use 100 billion XRP to
// ensure that we send the full SendMax amount.
Amount: '100000000000000000',
SendMax: {
currency: 'USD',
issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM',
value: '0.01'
},
DeliverMin: '10000',
Flags: this.api.txFlags.Payment.PartialPayment
}
return this.api.prepareTransaction(txJSON, localInstructions).then(
_.partial(checkResult,
responses.preparePayment.minAmountXRP, 'prepare'));
});
// prepareTransaction - Payment
it('min amount xrp2xrp', function () {
const txJSON = {
TransactionType: 'Payment',
Account: address,
Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo',
Amount: '10000',
Flags: 0
}
return this.api.prepareTransaction(txJSON, instructions).then(
_.partial(checkResult,
responses.preparePayment.minAmountXRPXRP, 'prepare'));
});
// prepareTransaction - Payment
it('with all options specified', function () {
return this.api.getLedgerVersion().then(ver => {
const localInstructions = {
maxLedgerVersion: ver + 100,
fee: '0.000012'
};
const txJSON = {
TransactionType: 'Payment',
Account: address,
Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo',
Amount: '10000',
InvoiceID: 'A98FD36C17BE2B8511AD36DC335478E7E89F06262949F36EB88E2D683BBCC50A',
SourceTag: 14,
DestinationTag: 58,
Memos: [
{
Memo: {
MemoType: this.api.convertStringToHex('test'),
MemoFormat: this.api.convertStringToHex('text/plain'),
MemoData: this.api.convertStringToHex('texted data')
}
}
],
Flags: 0 | this.api.txFlags.Payment.NoRippleDirect | this.api.txFlags.Payment.LimitQuality
}
return this.api.prepareTransaction(txJSON, localInstructions).then(
_.partial(checkResult,
responses.preparePayment.allOptions, 'prepare'));
});
});
// prepareTransaction - Payment
it('fee is capped at default maxFee of 2 XRP', function () {
this.api._feeCushion = 1000000;
const 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
}
const localInstructions = {
"maxLedgerVersion": 8820051
}
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\":\"2000000\",\"Sequence\":23}",
"instructions": {
"fee": "2",
"sequence": 23,
"maxLedgerVersion": 8820051
}
}
return this.api.prepareTransaction(txJSON, localInstructions).then(
_.partial(checkResult,
expectedResponse, 'prepare'));
});
// prepareTransaction - Payment
it('fee is capped to custom maxFeeXRP when maxFee exceeds maxFeeXRP', function () {
this.api._feeCushion = 1000000
this.api._maxFeeXRP = '3'
const localInstructions = _.defaults({
maxFee: '4' // We are testing that this does not matter; fee is still capped to maxFeeXRP
}, instructions);
const 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
}
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\":\"3000000\",\"Sequence\":23}",
"instructions": {
"fee": "3",
"sequence": 23,
"maxLedgerVersion": 8820051
}
}
return this.api.prepareTransaction(txJSON, localInstructions).then(
_.partial(checkResult,
expectedResponse, 'prepare'));
});
// prepareTransaction - Payment
it('fee is capped to maxFee', function () {
this.api._feeCushion = 1000000
this.api._maxFeeXRP = '5'
const localInstructions = _.defaults({
maxFee: '4' // maxFeeXRP does not matter if maxFee is lower than maxFeeXRP
}, instructions);
const 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,
}
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\":\"4000000\",\"Sequence\":23}",
"instructions": {
"fee": "4",
"sequence": 23,
"maxLedgerVersion": 8820051
}
}
return this.api.prepareTransaction(txJSON, localInstructions).then(
_.partial(checkResult,
expectedResponse, 'prepare'));
});
it('fee - calculated fee does not use more than 6 decimal places', function () {
this.api.connection._send(JSON.stringify({
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}",
"instructions": {
"fee": "0.064896",
"sequence": 23,
"maxLedgerVersion": 8820051
}
}
return this.api.preparePayment(
address, requests.preparePayment.normal, instructions).then(
_.partial(checkResult, expectedResponse, 'prepare'));
});
});
it('prepareTransaction - PaymentChannelCreate', function () {
const localInstructions = _.defaults({
maxFee: '0.000012'
}, instructions);
return this.api.prepareTransaction({
Account: address,
TransactionType: 'PaymentChannelCreate',
Amount: '1000000', // 1 XRP in drops. Use a string-encoded integer.
Destination: 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW',
SettleDelay: 86400,
PublicKey: '32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A'
// If cancelAfter is used, you must use RippleTime.
// You can use `iso8601ToRippleTime()` to convert to RippleTime.
// Other fields are available (but not used in this test),
// including `sourceTag` and `destinationTag`.
}, localInstructions).then(
_.partial(checkResult, responses.preparePaymentChannelCreate.normal,
'prepare'));
});
it('prepareTransaction - PaymentChannelCreate full', function () {
const txJSON = {
Account: address,
TransactionType: 'PaymentChannelCreate',
Amount: this.api.xrpToDrops('1'), // or '1000000'
Destination: 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW',
SettleDelay: 86400,
// Ensure this is in upper case if it is not already
PublicKey: '32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A'.toUpperCase(),
CancelAfter: this.api.iso8601ToRippleTime('2017-02-17T15:04:57Z'),
SourceTag: 11747,
DestinationTag: 23480
}
return this.api.prepareTransaction(txJSON).then(
_.partial(checkResult, responses.preparePaymentChannelCreate.full,
'prepare'));
});
it('prepareTransaction - PaymentChannelFund', function () {
const localInstructions = _.defaults({
maxFee: '0.000012'
}, instructions);
const txJSON = {
Account: address,
TransactionType: 'PaymentChannelFund',
Channel: 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198',
Amount: this.api.xrpToDrops('1') // or '1000000'
}
return this.api.prepareTransaction(txJSON, localInstructions).then(
_.partial(checkResult, responses.preparePaymentChannelFund.normal,
'prepare'));
});
it('prepareTransaction - PaymentChannelFund full', function () {
const txJSON = {
Account: address,
TransactionType: 'PaymentChannelFund',
Channel: 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198',
Amount: this.api.xrpToDrops('1'), // or '1000000'
Expiration: this.api.iso8601ToRippleTime('2017-02-17T15:04:57Z')
}
return this.api.prepareTransaction(txJSON).then(
_.partial(checkResult, responses.preparePaymentChannelFund.full,
'prepare'));
});
it('prepareTransaction - PaymentChannelClaim', function () {
const localInstructions = _.defaults({
maxFee: '0.000012'
}, instructions);
const txJSON = {
Account: address,
TransactionType: 'PaymentChannelClaim',
Channel: 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198',
Flags: 0
}
return this.api.prepareTransaction(txJSON, localInstructions).then(
_.partial(checkResult, responses.preparePaymentChannelClaim.normal,
'prepare'));
});
it('prepareTransaction - PaymentChannelClaim with renew', function () {
const localInstructions = _.defaults({
maxFee: '0.000012'
}, instructions);
const txJSON = {
Account: address,
TransactionType: 'PaymentChannelClaim',
Channel: 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198',
Balance: this.api.xrpToDrops('1'), // or '1000000'
Amount: this.api.xrpToDrops('1'), // or '1000000'
Signature: '30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B',
PublicKey: '32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A',
Flags: 0
}
txJSON.Flags |= this.api.txFlags.PaymentChannelClaim.Renew
return this.api.prepareTransaction(txJSON, localInstructions).then(
_.partial(checkResult, responses.preparePaymentChannelClaim.renew,
'prepare'));
});
it('prepareTransaction - PaymentChannelClaim with close', function () {
const localInstructions = _.defaults({
maxFee: '0.000012'
}, instructions);
const txJSON = {
Account: address,
TransactionType: 'PaymentChannelClaim',
Channel: 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198',
Balance: this.api.xrpToDrops('1'), // or 1000000
Amount: this.api.xrpToDrops('1'), // or 1000000
Signature: '30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B',
PublicKey: '32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A',
Flags: 0
}
txJSON.Flags |= this.api.txFlags.PaymentChannelClaim.Close
return this.api.prepareTransaction(txJSON, localInstructions).then(
_.partial(checkResult, responses.preparePaymentChannelClaim.close,
'prepare'));
});
it('preparePaymentChannelCreate', function () {
const localInstructions = _.defaults({
maxFee: '0.000012'
@@ -1052,6 +1495,17 @@ describe('RippleAPI', function () {
'getTransaction'));
});
it('getTransaction - payment - include raw transaction', function () {
const options = {
includeRawTransaction: true
}
return this.api.getTransaction(
hashes.VALID_TRANSACTION_HASH, options
).then(
_.partial(checkResult, responses.getTransaction.paymentIncludeRawTransaction,
'getTransaction'));
});
it('getTransaction - settings', function () {
const hash =
'4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA1B';
@@ -1060,6 +1514,19 @@ describe('RippleAPI', function () {
'getTransaction'));
});
it('getTransaction - settings - include raw transaction', function () {
const hash =
'4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA1B';
const options = {
includeRawTransaction: true
}
const expected = responses.getTransaction.settings
expected.rawTransaction = "{\"Account\":\"rLVKsA4F9iJBbA6rX2x4wCmkj6drgtqpQe\",\"Fee\":\"10\",\"Flags\":2147483648,\"Sequence\":1,\"SetFlag\":2,\"SigningPubKey\":\"03EA3ADCA632F125EC2CC4F7F6A82DE0DCE2B65290CAC1F22242C5163F0DA9652D\",\"TransactionType\":\"AccountSet\",\"TxnSignature\":\"3045022100DE8B666B1A31EA65011B0F32130AB91A5747E32FA49B3054CEE8E8362DBAB98A022040CF0CF254677A8E5CD04C59CA2ED7F6F15F7E184641BAE169C561650967B226\",\"date\":460832270,\"hash\":\"4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA1B\",\"inLedger\":8206418,\"ledger_index\":8206418,\"meta\":{\"AffectedNodes\":[{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"rLVKsA4F9iJBbA6rX2x4wCmkj6drgtqpQe\",\"Balance\":\"29999990\",\"Flags\":786432,\"OwnerCount\":0,\"Sequence\":2},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"3F5072C4875F32ED770DAF3610A716600ED7C7BB0348FADC7A98E011BB2CD36F\",\"PreviousFields\":{\"Balance\":\"30000000\",\"Flags\":4194304,\"Sequence\":1},\"PreviousTxnID\":\"3FB0350A3742BBCC0D8AA3C5247D1AEC01177D0A24D9C34762BAA2FEA8AD88B3\",\"PreviousTxnLgrSeq\":8206397}}],\"TransactionIndex\":5,\"TransactionResult\":\"tesSUCCESS\"},\"validated\":true}"
return this.api.getTransaction(hash, options).then(
_.partial(checkResult, expected,
'getTransaction'));
});
it('getTransaction - order', function () {
const hash =
'10A6FB4A66EE80BED46AAE4815D7DC43B97E944984CCD5B93BCF3F8538CABC51';
@@ -1120,6 +1587,14 @@ describe('RippleAPI', function () {
'getTransaction'));
});
it('getTransaction - trustline add memo', function () {
const hash =
'9D6AC5FD6545B2584885B85E36759EB6440CDD41B6C55859F84AFDEE2B428220';
return this.api.getTransaction(hash).then(
_.partial(checkResult, responses.getTransaction.trustlineAddMemo,
'getTransaction'));
});
it('getTransaction - not validated', function () {
const hash =
'4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA10';
@@ -1210,6 +1685,8 @@ describe('RippleAPI', function () {
assert(false, 'Should throw PendingLedgerVersionError');
}).catch(error => {
assert(error instanceof this.api.errors.PendingLedgerVersionError);
assert.strictEqual(error.message, 'maxLedgerVersion is greater than server\'s'
+ ' most recent validated ledger')
});
});
@@ -1387,6 +1864,18 @@ describe('RippleAPI', function () {
'getTransactions'));
});
it('getTransactions - include raw transactions', function () {
const options = {
types: ['payment', 'order'],
initiated: true,
limit: 2,
includeRawTransactions: true
};
return this.api.getTransactions(address, options).then(
_.partial(checkResult, responses.getTransactions.includeRawTransactions,
'getTransactions'));
});
it('getTransactions - earliest first', function () {
const options = {
types: ['payment', 'order'], initiated: true, limit: 2,
@@ -1774,7 +2263,21 @@ describe('RippleAPI', function () {
assert.strictEqual(fee, '2');
});
});
it('getFee - high load_factor with custom maxFeeXRP', function () {
// Ensure that overriding with high maxFeeXRP of '51540' causes no errors.
// (fee will actually be 51539.607552)
this.api._maxFeeXRP = '51540'
this.api.connection._send(JSON.stringify({
command: 'config',
data: { highLoadFactor: true }
}));
return this.api.getFee().then(fee => {
assert.strictEqual(fee, '51539.607552');
});
});
it('fee - default maxFee of 2 XRP', function () {
this.api._feeCushion = 1000000;
@@ -1853,6 +2356,23 @@ describe('RippleAPI', function () {
address, requests.preparePayment.normal, instructions).then(
_.partial(checkResult, expectedResponse, 'prepare'));
});
it('getFee custom cushion', function () {
this.api._feeCushion = 1.4;
return this.api.getFee().then(fee => {
assert.strictEqual(fee, '0.000014');
});
});
// This is not recommended since it may result in attempting to pay
// less than the base fee. However, this test verifies
// the existing behavior.
it('getFee cushion less than 1.0', function () {
this.api._feeCushion = 0.9;
return this.api.getFee().then(fee => {
assert.strictEqual(fee, '0.000009');
});
});
it('disconnect & isConnected', function () {
assert.strictEqual(this.api.isConnected(), true);
@@ -1866,6 +2386,45 @@ describe('RippleAPI', function () {
_.partial(checkResult, responses.getPaths.XrpToUsd, 'getPaths'));
});
it('getPaths - result path has source_amount in drops', function () {
return this.api.getPaths({
source: {
address: 'rB2NTuTTS3eNCsWxZYzJ4wqRqxNLZqA9Vx',
amount: {
value: this.api.dropsToXrp(1000000),
currency: 'XRP'
}
},
destination: {
address: 'rhpJkBfZGQyT1xeDbwtKEuSrSXw3QZSAy5',
amount: {
counterparty: 'rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u',
currency: 'EUR'
}
}
}).then(
_.partial(checkResult, [
{
"source": {
"address": "rB2NTuTTS3eNCsWxZYzJ4wqRqxNLZqA9Vx",
"amount": {
"currency": "XRP",
"value": "1"
}
},
"destination": {
"address": "rhpJkBfZGQyT1xeDbwtKEuSrSXw3QZSAy5",
"minAmount": {
"currency": "EUR",
"value": "1",
"counterparty": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u"
}
},
"paths": "[[{\"currency\":\"USD\",\"issuer\":\"rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u\"},{\"currency\":\"EUR\",\"issuer\":\"rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u\"}]]"
}
], 'getPaths'));
});
it('getPaths - queuing', function () {
return Promise.all([
this.api.getPaths(requests.getPaths.normal),
@@ -1987,8 +2546,6 @@ describe('RippleAPI', function () {
_.partial(checkResult, responses.getLedger.header, 'getLedger'));
});
// New in > 0.21.0
// future ledger versions are allowed, and passed to rippled as-is.
it('getLedger - future ledger version', function () {
return this.api.getLedger({ ledgerVersion: 14661789 }).then(response => {
assert(response)
@@ -2021,7 +2578,7 @@ describe('RippleAPI', function () {
const request = {
includeTransactions: true,
includeAllData: true,
ledgerVersion: 100000
ledgerVersion: 22420574
};
return this.api.getLedger(request).then(
_.partial(checkResult, responses.getLedger.withPartial, 'getLedger'));
@@ -2051,12 +2608,112 @@ describe('RippleAPI', function () {
.then(response => {
const ledger = _.assign({}, response,
{ parentCloseTime: response.closeTime });
const hash = this.api.computeLedgerHash(ledger);
const hash = this.api.computeLedgerHash(ledger, {computeTreeHashes: true});
assert.strictEqual(hash,
'E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E');
});
});
it('computeLedgerHash - given corrupt data - should fail', function () {
const request = {
includeTransactions: true,
includeState: true,
includeAllData: true,
ledgerVersion: 38129
};
return this.api.getLedger(request).then(ledger => {
assert.strictEqual(ledger.transactions[0].rawTransaction, "{\"Account\":\"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV\",\"Amount\":\"10000000000\",\"Destination\":\"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj\",\"Fee\":\"10\",\"Flags\":0,\"Sequence\":62,\"SigningPubKey\":\"034AADB09CFF4A4804073701EC53C3510CDC95917C2BB0150FB742D0C66E6CEE9E\",\"TransactionType\":\"Payment\",\"TxnSignature\":\"3045022022EB32AECEF7C644C891C19F87966DF9C62B1F34BABA6BE774325E4BB8E2DD62022100A51437898C28C2B297112DF8131F2BB39EA5FE613487DDD611525F1796264639\",\"hash\":\"3B1A4E1C9BB6A7208EB146BCDB86ECEA6068ED01466D933528CA2B4C64F753EF\",\"meta\":{\"AffectedNodes\":[{\"CreatedNode\":{\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"4C6ACBD635B0F07101F7FA25871B0925F8836155462152172755845CE691C49E\",\"NewFields\":{\"Account\":\"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj\",\"Balance\":\"10000000000\",\"Sequence\":1}}},{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV\",\"Balance\":\"981481999380\",\"Flags\":0,\"OwnerCount\":0,\"Sequence\":63},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"B33FDD5CF3445E1A7F2BE9B06336BEBD73A5E3EE885D3EF93F7E3E2992E46F1A\",\"PreviousFields\":{\"Balance\":\"991481999390\",\"Sequence\":62},\"PreviousTxnID\":\"2485FDC606352F1B0785DA5DE96FB9DBAF43EB60ECBB01B7F6FA970F512CDA5F\",\"PreviousTxnLgrSeq\":31317}}],\"TransactionIndex\":0,\"TransactionResult\":\"tesSUCCESS\"},\"ledger_index\":38129}");
// Change Amount to 12000000000
ledger.transactions[0].rawTransaction = "{\"Account\":\"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV\",\"Amount\":\"12000000000\",\"Destination\":\"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj\",\"Fee\":\"10\",\"Flags\":0,\"Sequence\":62,\"SigningPubKey\":\"034AADB09CFF4A4804073701EC53C3510CDC95917C2BB0150FB742D0C66E6CEE9E\",\"TransactionType\":\"Payment\",\"TxnSignature\":\"3045022022EB32AECEF7C644C891C19F87966DF9C62B1F34BABA6BE774325E4BB8E2DD62022100A51437898C28C2B297112DF8131F2BB39EA5FE613487DDD611525F1796264639\",\"hash\":\"3B1A4E1C9BB6A7208EB146BCDB86ECEA6068ED01466D933528CA2B4C64F753EF\",\"meta\":{\"AffectedNodes\":[{\"CreatedNode\":{\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"4C6ACBD635B0F07101F7FA25871B0925F8836155462152172755845CE691C49E\",\"NewFields\":{\"Account\":\"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj\",\"Balance\":\"10000000000\",\"Sequence\":1}}},{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV\",\"Balance\":\"981481999380\",\"Flags\":0,\"OwnerCount\":0,\"Sequence\":63},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"B33FDD5CF3445E1A7F2BE9B06336BEBD73A5E3EE885D3EF93F7E3E2992E46F1A\",\"PreviousFields\":{\"Balance\":\"991481999390\",\"Sequence\":62},\"PreviousTxnID\":\"2485FDC606352F1B0785DA5DE96FB9DBAF43EB60ECBB01B7F6FA970F512CDA5F\",\"PreviousTxnLgrSeq\":31317}}],\"TransactionIndex\":0,\"TransactionResult\":\"tesSUCCESS\"},\"ledger_index\":38129}";
ledger.parentCloseTime = ledger.closeTime;
let hash;
try {
hash = this.api.computeLedgerHash(ledger, {computeTreeHashes: true});
} catch (error) {
assert(error instanceof this.api.errors.ValidationError);
assert.strictEqual(error.message, 'transactionHash in header does not match computed hash of transactions');
assert.deepStrictEqual(error.data, {
transactionHashInHeader: 'DB83BF807416C5B3499A73130F843CF615AB8E797D79FE7D330ADF1BFA93951A',
computedHashOfTransactions: 'EAA1ADF4D627339450F0E95EA88B7069186DD64230BAEBDCF3EEC4D616A9FC68'
});
return;
}
assert(false, 'Should throw ValidationError instead of producing hash: ' + hash);
});
});
it('computeLedgerHash - given ledger without raw transactions - should throw', function () {
const request = {
includeTransactions: true,
includeState: true,
includeAllData: true,
ledgerVersion: 38129
};
return this.api.getLedger(request).then(ledger => {
assert.strictEqual(ledger.transactions[0].rawTransaction, "{\"Account\":\"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV\",\"Amount\":\"10000000000\",\"Destination\":\"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj\",\"Fee\":\"10\",\"Flags\":0,\"Sequence\":62,\"SigningPubKey\":\"034AADB09CFF4A4804073701EC53C3510CDC95917C2BB0150FB742D0C66E6CEE9E\",\"TransactionType\":\"Payment\",\"TxnSignature\":\"3045022022EB32AECEF7C644C891C19F87966DF9C62B1F34BABA6BE774325E4BB8E2DD62022100A51437898C28C2B297112DF8131F2BB39EA5FE613487DDD611525F1796264639\",\"hash\":\"3B1A4E1C9BB6A7208EB146BCDB86ECEA6068ED01466D933528CA2B4C64F753EF\",\"meta\":{\"AffectedNodes\":[{\"CreatedNode\":{\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"4C6ACBD635B0F07101F7FA25871B0925F8836155462152172755845CE691C49E\",\"NewFields\":{\"Account\":\"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj\",\"Balance\":\"10000000000\",\"Sequence\":1}}},{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV\",\"Balance\":\"981481999380\",\"Flags\":0,\"OwnerCount\":0,\"Sequence\":63},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"B33FDD5CF3445E1A7F2BE9B06336BEBD73A5E3EE885D3EF93F7E3E2992E46F1A\",\"PreviousFields\":{\"Balance\":\"991481999390\",\"Sequence\":62},\"PreviousTxnID\":\"2485FDC606352F1B0785DA5DE96FB9DBAF43EB60ECBB01B7F6FA970F512CDA5F\",\"PreviousTxnLgrSeq\":31317}}],\"TransactionIndex\":0,\"TransactionResult\":\"tesSUCCESS\"},\"ledger_index\":38129}");
// Delete rawTransaction
delete ledger.transactions[0].rawTransaction;
ledger.parentCloseTime = ledger.closeTime;
let hash;
try {
hash = this.api.computeLedgerHash(ledger, {computeTreeHashes: true});
} catch (error) {
assert(error instanceof this.api.errors.ValidationError);
assert.strictEqual(error.message, 'ledger'
+ ' is missing raw transactions');
return;
}
assert(false, 'Should throw ValidationError instead of producing hash: ' + hash);
});
});
it('computeLedgerHash - given ledger without state or transactions - only compute ledger hash', function () {
const request = {
includeTransactions: true,
includeState: true,
includeAllData: true,
ledgerVersion: 38129
};
return this.api.getLedger(request).then(ledger => {
assert.strictEqual(ledger.transactions[0].rawTransaction, "{\"Account\":\"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV\",\"Amount\":\"10000000000\",\"Destination\":\"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj\",\"Fee\":\"10\",\"Flags\":0,\"Sequence\":62,\"SigningPubKey\":\"034AADB09CFF4A4804073701EC53C3510CDC95917C2BB0150FB742D0C66E6CEE9E\",\"TransactionType\":\"Payment\",\"TxnSignature\":\"3045022022EB32AECEF7C644C891C19F87966DF9C62B1F34BABA6BE774325E4BB8E2DD62022100A51437898C28C2B297112DF8131F2BB39EA5FE613487DDD611525F1796264639\",\"hash\":\"3B1A4E1C9BB6A7208EB146BCDB86ECEA6068ED01466D933528CA2B4C64F753EF\",\"meta\":{\"AffectedNodes\":[{\"CreatedNode\":{\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"4C6ACBD635B0F07101F7FA25871B0925F8836155462152172755845CE691C49E\",\"NewFields\":{\"Account\":\"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj\",\"Balance\":\"10000000000\",\"Sequence\":1}}},{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV\",\"Balance\":\"981481999380\",\"Flags\":0,\"OwnerCount\":0,\"Sequence\":63},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"B33FDD5CF3445E1A7F2BE9B06336BEBD73A5E3EE885D3EF93F7E3E2992E46F1A\",\"PreviousFields\":{\"Balance\":\"991481999390\",\"Sequence\":62},\"PreviousTxnID\":\"2485FDC606352F1B0785DA5DE96FB9DBAF43EB60ECBB01B7F6FA970F512CDA5F\",\"PreviousTxnLgrSeq\":31317}}],\"TransactionIndex\":0,\"TransactionResult\":\"tesSUCCESS\"},\"ledger_index\":38129}");
ledger.parentCloseTime = ledger.closeTime;
const computeLedgerHash = this.api.computeLedgerHash;
const ValidationError = this.api.errors.ValidationError
function testCompute(ledger, expectedError) {
let hash = computeLedgerHash(ledger);
assert.strictEqual(hash,
'E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E');
// fail if required to compute tree hashes
try {
hash = computeLedgerHash(ledger, {computeTreeHashes: true});
} catch (error) {
assert(error instanceof ValidationError);
assert.strictEqual(error.message, expectedError);
return;
}
assert(false, 'Should throw ValidationError instead of producing hash: ' + hash);
}
const transactions = ledger.transactions;
delete ledger.transactions;
testCompute(ledger, 'transactions property is missing from the ledger');
delete ledger.rawState;
testCompute(ledger, 'transactions property is missing from the ledger');
ledger.transactions = transactions;
testCompute(ledger, 'rawState property is missing from the ledger');
});
});
it('computeLedgerHash - wrong hash', function () {
const request = {
includeTransactions: true,

View File

@@ -24,6 +24,5 @@
],
"invoiceID": "A98FD36C17BE2B8511AD36DC335478E7E89F06262949F36EB88E2D683BBCC50A",
"noDirectRipple": true,
"limitQuality": true,
"paths": "[[{\"account\":\"rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q\",\"currency\":\"USD\",\"issuer\":\"rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q\",\"type\":49,\"type_hex\":\"0000000000000031\"},{\"currency\":\"LTC\",\"issuer\":\"rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX\",\"type\":48,\"type_hex\":\"0000000000000030\"},{\"account\":\"rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX\",\"currency\":\"LTC\",\"issuer\":\"rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX\",\"type\":49,\"type_hex\":\"0000000000000031\"}]]"
"limitQuality": true
}

View File

@@ -3,8 +3,7 @@
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"amount": {
"value": "0.01",
"currency": "XRP",
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
"currency": "XRP"
}
},
"destination": {

File diff suppressed because one or more lines are too long

View File

@@ -25,12 +25,7 @@
}
},
"destination": {
"address": "rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4",
"amount": {
"currency": "USD",
"value": "10",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
"address": "rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4"
},
"allowPartialPayment": true
},
@@ -72,8 +67,8 @@
"orderbookChanges": {},
"ledgerVersion": 12345,
"indexInLedger": 1
}
},
"rawTransaction": "{\"Account\":\"rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX\",\"Amount\":{\"currency\":\"USD\",\"issuer\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\",\"value\":\"10\"},\"Destination\":\"rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4\",\"Fee\":\"10000\",\"Flags\":131072,\"Sequence\":23295,\"SigningPubKey\":\"02B205F4B92351AC0EEB04254B636F4C49EF922CFA3CAAD03C6477DA1E04E94B53\",\"TransactionType\":\"Payment\",\"TxnSignature\":\"3045022100FAF247A836D601DE74A515B2AADE31186D8B0DA9C23DE489E09753F5CF4BB81F0220477C5B5BC3AC89F2347744F9E00CCA62267E198489D747578162C4C7D156211D\",\"hash\":\"A0A074D10355223CBE2520A42F93A52E3CC8B4D692570EB4841084F9BBB39F7A\",\"meta\":{\"AffectedNodes\":[{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX\",\"Balance\":\"1930599790\",\"Flags\":0,\"OwnerCount\":2,\"Sequence\":23296},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"267C16D24EC42EEF8B03D5BE4E94266B1675FA54AFCE42DE795E02AB61031CBD\",\"PreviousFields\":{\"Balance\":\"1930609790\",\"Sequence\":23295},\"PreviousTxnID\":\"0F5396388E91D37BB26C8E24073A57E7C5D51E79AEE4CD855653B8499AE4E3DD\",\"PreviousTxnLgrSeq\":22419806}},{\"ModifiedNode\":{\"FinalFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-9.980959751659681\"},\"Flags\":2228224,\"HighLimit\":{\"currency\":\"USD\",\"issuer\":\"rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4\",\"value\":\"1000000\"},\"HighNode\":\"0000000000000000\",\"LowLimit\":{\"currency\":\"USD\",\"issuer\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\",\"value\":\"0\"},\"LowNode\":\"0000000000000423\"},\"LedgerEntryType\":\"RippleState\",\"LedgerIndex\":\"C66957AF25229357F9C2D2BA17CE47D88169788EDA7610AD0F29AD5BCB225EE5\",\"PreviousFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-0.0009198315\"}},\"PreviousTxnID\":\"2A01E994D7000000B43DD63825A081B4440A44AB2F6FA0D506158AC9CA6B2869\",\"PreviousTxnLgrSeq\":22420532}},{\"ModifiedNode\":{\"FinalFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-276666.975959\"},\"Flags\":131072,\"HighLimit\":{\"currency\":\"USD\",\"issuer\":\"rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX\",\"value\":\"1000000\"},\"HighNode\":\"0000000000000000\",\"LowLimit\":{\"currency\":\"USD\",\"issuer\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\",\"value\":\"0\"},\"LowNode\":\"00000000000002D7\"},\"LedgerEntryType\":\"RippleState\",\"LedgerIndex\":\"FFD710AE2074A98D920D00CC352F25744899F069A6C1B9E31DD32D2C6606E615\",\"PreviousFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-276676.975959\"}},\"PreviousTxnID\":\"BB9DFC87E9D4ED09CA2726DDFE83A4A396ED0D6545536322DE17CDACF45C0D5B\",\"PreviousTxnLgrSeq\":22419307}}],\"TransactionIndex\":1,\"TransactionResult\":\"tesSUCCESS\"},\"ledger_index\":12345}"
}
],
"rawTransactions": "[{\"Account\":\"rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX\",\"Amount\":{\"currency\":\"USD\",\"issuer\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\",\"value\":\"10\"},\"Destination\":\"rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4\",\"Fee\":\"10000\",\"Flags\":131072,\"Sequence\":23295,\"SigningPubKey\":\"02B205F4B92351AC0EEB04254B636F4C49EF922CFA3CAAD03C6477DA1E04E94B53\",\"TransactionType\":\"Payment\",\"TxnSignature\":\"3045022100FAF247A836D601DE74A515B2AADE31186D8B0DA9C23DE489E09753F5CF4BB81F0220477C5B5BC3AC89F2347744F9E00CCA62267E198489D747578162C4C7D156211D\",\"hash\":\"A0A074D10355223CBE2520A42F93A52E3CC8B4D692570EB4841084F9BBB39F7A\",\"metaData\":{\"AffectedNodes\":[{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX\",\"Balance\":\"1930599790\",\"Flags\":0,\"OwnerCount\":2,\"Sequence\":23296},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"267C16D24EC42EEF8B03D5BE4E94266B1675FA54AFCE42DE795E02AB61031CBD\",\"PreviousFields\":{\"Balance\":\"1930609790\",\"Sequence\":23295},\"PreviousTxnID\":\"0F5396388E91D37BB26C8E24073A57E7C5D51E79AEE4CD855653B8499AE4E3DD\",\"PreviousTxnLgrSeq\":22419806}},{\"ModifiedNode\":{\"FinalFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-9.980959751659681\"},\"Flags\":2228224,\"HighLimit\":{\"currency\":\"USD\",\"issuer\":\"rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4\",\"value\":\"1000000\"},\"HighNode\":\"0000000000000000\",\"LowLimit\":{\"currency\":\"USD\",\"issuer\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\",\"value\":\"0\"},\"LowNode\":\"0000000000000423\"},\"LedgerEntryType\":\"RippleState\",\"LedgerIndex\":\"C66957AF25229357F9C2D2BA17CE47D88169788EDA7610AD0F29AD5BCB225EE5\",\"PreviousFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-0.0009198315\"}},\"PreviousTxnID\":\"2A01E994D7000000B43DD63825A081B4440A44AB2F6FA0D506158AC9CA6B2869\",\"PreviousTxnLgrSeq\":22420532}},{\"ModifiedNode\":{\"FinalFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-276666.975959\"},\"Flags\":131072,\"HighLimit\":{\"currency\":\"USD\",\"issuer\":\"rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX\",\"value\":\"1000000\"},\"HighNode\":\"0000000000000000\",\"LowLimit\":{\"currency\":\"USD\",\"issuer\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\",\"value\":\"0\"},\"LowNode\":\"00000000000002D7\"},\"LedgerEntryType\":\"RippleState\",\"LedgerIndex\":\"FFD710AE2074A98D920D00CC352F25744899F069A6C1B9E31DD32D2C6606E615\",\"PreviousFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-276676.975959\"}},\"PreviousTxnID\":\"BB9DFC87E9D4ED09CA2726DDFE83A4A396ED0D6545536322DE17CDACF45C0D5B\",\"PreviousTxnLgrSeq\":22419307}}],\"TransactionIndex\":1,\"TransactionResult\":\"tesSUCCESS\"}}]"
]
}

File diff suppressed because one or more lines are too long

View File

@@ -30,8 +30,8 @@
},
"orderbookChanges": {},
"indexInLedger": 0
}
},
"rawTransaction": "{\"Account\":\"rEGy9CxMTFGXFgUHUMreTy2FbqArabGy38\",\"Fee\":\"10\",\"ledger_index\":4181996,\"Flags\":0,\"Sequence\":6478,\"SigningPubKey\":\"02CAB6F3A798712136DB5F105A98B0DE27C99AEDB68500181706B087CF1B6D0F2D\",\"TransactionType\":\"AccountSet\",\"TxnSignature\":\"304402202144BD33CC30793455B0F90954576EEE80F13C4C73538D2AEE012564C48E522E02207A8A4AD2CF2B4DB549FB2F05D38E065B5DD1EAA386310698E5247F1BB515E99F\",\"hash\":\"FEEFC959B0351156F58A2275F5A6B37B07AA85CCCE2C4AF8A1342A0196A3CD4D\",\"meta\":{\"AffectedNodes\":[{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"rEGy9CxMTFGXFgUHUMreTy2FbqArabGy38\",\"Balance\":\"403657865\",\"Flags\":0,\"OwnerCount\":2,\"Sequence\":6479},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"F64FAA4CAFDB9931DC06890FE30B4E29C32F7AD574FC7C3362B81265682BFAEA\",\"PreviousFields\":{\"Balance\":\"403657875\",\"Sequence\":6478},\"PreviousTxnID\":\"B257B95A637C6C396507AD0AE122161A849C701F065B67009BB939690DB74BC9\",\"PreviousTxnLgrSeq\":4181972}}],\"TransactionIndex\":0,\"TransactionResult\":\"tesSUCCESS\"}}"
}
],
"rawTransactions": "[{\"Account\":\"rEGy9CxMTFGXFgUHUMreTy2FbqArabGy38\",\"Fee\":\"10\",\"ledger_index\":4181996,\"Flags\":0,\"Sequence\":6478,\"SigningPubKey\":\"02CAB6F3A798712136DB5F105A98B0DE27C99AEDB68500181706B087CF1B6D0F2D\",\"TransactionType\":\"AccountSet\",\"TxnSignature\":\"304402202144BD33CC30793455B0F90954576EEE80F13C4C73538D2AEE012564C48E522E02207A8A4AD2CF2B4DB549FB2F05D38E065B5DD1EAA386310698E5247F1BB515E99F\",\"hash\":\"FEEFC959B0351156F58A2275F5A6B37B07AA85CCCE2C4AF8A1342A0196A3CD4D\",\"metaData\":{\"AffectedNodes\":[{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"rEGy9CxMTFGXFgUHUMreTy2FbqArabGy38\",\"Balance\":\"403657865\",\"Flags\":0,\"OwnerCount\":2,\"Sequence\":6479},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"F64FAA4CAFDB9931DC06890FE30B4E29C32F7AD574FC7C3362B81265682BFAEA\",\"PreviousFields\":{\"Balance\":\"403657875\",\"Sequence\":6478},\"PreviousTxnID\":\"B257B95A637C6C396507AD0AE122161A849C701F065B67009BB939690DB74BC9\",\"PreviousTxnLgrSeq\":4181972}}],\"TransactionIndex\":0,\"TransactionResult\":\"tesSUCCESS\"}}]"
]
}

View File

@@ -12,11 +12,7 @@
}
},
"destination": {
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"amount": {
"currency": "USD",
"value": "0.001"
}
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"paths": "[[{\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"type\":48,\"type_hex\":\"0000000000000030\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"type\":49,\"type_hex\":\"0000000000000031\"}]]"
}

View File

@@ -0,0 +1,89 @@
{
"type": "payment",
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"sequence": 4,
"id": "F4AB442A6D4CBB935D66E1DA7309A5FC71C7143ED4049053EC14E3875B0CF9BF",
"specification": {
"source": {
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"maxAmount": {
"currency": "XRP",
"value": "1.112209"
}
},
"destination": {
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"paths": "[[{\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"type\":48,\"type_hex\":\"0000000000000030\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"type\":49,\"type_hex\":\"0000000000000031\"}]]"
},
"outcome": {
"result": "tesSUCCESS",
"timestamp": "2013-03-12T23:56:50.000Z",
"fee": "0.00001",
"deliveredAmount": {
"currency": "USD",
"value": "0.001",
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"balanceChanges": {
"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo": [
{
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"currency": "USD",
"value": "-0.001"
},
{
"counterparty": "r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr",
"currency": "USD",
"value": "0.001002"
}
],
"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM": [
{
"counterparty": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"currency": "USD",
"value": "0.001"
}
],
"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59": [
{
"currency": "XRP",
"value": "-1.101208"
}
],
"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr": [
{
"currency": "XRP",
"value": "1.101198"
},
{
"counterparty": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"currency": "USD",
"value": "-0.001002"
}
]
},
"orderbookChanges": {
"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr": [
{
"direction": "buy",
"quantity": {
"currency": "XRP",
"value": "1.101198"
},
"totalPrice": {
"currency": "USD",
"counterparty": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"value": "0.001002"
},
"makerExchangeRate": "1099",
"sequence": 58,
"status": "partially-filled"
}
]
},
"ledgerVersion": 348860,
"indexInLedger": 0
},
"rawTransaction": "{\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Amount\":{\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\",\"value\":\"0.001\"},\"Destination\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\",\"Fee\":\"10\",\"Flags\":0,\"Paths\":[[{\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"type\":48,\"type_hex\":\"0000000000000030\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"type\":49,\"type_hex\":\"0000000000000031\"}]],\"SendMax\":\"1112209\",\"Sequence\":4,\"SigningPubKey\":\"02BC8C02199949B15C005B997E7C8594574E9B02BA2D0628902E0532989976CF9D\",\"TransactionType\":\"Payment\",\"TxnSignature\":\"304502204EE3E9D1B01D8959B08450FCA9E22025AF503DEF310E34A93863A85CAB3C0BC5022100B61F5B567F77026E8DEED89EED0B7CAF0E6C96C228A2A65216F0DC2D04D52083\",\"date\":416447810,\"hash\":\"F4AB442A6D4CBB935D66E1DA7309A5FC71C7143ED4049053EC14E3875B0CF9BF\",\"inLedger\":348860,\"ledger_index\":348860,\"validated\":true,\"meta\":{\"AffectedNodes\":[{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr\",\"BookDirectory\":\"4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5E03E788E09BB000\",\"BookNode\":\"0000000000000000\",\"Flags\":0,\"OwnerNode\":\"0000000000000000\",\"Sequence\":58,\"TakerGets\":{\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"value\":\"5.648998\"},\"TakerPays\":\"6208248802\"},\"LedgerEntryType\":\"Offer\",\"LedgerIndex\":\"3CFB3C79D4F1BDB1EE5245259372576D926D9A875713422F7169A6CC60AFA68B\",\"PreviousFields\":{\"TakerGets\":{\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"value\":\"5.65\"},\"TakerPays\":\"6209350000\"},\"PreviousTxnID\":\"8F571C346688D89AC1F737AE3B6BB5D976702B171CC7B4DE5CA3D444D5B8D6B4\",\"PreviousTxnLgrSeq\":348433}},{\"ModifiedNode\":{\"FinalFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-0.001\"},\"Flags\":131072,\"HighLimit\":{\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\",\"value\":\"1\"},\"HighNode\":\"0000000000000000\",\"LowLimit\":{\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"value\":\"0\"},\"LowNode\":\"0000000000000002\"},\"LedgerEntryType\":\"RippleState\",\"LedgerIndex\":\"4BD1874F8F3A60EDB0C23F5BD43E07953C2B8741B226648310D113DE2B486F01\",\"PreviousFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"0\"}},\"PreviousTxnID\":\"5B2006DAD0B3130F57ACF7CC5CCAC2EEBCD4B57AAA091A6FD0A24B073D08ABB8\",\"PreviousTxnLgrSeq\":343703}},{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Balance\":\"9998898762\",\"Flags\":0,\"OwnerCount\":3,\"Sequence\":5},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"4F83A2CF7E70F77F79A307E6A472BFC2585B806A70833CCD1C26105BAE0D6E05\",\"PreviousFields\":{\"Balance\":\"9999999970\",\"Sequence\":4},\"PreviousTxnID\":\"53354D84BAE8FDFC3F4DA879D984D24B929E7FEB9100D2AD9EFCD2E126BCCDC8\",\"PreviousTxnLgrSeq\":343570}},{\"ModifiedNode\":{\"FinalFields\":{\"Account\":\"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr\",\"Balance\":\"912695302618\",\"Flags\":0,\"OwnerCount\":10,\"Sequence\":59},\"LedgerEntryType\":\"AccountRoot\",\"LedgerIndex\":\"F3E119AAA87AF3607CF87F5523BB8278A83BCB4142833288305D767DD30C392A\",\"PreviousFields\":{\"Balance\":\"912694201420\"},\"PreviousTxnID\":\"8F571C346688D89AC1F737AE3B6BB5D976702B171CC7B4DE5CA3D444D5B8D6B4\",\"PreviousTxnLgrSeq\":348433}},{\"ModifiedNode\":{\"FinalFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-5.5541638883365\"},\"Flags\":131072,\"HighLimit\":{\"currency\":\"USD\",\"issuer\":\"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr\",\"value\":\"1000\"},\"HighNode\":\"0000000000000000\",\"LowLimit\":{\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"value\":\"0\"},\"LowNode\":\"000000000000000C\"},\"LedgerEntryType\":\"RippleState\",\"LedgerIndex\":\"FA1255C2E0407F1945BCF9351257C7C5C28B0F5F09BB81C08D35A03E9F0136BC\",\"PreviousFields\":{\"Balance\":{\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\",\"value\":\"-5.5551658883365\"}},\"PreviousTxnID\":\"8F571C346688D89AC1F737AE3B6BB5D976702B171CC7B4DE5CA3D444D5B8D6B4\",\"PreviousTxnLgrSeq\":348433}}],\"TransactionIndex\":0,\"TransactionResult\":\"tesSUCCESS\"}}"
}

View File

@@ -12,11 +12,7 @@
}
},
"destination": {
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"amount": {
"currency": "USD",
"value": "0.001"
}
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"paths": "[[{\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"type\":48,\"type_hex\":\"0000000000000030\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"type\":49,\"type_hex\":\"0000000000000031\"}]]"
},

View File

@@ -0,0 +1,34 @@
{
"type": "trustline",
"address": "r9nNHpMW4TfPnmWcRHi3Qmev2jjCJ2koi4",
"sequence": 40,
"id": "9D6AC5FD6545B2584885B85E36759EB6440CDD41B6C55859F84AFDEE2B428220",
"specification": {
"limit": "2000",
"currency": "USD",
"counterparty": "rkrbFLphJzLvyLE1obALNARQAnoVypoNX",
"memos": [
{
"type": "test",
"format": "plain/text",
"data": "test trust"
}
]
},
"outcome": {
"result": "tesSUCCESS",
"timestamp": "2018-09-18T03:36:51.000Z",
"fee": "0.000012",
"balanceChanges": {
"r9nNHpMW4TfPnmWcRHi3Qmev2jjCJ2koi4": [
{
"currency": "XRP",
"value": "-0.000012"
}
]
},
"orderbookChanges": {},
"ledgerVersion": 41608182,
"indexInLedger": 5
}
}

View File

@@ -0,0 +1,190 @@
[
{
"type": "payment",
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"sequence": 4,
"id": "99404A34E8170319521223A6C604AF48B9F1E3000C377E6141F9A1BF60B0B865",
"specification": {
"memos": [
{
"type": "client",
"format": "rt1.5.2"
}
],
"source": {
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"maxAmount": {
"currency": "XRP",
"value": "1.112209"
}
},
"destination": {
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"paths": "[[{\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"}]]"
},
"outcome": {
"result": "tesSUCCESS",
"fee": "0.00001",
"deliveredAmount": {
"currency": "USD",
"value": "0.001",
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"balanceChanges": {
"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo": [
{
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"currency": "USD",
"value": "-0.001"
},
{
"counterparty": "r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr",
"currency": "USD",
"value": "0.001002"
}
],
"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM": [
{
"counterparty": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"currency": "USD",
"value": "0.001"
}
],
"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59": [
{
"currency": "XRP",
"value": "-1.101208"
}
],
"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr": [
{
"currency": "XRP",
"value": "1.101198"
},
{
"counterparty": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"currency": "USD",
"value": "-0.001002"
}
]
},
"orderbookChanges": {
"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59": [
{
"direction": "buy",
"quantity": {
"currency": "XRP",
"value": "1.101198"
},
"totalPrice": {
"currency": "USD",
"counterparty": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"value": "0.001002"
},
"makerExchangeRate": "1099",
"sequence": 58,
"status": "partially-filled"
}
]
},
"ledgerVersion": 348859,
"indexInLedger": 0
},
"rawTransaction": "{\"TransactionType\":\"Payment\",\"Flags\":0,\"Sequence\":4,\"Amount\":{\"value\":\"0.001\",\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\"},\"Fee\":\"10\",\"SendMax\":\"1112209\",\"SigningPubKey\":\"02BC8C02199949B15C005B997E7C8594574E9B02BA2D0628902E0532989976CF9D\",\"TxnSignature\":\"304502204EE3E9D1B01D8959B08450FCA9E22025AF503DEF310E34A93863A85CAB3C0BC5022100B61F5B567F77026E8DEED89EED0B7CAF0E6C96C228A2A65216F0DC2D04D52083\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Destination\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\",\"Memos\":[{\"Memo\":{\"MemoType\":\"636C69656E74\",\"MemoFormat\":\"7274312E352E32\"}}],\"Paths\":[[{\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"}]],\"hash\":\"99404A34E8170319521223A6C604AF48B9F1E3000C377E6141F9A1BF60B0B865\",\"ledger_index\":348859,\"meta\":{\"TransactionIndex\":0,\"AffectedNodes\":[{\"ModifiedNode\":{\"LedgerEntryType\":\"Offer\",\"PreviousTxnLgrSeq\":348433,\"PreviousTxnID\":\"8F571C346688D89AC1F737AE3B6BB5D976702B171CC7B4DE5CA3D444D5B8D6B4\",\"LedgerIndex\":\"3CFB3C79D4F1BDB1EE5245259372576D926D9A875713422F7169A6CC60AFA68B\",\"PreviousFields\":{\"TakerPays\":\"6209350000\",\"TakerGets\":{\"value\":\"5.65\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\"}},\"FinalFields\":{\"Flags\":0,\"Sequence\":58,\"BookNode\":\"0000000000000000\",\"OwnerNode\":\"0000000000000000\",\"BookDirectory\":\"4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5E03E788E09BB000\",\"TakerPays\":\"6208248802\",\"TakerGets\":{\"value\":\"5.648998\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\"},\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\"}}},{\"ModifiedNode\":{\"LedgerEntryType\":\"RippleState\",\"PreviousTxnLgrSeq\":343703,\"PreviousTxnID\":\"5B2006DAD0B3130F57ACF7CC5CCAC2EEBCD4B57AAA091A6FD0A24B073D08ABB8\",\"LedgerIndex\":\"4BD1874F8F3A60EDB0C23F5BD43E07953C2B8741B226648310D113DE2B486F01\",\"PreviousFields\":{\"Balance\":{\"value\":\"0\",\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\"}},\"FinalFields\":{\"Flags\":131072,\"LowNode\":\"0000000000000002\",\"HighNode\":\"0000000000000000\",\"Balance\":{\"value\":\"-0.001\",\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\"},\"LowLimit\":{\"value\":\"0\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\"},\"HighLimit\":{\"value\":\"1\",\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\"}}}},{\"ModifiedNode\":{\"LedgerEntryType\":\"AccountRoot\",\"PreviousTxnLgrSeq\":343570,\"PreviousTxnID\":\"53354D84BAE8FDFC3F4DA879D984D24B929E7FEB9100D2AD9EFCD2E126BCCDC8\",\"LedgerIndex\":\"4F83A2CF7E70F77F79A307E6A472BFC2585B806A70833CCD1C26105BAE0D6E05\",\"PreviousFields\":{\"Sequence\":4,\"Balance\":\"9999999970\"},\"FinalFields\":{\"Flags\":0,\"Sequence\":5,\"OwnerCount\":3,\"Balance\":\"9998898762\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\"}}},{\"ModifiedNode\":{\"LedgerEntryType\":\"AccountRoot\",\"PreviousTxnLgrSeq\":348433,\"PreviousTxnID\":\"8F571C346688D89AC1F737AE3B6BB5D976702B171CC7B4DE5CA3D444D5B8D6B4\",\"LedgerIndex\":\"F3E119AAA87AF3607CF87F5523BB8278A83BCB4142833288305D767DD30C392A\",\"PreviousFields\":{\"Balance\":\"912694201420\"},\"FinalFields\":{\"Flags\":0,\"Sequence\":59,\"OwnerCount\":10,\"Balance\":\"912695302618\",\"Account\":\"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr\"}}},{\"ModifiedNode\":{\"LedgerEntryType\":\"RippleState\",\"PreviousTxnLgrSeq\":348433,\"PreviousTxnID\":\"8F571C346688D89AC1F737AE3B6BB5D976702B171CC7B4DE5CA3D444D5B8D6B4\",\"LedgerIndex\":\"FA1255C2E0407F1945BCF9351257C7C5C28B0F5F09BB81C08D35A03E9F0136BC\",\"PreviousFields\":{\"Balance\":{\"value\":\"-5.5551658883365\",\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\"}},\"FinalFields\":{\"Flags\":131072,\"LowNode\":\"000000000000000C\",\"HighNode\":\"0000000000000000\",\"Balance\":{\"value\":\"-5.5541638883365\",\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\"},\"LowLimit\":{\"value\":\"0\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\"},\"HighLimit\":{\"value\":\"1000\",\"currency\":\"USD\",\"issuer\":\"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr\"}}}}],\"TransactionResult\":\"tesSUCCESS\"},\"validated\":true}"
},
{
"type": "payment",
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"id": "99404A34E8170319521223A6C604AF48B9F1E3000C377E6141F9A1BF60B0B865",
"sequence": 4,
"specification": {
"memos": [
{
"type": "client",
"format": "rt1.5.2"
}
],
"source": {
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"maxAmount": {
"currency": "XRP",
"value": "1.112209"
}
},
"destination": {
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"paths": "[[{\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"}]]"
},
"outcome": {
"result": "tesSUCCESS",
"fee": "0.00001",
"deliveredAmount": {
"currency": "USD",
"value": "0.001",
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"balanceChanges": {
"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo": [
{
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"currency": "USD",
"value": "-0.001"
},
{
"counterparty": "r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr",
"currency": "USD",
"value": "0.001002"
}
],
"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM": [
{
"counterparty": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"currency": "USD",
"value": "0.001"
}
],
"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59": [
{
"currency": "XRP",
"value": "-1.101208"
}
],
"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr": [
{
"currency": "XRP",
"value": "1.101198"
},
{
"counterparty": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"currency": "USD",
"value": "-0.001002"
}
]
},
"orderbookChanges": {
"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59": [
{
"direction": "buy",
"quantity": {
"currency": "XRP",
"value": "1.101198"
},
"totalPrice": {
"currency": "USD",
"counterparty": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"value": "0.001002"
},
"makerExchangeRate": "1099",
"sequence": 58,
"status": "partially-filled"
}
]
},
"ledgerVersion": 348858,
"indexInLedger": 0
},
"rawTransaction": "{\"TransactionType\":\"Payment\",\"Flags\":0,\"Sequence\":4,\"Amount\":{\"value\":\"0.001\",\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\"},\"Fee\":\"10\",\"SendMax\":\"1112209\",\"SigningPubKey\":\"02BC8C02199949B15C005B997E7C8594574E9B02BA2D0628902E0532989976CF9D\",\"TxnSignature\":\"304502204EE3E9D1B01D8959B08450FCA9E22025AF503DEF310E34A93863A85CAB3C0BC5022100B61F5B567F77026E8DEED89EED0B7CAF0E6C96C228A2A65216F0DC2D04D52083\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Destination\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\",\"Memos\":[{\"Memo\":{\"MemoType\":\"636C69656E74\",\"MemoFormat\":\"7274312E352E32\"}}],\"Paths\":[[{\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"}]],\"hash\":\"99404A34E8170319521223A6C604AF48B9F1E3000C377E6141F9A1BF60B0B865\",\"ledger_index\":348858,\"meta\":{\"TransactionIndex\":0,\"AffectedNodes\":[{\"ModifiedNode\":{\"LedgerEntryType\":\"Offer\",\"PreviousTxnLgrSeq\":348433,\"PreviousTxnID\":\"8F571C346688D89AC1F737AE3B6BB5D976702B171CC7B4DE5CA3D444D5B8D6B4\",\"LedgerIndex\":\"3CFB3C79D4F1BDB1EE5245259372576D926D9A875713422F7169A6CC60AFA68B\",\"PreviousFields\":{\"TakerPays\":\"6209350000\",\"TakerGets\":{\"value\":\"5.65\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\"}},\"FinalFields\":{\"Flags\":0,\"Sequence\":58,\"BookNode\":\"0000000000000000\",\"OwnerNode\":\"0000000000000000\",\"BookDirectory\":\"4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5E03E788E09BB000\",\"TakerPays\":\"6208248802\",\"TakerGets\":{\"value\":\"5.648998\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\"},\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\"}}},{\"ModifiedNode\":{\"LedgerEntryType\":\"RippleState\",\"PreviousTxnLgrSeq\":343703,\"PreviousTxnID\":\"5B2006DAD0B3130F57ACF7CC5CCAC2EEBCD4B57AAA091A6FD0A24B073D08ABB8\",\"LedgerIndex\":\"4BD1874F8F3A60EDB0C23F5BD43E07953C2B8741B226648310D113DE2B486F01\",\"PreviousFields\":{\"Balance\":{\"value\":\"0\",\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\"}},\"FinalFields\":{\"Flags\":131072,\"LowNode\":\"0000000000000002\",\"HighNode\":\"0000000000000000\",\"Balance\":{\"value\":\"-0.001\",\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\"},\"LowLimit\":{\"value\":\"0\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\"},\"HighLimit\":{\"value\":\"1\",\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\"}}}},{\"ModifiedNode\":{\"LedgerEntryType\":\"AccountRoot\",\"PreviousTxnLgrSeq\":343570,\"PreviousTxnID\":\"53354D84BAE8FDFC3F4DA879D984D24B929E7FEB9100D2AD9EFCD2E126BCCDC8\",\"LedgerIndex\":\"4F83A2CF7E70F77F79A307E6A472BFC2585B806A70833CCD1C26105BAE0D6E05\",\"PreviousFields\":{\"Sequence\":4,\"Balance\":\"9999999970\"},\"FinalFields\":{\"Flags\":0,\"Sequence\":5,\"OwnerCount\":3,\"Balance\":\"9998898762\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\"}}},{\"ModifiedNode\":{\"LedgerEntryType\":\"AccountRoot\",\"PreviousTxnLgrSeq\":348433,\"PreviousTxnID\":\"8F571C346688D89AC1F737AE3B6BB5D976702B171CC7B4DE5CA3D444D5B8D6B4\",\"LedgerIndex\":\"F3E119AAA87AF3607CF87F5523BB8278A83BCB4142833288305D767DD30C392A\",\"PreviousFields\":{\"Balance\":\"912694201420\"},\"FinalFields\":{\"Flags\":0,\"Sequence\":59,\"OwnerCount\":10,\"Balance\":\"912695302618\",\"Account\":\"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr\"}}},{\"ModifiedNode\":{\"LedgerEntryType\":\"RippleState\",\"PreviousTxnLgrSeq\":348433,\"PreviousTxnID\":\"8F571C346688D89AC1F737AE3B6BB5D976702B171CC7B4DE5CA3D444D5B8D6B4\",\"LedgerIndex\":\"FA1255C2E0407F1945BCF9351257C7C5C28B0F5F09BB81C08D35A03E9F0136BC\",\"PreviousFields\":{\"Balance\":{\"value\":\"-5.5551658883365\",\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\"}},\"FinalFields\":{\"Flags\":131072,\"LowNode\":\"000000000000000C\",\"HighNode\":\"0000000000000000\",\"Balance\":{\"value\":\"-5.5541638883365\",\"currency\":\"USD\",\"issuer\":\"rrrrrrrrrrrrrrrrrrrrBZbvji\"},\"LowLimit\":{\"value\":\"0\",\"currency\":\"USD\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\"},\"HighLimit\":{\"value\":\"1000\",\"currency\":\"USD\",\"issuer\":\"r9tGqzZgKxVFvzKFdUqXAqTzazWBUia8Qr\"}}}}],\"TransactionResult\":\"tesSUCCESS\"},\"validated\":true}"
}
]

View File

@@ -19,11 +19,7 @@
}
},
"destination": {
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"amount": {
"currency": "USD",
"value": "0.001"
}
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"paths": "[[{\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"}]]"
},
@@ -116,11 +112,7 @@
}
},
"destination": {
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"amount": {
"currency": "USD",
"value": "0.001"
}
"address": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"paths": "[[{\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"},{\"account\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"issuer\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"currency\":\"USD\"}]]"
},

View File

@@ -35,6 +35,7 @@ module.exports = {
orderSell: require('./get-transaction-order-sell.json'),
noMeta: require('./get-transaction-no-meta.json'),
payment: require('./get-transaction-payment.json'),
paymentIncludeRawTransaction: require('./get-transaction-payment-include-raw-transaction.json'),
settings: require('./get-transaction-settings.json'),
trustline: require('./get-transaction-trustline-set.json'),
trackingOn: require('./get-transaction-settings-tracking-on.json'),
@@ -42,6 +43,7 @@ module.exports = {
setRegularKey: require('./get-transaction-settings-set-regular-key.json'),
trustlineFrozenOff: require('./get-transaction-trust-set-frozen-off.json'),
trustlineNoQuality: require('./get-transaction-trust-no-quality.json'),
trustlineAddMemo: require('./get-transaction-trust-add-memo.json'),
notValidated: require('./get-transaction-not-validated.json'),
checkCreate:
require('./get-transaction-check-create.json'),
@@ -68,6 +70,7 @@ module.exports = {
},
getTransactions: {
normal: require('./get-transactions.json'),
includeRawTransactions: require('./get-transactions-include-raw-transactions.json'),
one: require('./get-transactions-one.json')
},
getTrustlines: {

View File

@@ -75,6 +75,7 @@ module.exports = {
TrustSet: require('./tx/trust-set.json'),
TrustSetFrozenOff: require('./tx/trust-set-frozen-off.json'),
TrustSetNoQuality: require('./tx/trust-set-no-quality.json'),
TrustSetAddMemo: require('./tx/trust-set-add-memo.json'),
NotFound: require('./tx/not-found.json'),
NoLedgerIndex: require('./tx/no-ledger-index.json'),
NoLedgerFound: require('./tx/no-ledger-found.json'),

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
{
"id": 1,
"status": "success",
"type": "response",
"result": {
"Account": "r9nNHpMW4TfPnmWcRHi3Qmev2jjCJ2koi4",
"Fee": "12",
"Flags": 2147483648,
"LastLedgerSequence": 41608183,
"LimitAmount": {
"currency": "USD",
"issuer": "rkrbFLphJzLvyLE1obALNARQAnoVypoNX",
"value": "2000"
},
"Memos": [
{
"Memo": {
"MemoData": "74657374207472757374",
"MemoFormat": "706C61696E2F74657874",
"MemoType": "74657374"
}
}
],
"Sequence": 40,
"SigningPubKey": "033FD06C0EEE1D865B21B9E1CF35E672912241C5730C631E3965B205F014C9CF5A",
"TransactionType": "TrustSet",
"TxnSignature": "3045022100FA2BEFAB78C7EC214AEDAD18B423E03BBC48FD6728D93EC25A213B4C84A5D38102205B618CD7A52CD4351381D2676E0A6044E4181118716DE98E8DEFA845C097ECB9",
"date": 590557011,
"hash": "9D6AC5FD6545B2584885B85E36759EB6440CDD41B6C55859F84AFDEE2B428220",
"inLedger": 41608182,
"ledger_index": 41608182,
"meta": {
"AffectedNodes": [
{
"ModifiedNode": {
"FinalFields": {
"Account": "r9nNHpMW4TfPnmWcRHi3Qmev2jjCJ2koi4",
"Balance": "119672499",
"Flags": 0,
"OwnerCount": 4,
"Sequence": 41
},
"LedgerEntryType": "AccountRoot",
"LedgerIndex": "9FD944BCDE2F599A59FE8E8D7A764B69F4B0F818385C9E54C6CC46405F1E1925",
"PreviousFields": {
"Balance": "119672511",
"Sequence": 40
},
"PreviousTxnID": "8E16AD23970715E212DE6208E11397E4E394430D40EBF560F5A80FB8716429CF",
"PreviousTxnLgrSeq": 41607559
}
}
],
"TransactionIndex": 5,
"TransactionResult": "tesSUCCESS"
},
"validated": true
}
}

View File

@@ -256,7 +256,8 @@ module.exports = function createMockRippled(port) {
createLedgerResponse(request, fixtures.ledger.withoutCloseTime));
} else if (request.ledger_index === 4181996) {
conn.send(createLedgerResponse(request, fixtures.ledger.withSettingsTx));
} else if (request.ledger_index === 100000) {
} else if (request.ledger_index === 22420574 &&
request.expand === true && request.transactions === true) {
conn.send(
createLedgerResponse(request, fixtures.ledger.withPartialPayment));
} else if (request.ledger_index === 100001) {
@@ -266,8 +267,12 @@ module.exports = function createMockRippled(port) {
const response = _.assign({}, fixtures.ledger.normal,
{ result: { ledger: fullLedger } });
conn.send(createLedgerResponse(request, response));
} else {
} else if (request.ledger_index === 'validated' ||
request.ledger_index === 14661789 ||
request.ledger_index === 14661788 /* getTransaction - order */) {
conn.send(createLedgerResponse(request, fixtures.ledger.normal));
} else {
assert(false, 'Unrecognized ledger request: ' + JSON.stringify(request));
}
});
@@ -340,6 +345,9 @@ module.exports = function createMockRippled(port) {
'BAF1C678323C37CCB7735550C379287667D8288C30F83148AD3C1CB019FC9002') {
conn.send(createResponse(request, fixtures.tx.TrustSetNoQuality));
} else if (request.transaction ===
'9D6AC5FD6545B2584885B85E36759EB6440CDD41B6C55859F84AFDEE2B428220') {
conn.send(createResponse(request, fixtures.tx.TrustSetAddMemo));
}else if (request.transaction ===
'4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA10') {
conn.send(createResponse(request, fixtures.tx.NotValidated));
} else if (request.transaction === hashes.NOTFOUND_TRANSACTION_HASH) {
@@ -480,7 +488,57 @@ module.exports = function createMockRippled(port) {
if (request.subcommand === 'close') { // for path_find command
return;
}
if (request.source_account === addresses.NOTFOUND) {
if (request.source_account === 'rB2NTuTTS3eNCsWxZYzJ4wqRqxNLZqA9Vx') {
// getPaths - result path has source_amount in drops
response = createResponse(request, {
"id": 0,
"type": "response",
"status": "success",
"result": {
"alternatives": [
{
"destination_amount": {
"currency": "EUR",
"issuer": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u",
"value": "1"
},
"paths_canonical": [],
"paths_computed": [
[
{
"currency": "USD",
"issuer": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u",
"type": 48,
"type_hex": "0000000000000030"
},
{
"currency": "EUR",
"issuer": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u",
"type": 48,
"type_hex": "0000000000000030"
}
]
],
"source_amount": "1000000"
}
],
"destination_account": "rhpJkBfZGQyT1xeDbwtKEuSrSXw3QZSAy5",
"destination_amount": {
"currency": "EUR",
"issuer": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u",
"value": "-1"
},
"destination_currencies": [
"EUR",
"XRP"
],
"full_reply": true,
"id": 2,
"source_account": "rB2NTuTTS3eNCsWxZYzJ4wqRqxNLZqA9Vx",
"status": "success"
}
})
} else if (request.source_account === addresses.NOTFOUND) {
response = createResponse(request, fixtures.path_find.srcActNotFound);
} else if (request.source_account === addresses.SOURCE_LOW_FUNDS) {
response = createResponse(request, fixtures.path_find.sourceAmountLow);
@@ -492,8 +550,9 @@ module.exports = function createMockRippled(port) {
destination_address: request.destination_address
});
} else if (request.source_account === addresses.ACCOUNT) {
if (request.destination_account ===
'ra5nK24KXen9AHvsdFTKHSANinZseWnPcX') {
if (request.destination_account === 'ra5nK24KXen9AHvsdFTKHSANinZseWnPcX' &&
// Important: Ensure that destination_amount.value is correct
request.destination_amount.value === "-1") {
response = createResponse(request, fixtures.path_find.sendAll);
} else {
response = fixtures.path_find.generate.generateIOUPaymentPaths(

View File

@@ -4803,9 +4803,9 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript@^2.6.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624"
typescript@2.9.2:
version "2.9.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
uglify-es@^3.3.4:
version "3.3.9"