mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-05 05:15:48 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c23c6e4fc9 | ||
|
|
afdd60efe8 | ||
|
|
8f6ea573ff | ||
|
|
3271b544ef | ||
|
|
6e83130754 | ||
|
|
f6ebe32519 | ||
|
|
3caed3c761 | ||
|
|
ce1c55427a | ||
|
|
9cd72595f0 | ||
|
|
ad1d3e135f | ||
|
|
76866ab901 | ||
|
|
20b647dfbf | ||
|
|
99d08065e4 | ||
|
|
261fba3d21 | ||
|
|
e1d9de7b1f | ||
|
|
391b2f3622 | ||
|
|
86ff315ef2 | ||
|
|
8d8a850864 | ||
|
|
7bf2da6014 | ||
|
|
7eae3ce709 | ||
|
|
5f5e48e414 | ||
|
|
4f6a37f7b1 | ||
|
|
82613e7e8b | ||
|
|
588aa382a1 | ||
|
|
809d981987 | ||
|
|
cfc21fde8c | ||
|
|
5c06ef547b | ||
|
|
0990ad4a6f | ||
|
|
d8f967d2b8 | ||
|
|
fe1c3e7130 | ||
|
|
062148674c | ||
|
|
11320693fd | ||
|
|
7af7eaccb4 | ||
|
|
5d5cf868a2 | ||
|
|
ddf8fe5b1a |
33
HISTORY.md
33
HISTORY.md
@@ -1,3 +1,36 @@
|
||||
##0.16.2
|
||||
**Changes**
|
||||
+ [Bump ripple-binary-codec dependency version to 0.1.1 to fix issue with computeLedgerHash for transactions with DeliverMin]
|
||||
|
||||
##0.16.1
|
||||
**Changes**
|
||||
+ [FIX: Use assert not assert-diff](https://github.com/ripple/ripple-lib/commit/f6ebe325193e7208c5ee8d8e84a7504714f0009e)
|
||||
|
||||
##0.16.0
|
||||
**Breaking Changes**
|
||||
+ [Fix types of XRP values in getServerInfo response](https://github.com/ripple/ripple-lib/commit/99d08065e4bda3dda6ae1f183adbd11abc70a9b7)
|
||||
+ [Change error event format and fix crash due to error event on webscocket](https://github.com/ripple/ripple-lib/commit/9cd72595f0efc062d77b9d625695d6030c524cc6)
|
||||
|
||||
**Changes**
|
||||
+ [Fix generateAddress docs and add error event listener to boilerplate](https://github.com/ripple/ripple-lib/commit/809d981987a2890fac3a73a40a05c598b9040334)
|
||||
+ [Allow setting maxLedgerVersion to null to specify no maximum](https://github.com/ripple/ripple-lib/commit/82613e7e8b360d1ae1552eab4559ab4763c06d7e)
|
||||
+ [Add support for client certificates](https://github.com/ripple/ripple-lib/commit/5f5e48e4140345d166b8c1a3ee0847b0d9e2d893)
|
||||
+ [getFee returns a string not float](https://github.com/ripple/ripple-lib/commit/7bf2da6014c87e164542e69356efeaabb575a157)
|
||||
+ [Fix parsing of quality for getTrustlines](https://github.com/ripple/ripple-lib/commit/86ff315ef2a39dfdc2ce97e0e1c4aa73f04e363b)
|
||||
+ [Fix DeliverMin value when specifying minAmount](Fix DeliverMin value when specifying minAmount)
|
||||
+ [http server example](https://github.com/ripple/ripple-lib/commit/76866ab901ea46a2dd73181605e0f7f4220043d4)
|
||||
|
||||
|
||||
##0.15.2
|
||||
**Changes**
|
||||
+ [Fix support for proxy credentials in proxy URL and fix error when there are more than 10 outstanding requests](https://github.com/ripple/ripple-lib/commit/0990ad4a6f1d59ca9d2cb859b4e2d71693f3fc4b)
|
||||
|
||||
##0.15.1
|
||||
**Changes**
|
||||
+ [Fix babel-polyfill require](https://github.com/ripple/ripple-lib/commit/062148674c3b1293ab82c28e25615ddd530339fa)
|
||||
+ [Fix samples](https://github.com/ripple/ripple-lib/commit/5d5cf868a2ddb1b1cd40e4a4f0a782d0066c2055)
|
||||
+ [add unit tests for RippleAPIBroadcast](https://github.com/ripple/ripple-lib/commit/ddf8fe5b1a9c750490dca98fb9ffaaf8017f87e0)
|
||||
|
||||
##0.15.0
|
||||
**Breaking Changes**
|
||||
+ ["servers" parameter changed to single "server"](https://github.com/ripple/ripple-lib/commit/7061e9afe46f0682254d098adeff3dd7157521a1)
|
||||
|
||||
@@ -86,6 +86,9 @@ const {RippleAPI} = require('ripple-lib');
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server hosted by Ripple, Inc.
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
api.connect().then(() => {
|
||||
/* insert code here */
|
||||
}).then(() => {
|
||||
@@ -105,6 +108,10 @@ All the code snippets in this documentation assume that you have surrounded them
|
||||
If you omit the "catch" section, errors may not be visible.
|
||||
</aside>
|
||||
|
||||
<aside class="notice">
|
||||
The "error" event is emitted whenever an error occurs that cannot be associated with a specific request. If the listener is not registered, an exception will be thrown whenever the event is emitted.
|
||||
</aside>
|
||||
|
||||
### Parameters
|
||||
|
||||
The RippleAPI constructor optionally takes one argument, an object with the following options:
|
||||
@@ -112,7 +119,10 @@ The RippleAPI constructor optionally takes one argument, an object with the foll
|
||||
Name | Type | Description
|
||||
---- | ---- | -----------
|
||||
authorization | string | *Optional* Username and password for HTTP basic authentication to the rippled server in the format **username:password**.
|
||||
certificate | string | *Optional* A string containing the certificate key of the client in PEM format. (Can be an array of certificates).
|
||||
feeCushion | number | *Optional* Factor to multiply estimated fee by to provide a cushion in case the required fee rises during submission of a transaction. Defaults to `1.2`.
|
||||
key | string | *Optional* A string containing the private key of the client in PEM format. (Can be an array of keys).
|
||||
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://`.
|
||||
@@ -277,8 +287,8 @@ Name | Type | Description
|
||||
---- | ---- | -----------
|
||||
fee | [value](#value) | *Optional* An exact fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.
|
||||
maxFee | [value](#value) | *Optional* The maximum fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.
|
||||
maxLedgerVersion | integer | *Optional* The highest ledger version that the transaction can be included in.
|
||||
maxLedgerVersionOffset | integer | *Optional* Offset from current legder version to highest ledger version that the transaction can be included in.
|
||||
maxLedgerVersion | integer,null | *Optional* The highest ledger version that the transaction can be included in. If this option and `maxLedgerVersionOffset` are both omitted, the `maxLedgerVersion` option will default to 3 greater than the current validated ledger version (equivalent to `maxLedgerVersionOffset=3`). Use `null` to not set a maximum ledger version.
|
||||
maxLedgerVersionOffset | integer | *Optional* Offset from current validated legder version to highest ledger version that the transaction can be included in.
|
||||
sequence | [sequence](#account-sequence-number) | *Optional* The initiating account's sequence number for this transaction.
|
||||
|
||||
We recommended that you specify a `maxLedgerVersion` so that you can quickly determine that a failed transaction will never succeeed in the future. It is impossible for a transaction to succeed after the network ledger version exceeds the transaction's `maxLedgerVersion`. If you omit `maxLedgerVersion`, the "prepare*" method automatically supplies a `maxLedgerVersion` equal to the current ledger plus 3, which it includes in the return value from the "prepare*" method.
|
||||
@@ -673,10 +683,10 @@ pubkeyNode | string | Public key used to verify this node for internal communica
|
||||
serverState | string | A string indicating to what extent the server is participating in the network. See [Possible Server States](https://ripple.com/build/rippled-apis/#possible-server-states) for more details.
|
||||
validatedLedger | object | Information about the fully-validated ledger with the highest sequence number (the most recent).
|
||||
*validatedLedger.* age | integer | The time since the ledger was closed, in seconds.
|
||||
*validatedLedger.* baseFeeXRP | number | Base fee, in XRP. This may be represented in scientific notation such as 1e-05 for 0.00005.
|
||||
*validatedLedger.* baseFeeXRP | [value](#value) | Base fee, in XRP. This may be represented in scientific notation such as 1e-05 for 0.00005.
|
||||
*validatedLedger.* hash | string | Unique hash for the ledger, as an uppercase hexadecimal string.
|
||||
*validatedLedger.* reserveBaseXRP | integer | Minimum amount of XRP necessary for every account to keep in reserve.
|
||||
*validatedLedger.* reserveIncrementXRP | integer | Amount of XRP added to the account reserve for each object an account is responsible for in the ledger.
|
||||
*validatedLedger.* reserveBaseXRP | [value](#value) | Minimum amount of XRP necessary for every account to keep in reserve.
|
||||
*validatedLedger.* reserveIncrementXRP | [value](#value) | Amount of XRP added to the account reserve for each object an account is responsible for in the ledger.
|
||||
*validatedLedger.* ledgerVersion | integer | Identifying sequence number of this ledger version.
|
||||
validationQuorum | number | Minimum number of trusted validations required in order to validate a ledger version. Some circumstances may cause the server to require more validations.
|
||||
load | object | *Optional* *(Admin only)* Detailed information about the current load state of the server.
|
||||
@@ -707,10 +717,10 @@ return api.getServerInfo().then(info => {/* ... */});
|
||||
"serverState": "full",
|
||||
"validatedLedger": {
|
||||
"age": 5,
|
||||
"baseFeeXRP": 0.00001,
|
||||
"baseFeeXRP": "0.00001",
|
||||
"hash": "4482DEE5362332F54A4036ED57EE1767C9F33CF7CE5A6670355C16CECE381D46",
|
||||
"reserveBaseXRP": 20,
|
||||
"reserveIncrementXRP": 5,
|
||||
"reserveBaseXRP": "20",
|
||||
"reserveIncrementXRP": "5",
|
||||
"ledgerVersion": 6595042
|
||||
},
|
||||
"validationQuorum": 3
|
||||
@@ -730,7 +740,7 @@ This method has no parameters.
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a promise that resolves with a 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
|
||||
|
||||
@@ -739,7 +749,7 @@ return api.getFee().then(fee => {/* ... */});
|
||||
```
|
||||
|
||||
```json
|
||||
0.012
|
||||
"0.012"
|
||||
```
|
||||
|
||||
## getLedgerVersion
|
||||
@@ -2793,7 +2803,7 @@ txJSON | string | The prepared transaction in rippled JSON format.
|
||||
instructions | object | The instructions for how to execute the transaction after adding automatic defaults.
|
||||
*instructions.* fee | [value](#value) | An exact fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.
|
||||
*instructions.* sequence | [sequence](#account-sequence-number) | The initiating account's sequence number for this transaction.
|
||||
*instructions.* maxLedgerVersion | integer | *Optional* The highest ledger version that the transaction can be included in.
|
||||
*instructions.* maxLedgerVersion | integer,null | The highest ledger version that the transaction can be included in. Set to `null` if there is no maximum.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -2862,7 +2872,7 @@ txJSON | string | The prepared transaction in rippled JSON format.
|
||||
instructions | object | The instructions for how to execute the transaction after adding automatic defaults.
|
||||
*instructions.* fee | [value](#value) | An exact fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.
|
||||
*instructions.* sequence | [sequence](#account-sequence-number) | The initiating account's sequence number for this transaction.
|
||||
*instructions.* maxLedgerVersion | integer | *Optional* The highest ledger version that the transaction can be included in.
|
||||
*instructions.* maxLedgerVersion | integer,null | The highest ledger version that the transaction can be included in. Set to `null` if there is no maximum.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -2929,7 +2939,7 @@ txJSON | string | The prepared transaction in rippled JSON format.
|
||||
instructions | object | The instructions for how to execute the transaction after adding automatic defaults.
|
||||
*instructions.* fee | [value](#value) | An exact fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.
|
||||
*instructions.* sequence | [sequence](#account-sequence-number) | The initiating account's sequence number for this transaction.
|
||||
*instructions.* maxLedgerVersion | integer | *Optional* The highest ledger version that the transaction can be included in.
|
||||
*instructions.* maxLedgerVersion | integer,null | The highest ledger version that the transaction can be included in. Set to `null` if there is no maximum.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -2994,7 +3004,7 @@ txJSON | string | The prepared transaction in rippled JSON format.
|
||||
instructions | object | The instructions for how to execute the transaction after adding automatic defaults.
|
||||
*instructions.* fee | [value](#value) | An exact fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.
|
||||
*instructions.* sequence | [sequence](#account-sequence-number) | The initiating account's sequence number for this transaction.
|
||||
*instructions.* maxLedgerVersion | integer | *Optional* The highest ledger version that the transaction can be included in.
|
||||
*instructions.* maxLedgerVersion | integer,null | The highest ledger version that the transaction can be included in. Set to `null` if there is no maximum.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -3046,7 +3056,7 @@ txJSON | string | The prepared transaction in rippled JSON format.
|
||||
instructions | object | The instructions for how to execute the transaction after adding automatic defaults.
|
||||
*instructions.* fee | [value](#value) | An exact fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.
|
||||
*instructions.* sequence | [sequence](#account-sequence-number) | The initiating account's sequence number for this transaction.
|
||||
*instructions.* maxLedgerVersion | integer | *Optional* The highest ledger version that the transaction can be included in.
|
||||
*instructions.* maxLedgerVersion | integer,null | The highest ledger version that the transaction can be included in. Set to `null` if there is no maximum.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -3111,7 +3121,7 @@ txJSON | string | The prepared transaction in rippled JSON format.
|
||||
instructions | object | The instructions for how to execute the transaction after adding automatic defaults.
|
||||
*instructions.* fee | [value](#value) | An exact fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.
|
||||
*instructions.* sequence | [sequence](#account-sequence-number) | The initiating account's sequence number for this transaction.
|
||||
*instructions.* maxLedgerVersion | integer | *Optional* The highest ledger version that the transaction can be included in.
|
||||
*instructions.* maxLedgerVersion | integer,null | The highest ledger version that the transaction can be included in. Set to `null` if there is no maximum.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -3183,7 +3193,7 @@ txJSON | string | The prepared transaction in rippled JSON format.
|
||||
instructions | object | The instructions for how to execute the transaction after adding automatic defaults.
|
||||
*instructions.* fee | [value](#value) | An exact fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.
|
||||
*instructions.* sequence | [sequence](#account-sequence-number) | The initiating account's sequence number for this transaction.
|
||||
*instructions.* maxLedgerVersion | integer | *Optional* The highest ledger version that the transaction can be included in.
|
||||
*instructions.* maxLedgerVersion | integer,null | The highest ledger version that the transaction can be included in. Set to `null` if there is no maximum.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -3240,7 +3250,7 @@ txJSON | string | The prepared transaction in rippled JSON format.
|
||||
instructions | object | The instructions for how to execute the transaction after adding automatic defaults.
|
||||
*instructions.* fee | [value](#value) | An exact fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.
|
||||
*instructions.* sequence | [sequence](#account-sequence-number) | The initiating account's sequence number for this transaction.
|
||||
*instructions.* maxLedgerVersion | integer | *Optional* The highest ledger version that the transaction can be included in.
|
||||
*instructions.* maxLedgerVersion | integer,null | The highest ledger version that the transaction can be included in. Set to `null` if there is no maximum.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -3355,7 +3365,11 @@ Generate a new Ripple address and corresponding secret.
|
||||
|
||||
### Parameters
|
||||
|
||||
This method has no parameters.
|
||||
Name | Type | Description
|
||||
---- | ---- | -----------
|
||||
options | object | *Optional* Options to control how the address and secret are generated.
|
||||
*options.* algorithm | string | *Optional* The digital signature algorithm to generate an address for. Can be `ecdsa-secp256k1` (default) or `ed25519`.
|
||||
*options.* entropy | array\<integer\> | *Optional* The entropy to use to generate the seed.
|
||||
|
||||
### Return Value
|
||||
|
||||
@@ -3369,8 +3383,7 @@ secret | secret string | The secret corresponding to the `address`.
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
return api.generateAddress()
|
||||
.then(result => {/* ... */});
|
||||
return api.generateAddress();
|
||||
```
|
||||
|
||||
|
||||
@@ -3451,7 +3464,7 @@ Name | Type | Description
|
||||
baseFeeXRP | [value](#value) | Base fee, in XRP.
|
||||
ledgerHash | string | Unique hash of the ledger that was closed, as hex.
|
||||
ledgerTimestamp | date-time string | The time at which this ledger closed.
|
||||
reserveBaseXRP | [value](#value) | The minimum reserve, in drops of XRP, that is required for an account.
|
||||
reserveBaseXRP | [value](#value) | The minimum reserve, in XRP, that is required for an account.
|
||||
reserveIncrementXRP | [value](#value) | The increase in account reserve that is added for each item the account owns, such as offers or trust lines.
|
||||
transactionCount | integer | Number of new transactions included in this ledger.
|
||||
ledgerVersion | integer | Ledger version of the ledger that closed.
|
||||
@@ -3482,16 +3495,26 @@ api.on('ledger', ledger => {
|
||||
|
||||
## error
|
||||
|
||||
This event is emitted when there is an error on the connection to the server.
|
||||
This event is emitted when there is an error on the connection to the server that cannot be associated to a specific request.
|
||||
|
||||
### Return Value
|
||||
|
||||
The first parameter is a string indicating the error type, which may be `badMessage` (meaning that rippled returned a malformed message), or one of the [rippled Universal Errors](https://ripple.com/build/rippled-apis/#universal-errors). The second parameter is a message explaining the error, or the message that caused the error in the case of `badMessage`.
|
||||
The first parameter is a string indicating the error type:
|
||||
* `badMessage` - rippled returned a malformed message
|
||||
* `websocket` - the websocket library emitted an error
|
||||
* one of the error codes found in the [rippled Universal Errors](https://ripple.com/build/rippled-apis/#universal-errors).
|
||||
|
||||
The second parameter is a message explaining the error.
|
||||
|
||||
The third parameter is:
|
||||
* the message that caused the error for `badMessage`
|
||||
* the error object emitted for `websocket`
|
||||
* the parsed response for rippled errors
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
api.on('error', (errorCode, errorMessage, data) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
const RippleAPI = require('../../src').RippleAPI; // require('ripple-lib')
|
||||
|
||||
const api = new RippleAPI({servers: ['wss://s1.ripple.com:443']});
|
||||
const api = new RippleAPI({server: 'wss://s1.ripple.com:443'});
|
||||
const address = 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV';
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
@@ -4,13 +4,13 @@ const RippleAPI = require('../../src').RippleAPI; // require('ripple-lib')
|
||||
const address = 'INSERT ADDRESS HERE';
|
||||
const secret = 'INSERT SECRET HERE';
|
||||
|
||||
const api = new RippleAPI({servers: ['wss://s1.ripple.com:443']});
|
||||
const api = new RippleAPI({server: 'wss://s1.ripple.com:443'});
|
||||
const instructions = {maxLedgerVersionOffset: 5};
|
||||
|
||||
const payment = {
|
||||
source: {
|
||||
address: address,
|
||||
amount: {
|
||||
maxAmount: {
|
||||
value: '0.01',
|
||||
currency: 'XRP'
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ const {RippleAPI} = require('ripple-lib');
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server hosted by Ripple, Inc.
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
api.connect().then(() => {
|
||||
/* insert code here */
|
||||
}).then(() => {
|
||||
@@ -27,6 +30,10 @@ All the code snippets in this documentation assume that you have surrounded them
|
||||
If you omit the "catch" section, errors may not be visible.
|
||||
</aside>
|
||||
|
||||
<aside class="notice">
|
||||
The "error" event is emitted whenever an error occurs that cannot be associated with a specific request. If the listener is not registered, an exception will be thrown whenever the event is emitted.
|
||||
</aside>
|
||||
|
||||
### Parameters
|
||||
|
||||
The RippleAPI constructor optionally takes one argument, an object with the following options:
|
||||
|
||||
@@ -20,16 +20,26 @@ api.on('ledger', ledger => {
|
||||
|
||||
## error
|
||||
|
||||
This event is emitted when there is an error on the connection to the server.
|
||||
This event is emitted when there is an error on the connection to the server that cannot be associated to a specific request.
|
||||
|
||||
### Return Value
|
||||
|
||||
The first parameter is a string indicating the error type, which may be `badMessage` (meaning that rippled returned a malformed message), or one of the [rippled Universal Errors](https://ripple.com/build/rippled-apis/#universal-errors). The second parameter is a message explaining the error, or the message that caused the error in the case of `badMessage`.
|
||||
The first parameter is a string indicating the error type:
|
||||
* `badMessage` - rippled returned a malformed message
|
||||
* `websocket` - the websocket library emitted an error
|
||||
* one of the error codes found in the [rippled Universal Errors](https://ripple.com/build/rippled-apis/#universal-errors).
|
||||
|
||||
The second parameter is a message explaining the error.
|
||||
|
||||
The third parameter is:
|
||||
* the message that caused the error for `badMessage`
|
||||
* the error object emitted for `websocket`
|
||||
* the parsed response for rippled errors
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
api.on('error', (errorCode, errorMessage, data) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
```
|
||||
|
||||
@@ -6,7 +6,7 @@ Generate a new Ripple address and corresponding secret.
|
||||
|
||||
### Parameters
|
||||
|
||||
This method has no parameters.
|
||||
<%- renderSchema('input/generate-address.json') %>
|
||||
|
||||
### Return Value
|
||||
|
||||
@@ -17,8 +17,7 @@ This method returns an object with the following structure:
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
return api.generateAddress()
|
||||
.then(result => {/* ... */});
|
||||
return api.generateAddress();
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/generate-address.json') %>
|
||||
|
||||
@@ -10,7 +10,7 @@ This method has no parameters.
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a promise that resolves with a 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 +19,5 @@ return api.getFee().then(fee => {/* ... */});
|
||||
```
|
||||
|
||||
```json
|
||||
0.012
|
||||
"0.012"
|
||||
```
|
||||
|
||||
137
npm-shrinkwrap.json
generated
137
npm-shrinkwrap.json
generated
@@ -1,30 +1,35 @@
|
||||
{
|
||||
"name": "ripple-lib",
|
||||
"version": "0.15.0",
|
||||
"version": "0.16.2",
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "1.4.8",
|
||||
"from": "https://registry.npmjs.org/ajv/-/ajv-1.4.8.tgz",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-1.4.8.tgz",
|
||||
"version": "1.4.10",
|
||||
"from": "ajv@>=1.4.8 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-1.4.10.tgz",
|
||||
"dependencies": {
|
||||
"json-stable-stringify": {
|
||||
"version": "1.0.0",
|
||||
"from": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.0.tgz",
|
||||
"from": "json-stable-stringify@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.0.tgz",
|
||||
"dependencies": {
|
||||
"jsonify": {
|
||||
"version": "0.0.0",
|
||||
"from": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
|
||||
"from": "jsonify@>=0.0.0 <0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ajv-i18n": {
|
||||
"version": "0.1.1",
|
||||
"from": "ajv-i18n@>=0.1.0 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv-i18n/-/ajv-i18n-0.1.1.tgz"
|
||||
},
|
||||
"babel-polyfill": {
|
||||
"version": "6.2.0",
|
||||
"from": "babel-polyfill@*",
|
||||
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.2.0.tgz",
|
||||
"version": "6.3.14",
|
||||
"from": "babel-polyfill@>=6.2.0 <7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.3.14.tgz",
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "1.2.6",
|
||||
@@ -32,28 +37,28 @@
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz"
|
||||
},
|
||||
"babel-regenerator-runtime": {
|
||||
"version": "6.2.0",
|
||||
"from": "babel-regenerator-runtime@>=6.2.0 <7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-regenerator-runtime/-/babel-regenerator-runtime-6.2.0.tgz"
|
||||
"version": "6.3.13",
|
||||
"from": "babel-regenerator-runtime@>=6.3.13 <7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-regenerator-runtime/-/babel-regenerator-runtime-6.3.13.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-runtime": {
|
||||
"version": "5.8.29",
|
||||
"from": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.29.tgz",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.29.tgz",
|
||||
"version": "5.8.34",
|
||||
"from": "babel-runtime@>=5.5.4 <6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.34.tgz",
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "1.2.3",
|
||||
"from": "https://registry.npmjs.org/core-js/-/core-js-1.2.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.3.tgz"
|
||||
"version": "1.2.6",
|
||||
"from": "core-js@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.2",
|
||||
"from": "bignumber.js@>=2.0.3 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.1.0.tgz"
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.1.2.tgz"
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "1.0.0",
|
||||
@@ -91,6 +96,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"jayson": {
|
||||
"version": "1.2.2",
|
||||
"from": "jayson@>=1.2.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-1.2.2.tgz",
|
||||
"dependencies": {
|
||||
"JSONStream": {
|
||||
"version": "1.0.3",
|
||||
"from": "JSONStream@1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.0.3.tgz",
|
||||
"dependencies": {
|
||||
"jsonparse": {
|
||||
"version": "1.0.0",
|
||||
"from": "jsonparse@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.0.0.tgz"
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"from": "through@>=2.2.7 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "1.3.2",
|
||||
"from": "commander@1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-1.3.2.tgz",
|
||||
"dependencies": {
|
||||
"keypress": {
|
||||
"version": "0.1.0",
|
||||
"from": "keypress@>=0.1.0 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyes": {
|
||||
"version": "0.1.8",
|
||||
"from": "eyes@0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz"
|
||||
},
|
||||
"lodash": {
|
||||
"version": "3.6.0",
|
||||
"from": "lodash@3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "3.10.1",
|
||||
"from": "lodash@>=3.1.0 <4.0.0",
|
||||
@@ -128,9 +179,9 @@
|
||||
}
|
||||
},
|
||||
"ripple-binary-codec": {
|
||||
"version": "0.1.0",
|
||||
"from": "ripple-binary-codec@0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-0.1.0.tgz",
|
||||
"version": "0.1.1",
|
||||
"from": "ripple-binary-codec@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-0.1.1.tgz",
|
||||
"dependencies": {
|
||||
"bn.js": {
|
||||
"version": "3.3.0",
|
||||
@@ -166,14 +217,14 @@
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@>=2.0.1 <3.0.0",
|
||||
"from": "inherits@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ripple-hashes": {
|
||||
"version": "0.1.0",
|
||||
"from": "ripple-hashes@0.1.0",
|
||||
"from": "ripple-hashes@>=0.1.0 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-hashes/-/ripple-hashes-0.1.0.tgz",
|
||||
"dependencies": {
|
||||
"create-hash": {
|
||||
@@ -227,7 +278,7 @@
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@>=2.0.1 <3.0.0",
|
||||
"from": "inherits@>=2.0.1 <2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
}
|
||||
}
|
||||
@@ -265,40 +316,6 @@
|
||||
"version": "1.0.2",
|
||||
"from": "ultron@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz"
|
||||
},
|
||||
"bufferutil": {
|
||||
"version": "1.1.0",
|
||||
"from": "bufferutil@>=1.1.0 <1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-1.1.0.tgz",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1",
|
||||
"from": "bindings@>=1.2.0 <1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.8.4",
|
||||
"from": "nan@>=1.8.0 <1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"version": "1.1.0",
|
||||
"from": "utf-8-validate@>=1.1.0 <1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-1.1.0.tgz",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1",
|
||||
"from": "bindings@>=1.2.0 <1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.8.4",
|
||||
"from": "nan@>=1.8.0 <1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripple-lib",
|
||||
"version": "0.15.0",
|
||||
"version": "0.16.2",
|
||||
"license": "ISC",
|
||||
"description": "A JavaScript API for interacting with Ripple in Node.js and the browser",
|
||||
"files": [
|
||||
@@ -20,9 +20,10 @@
|
||||
"babel-runtime": "^5.5.4",
|
||||
"bignumber.js": "^2.0.3",
|
||||
"https-proxy-agent": "^1.0.0",
|
||||
"jayson": "^1.2.2",
|
||||
"lodash": "^3.1.0",
|
||||
"ripple-address-codec": "^2.0.1",
|
||||
"ripple-binary-codec": "^0.1.0",
|
||||
"ripple-binary-codec": "^0.1.1",
|
||||
"ripple-hashes": "^0.1.0",
|
||||
"ripple-keypairs": "^0.10.0",
|
||||
"ripple-lib-transactionparser": "^0.6.0",
|
||||
@@ -65,7 +66,8 @@
|
||||
"test": "istanbul test _mocha",
|
||||
"coveralls": "cat ./coverage/lcov.info | coveralls",
|
||||
"lint": "if ! [ -f eslintrc ]; then curl -o eslintrc 'https://raw.githubusercontent.com/ripple/javascript-style-guide/es6/eslintrc'; echo 'parser: babel-eslint' >> eslintrc; fi; eslint -c eslintrc src/",
|
||||
"perf": "./scripts/perf_test.sh"
|
||||
"perf": "./scripts/perf_test.sh",
|
||||
"start": "babel-node scripts/http.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -34,6 +34,7 @@ unittest() {
|
||||
|
||||
integrationtest() {
|
||||
mocha test/integration/integration-test.js
|
||||
mocha test/integration/http-integration-test.js
|
||||
}
|
||||
|
||||
doctest() {
|
||||
|
||||
16
scripts/http.js
Normal file
16
scripts/http.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const createHTTPServer = require('../src/index').createHTTPServer;
|
||||
const port = 5990;
|
||||
const serverUrl = 'wss://s1.ripple.com';
|
||||
|
||||
|
||||
function main() {
|
||||
const server = createHTTPServer({server: serverUrl}, port);
|
||||
server.start().then(() => {
|
||||
console.log('Server started on port ' + String(port));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
main();
|
||||
@@ -9,7 +9,7 @@
|
||||
// In node.js env, polyfill might be already loaded (from any npm package),
|
||||
// that's why we do this check.
|
||||
if (!global._babelPolyfill) {
|
||||
require('babel-core/polyfill');
|
||||
require('babel-polyfill');
|
||||
}
|
||||
|
||||
const _ = require('lodash');
|
||||
@@ -46,7 +46,8 @@ const prepareSettings = require('./transaction/settings');
|
||||
const sign = require('./transaction/sign');
|
||||
const submit = require('./transaction/submit');
|
||||
const errors = require('./common').errors;
|
||||
const generateAddress = common.generateAddressAPI;
|
||||
const generateAddress =
|
||||
require('./offline/generate-address').generateAddressAPI;
|
||||
const computeLedgerHash = require('./offline/ledgerhash');
|
||||
const getLedger = require('./ledger/ledger');
|
||||
|
||||
@@ -84,8 +85,8 @@ class RippleAPI extends EventEmitter {
|
||||
this.connection.on('ledgerClosed', message => {
|
||||
this.emit('ledger', server.formatLedgerClose(message));
|
||||
});
|
||||
this.connection.on('error', (type, info) => {
|
||||
this.emit('error', type, info);
|
||||
this.connection.on('error', (errorCode, errorMessage, data) => {
|
||||
this.emit('error', errorCode, errorMessage, data);
|
||||
});
|
||||
} else {
|
||||
// use null object pattern to provide better error message if user
|
||||
|
||||
@@ -37,7 +37,8 @@ class RippleAPIBroadcast extends RippleAPI {
|
||||
|
||||
apis.forEach(api => {
|
||||
api.on('ledger', this.onLedgerEvent.bind(this));
|
||||
api.on('error', (type, info) => this.emit('error', type, info));
|
||||
api.on('error', (errorCode, errorMessage, data) =>
|
||||
this.emit('error', errorCode, errorMessage, data));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const {EventEmitter} = require('events');
|
||||
const WebSocket = require('ws');
|
||||
const parseURL = require('url').parse;
|
||||
@@ -15,6 +16,7 @@ function isStreamMessageType(type) {
|
||||
class Connection extends EventEmitter {
|
||||
constructor(url, options = {}) {
|
||||
super();
|
||||
this.setMaxListeners(Infinity);
|
||||
this._url = url;
|
||||
this._trace = options.trace;
|
||||
if (this._trace) {
|
||||
@@ -25,6 +27,9 @@ class Connection extends EventEmitter {
|
||||
this._proxyAuthorization = options.proxyAuthorization;
|
||||
this._authorization = options.authorization;
|
||||
this._trustedCertificates = options.trustedCertificates;
|
||||
this._key = options.key;
|
||||
this._passphrase = options.passphrase;
|
||||
this._certificate = options.certificate;
|
||||
this._timeout = options.timeout || (20 * 1000);
|
||||
this._isReady = false;
|
||||
this._ws = null;
|
||||
@@ -50,7 +55,7 @@ class Connection extends EventEmitter {
|
||||
}
|
||||
return [data.type, data];
|
||||
} else if (data.type === undefined && data.error) {
|
||||
return ['error', data.error, data.error_message]; // e.g. slowDown
|
||||
return ['error', data.error, data.error_message, data]; // e.g. slowDown
|
||||
}
|
||||
throw new ResponseFormatError('unrecognized message type: ' + data.type);
|
||||
}
|
||||
@@ -63,7 +68,7 @@ class Connection extends EventEmitter {
|
||||
try {
|
||||
parameters = this._parseMessage(message);
|
||||
} catch (error) {
|
||||
this.emit('error', 'badMessage', message);
|
||||
this.emit('error', 'badMessage', error.message, message);
|
||||
return;
|
||||
}
|
||||
// we don't want this inside the try/catch or exceptions in listener
|
||||
@@ -103,18 +108,21 @@ class Connection extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
_createWebSocket(url, proxyURL, proxyAuthorization, authorization,
|
||||
trustedCertificates) {
|
||||
_createWebSocket() {
|
||||
const options = {};
|
||||
if (proxyURL !== undefined) {
|
||||
const parsedURL = parseURL(url);
|
||||
const proxyOptions = parseURL(proxyURL);
|
||||
proxyOptions.secureEndpoint = (parsedURL.protocol === 'wss:');
|
||||
proxyOptions.secureProxy = (proxyOptions.protocol === 'https:');
|
||||
proxyOptions.auth = proxyAuthorization;
|
||||
if (trustedCertificates) {
|
||||
proxyOptions.ca = trustedCertificates;
|
||||
}
|
||||
if (this._proxyURL !== undefined) {
|
||||
const parsedURL = parseURL(this._url);
|
||||
const parsedProxyURL = parseURL(this._proxyURL);
|
||||
const proxyOverrides = _.omit({
|
||||
secureEndpoint: (parsedURL.protocol === 'wss:'),
|
||||
secureProxy: (parsedProxyURL.protocol === 'https:'),
|
||||
auth: this._proxyAuthorization,
|
||||
ca: this._trustedCertificates,
|
||||
key: this._key,
|
||||
passphrase: this._passphrase,
|
||||
cert: this._certificate
|
||||
}, _.isUndefined);
|
||||
const proxyOptions = _.assign({}, parsedProxyURL, proxyOverrides);
|
||||
let HttpsProxyAgent;
|
||||
try {
|
||||
HttpsProxyAgent = require('https-proxy-agent');
|
||||
@@ -123,11 +131,22 @@ class Connection extends EventEmitter {
|
||||
}
|
||||
options.agent = new HttpsProxyAgent(proxyOptions);
|
||||
}
|
||||
if (authorization !== undefined) {
|
||||
const base64 = new Buffer(authorization).toString('base64');
|
||||
if (this._authorization !== undefined) {
|
||||
const base64 = new Buffer(this._authorization).toString('base64');
|
||||
options.headers = {Authorization: `Basic ${base64}`};
|
||||
}
|
||||
return new WebSocket(url, options);
|
||||
const optionsOverrides = _.omit({
|
||||
ca: this._trustedCertificates,
|
||||
key: this._key,
|
||||
passphrase: this._passphrase,
|
||||
cert: this._certificate
|
||||
}, _.isUndefined);
|
||||
const websocketOptions = _.assign({}, options, optionsOverrides);
|
||||
const websocket = new WebSocket(this._url, websocketOptions);
|
||||
// we will have a listener for each outstanding request,
|
||||
// so we have to raise the limit (the default is 10)
|
||||
websocket.setMaxListeners(Infinity);
|
||||
return websocket;
|
||||
}
|
||||
|
||||
connect() {
|
||||
@@ -141,9 +160,13 @@ class Connection extends EventEmitter {
|
||||
} else if (this._state === WebSocket.CONNECTING) {
|
||||
this._ws.once('open', resolve);
|
||||
} else {
|
||||
this._ws = this._createWebSocket(this._url, this._proxyURL,
|
||||
this._proxyAuthorization, this._authorization,
|
||||
this._trustedCertificates);
|
||||
this._ws = this._createWebSocket();
|
||||
// when an error causes the connection to close, the close event
|
||||
// should still be emitted; the "ws" documentation says: "The close
|
||||
// event is also emitted when then underlying net.Socket closes the
|
||||
// connection (end or close)."
|
||||
this._ws.on('error', error =>
|
||||
this.emit('error', 'websocket', error.messsage, error));
|
||||
this._ws.on('message', this._onMessage.bind(this));
|
||||
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this);
|
||||
this._ws.once('close', this._onUnexpectedCloseBound);
|
||||
|
||||
@@ -92,8 +92,9 @@ function loadSchemas() {
|
||||
require('./schemas/input/prepare-suspended-payment-cancellation.json'),
|
||||
require('./schemas/input/prepare-suspended-payment-execution.json'),
|
||||
require('./schemas/input/compute-ledger-hash'),
|
||||
require('./schemas/input/sign'),
|
||||
require('./schemas/input/submit')
|
||||
require('./schemas/input/sign.json'),
|
||||
require('./schemas/input/submit.json'),
|
||||
require('./schemas/input/generate-address.json')
|
||||
];
|
||||
const titles = _.map(schemas, schema => schema.title);
|
||||
const duplicates = _.keys(_.pick(_.countBy(titles), count => count > 1));
|
||||
|
||||
@@ -42,6 +42,18 @@
|
||||
"type": "string",
|
||||
"description": "A PEM-formatted SSL certificate to trust when connecting to a proxy."
|
||||
}
|
||||
},
|
||||
"key": {
|
||||
"type": "string",
|
||||
"description": "A string containing the private key of the client in PEM format. (Can be an array of keys)."
|
||||
},
|
||||
"passphrase": {
|
||||
"type": "string",
|
||||
"description": "The passphrase for the private key of the client."
|
||||
},
|
||||
"certificate": {
|
||||
"type": "string",
|
||||
"description": "A string containing the certificate key of the client in PEM format. (Can be an array of certificates)."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
29
src/common/schemas/input/generate-address.json
Normal file
29
src/common/schemas/input/generate-address.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "generateAddressParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"options": {
|
||||
"type": "object",
|
||||
"description": "Options to control how the address and secret are generated.",
|
||||
"properties": {
|
||||
"entropy": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"description": "The entropy to use to generate the seed."
|
||||
},
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"enum": ["ecdsa-secp256k1", "ed25519"],
|
||||
"description": "The digital signature algorithm to generate an address for. Can be `ecdsa-secp256k1` (default) or `ed25519`."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -18,11 +18,14 @@
|
||||
"$ref": "value"
|
||||
},
|
||||
"maxLedgerVersion": {
|
||||
"description": "The highest ledger version that the transaction can be included in.",
|
||||
"$ref": "ledgerVersion"
|
||||
"description": "The highest ledger version that the transaction can be included in. If this option and `maxLedgerVersionOffset` are both omitted, the `maxLedgerVersion` option will default to 3 greater than the current validated ledger version (equivalent to `maxLedgerVersionOffset=3`). Use `null` to not set a maximum ledger version.",
|
||||
"oneOf": [
|
||||
{"$ref": "ledgerVersion"},
|
||||
{"type": "null"}
|
||||
]
|
||||
},
|
||||
"maxLedgerVersionOffset": {
|
||||
"description": "Offset from current legder version to highest ledger version that the transaction can be included in.",
|
||||
"description": "Offset from current validated legder version to highest ledger version that the transaction can be included in.",
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
"description": "The time since the ledger was closed, in seconds."
|
||||
},
|
||||
"baseFeeXRP": {
|
||||
"type": "number",
|
||||
"$ref": "value",
|
||||
"description": "Base fee, in XRP. This may be represented in scientific notation such as 1e-05 for 0.00005."
|
||||
},
|
||||
"hash": {
|
||||
@@ -91,13 +91,11 @@
|
||||
"description": "Unique hash for the ledger, as an uppercase hexadecimal string."
|
||||
},
|
||||
"reserveBaseXRP": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"$ref": "value",
|
||||
"description": "Minimum amount of XRP necessary for every account to keep in reserve."
|
||||
},
|
||||
"reserveIncrementXRP": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"$ref": "value",
|
||||
"description": "Amount of XRP added to the account reserve for each object an account is responsible for in the ledger."
|
||||
},
|
||||
"ledgerVersion": {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"reserveBaseXRP": {
|
||||
"$ref": "value",
|
||||
"description": "The minimum reserve, in drops of XRP, that is required for an account."
|
||||
"description": "The minimum reserve, in XRP, that is required for an account."
|
||||
},
|
||||
"reserveIncrementXRP": {
|
||||
"$ref": "value",
|
||||
|
||||
@@ -21,12 +21,15 @@
|
||||
"description": "The initiating account's sequence number for this transaction."
|
||||
},
|
||||
"maxLedgerVersion": {
|
||||
"$ref": "ledgerVersion",
|
||||
"description": "The highest ledger version that the transaction can be included in."
|
||||
"oneOf": [
|
||||
{"$ref": "ledgerVersion"},
|
||||
{"type": "null"}
|
||||
],
|
||||
"description": "The highest ledger version that the transaction can be included in. Set to `null` if there is no maximum."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["fee", "sequence"]
|
||||
"required": ["fee", "sequence", "maxLedgerVersion"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -6,7 +6,7 @@ import type {Connection} from './connection';
|
||||
export type GetServerInfoResponse = {
|
||||
buildVersion: string,
|
||||
completeLedgers: string,
|
||||
hostid: string,
|
||||
hostID: string,
|
||||
ioLatencyMs: number,
|
||||
load?: {
|
||||
jobTypes: Array<Object>,
|
||||
@@ -23,11 +23,11 @@ export type GetServerInfoResponse = {
|
||||
serverState: string,
|
||||
validatedLedger: {
|
||||
age: number,
|
||||
baseFeeXrp: number,
|
||||
baseFeeXRP: string,
|
||||
hash: string,
|
||||
reserveBaseXrp: number,
|
||||
reserveIncXrp: number,
|
||||
seq: number
|
||||
reserveBaseXRP: string,
|
||||
reserveIncrementXRP: string,
|
||||
ledgerVersion: number
|
||||
},
|
||||
validationQuorum: number
|
||||
}
|
||||
@@ -49,6 +49,12 @@ function getServerInfo(connection: Connection): Promise<GetServerInfoResponse> {
|
||||
reserveIncXrp: 'reserveIncrementXRP',
|
||||
seq: 'ledgerVersion'
|
||||
});
|
||||
info.validatedLedger.baseFeeXRP =
|
||||
info.validatedLedger.baseFeeXRP.toString();
|
||||
info.validatedLedger.reserveBaseXRP =
|
||||
info.validatedLedger.reserveBaseXRP.toString();
|
||||
info.validatedLedger.reserveIncrementXRP =
|
||||
info.validatedLedger.reserveIncrementXRP.toString();
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const BigNumber = require('bignumber.js');
|
||||
const errors = require('./errors');
|
||||
const keypairs = require('ripple-keypairs');
|
||||
const {deriveKeypair} = require('ripple-keypairs');
|
||||
|
||||
import type {Amount, RippledAmount} from './types.js';
|
||||
@@ -37,21 +35,6 @@ function toRippledAmount(amount: Amount): RippledAmount {
|
||||
};
|
||||
}
|
||||
|
||||
function generateAddress(options?: Object): Object {
|
||||
const secret = keypairs.generateSeed(options);
|
||||
const keypair = keypairs.deriveKeypair(secret);
|
||||
const address = keypairs.deriveAddress(keypair.publicKey);
|
||||
return {secret, address};
|
||||
}
|
||||
|
||||
function generateAddressAPI(options?: Object): Object {
|
||||
try {
|
||||
return generateAddress(options);
|
||||
} catch (error) {
|
||||
throw new errors.UnexpectedError(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g;
|
||||
function convertKeysFromSnakeCaseToCamelCase(obj: any): any {
|
||||
if (typeof obj === 'object') {
|
||||
@@ -101,8 +84,6 @@ module.exports = {
|
||||
dropsToXrp,
|
||||
xrpToDrops,
|
||||
toRippledAmount,
|
||||
generateAddress,
|
||||
generateAddressAPI,
|
||||
convertKeysFromSnakeCaseToCamelCase,
|
||||
removeUndefined,
|
||||
rippleTimeToISO8601,
|
||||
|
||||
@@ -49,6 +49,7 @@ module.exports = {
|
||||
sign: _.partial(schemaValidate, 'signParameters'),
|
||||
submit: _.partial(schemaValidate, 'submitParameters'),
|
||||
computeLedgerHash: _.partial(schemaValidate, 'computeLedgerHashParameters'),
|
||||
generateAddress: _.partial(schemaValidate, 'generateAddressParameters'),
|
||||
apiOptions: _.partial(schemaValidate, 'api-options'),
|
||||
instructions: _.partial(schemaValidate, 'instructions')
|
||||
};
|
||||
|
||||
85
src/http.js
Normal file
85
src/http.js
Normal file
@@ -0,0 +1,85 @@
|
||||
/* eslint-disable new-cap */
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const _ = require('lodash');
|
||||
const jayson = require('jayson');
|
||||
|
||||
const RippleAPI = require('./api').RippleAPI;
|
||||
|
||||
|
||||
function createHTTPServer(options, httpPort) {
|
||||
const rippleAPI = new RippleAPI(options);
|
||||
|
||||
const methodNames = _.filter(_.keys(RippleAPI.prototype), k => {
|
||||
return typeof RippleAPI.prototype[k] === 'function'
|
||||
&& k !== 'connect'
|
||||
&& k !== 'disconnect'
|
||||
&& k !== 'constructor'
|
||||
&& k !== 'RippleAPI';
|
||||
});
|
||||
|
||||
function applyPromiseWithCallback(fnName, callback, args_) {
|
||||
try {
|
||||
let args = args_;
|
||||
if (!_.isArray(args_)) {
|
||||
const fnParameters = jayson.Utils.getParameterNames(rippleAPI[fnName]);
|
||||
args = fnParameters.map(name => args_[name]);
|
||||
const defaultArgs = _.omit(args_, fnParameters);
|
||||
assert(_.size(defaultArgs) <= 1,
|
||||
'Function must have no more than one default argument');
|
||||
if (_.size(defaultArgs) > 0) {
|
||||
args.push(defaultArgs[_.keys(defaultArgs)[0]]);
|
||||
}
|
||||
}
|
||||
Promise.resolve(rippleAPI[fnName].apply(rippleAPI, args))
|
||||
.then(res => callback(null, res))
|
||||
.catch(err => {
|
||||
callback({code: 99, message: err.message, data: {name: err.name}});
|
||||
});
|
||||
} catch (err) {
|
||||
callback({code: 99, message: err.message, data: {name: err.name}});
|
||||
}
|
||||
}
|
||||
|
||||
const methods = {};
|
||||
_.forEach(methodNames, fn => {
|
||||
methods[fn] = jayson.Method((args, cb) => {
|
||||
applyPromiseWithCallback(fn, cb, args);
|
||||
}, {collect: true});
|
||||
});
|
||||
|
||||
const server = jayson.server(methods);
|
||||
let httpServer = null;
|
||||
|
||||
return {
|
||||
server: server,
|
||||
start: function() {
|
||||
if (httpServer !== null) {
|
||||
return Promise.reject('Already started');
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
rippleAPI.connect().then(() => {
|
||||
httpServer = server.http();
|
||||
httpServer.listen(httpPort, resolve);
|
||||
});
|
||||
});
|
||||
},
|
||||
stop: function() {
|
||||
if (httpServer === null) {
|
||||
return Promise.reject('Not started');
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
rippleAPI.disconnect();
|
||||
httpServer.close(() => {
|
||||
httpServer = null;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createHTTPServer
|
||||
};
|
||||
@@ -2,5 +2,8 @@
|
||||
|
||||
module.exports = {
|
||||
RippleAPI: require('./api').RippleAPI,
|
||||
RippleAPIBroadcast: require('./broadcast').RippleAPIBroadcast
|
||||
// Broadcast api is experimental
|
||||
RippleAPIBroadcast: require('./broadcast').RippleAPIBroadcast,
|
||||
// HTTP server is experimental
|
||||
createHTTPServer: require('./http').createHTTPServer
|
||||
};
|
||||
|
||||
@@ -24,8 +24,8 @@ function parseAccountTrustline(trustline: Trustline): AccountTrustline {
|
||||
limit: trustline.limit,
|
||||
currency: trustline.currency,
|
||||
counterparty: trustline.account,
|
||||
qualityIn: trustline.quality_in || undefined,
|
||||
qualityOut: trustline.quality_out || undefined,
|
||||
qualityIn: utils.parseQuality(trustline.quality_in) || undefined,
|
||||
qualityOut: utils.parseQuality(trustline.quality_out) || undefined,
|
||||
ripplingDisabled: trustline.no_ripple || undefined,
|
||||
frozen: trustline.freeze || undefined,
|
||||
authorized: trustline.authorized || undefined
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
const assert = require('assert');
|
||||
const utils = require('./utils');
|
||||
const flags = utils.txFlags.TrustSet;
|
||||
const BigNumber = require('bignumber.js');
|
||||
|
||||
function parseFlag(flagsValue, trueValue, falseValue) {
|
||||
if (flagsValue & trueValue) {
|
||||
@@ -15,13 +14,6 @@ function parseFlag(flagsValue, trueValue, falseValue) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseQuality(quality?: number) {
|
||||
if (typeof quality === 'number') {
|
||||
return (new BigNumber(quality)).shift(-9).toNumber();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseTrustline(tx: Object): Object {
|
||||
assert(tx.TransactionType === 'TrustSet');
|
||||
|
||||
@@ -29,8 +21,8 @@ function parseTrustline(tx: Object): Object {
|
||||
limit: tx.LimitAmount.value,
|
||||
currency: tx.LimitAmount.currency,
|
||||
counterparty: tx.LimitAmount.issuer,
|
||||
qualityIn: parseQuality(tx.QualityIn),
|
||||
qualityOut: parseQuality(tx.QualityOut),
|
||||
qualityIn: utils.parseQuality(tx.QualityIn),
|
||||
qualityOut: utils.parseQuality(tx.QualityOut),
|
||||
ripplingDisabled: parseFlag(
|
||||
tx.Flags, flags.SetNoRipple, flags.ClearNoRipple),
|
||||
frozen: parseFlag(tx.Flags, flags.SetFreeze, flags.ClearFreeze),
|
||||
|
||||
@@ -17,6 +17,13 @@ function adjustQualityForXRP(
|
||||
(new BigNumber(quality)).shift(shift).toString();
|
||||
}
|
||||
|
||||
function parseQuality(quality: ?number) {
|
||||
if (typeof quality === 'number') {
|
||||
return (new BigNumber(quality)).shift(-9).toNumber();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseTimestamp(rippleTime: number): string | void {
|
||||
return rippleTime ? utils.common.rippleTimeToISO8601(rippleTime) : undefined;
|
||||
}
|
||||
@@ -80,6 +87,7 @@ function parseMemos(tx: Object): ?Array<Object> {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parseQuality,
|
||||
parseOutcome,
|
||||
parseMemos,
|
||||
hexToString,
|
||||
|
||||
@@ -170,11 +170,11 @@ function getTransactions(address: string, options: TransactionsOptions = {}
|
||||
const ledgerVersion = tx.outcome.ledgerVersion;
|
||||
const bound = options.earliestFirst ?
|
||||
{minLedgerVersion: ledgerVersion} : {maxLedgerVersion: ledgerVersion};
|
||||
const newOptions = _.assign(defaults, options, {startTx: tx}, bound);
|
||||
const newOptions = _.assign({}, defaults, options, {startTx: tx}, bound);
|
||||
return getTransactionsInternal(this.connection, address, newOptions);
|
||||
});
|
||||
}
|
||||
const newOptions = _.assign(defaults, options);
|
||||
const newOptions = _.assign({}, defaults, options);
|
||||
return getTransactionsInternal(this.connection, address, newOptions);
|
||||
}
|
||||
|
||||
|
||||
24
src/offline/generate-address.js
Normal file
24
src/offline/generate-address.js
Normal file
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
const keypairs = require('ripple-keypairs');
|
||||
const common = require('../common');
|
||||
const {errors, validate} = common;
|
||||
|
||||
function generateAddress(options?: Object): Object {
|
||||
const secret = keypairs.generateSeed(options);
|
||||
const keypair = keypairs.deriveKeypair(secret);
|
||||
const address = keypairs.deriveAddress(keypair.publicKey);
|
||||
return {secret, address};
|
||||
}
|
||||
|
||||
function generateAddressAPI(options?: Object): Object {
|
||||
validate.generateAddress({options});
|
||||
try {
|
||||
return generateAddress(options);
|
||||
} catch (error) {
|
||||
throw new errors.UnexpectedError(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generateAddressAPI
|
||||
};
|
||||
@@ -64,7 +64,7 @@ function createMaximalAmount(amount: Amount): Amount {
|
||||
const maxXRPValue = '100000000000';
|
||||
const maxIOUValue = '9999999999999999e80';
|
||||
const maxValue = amount.currency === 'XRP' ? maxXRPValue : maxIOUValue;
|
||||
return _.assign(amount, {value: maxValue});
|
||||
return _.assign({}, amount, {value: maxValue});
|
||||
}
|
||||
|
||||
function createPaymentTransaction(address: string, paymentArgument: Payment
|
||||
|
||||
@@ -10,7 +10,8 @@ function formatPrepareResponse(txJSON: Object): Object {
|
||||
const instructions = {
|
||||
fee: common.dropsToXrp(txJSON.Fee),
|
||||
sequence: txJSON.Sequence,
|
||||
maxLedgerVersion: txJSON.LastLedgerSequence
|
||||
maxLedgerVersion: txJSON.LastLedgerSequence === undefined ?
|
||||
null : txJSON.LastLedgerSequence
|
||||
};
|
||||
return {
|
||||
txJSON: JSON.stringify(txJSON),
|
||||
@@ -36,7 +37,9 @@ function prepareTransaction(txJSON: Object, api: Object,
|
||||
|
||||
function prepareMaxLedgerVersion(): Promise<Object> {
|
||||
if (instructions.maxLedgerVersion !== undefined) {
|
||||
txJSON.LastLedgerSequence = instructions.maxLedgerVersion;
|
||||
if (instructions.maxLedgerVersion !== null) {
|
||||
txJSON.LastLedgerSequence = instructions.maxLedgerVersion;
|
||||
}
|
||||
return Promise.resolve(txJSON);
|
||||
}
|
||||
const offset = instructions.maxLedgerVersionOffset !== undefined ?
|
||||
|
||||
@@ -14,6 +14,7 @@ const address = addresses.ACCOUNT;
|
||||
const utils = RippleAPI._PRIVATE.ledgerUtils;
|
||||
const ledgerClosed = require('./fixtures/rippled/ledger-close-newer');
|
||||
const schemaValidator = RippleAPI._PRIVATE.schemaValidator;
|
||||
assert.options.strict = true;
|
||||
|
||||
function unused() {
|
||||
}
|
||||
@@ -186,6 +187,13 @@ describe('RippleAPI', function() {
|
||||
_.partial(checkResult, responses.prepareSettings.flags, 'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - no maxLedgerVersion', function() {
|
||||
return this.api.prepareSettings(
|
||||
address, requests.prepareSettings, {maxLedgerVersion: null}).then(
|
||||
_.partial(checkResult, responses.prepareSettings.noMaxLedgerVersion,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - no instructions', function() {
|
||||
return this.api.prepareSettings(
|
||||
address, requests.prepareSettings).then(
|
||||
|
||||
62
test/broadcast-api-test.js
Normal file
62
test/broadcast-api-test.js
Normal file
@@ -0,0 +1,62 @@
|
||||
/* eslint-disable max-nested-callbacks */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert-diff');
|
||||
const setupAPI = require('./setup-api');
|
||||
const responses = require('./fixtures').responses;
|
||||
const ledgerClosed = require('./fixtures/rippled/ledger-close');
|
||||
const RippleAPI = require('ripple-api').RippleAPI;
|
||||
const schemaValidator = RippleAPI._PRIVATE.schemaValidator;
|
||||
|
||||
function checkResult(expected, schemaName, response) {
|
||||
if (expected.txJSON) {
|
||||
assert(response.txJSON);
|
||||
assert.deepEqual(JSON.parse(response.txJSON), JSON.parse(expected.txJSON));
|
||||
}
|
||||
assert.deepEqual(_.omit(response, 'txJSON'), _.omit(expected, 'txJSON'));
|
||||
if (schemaName) {
|
||||
schemaValidator.schemaValidate(schemaName, response);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
describe('RippleAPIBroadcast', function() {
|
||||
beforeEach(setupAPI.setupBroadcast);
|
||||
afterEach(setupAPI.teardown);
|
||||
|
||||
it('base', function() {
|
||||
const expected = {request_server_info: 1};
|
||||
this.mocks.forEach(mock => mock.expect(_.assign({}, expected)));
|
||||
assert(this.api.isConnected());
|
||||
return this.api.getServerInfo().then(
|
||||
_.partial(checkResult, responses.getServerInfo, 'getServerInfo'));
|
||||
});
|
||||
|
||||
it('ledger', function(done) {
|
||||
let gotLedger = 0;
|
||||
this.api.on('ledger', () => {
|
||||
gotLedger++;
|
||||
});
|
||||
const ledgerNext = _.assign({}, ledgerClosed);
|
||||
ledgerNext.ledger_index++;
|
||||
this.mocks.forEach(mock => mock.socket.send(JSON.stringify(ledgerNext)));
|
||||
|
||||
setTimeout(() => {
|
||||
console.log('-- ledgerVersion', this.api.ledgerVersion);
|
||||
assert.strictEqual(gotLedger, 1);
|
||||
done();
|
||||
}, 50);
|
||||
|
||||
});
|
||||
|
||||
it('error propagation', function(done) {
|
||||
this.api.once('error', (type, info) => {
|
||||
assert.strictEqual(type, 'type');
|
||||
assert.strictEqual(info, 'info');
|
||||
done();
|
||||
});
|
||||
this.mocks[1].socket.send(
|
||||
JSON.stringify({error: 'type', error_message: 'info'}));
|
||||
});
|
||||
|
||||
});
|
||||
@@ -227,8 +227,9 @@ describe('Connection', function() {
|
||||
});
|
||||
|
||||
it('invalid message id', function(done) {
|
||||
this.api.on('error', (type, message) => {
|
||||
assert.strictEqual(type, 'badMessage');
|
||||
this.api.on('error', (errorCode, errorMessage, message) => {
|
||||
assert.strictEqual(errorCode, 'badMessage');
|
||||
assert.strictEqual(errorMessage, 'valid id not found in response');
|
||||
assert.strictEqual(message,
|
||||
'{"type":"response","id":"must be integer"}');
|
||||
done();
|
||||
@@ -239,9 +240,10 @@ describe('Connection', function() {
|
||||
});
|
||||
|
||||
it('propagate error message', function(done) {
|
||||
this.api.on('error', (type, message) => {
|
||||
assert.strictEqual(type, 'slowDown');
|
||||
assert.strictEqual(message, 'slow down');
|
||||
this.api.on('error', (errorCode, errorMessage, data) => {
|
||||
assert.strictEqual(errorCode, 'slowDown');
|
||||
assert.strictEqual(errorMessage, 'slow down');
|
||||
assert.deepEqual(data, {error: 'slowDown', error_message: 'slow down'});
|
||||
done();
|
||||
});
|
||||
this.api.connection._onMessage(JSON.stringify({
|
||||
@@ -250,8 +252,9 @@ describe('Connection', function() {
|
||||
});
|
||||
|
||||
it('unrecognized message type', function(done) {
|
||||
this.api.on('error', (type, message) => {
|
||||
assert.strictEqual(type, 'badMessage');
|
||||
this.api.on('error', (errorCode, errorMessage, message) => {
|
||||
assert.strictEqual(errorCode, 'badMessage');
|
||||
assert.strictEqual(errorMessage, 'unrecognized message type: unknown');
|
||||
assert.strictEqual(message, '{"type":"unknown"}');
|
||||
done();
|
||||
});
|
||||
|
||||
6
test/fixtures/responses/get-server-info.json
vendored
6
test/fixtures/responses/get-server-info.json
vendored
@@ -13,10 +13,10 @@
|
||||
"serverState": "full",
|
||||
"validatedLedger": {
|
||||
"age": 5,
|
||||
"baseFeeXRP": 0.00001,
|
||||
"baseFeeXRP": "0.00001",
|
||||
"hash": "4482DEE5362332F54A4036ED57EE1767C9F33CF7CE5A6670355C16CECE381D46",
|
||||
"reserveBaseXRP": 20,
|
||||
"reserveIncrementXRP": 5,
|
||||
"reserveBaseXRP": "20",
|
||||
"reserveIncrementXRP": "5",
|
||||
"ledgerVersion": 6595042
|
||||
},
|
||||
"validationQuorum": 3
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
"specification": {
|
||||
"limit": "0",
|
||||
"currency": "ASP",
|
||||
"counterparty": "r3vi7mWxru9rJCxETCyA1CHvzL96eZWx5z"
|
||||
"counterparty": "r3vi7mWxru9rJCxETCyA1CHvzL96eZWx5z",
|
||||
"qualityIn": 1
|
||||
},
|
||||
"counterparty": {
|
||||
"limit": "10"
|
||||
|
||||
7
test/fixtures/responses/index.js
vendored
7
test/fixtures/responses/index.js
vendored
@@ -71,8 +71,8 @@ module.exports = {
|
||||
},
|
||||
preparePayment: {
|
||||
normal: require('./prepare-payment.json'),
|
||||
minAmountXRP: require('./prepare-payment-min-amont-xrp.json'),
|
||||
minAmountXRPXRP: require('./prepare-payment-min-amont-xrp-xrp.json'),
|
||||
minAmountXRP: require('./prepare-payment-min-amount-xrp.json'),
|
||||
minAmountXRPXRP: require('./prepare-payment-min-amount-xrp-xrp.json'),
|
||||
allOptions: require('./prepare-payment-all-options.json'),
|
||||
noCounterparty: require('./prepare-payment-no-counterparty.json'),
|
||||
minAmount: require('./prepare-payment-min-amount.json')
|
||||
@@ -86,7 +86,8 @@ module.exports = {
|
||||
setTransferRate: require('./prepare-settings-set-transfer-rate.json'),
|
||||
fieldClear: require('./prepare-settings-field-clear.json'),
|
||||
noInstructions: require('./prepare-settings-no-instructions.json'),
|
||||
signed: require('./prepare-settings-signed.json')
|
||||
signed: require('./prepare-settings-signed.json'),
|
||||
noMaxLedgerVersion: require('./prepare-settings-no-maxledgerversion.json')
|
||||
},
|
||||
prepareSuspendedPaymentCreation: {
|
||||
normal: require('./prepare-suspended-payment-creation'),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"txJSON": "{\"TransactionType\":\"Payment\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Destination\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"Amount\":\"100000000000000000\",\"Flags\":2147614720,\"SendMax\":{\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\",\"value\":\"0.01\"},\"DeliverMin\":\"100000000000000000\",\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}",
|
||||
"txJSON": "{\"TransactionType\":\"Payment\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Destination\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"Amount\":\"100000000000000000\",\"Flags\":2147614720,\"SendMax\":{\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\",\"value\":\"0.01\"},\"DeliverMin\":\"10000\",\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}",
|
||||
"instructions": {
|
||||
"fee": "0.000012",
|
||||
"sequence": 23,
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"txJSON": "{\"Flags\":2147614720,\"TransactionType\":\"Payment\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Destination\":\"ra5nK24KXen9AHvsdFTKHSANinZseWnPcX\",\"Amount\":{\"value\":\"9999999999999999e80\",\"currency\":\"USD\",\"issuer\":\"ra5nK24KXen9AHvsdFTKHSANinZseWnPcX\"},\"SendMax\":{\"value\":\"5\",\"currency\":\"USD\",\"issuer\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\"},\"DeliverMin\":{\"value\":\"9999999999999999e80\",\"currency\":\"USD\",\"issuer\":\"ra5nK24KXen9AHvsdFTKHSANinZseWnPcX\"},\"Paths\":[[{\"account\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\"},{\"currency\":\"XRP\"},{\"issuer\":\"rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q\",\"currency\":\"USD\"},{\"account\":\"rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q\"},{\"account\":\"rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn\"}],[{\"account\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\"},{\"currency\":\"XRP\"},{\"issuer\":\"rfsEoNBUBbvkf4jPcFe2u9CyaQagLVHGfP\",\"currency\":\"USD\"},{\"account\":\"rfsEoNBUBbvkf4jPcFe2u9CyaQagLVHGfP\"},{\"account\":\"rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q\"}]],\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}",
|
||||
"txJSON": "{\"Flags\":2147614720,\"TransactionType\":\"Payment\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Destination\":\"ra5nK24KXen9AHvsdFTKHSANinZseWnPcX\",\"Amount\":{\"value\":\"9999999999999999e80\",\"currency\":\"USD\",\"issuer\":\"ra5nK24KXen9AHvsdFTKHSANinZseWnPcX\"},\"SendMax\":{\"value\":\"5\",\"currency\":\"USD\",\"issuer\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\"},\"DeliverMin\":{\"value\":\"4.93463759481038\",\"currency\":\"USD\",\"issuer\":\"ra5nK24KXen9AHvsdFTKHSANinZseWnPcX\"},\"Paths\":[[{\"account\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\"},{\"currency\":\"XRP\"},{\"issuer\":\"rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q\",\"currency\":\"USD\"},{\"account\":\"rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q\"},{\"account\":\"rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn\"}],[{\"account\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\"},{\"currency\":\"XRP\"},{\"issuer\":\"rfsEoNBUBbvkf4jPcFe2u9CyaQagLVHGfP\",\"currency\":\"USD\"},{\"account\":\"rfsEoNBUBbvkf4jPcFe2u9CyaQagLVHGfP\"},{\"account\":\"rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q\"}]],\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}",
|
||||
"instructions": {
|
||||
"fee": "0.000012",
|
||||
"sequence": 23,
|
||||
|
||||
8
test/fixtures/responses/prepare-settings-no-maxledgerversion.json
vendored
Normal file
8
test/fixtures/responses/prepare-settings-no-maxledgerversion.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"txJSON": "{\"TransactionType\":\"AccountSet\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Memos\":[{\"Memo\":{\"MemoData\":\"7465787465642064617461\",\"MemoType\":\"74657374\",\"MemoFormat\":\"706C61696E2F74657874\"}}],\"Domain\":\"726970706C652E636F6D\",\"Flags\":2147483648,\"Fee\":\"12\",\"Sequence\":23}",
|
||||
"instructions": {
|
||||
"fee": "0.000012",
|
||||
"sequence": 23,
|
||||
"maxLedgerVersion": null
|
||||
}
|
||||
}
|
||||
2
test/fixtures/rippled/account-lines.js
vendored
2
test/fixtures/rippled/account-lines.js
vendored
@@ -22,7 +22,7 @@ module.exports.normal = function(request, options = {}) {
|
||||
currency: 'ASP',
|
||||
limit: '0',
|
||||
limit_peer: '10',
|
||||
quality_in: 0,
|
||||
quality_in: 1000000000,
|
||||
quality_out: 0
|
||||
},
|
||||
{
|
||||
|
||||
74
test/integration/fixtures/get-transaction.json
Normal file
74
test/integration/fixtures/get-transaction.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "2",
|
||||
"result": {
|
||||
"type": "order",
|
||||
"address": "rK5j9n8baXfL4gzUoZsfxBvvsv97P5swaV",
|
||||
"sequence": 7973823,
|
||||
"id": "4EB6B76237DEEE99F1EA16FAACED2D1E69C5F9CB54F727A4ECA51A08AD3AF466",
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.000709756467",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "JPY",
|
||||
"value": "0.086630181788",
|
||||
"counterparty": "r94s8px6kSw1uZ1MV98dhSRTvc6VMPoPcN"
|
||||
}
|
||||
},
|
||||
"outcome": {
|
||||
"result": "tesSUCCESS",
|
||||
"timestamp": "2015-12-03T00:53:21.000Z",
|
||||
"fee": "0.010001",
|
||||
"balanceChanges": {
|
||||
"rK5j9n8baXfL4gzUoZsfxBvvsv97P5swaV": [
|
||||
{
|
||||
"currency": "XRP",
|
||||
"value": "-0.010001"
|
||||
}
|
||||
]
|
||||
},
|
||||
"orderbookChanges": {
|
||||
"rK5j9n8baXfL4gzUoZsfxBvvsv97P5swaV": [
|
||||
{
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
|
||||
"value": "0.000709260645"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "JPY",
|
||||
"counterparty": "r94s8px6kSw1uZ1MV98dhSRTvc6VMPoPcN",
|
||||
"value": "0.086665436143"
|
||||
},
|
||||
"sequence": 7973725,
|
||||
"status": "cancelled",
|
||||
"makerExchangeRate": "0.008183892870852266"
|
||||
},
|
||||
{
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
|
||||
"value": "0.000709756467"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "JPY",
|
||||
"counterparty": "r94s8px6kSw1uZ1MV98dhSRTvc6VMPoPcN",
|
||||
"value": "0.086630181788"
|
||||
},
|
||||
"sequence": 7973823,
|
||||
"status": "created",
|
||||
"makerExchangeRate": "0.008192946757712049"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ledgerVersion": 17445469,
|
||||
"indexInLedger": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
72
test/integration/fixtures/get-transactions.json
Normal file
72
test/integration/fixtures/get-transactions.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "3",
|
||||
"result": [
|
||||
{
|
||||
"type": "order",
|
||||
"address": "rpP2JgiMyTF5jR5hLG3xHCPi1knBb1v9cM",
|
||||
"sequence": 3372206,
|
||||
"id": "848397FA686BD4A59F91EC1F4DE717360470EE8BD67CAA01D5FD333EDA8D97B3",
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "JPY",
|
||||
"value": "27865.90216965619",
|
||||
"counterparty": "rJRi8WW24gt9X85PHAxfWNPCizMMhqUQwg"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "XRP",
|
||||
"value": "40000"
|
||||
}
|
||||
},
|
||||
"outcome": {
|
||||
"result": "tesSUCCESS",
|
||||
"fee": "0.011",
|
||||
"balanceChanges": {
|
||||
"rpP2JgiMyTF5jR5hLG3xHCPi1knBb1v9cM": [
|
||||
{
|
||||
"currency": "XRP",
|
||||
"value": "-0.011"
|
||||
}
|
||||
]
|
||||
},
|
||||
"orderbookChanges": {
|
||||
"rpP2JgiMyTF5jR5hLG3xHCPi1knBb1v9cM": [
|
||||
{
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "JPY",
|
||||
"counterparty": "rJRi8WW24gt9X85PHAxfWNPCizMMhqUQwg",
|
||||
"value": "27880.6855384734"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "XRP",
|
||||
"value": "40000"
|
||||
},
|
||||
"sequence": 3372204,
|
||||
"status": "cancelled",
|
||||
"makerExchangeRate": "0.697017138461835"
|
||||
},
|
||||
{
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "JPY",
|
||||
"counterparty": "rJRi8WW24gt9X85PHAxfWNPCizMMhqUQwg",
|
||||
"value": "27865.90216965619"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "XRP",
|
||||
"value": "40000"
|
||||
},
|
||||
"sequence": 3372206,
|
||||
"status": "created",
|
||||
"makerExchangeRate": "0.6966475542414048"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ledgerVersion": 17533547,
|
||||
"indexInLedger": 12
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
test/integration/fixtures/index.js
Normal file
6
test/integration/fixtures/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
getTransaction: require('./get-transaction'),
|
||||
getTransactions: require('./get-transactions')
|
||||
};
|
||||
157
test/integration/http-integration-test.js
Normal file
157
test/integration/http-integration-test.js
Normal file
@@ -0,0 +1,157 @@
|
||||
/* eslint-disable max-nested-callbacks */
|
||||
'use strict';
|
||||
const assert = require('assert-diff');
|
||||
const _ = require('lodash');
|
||||
const jayson = require('jayson');
|
||||
|
||||
const createHTTPServer = require('../../src/index').createHTTPServer;
|
||||
|
||||
const apiFixtures = require('../fixtures');
|
||||
const apiRequests = apiFixtures.requests;
|
||||
const apiResponses = apiFixtures.responses;
|
||||
|
||||
const fixtures = require('./fixtures');
|
||||
|
||||
const TIMEOUT = 20000; // how long before each test case times out
|
||||
|
||||
const apiOptions = {
|
||||
server: 'wss://s1.ripple.com'
|
||||
};
|
||||
|
||||
const httpPort = 3000;
|
||||
|
||||
function createClient() {
|
||||
return jayson.client.http({port: httpPort, hostname: 'localhost'});
|
||||
}
|
||||
|
||||
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
|
||||
|
||||
function makePositionalParams(params) {
|
||||
return params.map(value => value[_.keys(value)[0]]);
|
||||
}
|
||||
|
||||
function makeNamedParams(params) {
|
||||
return _.reduce(params, _.assign, {});
|
||||
}
|
||||
|
||||
function random() {
|
||||
return _.fill(Array(16), 0);
|
||||
}
|
||||
|
||||
describe('http server integration tests', function() {
|
||||
this.timeout(TIMEOUT);
|
||||
|
||||
let server = null;
|
||||
let client = null;
|
||||
|
||||
function createTestInternal(testName, methodName, params, testFunc, id) {
|
||||
it(testName, function() {
|
||||
return new Promise((resolve, reject) => {
|
||||
client.request(methodName, params, id,
|
||||
(err, result) => err ? reject(err) : resolve(testFunc(result)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createTest(name, params, testFunc, id) {
|
||||
createTestInternal(name + ' - positional params', name,
|
||||
makePositionalParams(params), testFunc, id);
|
||||
createTestInternal(name + ' - named params', name,
|
||||
makeNamedParams(params), testFunc, id);
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
server = createHTTPServer(apiOptions, httpPort);
|
||||
return server.start().then(() => {
|
||||
this.client = createClient();
|
||||
client = this.client;
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
return server.stop();
|
||||
});
|
||||
|
||||
|
||||
createTest(
|
||||
'getLedgerVersion',
|
||||
[],
|
||||
result => assert(_.isNumber(result.result))
|
||||
);
|
||||
|
||||
createTest(
|
||||
'getServerInfo',
|
||||
[],
|
||||
result => assert(_.isNumber(result.result.validatedLedger.ledgerVersion))
|
||||
);
|
||||
|
||||
createTest(
|
||||
'getTransaction',
|
||||
[{id: '4EB6B76237DEEE99F1EA16FAACED2D1E69C5F9CB54F727A4ECA51A08AD3AF466'}],
|
||||
result => assert.deepEqual(result, fixtures.getTransaction),
|
||||
'2'
|
||||
);
|
||||
|
||||
createTest(
|
||||
'getTransactions',
|
||||
[{address: 'rpP2JgiMyTF5jR5hLG3xHCPi1knBb1v9cM'}, {
|
||||
options: {
|
||||
binary: true,
|
||||
limit: 1,
|
||||
start:
|
||||
'FBAAC31D6BAEEFA9E501266FD62DA7A7982662BC19BC42F49BB41405C2F820DB'
|
||||
}
|
||||
}],
|
||||
result => assert.deepEqual(result, fixtures.getTransactions),
|
||||
'3'
|
||||
);
|
||||
|
||||
createTest(
|
||||
'prepareSettings',
|
||||
[
|
||||
{address},
|
||||
{settings: apiRequests.prepareSettings},
|
||||
{instructions: {
|
||||
maxFee: '0.000012',
|
||||
sequence: 23,
|
||||
maxLedgerVersion: 8820051
|
||||
}}
|
||||
],
|
||||
result => {
|
||||
const got = JSON.parse(result.result.txJSON);
|
||||
const expected = JSON.parse(apiResponses.prepareSettings.flags.txJSON);
|
||||
assert.deepEqual(got, expected);
|
||||
}
|
||||
);
|
||||
|
||||
createTest(
|
||||
'sign',
|
||||
[{txJSON: apiRequests.sign.normal.txJSON},
|
||||
{secret: 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'}],
|
||||
result => assert.deepEqual(result.result, apiResponses.sign.normal)
|
||||
);
|
||||
|
||||
createTest(
|
||||
'generateAddress',
|
||||
[{options: {entropy: random()}}],
|
||||
result => assert.deepEqual(result.result, apiResponses.generateAddress)
|
||||
);
|
||||
|
||||
createTest(
|
||||
'computeLedgerHash',
|
||||
[{ledger: _.assign({}, apiResponses.getLedger.full,
|
||||
{parentCloseTime: apiResponses.getLedger.full.closeTime})
|
||||
}],
|
||||
result => {
|
||||
assert.strictEqual(result.result,
|
||||
'E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E');
|
||||
}
|
||||
);
|
||||
|
||||
createTest(
|
||||
'isConnected',
|
||||
[],
|
||||
result => assert(result.result)
|
||||
);
|
||||
|
||||
});
|
||||
@@ -71,6 +71,7 @@ module.exports = function(port) {
|
||||
};
|
||||
|
||||
mock.on('connection', function(conn) {
|
||||
this.socket = conn;
|
||||
conn.on('message', function(requestJSON) {
|
||||
const request = JSON.parse(requestJSON);
|
||||
mock.emit('request_' + request.command, request, conn);
|
||||
|
||||
@@ -1,52 +1,77 @@
|
||||
'use strict';
|
||||
const net = require('net');
|
||||
const RippleAPI = require('ripple-api').RippleAPI;
|
||||
const RippleAPIBroadcast = require('ripple-api').RippleAPIBroadcast;
|
||||
const ledgerClosed = require('./fixtures/rippled/ledger-close');
|
||||
const createMockRippled = require('./mock-rippled');
|
||||
|
||||
// using a free port instead of a constant port enables parallelization
|
||||
function getFreePort(callback) {
|
||||
const server = net.createServer();
|
||||
let port;
|
||||
server.on('listening', function() {
|
||||
port = server.address().port;
|
||||
server.close();
|
||||
function getFreePort() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = net.createServer();
|
||||
let port;
|
||||
server.on('listening', function() {
|
||||
port = server.address().port;
|
||||
server.close();
|
||||
});
|
||||
server.on('close', function() {
|
||||
resolve(port);
|
||||
});
|
||||
server.on('error', function(error) {
|
||||
reject(error);
|
||||
});
|
||||
server.listen(0);
|
||||
});
|
||||
server.on('close', function() {
|
||||
callback(null, port);
|
||||
});
|
||||
server.on('error', function(error) {
|
||||
callback(error);
|
||||
});
|
||||
server.listen(0);
|
||||
}
|
||||
|
||||
function setupMockRippledConnection(testcase, port, done) {
|
||||
testcase.mockRippled = createMockRippled(port);
|
||||
testcase.api = new RippleAPI({server: 'ws://localhost:' + port});
|
||||
testcase.api.connect().then(() => {
|
||||
testcase.api.once('ledger', () => done());
|
||||
testcase.api.connection._ws.emit('message', JSON.stringify(ledgerClosed));
|
||||
}).catch(done);
|
||||
function setupMockRippledConnection(testcase, port) {
|
||||
return new Promise((resolve, reject) => {
|
||||
testcase.mockRippled = createMockRippled(port);
|
||||
testcase.api = new RippleAPI({server: 'ws://localhost:' + port});
|
||||
testcase.api.connect().then(() => {
|
||||
testcase.api.once('ledger', () => resolve());
|
||||
testcase.api.connection._ws.emit('message', JSON.stringify(ledgerClosed));
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
function setup(done) {
|
||||
getFreePort((error, port) => {
|
||||
if (error) {
|
||||
throw new Error('Unable to obtain a free port: ' + error);
|
||||
}
|
||||
setupMockRippledConnection(this, port, done);
|
||||
function setupMockRippledConnectionForBroadcast(testcase, ports) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const servers = ports.map(port => 'ws://localhost:' + port);
|
||||
testcase.mocks = ports.map(port => createMockRippled(port));
|
||||
testcase.api = new RippleAPIBroadcast(servers);
|
||||
testcase.api.connect().then(() => {
|
||||
testcase.api.once('ledger', () => resolve());
|
||||
testcase.mocks[0].socket.send(JSON.stringify(ledgerClosed));
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
function setup() {
|
||||
return getFreePort().then(port => {
|
||||
return setupMockRippledConnection(this, port);
|
||||
});
|
||||
}
|
||||
|
||||
function setupBroadcast() {
|
||||
return Promise.all([getFreePort(), getFreePort()]).then(ports => {
|
||||
return setupMockRippledConnectionForBroadcast(this, ports);
|
||||
});
|
||||
}
|
||||
|
||||
function teardown(done) {
|
||||
this.api.disconnect().then(() => {
|
||||
this.mockRippled.close();
|
||||
if (this.mockRippled !== undefined) {
|
||||
this.mockRippled.close();
|
||||
} else {
|
||||
this.mocks.forEach(mock => mock.close());
|
||||
}
|
||||
setImmediate(done);
|
||||
}).catch(done);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setup: setup,
|
||||
teardown: teardown
|
||||
teardown: teardown,
|
||||
setupBroadcast: setupBroadcast
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user