mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-17 10:55:48 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b56752e45b | ||
|
|
4632f511ab | ||
|
|
e17b6f172d | ||
|
|
eb04e878ba | ||
|
|
c71febd116 | ||
|
|
69c1ccbb6b | ||
|
|
499b8c8d8b | ||
|
|
ea009f9a84 | ||
|
|
dc784d4567 | ||
|
|
9ffc8a2c0b | ||
|
|
5b20fe573e | ||
|
|
7e466bb80f | ||
|
|
1f8418b447 | ||
|
|
ccfc57fc62 | ||
|
|
1d31fccd72 |
@@ -61,6 +61,8 @@
|
||||
- [API Events](#api-events)
|
||||
- [ledger](#ledger)
|
||||
- [error](#error)
|
||||
- [connected](#connected)
|
||||
- [disconnected](#disconnected)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
@@ -90,6 +92,14 @@ const api = new RippleAPI({
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
api.on('connected', () => {
|
||||
console.log('connected');
|
||||
});
|
||||
api.on('disconnected', (code) => {
|
||||
// code - [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) sent by the server
|
||||
// will be 1000 if this was normal closure
|
||||
console.log('disconnected, code:', code);
|
||||
});
|
||||
api.connect().then(() => {
|
||||
/* insert code here */
|
||||
}).then(() => {
|
||||
@@ -3593,3 +3603,35 @@ api.on('error', (errorCode, errorMessage, data) => {
|
||||
tooBusy: The server is too busy to help you now.
|
||||
```
|
||||
|
||||
## connected
|
||||
|
||||
This event is emitted after connection successfully opened.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
api.on('connected', () => {
|
||||
console.log('Connection is open now.');
|
||||
});
|
||||
```
|
||||
|
||||
## disconnected
|
||||
|
||||
This event is emitted when connection is closed.
|
||||
|
||||
### Return Value
|
||||
|
||||
The only parameter is a number containing the [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) send by the server.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
api.on('disconnected', (code) => {
|
||||
if (code !== 1000) {
|
||||
console.log('Connection is closed due to error.');
|
||||
} else {
|
||||
console.log('Connection is closed normally.');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
@@ -11,6 +11,14 @@ const api = new RippleAPI({
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
api.on('connected', () => {
|
||||
console.log('connected');
|
||||
});
|
||||
api.on('disconnected', (code) => {
|
||||
// code - [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) sent by the server
|
||||
// will be 1000 if this was normal closure
|
||||
console.log('disconnected, code:', code);
|
||||
});
|
||||
api.connect().then(() => {
|
||||
/* insert code here */
|
||||
}).then(() => {
|
||||
|
||||
@@ -47,3 +47,35 @@ api.on('error', (errorCode, errorMessage, data) => {
|
||||
```
|
||||
tooBusy: The server is too busy to help you now.
|
||||
```
|
||||
|
||||
## connected
|
||||
|
||||
This event is emitted after connection successfully opened.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
api.on('connected', () => {
|
||||
console.log('Connection is open now.');
|
||||
});
|
||||
```
|
||||
|
||||
## disconnected
|
||||
|
||||
This event is emitted when connection is closed.
|
||||
|
||||
### Return Value
|
||||
|
||||
The only parameter is a number containing the [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) send by the server.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
api.on('disconnected', (code) => {
|
||||
if (code !== 1000) {
|
||||
console.log('Connection is closed due to error.');
|
||||
} else {
|
||||
console.log('Connection is closed normally.');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
2
npm-shrinkwrap.json
generated
2
npm-shrinkwrap.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripple-lib",
|
||||
"version": "0.16.8",
|
||||
"version": "0.16.10",
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "1.4.10",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripple-lib",
|
||||
"version": "0.16.8",
|
||||
"version": "0.16.10",
|
||||
"license": "ISC",
|
||||
"description": "A JavaScript API for interacting with Ripple in Node.js and the browser",
|
||||
"files": [
|
||||
@@ -33,7 +33,7 @@
|
||||
"assert-diff": "^1.0.1",
|
||||
"babel-cli": "^6.4.0",
|
||||
"babel-core": "^6.4.0",
|
||||
"babel-eslint": "^4.1.6",
|
||||
"babel-eslint": "^4.1.8",
|
||||
"babel-loader": "^6.2.1",
|
||||
"babel-plugin-syntax-flow": "^6.3.13",
|
||||
"babel-plugin-transform-flow-strip-types": "^6.4.0",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const MochaSauce = require('mocha-in-sauce');
|
||||
@@ -18,7 +17,6 @@ function main() {
|
||||
maxDuration: 180000,
|
||||
// the current build name (optional)
|
||||
build: Date.now(),
|
||||
seleniumVersion: '2.50.1',
|
||||
url: testUrl,
|
||||
runSauceConnect: true
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
'use strict'; // eslint-disable-line
|
||||
|
||||
/* eslint-disable max-len */
|
||||
// Enable core-js polyfills. This allows use of ES6/7 extensions listed here:
|
||||
@@ -89,6 +89,12 @@ class RippleAPI extends EventEmitter {
|
||||
this.connection.on('error', (errorCode, errorMessage, data) => {
|
||||
this.emit('error', errorCode, errorMessage, data);
|
||||
});
|
||||
this.connection.on('connected', () => {
|
||||
this.emit('connected');
|
||||
});
|
||||
this.connection.on('disconnected', code => {
|
||||
this.emit('disconnected', code);
|
||||
});
|
||||
} else {
|
||||
// use null object pattern to provide better error message if user
|
||||
// tries to call a method that requires a connection
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict'; // eslint-disable-line
|
||||
|
||||
const _ = require('lodash');
|
||||
const {EventEmitter} = require('events');
|
||||
const WebSocket = require('ws');
|
||||
@@ -35,6 +37,8 @@ class Connection extends EventEmitter {
|
||||
this._ledgerVersion = null;
|
||||
this._availableLedgerVersions = new RangeSet();
|
||||
this._nextRequestID = 1;
|
||||
this._retry = 0;
|
||||
this._retryTimer = null;
|
||||
}
|
||||
|
||||
_updateLedgerVersions(data) {
|
||||
@@ -95,38 +99,88 @@ class Connection extends EventEmitter {
|
||||
return this._state === WebSocket.OPEN && this._isReady;
|
||||
}
|
||||
|
||||
_onUnexpectedClose(resolve = function() {}, reject = function() {}) {
|
||||
_onUnexpectedClose(beforeOpen, resolve, reject, code) {
|
||||
if (this._onOpenErrorBound) {
|
||||
this._ws.removeListener('error', this._onOpenErrorBound);
|
||||
this._onOpenErrorBound = null;
|
||||
}
|
||||
this._ws = null;
|
||||
this._isReady = false;
|
||||
this.connect().then(resolve, reject);
|
||||
if (beforeOpen) {
|
||||
// connection was closed before it was properly opened, so we must return
|
||||
// error to connect's caller
|
||||
this.connect().then(resolve, reject);
|
||||
} else {
|
||||
// if first parameter ws lib sends close code,
|
||||
// but sometimes it forgots about it, so default to 1006 - CLOSE_ABNORMAL
|
||||
this.emit('disconnected', code || 1006);
|
||||
this._retryConnect();
|
||||
}
|
||||
}
|
||||
|
||||
_calculateTimeout(retriesCount) {
|
||||
return (retriesCount < 40)
|
||||
// First, for 2 seconds: 20 times per second
|
||||
? (1000 / 20)
|
||||
: (retriesCount < 40 + 60)
|
||||
// Then, for 1 minute: once per second
|
||||
? (1000)
|
||||
: (retriesCount < 40 + 60 + 60)
|
||||
// Then, for 10 minutes: once every 10 seconds
|
||||
? (10 * 1000)
|
||||
// Then: once every 30 seconds
|
||||
: (30 * 1000);
|
||||
}
|
||||
|
||||
_retryConnect() {
|
||||
this._retry += 1;
|
||||
const retryTimeout = this._calculateTimeout(this._retry);
|
||||
this._retryTimer = setTimeout(() => {
|
||||
this.connect().catch(this._retryConnect.bind(this));
|
||||
}, retryTimeout);
|
||||
}
|
||||
|
||||
_clearReconnectTimer() {
|
||||
clearTimeout(this._retryTimer);
|
||||
this._retryTimer = null;
|
||||
}
|
||||
|
||||
_onOpen() {
|
||||
this._ws.removeListener('close', this._onUnexpectedCloseBound);
|
||||
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this);
|
||||
this._ws.once('close', this._onUnexpectedCloseBound);
|
||||
|
||||
this._ws.removeListener('error', this._onOpenErrorBound);
|
||||
this._onOpenErrorBound = null;
|
||||
this._ws.on('error', error =>
|
||||
this.emit('error', 'websocket', error.message, error));
|
||||
|
||||
const request = {
|
||||
command: 'subscribe',
|
||||
streams: ['ledger']
|
||||
};
|
||||
return this.request(request).then(data => {
|
||||
if (_.isEmpty(data) || !data.ledger_index) {
|
||||
// rippled instance doesn't have validated ledgers
|
||||
return this._disconnect(false).then(() => {
|
||||
throw new NotConnectedError('Rippled not initialized');
|
||||
});
|
||||
}
|
||||
|
||||
this._updateLedgerVersions(data);
|
||||
|
||||
this._ws.removeListener('close', this._onUnexpectedCloseBound);
|
||||
this._onUnexpectedCloseBound =
|
||||
this._onUnexpectedClose.bind(this, false, null, null);
|
||||
this._ws.once('close', this._onUnexpectedCloseBound);
|
||||
|
||||
this._retry = 0;
|
||||
this._ws.on('error', error =>
|
||||
this.emit('error', 'websocket', error.message, error));
|
||||
|
||||
this._isReady = true;
|
||||
this.emit('connected');
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
_onOpenError(reject, error) {
|
||||
this._onOpenErrorBound = null;
|
||||
reject(new NotConnectedError(error && error.message));
|
||||
}
|
||||
|
||||
@@ -174,6 +228,7 @@ class Connection extends EventEmitter {
|
||||
}
|
||||
|
||||
connect() {
|
||||
this._clearReconnectTimer();
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this._url) {
|
||||
reject(new ConnectionError(
|
||||
@@ -199,7 +254,7 @@ class Connection extends EventEmitter {
|
||||
// resolve connect's promise after reconnect in that case.
|
||||
// after open event we will rebound _onUnexpectedCloseBound
|
||||
// without resolve and reject functions
|
||||
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this,
|
||||
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this, true,
|
||||
resolve, reject);
|
||||
this._ws.once('close', this._onUnexpectedCloseBound);
|
||||
this._ws.once('open', () => this._onOpen().then(resolve, reject));
|
||||
@@ -208,6 +263,14 @@ class Connection extends EventEmitter {
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
return this._disconnect(true);
|
||||
}
|
||||
|
||||
_disconnect(calledByUser) {
|
||||
if (calledByUser) {
|
||||
this._clearReconnectTimer();
|
||||
this._retry = 0;
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
if (this._state === WebSocket.CLOSED) {
|
||||
resolve();
|
||||
@@ -215,9 +278,12 @@ class Connection extends EventEmitter {
|
||||
this._ws.once('close', resolve);
|
||||
} else {
|
||||
this._ws.removeListener('close', this._onUnexpectedCloseBound);
|
||||
this._ws.once('close', () => {
|
||||
this._ws.once('close', code => {
|
||||
this._ws = null;
|
||||
this._isReady = false;
|
||||
if (calledByUser) {
|
||||
this.emit('disconnected', code || 1000); // 1000 - CLOSE_NORMAL
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
this._ws.close();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
'use strict'; // eslint-disable-line
|
||||
const _ = require('lodash');
|
||||
const {convertKeysFromSnakeCaseToCamelCase} = require('./utils');
|
||||
import type {Connection} from './connection';
|
||||
@@ -43,18 +43,20 @@ function getServerInfo(connection: Connection): Promise<GetServerInfoResponse> {
|
||||
return connection.request({command: 'server_info'}).then(response => {
|
||||
const info = convertKeysFromSnakeCaseToCamelCase(response.info);
|
||||
renameKeys(info, {hostid: 'hostID'});
|
||||
renameKeys(info.validatedLedger, {
|
||||
baseFeeXrp: 'baseFeeXRP',
|
||||
reserveBaseXrp: 'reserveBaseXRP',
|
||||
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();
|
||||
if (info.validatedLedger) {
|
||||
renameKeys(info.validatedLedger, {
|
||||
baseFeeXrp: 'baseFeeXRP',
|
||||
reserveBaseXrp: 'reserveBaseXRP',
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
'use strict'; // eslint-disable-line strict
|
||||
const utils = require('./utils');
|
||||
const flags = require('./flags').orderFlags;
|
||||
const parseAmount = require('./amount');
|
||||
@@ -31,11 +31,14 @@ function parseAccountOrder(address: string, order: Object): Object {
|
||||
expirationTime: utils.parseTimestamp(order.expiration)
|
||||
});
|
||||
|
||||
const makerExchangeRate = order.quality ?
|
||||
utils.adjustQualityForXRP(order.quality.toString(),
|
||||
takerGetsAmount.currency, takerPaysAmount.currency) :
|
||||
computeQuality(takerGetsAmount, takerPaysAmount);
|
||||
const properties = {
|
||||
maker: address,
|
||||
sequence: order.seq,
|
||||
makerExchangeRate: order.quality ? order.quality.toString()
|
||||
: computeQuality(takerGetsAmount, takerPaysAmount)
|
||||
makerExchangeRate: makerExchangeRate
|
||||
};
|
||||
|
||||
return {specification, properties};
|
||||
|
||||
@@ -93,7 +93,7 @@ function filterSourceFundsLowPaths(pathfind: PathFind,
|
||||
paths.alternatives = _.filter(paths.alternatives, alt => {
|
||||
return alt.source_amount &&
|
||||
pathfind.source.amount &&
|
||||
alt.source_amount.value === pathfind.source.amount.value;
|
||||
new BigNumber(alt.source_amount.value).eq(pathfind.source.amount.value);
|
||||
});
|
||||
}
|
||||
return paths;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable max-nested-callbacks */
|
||||
'use strict';
|
||||
'use strict'; // eslint-disable-line
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert-diff');
|
||||
const setupAPI = require('./setup-api');
|
||||
@@ -981,6 +981,19 @@ describe('RippleAPI', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('getServerInfo - no validated ledger', function() {
|
||||
this.api.connection._send(JSON.stringify({
|
||||
command: 'config',
|
||||
data: {serverInfoWithoutValidated: true}
|
||||
}));
|
||||
|
||||
return this.api.getServerInfo().then(info => {
|
||||
assert.strictEqual(info.networkLedger, 'waiting');
|
||||
}).catch(error => {
|
||||
assert(false, 'Should not throw Error, got ' + String(error));
|
||||
});
|
||||
});
|
||||
|
||||
it('getFee', function() {
|
||||
return this.api.getFee().then(fee => {
|
||||
assert.strictEqual(fee, '0.000012');
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use strict'; // eslint-disable-line
|
||||
/* eslint-disable max-nested-callbacks */
|
||||
|
||||
const _ = require('lodash');
|
||||
@@ -117,7 +118,9 @@ describe('Connection', function() {
|
||||
}
|
||||
}
|
||||
|
||||
const connection = new utils.common.Connection('ws://127.0.0.1:321');
|
||||
// Address where no one listens
|
||||
const connection =
|
||||
new utils.common.Connection('ws://testripple.circleci.com:129');
|
||||
connection.on('error', done);
|
||||
connection.connect().catch(error => {
|
||||
assert(error instanceof this.api.errors.NotConnectedError);
|
||||
@@ -191,6 +194,81 @@ describe('Connection', function() {
|
||||
}, 1);
|
||||
});
|
||||
|
||||
it('reconnect on several unexpected close', function(done) {
|
||||
if (process.browser) {
|
||||
// can't be tested in browser this way, so skipping
|
||||
done();
|
||||
return;
|
||||
}
|
||||
this.timeout(7000);
|
||||
const self = this;
|
||||
function breakConnection() {
|
||||
setTimeout(() => {
|
||||
self.mockRippled.close();
|
||||
setTimeout(() => {
|
||||
self.mockRippled = setupAPI.createMockRippled(self._mockedServerPort);
|
||||
}, 1500);
|
||||
}, 21);
|
||||
}
|
||||
|
||||
let connectsCount = 0;
|
||||
let disconnectsCount = 0;
|
||||
let code = 0;
|
||||
this.api.connection.on('disconnected', _code => {
|
||||
code = _code;
|
||||
disconnectsCount += 1;
|
||||
});
|
||||
this.api.connection.on('connected', () => {
|
||||
connectsCount += 1;
|
||||
if (connectsCount < 3) {
|
||||
breakConnection();
|
||||
}
|
||||
if (connectsCount === 3) {
|
||||
if (disconnectsCount !== 3) {
|
||||
done(new Error('disconnectsCount must be equal to 3 (got ' +
|
||||
disconnectsCount + ' instead)'));
|
||||
} else if (code !== 1006) {
|
||||
done(new Error('disconnect must send code 1006 (got ' + code +
|
||||
' instead)'));
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
breakConnection();
|
||||
});
|
||||
|
||||
it('should emit disconnected event with code 1000 (CLOSE_NORMAL)',
|
||||
function(done
|
||||
) {
|
||||
this.api.once('disconnected', code => {
|
||||
assert.strictEqual(code, 1000);
|
||||
done();
|
||||
});
|
||||
this.api.disconnect();
|
||||
});
|
||||
|
||||
it('should emit disconnected event with code 1006 (CLOSE_ABNORMAL)',
|
||||
function(done
|
||||
) {
|
||||
if (process.browser) {
|
||||
// can't be tested in browser this way, so skipping
|
||||
done();
|
||||
return;
|
||||
}
|
||||
this.api.once('disconnected', code => {
|
||||
assert.strictEqual(code, 1006);
|
||||
done();
|
||||
});
|
||||
this.mockRippled.close();
|
||||
});
|
||||
|
||||
it('should emit connected event on after reconnect', function(done) {
|
||||
this.api.once('connected', done);
|
||||
this.api.connection._ws.close();
|
||||
});
|
||||
|
||||
it('Multiply connect calls', function() {
|
||||
return this.api.connect().then(() => {
|
||||
return this.api.connect();
|
||||
@@ -301,4 +379,58 @@ describe('Connection', function() {
|
||||
});
|
||||
this.api.connection._ws.emit('message', JSON.stringify(message));
|
||||
});
|
||||
|
||||
it('should throw NotConnectedError if server does not have validated ledgers',
|
||||
function() {
|
||||
if (process.browser) {
|
||||
// do not work in browser now, skipping
|
||||
return false;
|
||||
}
|
||||
this.timeout(3000);
|
||||
|
||||
this.api.connection._send(JSON.stringify({
|
||||
command: 'global_config',
|
||||
data: {returnEmptySubscribeRequest: 1}
|
||||
}));
|
||||
|
||||
const api = new RippleAPI({server: this.api.connection._url});
|
||||
return api.connect().then(() => {
|
||||
assert(false, 'Must have thrown!');
|
||||
}, error => {
|
||||
assert(error instanceof this.api.errors.NotConnectedError,
|
||||
'Must throw NotConnectedError, got instead ' + String(error));
|
||||
});
|
||||
});
|
||||
|
||||
it('should try to reconnect on empty subscribe response on reconnect',
|
||||
function(done) {
|
||||
if (process.browser) {
|
||||
// do not work in browser now, skipping
|
||||
done();
|
||||
return;
|
||||
}
|
||||
this.timeout(23000);
|
||||
|
||||
this.api.on('error', error => {
|
||||
done(error || new Error('Should not emit error.'));
|
||||
});
|
||||
let disconncedCount = 0;
|
||||
this.api.on('connected', () => {
|
||||
done(disconncedCount !== 1 ?
|
||||
new Error('Wrong number of disconnects') : undefined);
|
||||
});
|
||||
this.api.on('disconnected', () => {
|
||||
disconncedCount++;
|
||||
});
|
||||
|
||||
this.api.connection._send(JSON.stringify({
|
||||
command: 'global_config',
|
||||
data: {returnEmptySubscribeRequest: 3}
|
||||
}));
|
||||
|
||||
this.api.connection._send(JSON.stringify({
|
||||
command: 'test_command',
|
||||
data: {disconnectIn: 10}
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
|
||||
"amount": {
|
||||
"currency": "USD",
|
||||
"value": "5"
|
||||
"value": "5.00"
|
||||
}
|
||||
},
|
||||
"destination": {
|
||||
|
||||
3
test/fixtures/rippled/account-offers.js
vendored
3
test/fixtures/rippled/account-offers.js
vendored
@@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
'use strict'; // eslint-disable-line strict
|
||||
const _ = require('lodash');
|
||||
const addresses = require('../addresses');
|
||||
|
||||
@@ -160,6 +160,7 @@ module.exports = function(request, options = {}) {
|
||||
{
|
||||
'flags': 0,
|
||||
'seq': 814018,
|
||||
'quality': '16922629533.64839',
|
||||
'taker_gets': {
|
||||
'currency': 'NZD',
|
||||
'issuer': 'rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc',
|
||||
|
||||
7
test/fixtures/rippled/empty.json
vendored
Normal file
7
test/fixtures/rippled/empty.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
}
|
||||
}
|
||||
4
test/fixtures/rippled/index.js
vendored
4
test/fixtures/rippled/index.js
vendored
@@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
'use strict'; // eslint-disable-line
|
||||
|
||||
module.exports = {
|
||||
submit: {
|
||||
@@ -12,6 +12,7 @@ module.exports = {
|
||||
withSettingsTx: require('./ledger-with-settings-tx'),
|
||||
withStateAsHashes: require('./ledger-with-state-as-hashes')
|
||||
},
|
||||
empty: require('./empty'),
|
||||
subscribe: require('./subscribe'),
|
||||
unsubscribe: require('./unsubscribe'),
|
||||
account_info: {
|
||||
@@ -31,6 +32,7 @@ module.exports = {
|
||||
},
|
||||
server_info: {
|
||||
normal: require('./server-info'),
|
||||
noValidated: require('./server-info-no-validated'),
|
||||
error: require('./server-info-error')
|
||||
},
|
||||
path_find: {
|
||||
|
||||
31
test/fixtures/rippled/server-info-no-validated.json
vendored
Normal file
31
test/fixtures/rippled/server-info-no-validated.json
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"id": 0,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"info": {
|
||||
"build_version": "0.30.1-hf2",
|
||||
"complete_ledgers": "empty",
|
||||
"hostid": "ARTS",
|
||||
"io_latency_ms": 1,
|
||||
"last_close": {
|
||||
"converge_time_s": 2.007,
|
||||
"proposers": 4
|
||||
},
|
||||
"load_factor": 1,
|
||||
"peers": 53,
|
||||
"pubkey_node": "n94wWvFUmaKGYrKUGgpv1DyYgDeXRGdACkNQaSe7zJiy5Znio7UC",
|
||||
"server_state": "connected",
|
||||
"network_ledger" : "waiting",
|
||||
"closed_ledger": {
|
||||
"age": 5,
|
||||
"base_fee_xrp": 0.00001,
|
||||
"hash": "4482DEE5362332F54A4036ED57EE1767C9F33CF7CE5A6670355C16CECE381D46",
|
||||
"reserve_base_xrp": 20,
|
||||
"reserve_inc_xrp": 5,
|
||||
"seq": 6595042
|
||||
},
|
||||
"validation_quorum": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
'use strict'; // eslint-disable-line
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
const WebSocketServer = require('ws').Server;
|
||||
@@ -79,6 +79,8 @@ module.exports = function(port) {
|
||||
});
|
||||
});
|
||||
|
||||
mock.config = {};
|
||||
|
||||
mock.onAny(function() {
|
||||
if (this.event.indexOf('request_') !== 0) {
|
||||
return;
|
||||
@@ -101,6 +103,18 @@ module.exports = function(port) {
|
||||
conn.config = _.assign(conn.config, request.data);
|
||||
});
|
||||
|
||||
mock.on('request_test_command', function(request, conn) {
|
||||
assert.strictEqual(request.command, 'test_command');
|
||||
if (request.data.disconnectIn) {
|
||||
setTimeout(conn.terminate.bind(conn), request.data.disconnectIn);
|
||||
}
|
||||
});
|
||||
|
||||
mock.on('request_global_config', function(request, conn) {
|
||||
assert.strictEqual(request.command, 'global_config');
|
||||
mock.config = _.assign(conn.config, request.data);
|
||||
});
|
||||
|
||||
mock.on('request_echo', function(request, conn) {
|
||||
assert.strictEqual(request.command, 'echo');
|
||||
conn.send(JSON.stringify(request.data));
|
||||
@@ -112,6 +126,8 @@ module.exports = function(port) {
|
||||
conn.send(createResponse(request, fixtures.server_info.error));
|
||||
} else if (conn.config.disconnectOnServerInfo) {
|
||||
conn.close();
|
||||
} else if (conn.config.serverInfoWithoutValidated) {
|
||||
conn.send(createResponse(request, fixtures.server_info.noValidated));
|
||||
} else {
|
||||
conn.send(createResponse(request, fixtures.server_info.normal));
|
||||
}
|
||||
@@ -119,7 +135,10 @@ module.exports = function(port) {
|
||||
|
||||
mock.on('request_subscribe', function(request, conn) {
|
||||
assert.strictEqual(request.command, 'subscribe');
|
||||
if (request.accounts) {
|
||||
if (mock.config.returnEmptySubscribeRequest) {
|
||||
mock.config.returnEmptySubscribeRequest--;
|
||||
conn.send(createResponse(request, fixtures.empty));
|
||||
} else if (request.accounts) {
|
||||
assert(_.indexOf(_.values(addresses), request.accounts[0]) !== -1);
|
||||
}
|
||||
conn.send(createResponse(request, fixtures.subscribe));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
'use strict';
|
||||
'use strict'; // eslint-disable-line
|
||||
|
||||
const net = require('net');
|
||||
const RippleAPI = require('ripple-api').RippleAPI;
|
||||
const RippleAPIBroadcast = require('ripple-api').RippleAPIBroadcast;
|
||||
@@ -27,6 +28,7 @@ function getFreePort() {
|
||||
function setupMockRippledConnection(testcase, port) {
|
||||
return new Promise((resolve, reject) => {
|
||||
testcase.mockRippled = createMockRippled(port);
|
||||
testcase._mockedServerPort = port;
|
||||
testcase.api = new RippleAPI({server: 'ws://localhost:' + port});
|
||||
testcase.api.connect().then(() => {
|
||||
testcase.api.once('ledger', () => resolve());
|
||||
@@ -73,5 +75,6 @@ function teardown(done) {
|
||||
module.exports = {
|
||||
setup: setup,
|
||||
teardown: teardown,
|
||||
setupBroadcast: setupBroadcast
|
||||
setupBroadcast: setupBroadcast,
|
||||
createMockRippled: createMockRippled
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user