mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 12:15:51 +00:00
Merge pull request #612 from clark800/delete-core
BREAKING CHANGE: Remove dependency of src/api on src/core, removes multiserver support
This commit is contained in:
82
npm-shrinkwrap.json
generated
82
npm-shrinkwrap.json
generated
@@ -9,32 +9,22 @@
|
|||||||
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz"
|
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz"
|
||||||
},
|
},
|
||||||
"babel-runtime": {
|
"babel-runtime": {
|
||||||
"version": "5.8.25",
|
"version": "5.8.29",
|
||||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.25.tgz",
|
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.29.tgz",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": {
|
"core-js": {
|
||||||
"version": "1.1.4",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.1.4.tgz"
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.3.tgz"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bignumber.js": {
|
"bignumber.js": {
|
||||||
"version": "2.0.7",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.0.7.tgz"
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.1.0.tgz"
|
||||||
},
|
},
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "3.1.2",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-3.1.2.tgz"
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-3.2.0.tgz"
|
||||||
},
|
|
||||||
"es6-promisify": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-2.0.0.tgz",
|
|
||||||
"dependencies": {
|
|
||||||
"es6-promise": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"extend": {
|
"extend": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
@@ -121,8 +111,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-2.0.1.tgz",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"x-address-codec": {
|
"x-address-codec": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/x-address-codec/-/x-address-codec-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/x-address-codec/-/x-address-codec-0.7.2.tgz",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"base-x": {
|
"base-x": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -136,17 +126,13 @@
|
|||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-0.0.6.tgz",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
|
||||||
"version": "3.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-3.2.0.tgz"
|
|
||||||
},
|
|
||||||
"create-hash": {
|
"create-hash": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cipher-base": {
|
"cipher-base": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.1.tgz"
|
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.2.tgz"
|
||||||
},
|
},
|
||||||
"ripemd160": {
|
"ripemd160": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -177,8 +163,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cipher-base": {
|
"cipher-base": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.1.tgz"
|
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.2.tgz"
|
||||||
},
|
},
|
||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
@@ -205,8 +191,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz"
|
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz"
|
||||||
},
|
},
|
||||||
"elliptic": {
|
"elliptic": {
|
||||||
"version": "5.1.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-5.2.0.tgz",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
@@ -222,7 +208,13 @@
|
|||||||
},
|
},
|
||||||
"ripple-lib-value": {
|
"ripple-lib-value": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ripple-lib-value/-/ripple-lib-value-0.1.0.tgz"
|
"resolved": "https://registry.npmjs.org/ripple-lib-value/-/ripple-lib-value-0.1.0.tgz",
|
||||||
|
"dependencies": {
|
||||||
|
"bignumber.js": {
|
||||||
|
"version": "2.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.0.8.tgz"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"sjcl-codec": {
|
"sjcl-codec": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
@@ -232,20 +224,6 @@
|
|||||||
"version": "0.7.2",
|
"version": "0.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-0.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-0.7.2.tgz",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bufferutil": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-1.1.0.tgz",
|
|
||||||
"dependencies": {
|
|
||||||
"bindings": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz"
|
|
||||||
},
|
|
||||||
"nan": {
|
|
||||||
"version": "1.8.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"options": {
|
"options": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz"
|
"resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz"
|
||||||
@@ -253,20 +231,6 @@
|
|||||||
"ultron": {
|
"ultron": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz"
|
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz"
|
||||||
},
|
|
||||||
"utf-8-validate": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-1.1.0.tgz",
|
|
||||||
"dependencies": {
|
|
||||||
"bindings": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz"
|
|
||||||
},
|
|
||||||
"nan": {
|
|
||||||
"version": "1.8.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
"babel-runtime": "^5.5.4",
|
"babel-runtime": "^5.5.4",
|
||||||
"bignumber.js": "^2.0.3",
|
"bignumber.js": "^2.0.3",
|
||||||
"bn.js": "^3.1.1",
|
"bn.js": "^3.1.1",
|
||||||
"es6-promisify": "^2.0.0",
|
|
||||||
"extend": "~1.2.1",
|
"extend": "~1.2.1",
|
||||||
"hash.js": "^1.0.3",
|
"hash.js": "^1.0.3",
|
||||||
"https-proxy-agent": "^1.0.0",
|
"https-proxy-agent": "^1.0.0",
|
||||||
@@ -39,7 +38,7 @@
|
|||||||
"assert-diff": "^1.0.1",
|
"assert-diff": "^1.0.1",
|
||||||
"babel": "^5.8.21",
|
"babel": "^5.8.21",
|
||||||
"babel-core": "^5.8.22",
|
"babel-core": "^5.8.22",
|
||||||
"babel-eslint": "^4.0.5",
|
"babel-eslint": "^4.1.3",
|
||||||
"babel-loader": "^5.3.2",
|
"babel-loader": "^5.3.2",
|
||||||
"coveralls": "~2.10.0",
|
"coveralls": "~2.10.0",
|
||||||
"eslint": "^1.3.0",
|
"eslint": "^1.3.0",
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
const {EventEmitter} = require('events');
|
const {EventEmitter} = require('events');
|
||||||
const WebSocket = require('ws');
|
const WebSocket = require('ws');
|
||||||
// temporary: RangeSet will be moved to api/common soon
|
// temporary: RangeSet will be moved to api/common soon
|
||||||
const RangeSet = require('./utils').core._test.RangeSet;
|
const RangeSet = require('./rangeset').RangeSet;
|
||||||
|
const {RippledError, DisconnectedError, NotConnectedError,
|
||||||
|
TimeoutError, UnexpectedError} = require('./errors');
|
||||||
|
|
||||||
function isStreamMessageType(type) {
|
function isStreamMessageType(type) {
|
||||||
return type === 'ledgerClosed' ||
|
return type === 'ledgerClosed' ||
|
||||||
@@ -10,48 +12,6 @@ function isStreamMessageType(type) {
|
|||||||
type === 'path_find';
|
type === 'path_find';
|
||||||
}
|
}
|
||||||
|
|
||||||
class RippledError extends Error {
|
|
||||||
constructor(message) {
|
|
||||||
super(message);
|
|
||||||
this.name = this.constructor.name;
|
|
||||||
this.message = message;
|
|
||||||
Error.captureStackTrace(this, this.constructor.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConnectionError extends Error {
|
|
||||||
constructor(message) {
|
|
||||||
super(message);
|
|
||||||
this.name = this.constructor.name;
|
|
||||||
this.message = message;
|
|
||||||
Error.captureStackTrace(this, this.constructor.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotConnectedError extends ConnectionError {
|
|
||||||
constructor(message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisconnectedError extends ConnectionError {
|
|
||||||
constructor(message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TimeoutError extends ConnectionError {
|
|
||||||
constructor(message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class UnexpectedError extends ConnectionError {
|
|
||||||
constructor(message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Connection extends EventEmitter {
|
class Connection extends EventEmitter {
|
||||||
constructor(url, options = {}) {
|
constructor(url, options = {}) {
|
||||||
super();
|
super();
|
||||||
@@ -64,31 +24,42 @@ class Connection extends EventEmitter {
|
|||||||
this._nextRequestID = 1;
|
this._nextRequestID = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onMessage(message) {
|
// return value is array of arguments to Connection.emit
|
||||||
try {
|
_parseMessage(message) {
|
||||||
const data = JSON.parse(message);
|
const data = JSON.parse(message);
|
||||||
if (data.type === 'response') {
|
if (data.type === 'response') {
|
||||||
if (!(Number.isInteger(data.id) && data.id >= 0)) {
|
if (!(Number.isInteger(data.id) && data.id >= 0)) {
|
||||||
throw new UnexpectedError('valid id not found in response');
|
throw new UnexpectedError('valid id not found in response');
|
||||||
}
|
}
|
||||||
this.emit(data.id.toString(), data);
|
return [data.id.toString(), data];
|
||||||
} else if (isStreamMessageType(data.type)) {
|
} else if (isStreamMessageType(data.type)) {
|
||||||
if (data.type === 'ledgerClosed') {
|
if (data.type === 'ledgerClosed') {
|
||||||
this._ledgerVersion = Number(data.ledger_index);
|
this._ledgerVersion = Number(data.ledger_index);
|
||||||
this._availableLedgerVersions.addValue(this._ledgerVersion);
|
this._availableLedgerVersions.reset();
|
||||||
|
this._availableLedgerVersions.parseAndAddRanges(
|
||||||
|
data.validated_ledgers);
|
||||||
}
|
}
|
||||||
this.emit(data.type, data);
|
return [data.type, data];
|
||||||
} else if (data.type === undefined && data.error) {
|
} else if (data.type === undefined && data.error) {
|
||||||
this.emit('error', data.error, data.error_message); // e.g. slowDown
|
return ['error', data.error, data.error_message]; // e.g. slowDown
|
||||||
} else {
|
}
|
||||||
throw new UnexpectedError('unrecognized message type: ' + data.type);
|
throw new UnexpectedError('unrecognized message type: ' + data.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onMessage(message) {
|
||||||
|
let parameters;
|
||||||
|
try {
|
||||||
|
parameters = this._parseMessage(message);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.emit('error', 'badMessage', message);
|
this.emit('error', 'badMessage', message);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// we don't want this inside the try/catch or exceptions in listener
|
||||||
|
// will be caught
|
||||||
|
this.emit.apply(this, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
get state() {
|
get _state() {
|
||||||
return this._ws ? this._ws.readyState : WebSocket.CLOSED;
|
return this._ws ? this._ws.readyState : WebSocket.CLOSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,32 +67,34 @@ class Connection extends EventEmitter {
|
|||||||
return this._ws !== null;
|
return this._ws !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isConnected() {
|
||||||
|
return this._state === WebSocket.OPEN && this._isReady;
|
||||||
|
}
|
||||||
|
|
||||||
_onUnexpectedClose() {
|
_onUnexpectedClose() {
|
||||||
this._isReady = false;
|
this._isReady = false;
|
||||||
this.connect().then();
|
this.connect().then();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onOpen() {
|
_onOpen() {
|
||||||
const subscribeRequest = {
|
const request = {
|
||||||
command: 'subscribe',
|
command: 'subscribe',
|
||||||
streams: ['ledger']
|
streams: ['ledger']
|
||||||
};
|
};
|
||||||
return this.request(subscribeRequest).then(() => {
|
return this.request(request).then(response => {
|
||||||
return this.request({command: 'server_info'}).then(response => {
|
this._ledgerVersion = Number(response.ledger_index);
|
||||||
this._ledgerVersion = Number(response.info.validated_ledger.seq);
|
|
||||||
this._availableLedgerVersions.parseAndAddRanges(
|
this._availableLedgerVersions.parseAndAddRanges(
|
||||||
response.info.complete_ledgers);
|
response.validated_ledgers);
|
||||||
this._isReady = true;
|
this._isReady = true;
|
||||||
this.emit('connected');
|
this.emit('connected');
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (this.state === WebSocket.OPEN) {
|
if (this._state === WebSocket.OPEN) {
|
||||||
resolve();
|
resolve();
|
||||||
} else if (this.state === WebSocket.CONNECTING) {
|
} else if (this._state === WebSocket.CONNECTING) {
|
||||||
this._ws.once('open', resolve);
|
this._ws.once('open', resolve);
|
||||||
} else {
|
} else {
|
||||||
this._ws = new WebSocket(this._url);
|
this._ws = new WebSocket(this._url);
|
||||||
@@ -133,10 +106,10 @@ class Connection extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
return new Promise((resolve) => {
|
return new Promise(resolve => {
|
||||||
if (this.state === WebSocket.CLOSED) {
|
if (this._state === WebSocket.CLOSED) {
|
||||||
resolve();
|
resolve();
|
||||||
} else if (this.state === WebSocket.CLOSING) {
|
} else if (this._state === WebSocket.CLOSING) {
|
||||||
this._ws.once('close', resolve);
|
this._ws.once('close', resolve);
|
||||||
} else {
|
} else {
|
||||||
this._ws.removeListener('close', this._onUnexpectedClose);
|
this._ws.removeListener('close', this._onUnexpectedClose);
|
||||||
@@ -158,7 +131,7 @@ class Connection extends EventEmitter {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!this._shouldBeConnected) {
|
if (!this._shouldBeConnected) {
|
||||||
reject(new NotConnectedError());
|
reject(new NotConnectedError());
|
||||||
} else if (this.state === WebSocket.OPEN && this._isReady) {
|
} else if (this._state === WebSocket.OPEN && this._isReady) {
|
||||||
promise.then(resolve, reject);
|
promise.then(resolve, reject);
|
||||||
} else {
|
} else {
|
||||||
this.once('connected', () => promise.then(resolve, reject));
|
this.once('connected', () => promise.then(resolve, reject));
|
||||||
@@ -167,14 +140,13 @@ class Connection extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getLedgerVersion() {
|
getLedgerVersion() {
|
||||||
return this._whenReady(
|
return this._whenReady(Promise.resolve(this._ledgerVersion));
|
||||||
new Promise(resolve => resolve(this._ledgerVersion)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasLedgerVersions(lowLedgerVersion, highLedgerVersion) {
|
hasLedgerVersions(lowLedgerVersion, highLedgerVersion) {
|
||||||
return this._whenReady(new Promise(resolve =>
|
return this._whenReady(Promise.resolve(
|
||||||
resolve(this._availableLedgerVersions.containsRange(
|
this._availableLedgerVersions.containsRange(
|
||||||
lowLedgerVersion, highLedgerVersion))));
|
lowLedgerVersion, highLedgerVersion || this._ledgerVersion)));
|
||||||
}
|
}
|
||||||
|
|
||||||
hasLedgerVersion(ledgerVersion) {
|
hasLedgerVersion(ledgerVersion) {
|
||||||
@@ -214,8 +186,10 @@ class Connection extends EventEmitter {
|
|||||||
function cleanup() {
|
function cleanup() {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
self.removeAllListeners(eventName);
|
self.removeAllListeners(eventName);
|
||||||
|
if (self._ws !== null) {
|
||||||
self._ws.removeListener('close', onDisconnect);
|
self._ws.removeListener('close', onDisconnect);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _resolve(response) {
|
function _resolve(response) {
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const core = require('./utils').core;
|
|
||||||
const flagIndices = require('./txflags').txFlagIndices.AccountSet;
|
const flagIndices = require('./txflags').txFlagIndices.AccountSet;
|
||||||
const flags = core.Remote.flags.account_root;
|
|
||||||
|
const accountRootFlags = {
|
||||||
|
PasswordSpent: 0x00010000, // password set fee is spent
|
||||||
|
RequireDestTag: 0x00020000, // require a DestinationTag for payments
|
||||||
|
RequireAuth: 0x00040000, // require a authorization to hold IOUs
|
||||||
|
DisallowXRP: 0x00080000, // disallow sending XRP
|
||||||
|
DisableMaster: 0x00100000, // force regular key
|
||||||
|
NoFreeze: 0x00200000, // permanently disallowed freezing trustlines
|
||||||
|
GlobalFreeze: 0x00400000, // trustlines globally frozen
|
||||||
|
DefaultRipple: 0x00800000
|
||||||
|
};
|
||||||
|
|
||||||
const AccountFlags = {
|
const AccountFlags = {
|
||||||
passwordSpent: flags.PasswordSpent,
|
passwordSpent: accountRootFlags.PasswordSpent,
|
||||||
requireDestinationTag: flags.RequireDestTag,
|
requireDestinationTag: accountRootFlags.RequireDestTag,
|
||||||
requireAuthorization: flags.RequireAuth,
|
requireAuthorization: accountRootFlags.RequireAuth,
|
||||||
disallowIncomingXRP: flags.DisallowXRP,
|
disallowIncomingXRP: accountRootFlags.DisallowXRP,
|
||||||
disableMasterKey: flags.DisableMaster,
|
disableMasterKey: accountRootFlags.DisableMaster,
|
||||||
noFreeze: flags.NoFreeze,
|
noFreeze: accountRootFlags.NoFreeze,
|
||||||
globalFreeze: flags.GlobalFreeze,
|
globalFreeze: accountRootFlags.GlobalFreeze,
|
||||||
defaultRipple: flags.DefaultRipple
|
defaultRipple: accountRootFlags.DefaultRipple
|
||||||
};
|
};
|
||||||
|
|
||||||
const AccountFlagIndices = {
|
const AccountFlagIndices = {
|
||||||
|
|||||||
@@ -34,6 +34,48 @@ RippleError.prototype.inspect = function(depth) {
|
|||||||
return this.toString();
|
return this.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RippledError extends RippleError {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = this.constructor.name;
|
||||||
|
this.message = message;
|
||||||
|
Error.captureStackTrace(this, this.constructor.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConnectionError extends RippleError {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = this.constructor.name;
|
||||||
|
this.message = message;
|
||||||
|
Error.captureStackTrace(this, this.constructor.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotConnectedError extends ConnectionError {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DisconnectedError extends ConnectionError {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimeoutError extends ConnectionError {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnexpectedError extends ConnectionError {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function ValidationError(message) {
|
function ValidationError(message) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
@@ -117,5 +159,11 @@ module.exports = {
|
|||||||
MissingLedgerHistoryError,
|
MissingLedgerHistoryError,
|
||||||
TimeOutError,
|
TimeOutError,
|
||||||
ApiError,
|
ApiError,
|
||||||
RippleError
|
RippleError,
|
||||||
|
ConnectionError,
|
||||||
|
RippledError,
|
||||||
|
NotConnectedError,
|
||||||
|
DisconnectedError,
|
||||||
|
TimeoutError,
|
||||||
|
UnexpectedError
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ const utils = require('./utils');
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Connection: require('./connection'),
|
Connection: require('./connection'),
|
||||||
core: utils.core,
|
|
||||||
constants: require('./constants'),
|
constants: require('./constants'),
|
||||||
errors: require('./errors'),
|
errors: require('./errors'),
|
||||||
validate: require('./validate'),
|
validate: require('./validate'),
|
||||||
@@ -13,12 +12,11 @@ module.exports = {
|
|||||||
xrpToDrops: utils.xrpToDrops,
|
xrpToDrops: utils.xrpToDrops,
|
||||||
toRippledAmount: utils.toRippledAmount,
|
toRippledAmount: utils.toRippledAmount,
|
||||||
generateAddress: utils.generateAddress,
|
generateAddress: utils.generateAddress,
|
||||||
composeAsync: utils.composeAsync,
|
generateAddressAPI: utils.generateAddressAPI,
|
||||||
wrapCatch: utils.wrapCatch,
|
|
||||||
removeUndefined: utils.removeUndefined,
|
removeUndefined: utils.removeUndefined,
|
||||||
convertErrors: utils.convertErrors,
|
|
||||||
convertExceptions: utils.convertExceptions,
|
convertExceptions: utils.convertExceptions,
|
||||||
convertKeysFromSnakeCaseToCamelCase:
|
convertKeysFromSnakeCaseToCamelCase:
|
||||||
utils.convertKeysFromSnakeCaseToCamelCase,
|
utils.convertKeysFromSnakeCaseToCamelCase,
|
||||||
promisify: utils.promisify
|
rippleToUnixTimestamp: utils.rippleToUnixTimestamp,
|
||||||
|
unixToRippleTimestamp: utils.unixToRippleTimestamp
|
||||||
};
|
};
|
||||||
|
|||||||
61
src/api/common/rangeset.js
Normal file
61
src/api/common/rangeset.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/* @flow */
|
||||||
|
'use strict';
|
||||||
|
const _ = require('lodash');
|
||||||
|
const assert = require('assert');
|
||||||
|
const ranges = Symbol();
|
||||||
|
|
||||||
|
function mergeIntervals(intervals: Array<[number, number]>) {
|
||||||
|
const stack = [[-Infinity, -Infinity]];
|
||||||
|
_.forEach(_.sortBy(intervals, x => x[0]), interval => {
|
||||||
|
const lastInterval = stack.pop();
|
||||||
|
if (interval[0] <= lastInterval[1] + 1) {
|
||||||
|
stack.push([lastInterval[0], Math.max(interval[1], lastInterval[1])]);
|
||||||
|
} else {
|
||||||
|
stack.push(lastInterval);
|
||||||
|
stack.push(interval);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return stack.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
class RangeSet {
|
||||||
|
constructor() {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this[ranges] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
serialize() {
|
||||||
|
return this[ranges].map(range =>
|
||||||
|
range[0].toString() + '-' + range[1].toString()).join(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
addRange(start: number, end: number) {
|
||||||
|
assert(start <= end, 'invalid range');
|
||||||
|
this[ranges] = mergeIntervals(this[ranges].concat([[start, end]]));
|
||||||
|
}
|
||||||
|
|
||||||
|
addValue(value: number) {
|
||||||
|
this.addRange(value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseAndAddRanges(rangesString: string) {
|
||||||
|
const rangeStrings = rangesString.split(',');
|
||||||
|
_.forEach(rangeStrings, rangeString => {
|
||||||
|
const range = rangeString.split('-').map(Number);
|
||||||
|
this.addRange(range[0], range.length === 1 ? range[0] : range[1]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
containsRange(start: number, end: number) {
|
||||||
|
return _.some(this[ranges], range => range[0] <= start && range[1] >= end);
|
||||||
|
}
|
||||||
|
|
||||||
|
containsValue(value: number) {
|
||||||
|
return this.containsRange(value, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.RangeSet = RangeSet;
|
||||||
@@ -53,7 +53,7 @@ function loadSchemas() {
|
|||||||
require('./schemas/payment-transaction.json'),
|
require('./schemas/payment-transaction.json'),
|
||||||
require('./schemas/payment.json'),
|
require('./schemas/payment.json'),
|
||||||
require('./schemas/quality.json'),
|
require('./schemas/quality.json'),
|
||||||
require('./schemas/remote-options.json'),
|
require('./schemas/api-options.json'),
|
||||||
require('./schemas/sequence.json'),
|
require('./schemas/sequence.json'),
|
||||||
require('./schemas/settings-options.json'),
|
require('./schemas/settings-options.json'),
|
||||||
require('./schemas/settings-transaction.json'),
|
require('./schemas/settings-transaction.json'),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
"title": "remote-options",
|
"title": "api-options",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"trace": {"type": "boolean"},
|
"trace": {"type": "boolean"},
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const {RippledNetworkError} = require('./errors');
|
const {convertKeysFromSnakeCaseToCamelCase} = require('./utils');
|
||||||
const {promisify, convertKeysFromSnakeCaseToCamelCase} = require('./utils');
|
import type {Connection} from './connection';
|
||||||
|
|
||||||
export type GetServerInfoResponse = {
|
export type GetServerInfoResponse = {
|
||||||
buildVersion: string,
|
buildVersion: string,
|
||||||
@@ -32,21 +32,10 @@ export type GetServerInfoResponse = {
|
|||||||
validationQuorum: number
|
validationQuorum: number
|
||||||
}
|
}
|
||||||
|
|
||||||
function getServerInfoAsync(remote,
|
function getServerInfo(connection: Connection): Promise<GetServerInfoResponse> {
|
||||||
callback: (err: any, data?: GetServerInfoResponse) => void
|
return connection.request({command: 'server_info'}).then(response =>
|
||||||
): void {
|
convertKeysFromSnakeCaseToCamelCase(response.info)
|
||||||
remote.rawRequest({command: 'server_info'}, (error, response) => {
|
);
|
||||||
if (error) {
|
|
||||||
const message = _.get(error, ['remote', 'error_message'], error.message);
|
|
||||||
callback(new RippledNetworkError(message));
|
|
||||||
} else {
|
|
||||||
callback(null, convertKeysFromSnakeCaseToCamelCase(response.info));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getServerInfo(remote: Object): Promise<GetServerInfoResponse> {
|
|
||||||
return promisify(getServerInfoAsync)(remote);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeFeeFromServerInfo(cushion: number,
|
function computeFeeFromServerInfo(cushion: number,
|
||||||
@@ -56,8 +45,8 @@ function computeFeeFromServerInfo(cushion: number,
|
|||||||
* Number(serverInfo.loadFactor) * cushion).toString();
|
* Number(serverInfo.loadFactor) * cushion).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFee(remote: Object, cushion: number) {
|
function getFee(connection: Connection, cushion: number) {
|
||||||
return getServerInfo(remote).then(
|
return getServerInfo(connection).then(
|
||||||
_.partial(computeFeeFromServerInfo, cushion));
|
_.partial(computeFeeFromServerInfo, cushion));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const BigNumber = require('bignumber.js');
|
const BigNumber = require('bignumber.js');
|
||||||
const core = require('../../core');
|
|
||||||
const errors = require('./errors');
|
const errors = require('./errors');
|
||||||
const es6promisify = require('es6-promisify');
|
|
||||||
const keypairs = require('ripple-keypairs');
|
const keypairs = require('ripple-keypairs');
|
||||||
|
|
||||||
import type {Amount, RippledAmount} from './types.js';
|
import type {Amount, RippledAmount} from './types.js';
|
||||||
@@ -36,63 +34,12 @@ function generateAddress(options?: Object): Object {
|
|||||||
return {secret, address};
|
return {secret, address};
|
||||||
}
|
}
|
||||||
|
|
||||||
type AsyncFunction = (...x: any) => void
|
function generateAddressAPI(options?: Object): Object {
|
||||||
|
|
||||||
function wrapCatch(asyncFunction: AsyncFunction): AsyncFunction {
|
|
||||||
return function() {
|
|
||||||
try {
|
try {
|
||||||
asyncFunction.apply(this, arguments);
|
return generateAddress(options);
|
||||||
} catch (error) {
|
|
||||||
const callback = arguments[arguments.length - 1];
|
|
||||||
callback(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
type Callback = (err: any, data: any) => void
|
|
||||||
type Wrapper = (data: any) => any
|
|
||||||
|
|
||||||
function composeAsync(wrapper: Wrapper, callback: Callback): Callback {
|
|
||||||
return function(error, data) {
|
|
||||||
if (error) {
|
|
||||||
callback(error, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let result;
|
|
||||||
try {
|
|
||||||
result = wrapper(data);
|
|
||||||
} catch (exception) {
|
|
||||||
callback(exception);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback(null, result);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertErrors(callback: Callback): () => void {
|
|
||||||
return function(error, data) {
|
|
||||||
if (error && !(error instanceof errors.RippleError)) {
|
|
||||||
const message = _.get(error, ['remote', 'error_message'], error.message);
|
|
||||||
const error_ = new errors.RippleError(message);
|
|
||||||
error_.data = data;
|
|
||||||
callback(error_, data);
|
|
||||||
} else if (error) {
|
|
||||||
error.data = data;
|
|
||||||
callback(error, data);
|
|
||||||
} else {
|
|
||||||
callback(error, data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertExceptions<T>(f: () => T): () => T {
|
|
||||||
return function() {
|
|
||||||
try {
|
|
||||||
return f.apply(this, arguments);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new errors.ApiError(error.message);
|
throw new errors.ApiError(error.message);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g;
|
const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g;
|
||||||
@@ -111,25 +58,38 @@ function convertKeysFromSnakeCaseToCamelCase(obj: any): any {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
function promisify(asyncFunction: AsyncFunction): Function {
|
|
||||||
return es6promisify(wrapCatch(asyncFunction));
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeUndefined(obj: Object): Object {
|
function removeUndefined(obj: Object): Object {
|
||||||
return _.omit(obj, _.isUndefined);
|
return _.omit(obj, _.isUndefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} rpepoch (seconds since 1/1/2000 GMT)
|
||||||
|
* @return {Number} ms since unix epoch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function rippleToUnixTimestamp(rpepoch: number): number {
|
||||||
|
return (rpepoch + 0x386D4380) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number|Date} timestamp (ms since unix epoch)
|
||||||
|
* @return {Number} seconds since ripple epoch ( 1/1/2000 GMT)
|
||||||
|
*/
|
||||||
|
function unixToRippleTimestamp(timestamp: number | Date): number {
|
||||||
|
const timestamp_ = timestamp instanceof Date ?
|
||||||
|
timestamp.getTime() :
|
||||||
|
timestamp;
|
||||||
|
return Math.round(timestamp_ / 1000) - 0x386D4380;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
core,
|
|
||||||
dropsToXrp,
|
dropsToXrp,
|
||||||
xrpToDrops,
|
xrpToDrops,
|
||||||
toRippledAmount,
|
toRippledAmount,
|
||||||
generateAddress,
|
generateAddress,
|
||||||
composeAsync,
|
generateAddressAPI,
|
||||||
wrapCatch,
|
|
||||||
convertExceptions,
|
|
||||||
convertErrors,
|
|
||||||
convertKeysFromSnakeCaseToCamelCase,
|
convertKeysFromSnakeCaseToCamelCase,
|
||||||
promisify,
|
removeUndefined,
|
||||||
removeUndefined
|
rippleToUnixTimestamp,
|
||||||
|
unixToRippleTimestamp
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -88,6 +88,6 @@ module.exports = {
|
|||||||
getTransactionOptions: _.partial(validateOptions, 'transaction-options'),
|
getTransactionOptions: _.partial(validateOptions, 'transaction-options'),
|
||||||
getLedgerOptions: _.partial(validateOptions, 'ledger-options'),
|
getLedgerOptions: _.partial(validateOptions, 'ledger-options'),
|
||||||
options: _.partial(validateOptions, 'options'),
|
options: _.partial(validateOptions, 'options'),
|
||||||
remoteOptions: _.partial(schemaValidate, 'remote-options'),
|
apiOptions: _.partial(schemaValidate, 'api-options'),
|
||||||
instructions: _.partial(schemaValidate, 'instructions')
|
instructions: _.partial(schemaValidate, 'instructions')
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,22 +36,34 @@ const prepareSettings = require('./transaction/settings');
|
|||||||
const sign = require('./transaction/sign');
|
const sign = require('./transaction/sign');
|
||||||
const submit = require('./transaction/submit');
|
const submit = require('./transaction/submit');
|
||||||
const errors = require('./common').errors;
|
const errors = require('./common').errors;
|
||||||
const convertExceptions = require('./common').convertExceptions;
|
const generateAddress = common.generateAddressAPI;
|
||||||
const generateAddress = convertExceptions(common.generateAddress);
|
|
||||||
const computeLedgerHash = require('./offline/ledgerhash');
|
const computeLedgerHash = require('./offline/ledgerhash');
|
||||||
const getLedger = require('./ledger/ledger');
|
const getLedger = require('./ledger/ledger');
|
||||||
|
|
||||||
function RippleAPI(options: {}) {
|
type APIOptions = {
|
||||||
common.validate.remoteOptions(options);
|
servers?: Array<string>,
|
||||||
|
feeCushion?: number,
|
||||||
|
trace?: boolean,
|
||||||
|
proxy?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function RippleAPI(options: APIOptions = {}) {
|
||||||
|
common.validate.apiOptions(options);
|
||||||
if (EventEmitter instanceof Function) { // always true, needed for flow
|
if (EventEmitter instanceof Function) { // always true, needed for flow
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
}
|
}
|
||||||
const _options = _.assign({}, options, {automatic_resubmission: false});
|
if (options.servers !== undefined) {
|
||||||
this._feeCushion = _options.feeCushion || 1.2;
|
const servers: Array<string> = options.servers;
|
||||||
this.remote = new common.core.Remote(_options);
|
if (servers.length === 1) {
|
||||||
this.remote.on('ledger_closed', message => {
|
this._feeCushion = options.feeCushion || 1.2;
|
||||||
|
this.connection = new common.Connection(servers[0], options);
|
||||||
|
this.connection.on('ledgerClosed', message => {
|
||||||
this.emit('ledgerClosed', server.formatLedgerClose(message));
|
this.emit('ledgerClosed', server.formatLedgerClose(message));
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
throw new errors.RippleError('Multi-server not implemented');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(RippleAPI, EventEmitter);
|
util.inherits(RippleAPI, EventEmitter);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const {validate, composeAsync, convertErrors, removeUndefined} = utils.common;
|
const {validate, removeUndefined} = utils.common;
|
||||||
|
|
||||||
type AccountData = {
|
type AccountData = {
|
||||||
Sequence: number,
|
Sequence: number,
|
||||||
@@ -29,8 +29,6 @@ type AccountInfoOptions = {
|
|||||||
ledgerVersion?: number
|
ledgerVersion?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccountInfoCallback = (err: any, data: AccountInfoResponse) => void
|
|
||||||
|
|
||||||
type AccountInfoResponse = {
|
type AccountInfoResponse = {
|
||||||
sequence: number,
|
sequence: number,
|
||||||
xrpBalance: string,
|
xrpBalance: string,
|
||||||
@@ -52,9 +50,8 @@ function formatAccountInfo(response: AccountDataResponse) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAccountInfoAsync(account: string, options: AccountInfoOptions,
|
function getAccountInfo(account: string, options: AccountInfoOptions = {}
|
||||||
callback: AccountInfoCallback
|
): Promise<AccountInfoResponse> {
|
||||||
) {
|
|
||||||
validate.address(account);
|
validate.address(account);
|
||||||
validate.getAccountInfoOptions(options);
|
validate.getAccountInfoOptions(options);
|
||||||
|
|
||||||
@@ -64,13 +61,7 @@ function getAccountInfoAsync(account: string, options: AccountInfoOptions,
|
|||||||
ledger_index: options.ledgerVersion || 'validated'
|
ledger_index: options.ledgerVersion || 'validated'
|
||||||
};
|
};
|
||||||
|
|
||||||
this.remote.rawRequest(request,
|
return this.connection.request(request).then(formatAccountInfo);
|
||||||
composeAsync(formatAccountInfo, convertErrors(callback)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAccountInfo(account: string, options: AccountInfoOptions = {}
|
|
||||||
): Promise<AccountInfoResponse> {
|
|
||||||
return utils.promisify(getAccountInfoAsync).call(this, account, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getAccountInfo;
|
module.exports = getAccountInfo;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const {validate, composeAsync, convertErrors} = utils.common;
|
const {validate} = utils.common;
|
||||||
import type {Amount} from '../common/types.js';
|
import type {Amount} from '../common/types.js';
|
||||||
|
|
||||||
type BalanceSheetOptions = {
|
type BalanceSheetOptions = {
|
||||||
@@ -47,42 +47,22 @@ function formatBalanceSheet(balanceSheet): GetBalanceSheet {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBalanceSheetAsync(address: string, options: BalanceSheetOptions,
|
function getBalanceSheet(address: string, options: BalanceSheetOptions = {}
|
||||||
callback
|
): Promise<GetBalanceSheet> {
|
||||||
) {
|
|
||||||
validate.address(address);
|
validate.address(address);
|
||||||
validate.getBalanceSheetOptions(options);
|
validate.getBalanceSheetOptions(options);
|
||||||
|
|
||||||
|
return utils.ensureLedgerVersion.call(this, options).then(_options => {
|
||||||
const request = {
|
const request = {
|
||||||
command: 'gateway_balances',
|
command: 'gateway_balances',
|
||||||
account: address,
|
account: address,
|
||||||
strict: true,
|
strict: true,
|
||||||
hotwallet: options.excludeAddresses,
|
hotwallet: _options.excludeAddresses,
|
||||||
ledger_index: options.ledgerVersion
|
ledger_index: _options.ledgerVersion
|
||||||
};
|
};
|
||||||
|
|
||||||
const requestCallback = composeAsync(
|
return this.connection.request(request).then(formatBalanceSheet);
|
||||||
formatBalanceSheet, convertErrors(callback));
|
|
||||||
|
|
||||||
if (_.isUndefined(request.ledger_index)) {
|
|
||||||
this.remote.getLedgerSequence((err, ledgerVersion) => {
|
|
||||||
if (err) {
|
|
||||||
convertErrors(callback)(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
request.ledger_index = ledgerVersion;
|
|
||||||
|
|
||||||
this.remote.rawRequest(request, requestCallback);
|
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
this.remote.rawRequest(request, requestCallback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBalanceSheet(address: string, options: BalanceSheetOptions = {}
|
|
||||||
): Promise<GetBalanceSheet> {
|
|
||||||
return utils.promisify(getBalanceSheetAsync).call(this, address, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getBalanceSheet;
|
module.exports = getBalanceSheet;
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
|
||||||
const async = require('async');
|
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const getTrustlines = require('./trustlines');
|
const {validate} = utils.common;
|
||||||
const {validate, composeAsync, convertErrors} = utils.common;
|
import type {Connection} from '../common/connection.js';
|
||||||
import type {Remote, GetLedgerSequenceCallback} from '../../core/remote';
|
|
||||||
import type {TrustlinesOptions, Trustline} from './trustlines-types.js';
|
import type {TrustlinesOptions, Trustline} from './trustlines-types.js';
|
||||||
|
|
||||||
|
|
||||||
@@ -43,42 +40,26 @@ function formatBalances(options, balances) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTrustlinesAsync(account: string, options: TrustlinesOptions,
|
function getLedgerVersionHelper(connection: Connection, optionValue?: number
|
||||||
callback
|
): Promise<number> {
|
||||||
) {
|
|
||||||
getTrustlines.call(this, account, options)
|
|
||||||
.then(data => callback(null, data))
|
|
||||||
.catch(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLedgerVersionHelper(remote: Remote, optionValue?: number,
|
|
||||||
callback: GetLedgerSequenceCallback
|
|
||||||
) {
|
|
||||||
if (optionValue !== undefined && optionValue !== null) {
|
if (optionValue !== undefined && optionValue !== null) {
|
||||||
callback(null, optionValue);
|
return Promise.resolve(optionValue);
|
||||||
} else {
|
|
||||||
remote.getLedgerSequence(callback);
|
|
||||||
}
|
}
|
||||||
}
|
return connection.getLedgerVersion();
|
||||||
|
|
||||||
function getBalancesAsync(account: string, options: TrustlinesOptions,
|
|
||||||
callback
|
|
||||||
) {
|
|
||||||
validate.address(account);
|
|
||||||
validate.getBalancesOptions(options);
|
|
||||||
|
|
||||||
async.parallel({
|
|
||||||
xrp: async.seq(
|
|
||||||
_.partial(getLedgerVersionHelper, this.remote, options.ledgerVersion),
|
|
||||||
_.partial(utils.getXRPBalance, this.remote, account)
|
|
||||||
),
|
|
||||||
trustlines: _.partial(getTrustlinesAsync.bind(this), account, options)
|
|
||||||
}, composeAsync(_.partial(formatBalances, options), convertErrors(callback)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBalances(account: string, options: TrustlinesOptions = {}
|
function getBalances(account: string, options: TrustlinesOptions = {}
|
||||||
): Promise<GetBalances> {
|
): Promise<GetBalances> {
|
||||||
return utils.promisify(getBalancesAsync).call(this, account, options);
|
validate.address(account);
|
||||||
|
validate.getBalancesOptions(options);
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
getLedgerVersionHelper(this.connection, options.ledgerVersion).then(
|
||||||
|
ledgerVersion =>
|
||||||
|
utils.getXRPBalance(this.connection, account, ledgerVersion)),
|
||||||
|
this.getTrustlines(account, options)
|
||||||
|
]).then(results =>
|
||||||
|
formatBalances(options, {xrp: results[0], trustlines: results[1]}));
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getBalances;
|
module.exports = getBalances;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const {validate, composeAsync, convertErrors} = utils.common;
|
const {validate} = utils.common;
|
||||||
const parseLedger = require('./parse/ledger');
|
const parseLedger = require('./parse/ledger');
|
||||||
import type {GetLedger} from './types.js';
|
import type {GetLedger} from './types.js';
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ type LedgerOptions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getLedgerAsync(options: LedgerOptions, callback) {
|
function getLedger(options: LedgerOptions = {}): Promise<GetLedger> {
|
||||||
validate.getLedgerOptions(options);
|
validate.getLedgerOptions(options);
|
||||||
|
|
||||||
const request = {
|
const request = {
|
||||||
@@ -24,13 +24,8 @@ function getLedgerAsync(options: LedgerOptions, callback) {
|
|||||||
accounts: options.includeState
|
accounts: options.includeState
|
||||||
};
|
};
|
||||||
|
|
||||||
this.remote.rawRequest(request,
|
return this.connection.request(request).then(response =>
|
||||||
composeAsync(response => parseLedger(response.ledger),
|
parseLedger(response.ledger));
|
||||||
convertErrors(callback)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLedger(options: LedgerOptions = {}): Promise<GetLedger> {
|
|
||||||
return utils.promisify(getLedgerAsync).call(this, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getLedger;
|
module.exports = getLedger;
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const async = require('async');
|
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const {validate, composeAsync, convertErrors} = utils.common;
|
const {validate} = utils.common;
|
||||||
const parseOrderbookOrder = require('./parse/orderbook-order');
|
const parseOrderbookOrder = require('./parse/orderbook-order');
|
||||||
import type {Remote} from '../../core/remote';
|
import type {Connection} from '../common/connection.js';
|
||||||
import type {OrdersOptions, OrderSpecification} from './types.js';
|
import type {OrdersOptions, OrderSpecification} from './types.js';
|
||||||
import type {Amount, Issue} from '../common/types.js';
|
import type {Amount, Issue} from '../common/types.js';
|
||||||
|
|
||||||
@@ -36,18 +35,18 @@ type GetOrderbook = {
|
|||||||
|
|
||||||
// account is to specify a "perspective", which affects which unfunded offers
|
// account is to specify a "perspective", which affects which unfunded offers
|
||||||
// are returned
|
// are returned
|
||||||
function getBookOffers(remote: Remote, account: string,
|
function getBookOffers(connection: Connection, account: string,
|
||||||
ledgerVersion?: number, limit?: number, takerGets: Issue,
|
ledgerVersion?: number, limit?: number, takerGets: Issue,
|
||||||
takerPays: Issue, callback
|
takerPays: Issue
|
||||||
) {
|
): Promise {
|
||||||
remote.rawRequest(utils.renameCounterpartyToIssuerInOrder({
|
return connection.request(utils.renameCounterpartyToIssuerInOrder({
|
||||||
command: 'book_offers',
|
command: 'book_offers',
|
||||||
taker_gets: takerGets,
|
taker_gets: takerGets,
|
||||||
taker_pays: takerPays,
|
taker_pays: takerPays,
|
||||||
ledger_index: ledgerVersion || 'validated',
|
ledger_index: ledgerVersion || 'validated',
|
||||||
limit: limit,
|
limit: limit,
|
||||||
taker: account
|
taker: account
|
||||||
}), composeAsync(data => data.offers, convertErrors(callback)));
|
})).then(data => data.offers);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSameIssue(a: Amount, b: Amount) {
|
function isSameIssue(a: Amount, b: Amount) {
|
||||||
@@ -92,27 +91,19 @@ function formatBidsAndAsks(orderbook: Orderbook, offers) {
|
|||||||
return {bids, asks};
|
return {bids, asks};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOrderbookAsync(account: string, orderbook: Orderbook,
|
function getOrderbook(account: string, orderbook: Orderbook,
|
||||||
options: OrdersOptions, callback
|
options: OrdersOptions = {}
|
||||||
) {
|
): Promise<GetOrderbook> {
|
||||||
validate.address(account);
|
validate.address(account);
|
||||||
validate.orderbook(orderbook);
|
validate.orderbook(orderbook);
|
||||||
validate.getOrderbookOptions(options);
|
validate.getOrderbookOptions(options);
|
||||||
|
|
||||||
const getter = _.partial(getBookOffers, this.remote, account,
|
const getter = _.partial(getBookOffers, this.connection, account,
|
||||||
options.ledgerVersion, options.limit);
|
options.ledgerVersion, options.limit);
|
||||||
const getOffers = _.partial(getter, orderbook.base, orderbook.counter);
|
const getOffers = _.partial(getter, orderbook.base, orderbook.counter);
|
||||||
const getReverseOffers = _.partial(getter, orderbook.counter, orderbook.base);
|
const getReverseOffers = _.partial(getter, orderbook.counter, orderbook.base);
|
||||||
async.parallel([getOffers, getReverseOffers],
|
return Promise.all([getOffers(), getReverseOffers()]).then(data =>
|
||||||
composeAsync((data) => formatBidsAndAsks(orderbook, _.flatten(data)),
|
formatBidsAndAsks(orderbook, _.flatten(data)));
|
||||||
callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOrderbook(account: string, orderbook: Orderbook,
|
|
||||||
options: OrdersOptions = {}
|
|
||||||
): Promise<GetOrderbook> {
|
|
||||||
return utils.promisify(getOrderbookAsync).call(this,
|
|
||||||
account, orderbook, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getOrderbook;
|
module.exports = getOrderbook;
|
||||||
|
|||||||
@@ -1,47 +1,42 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const async = require('async');
|
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const {validate, composeAsync, convertErrors} = utils.common;
|
const {validate} = utils.common;
|
||||||
const parseAccountOrder = require('./parse/account-order');
|
const parseAccountOrder = require('./parse/account-order');
|
||||||
import type {Remote} from '../../core/remote';
|
import type {Connection} from '../common/connection.js';
|
||||||
import type {OrdersOptions, Order} from './types.js';
|
import type {OrdersOptions, Order} from './types.js';
|
||||||
|
|
||||||
type GetOrders = Array<Order>
|
type GetOrders = Array<Order>
|
||||||
|
|
||||||
function requestAccountOffers(remote: Remote, address: string,
|
function requestAccountOffers(connection: Connection, address: string,
|
||||||
ledgerVersion: number, marker: string, limit: number, callback
|
ledgerVersion: number, marker: string, limit: number
|
||||||
) {
|
): Promise {
|
||||||
remote.rawRequest({
|
return connection.request({
|
||||||
command: 'account_offers',
|
command: 'account_offers',
|
||||||
account: address,
|
account: address,
|
||||||
marker: marker,
|
marker: marker,
|
||||||
limit: utils.clamp(limit, 10, 400),
|
limit: utils.clamp(limit, 10, 400),
|
||||||
ledger_index: ledgerVersion
|
ledger_index: ledgerVersion
|
||||||
},
|
}).then(data => {
|
||||||
composeAsync((data) => ({
|
return {
|
||||||
marker: data.marker,
|
marker: data.marker,
|
||||||
results: data.offers.map(_.partial(parseAccountOrder, address))
|
results: data.offers.map(_.partial(parseAccountOrder, address))
|
||||||
}), convertErrors(callback)));
|
};
|
||||||
}
|
});
|
||||||
|
|
||||||
function getOrdersAsync(account: string, options: OrdersOptions, callback) {
|
|
||||||
validate.address(account);
|
|
||||||
validate.getOrdersOptions(options);
|
|
||||||
|
|
||||||
const getter = _.partial(requestAccountOffers, this.remote, account,
|
|
||||||
options.ledgerVersion);
|
|
||||||
utils.getRecursive(getter, options.limit,
|
|
||||||
composeAsync((orders) => _.sortBy(orders,
|
|
||||||
(order) => order.properties.sequence), callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOrders(account: string, options: OrdersOptions = {}
|
function getOrders(account: string, options: OrdersOptions = {}
|
||||||
): Promise<GetOrders> {
|
): Promise<GetOrders> {
|
||||||
return utils.promisify(async.seq(
|
validate.address(account);
|
||||||
utils.getLedgerOptionsWithLedgerVersion,
|
validate.getOrdersOptions(options);
|
||||||
getOrdersAsync)).call(this, account, options);
|
|
||||||
|
return utils.ensureLedgerVersion.call(this, options).then(_options => {
|
||||||
|
const getter = _.partial(requestAccountOffers, this.connection, account,
|
||||||
|
_options.ledgerVersion);
|
||||||
|
return utils.getRecursive(getter, _options.limit).then(orders =>
|
||||||
|
_.sortBy(orders, (order) => order.properties.sequence));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getOrders;
|
module.exports = getOrders;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const flags = utils.core.Remote.flags.offer;
|
const flags = require('./flags').orderFlags;
|
||||||
const parseAmount = require('./amount');
|
const parseAmount = require('./amount');
|
||||||
const BigNumber = require('bignumber.js');
|
const BigNumber = require('bignumber.js');
|
||||||
|
|
||||||
|
|||||||
22
src/api/ledger/parse/flags.js
Normal file
22
src/api/ledger/parse/flags.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const orderFlags = {
|
||||||
|
Passive: 0x00010000,
|
||||||
|
Sell: 0x00020000 // offer was placed as a sell
|
||||||
|
};
|
||||||
|
|
||||||
|
const trustlineFlags = {
|
||||||
|
LowReserve: 0x00010000, // entry counts toward reserve
|
||||||
|
HighReserve: 0x00020000,
|
||||||
|
LowAuth: 0x00040000,
|
||||||
|
HighAuth: 0x00080000,
|
||||||
|
LowNoRipple: 0x00100000,
|
||||||
|
HighNoRipple: 0x00200000,
|
||||||
|
LowFreeze: 0x00400000,
|
||||||
|
HighFreeze: 0x00800000
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
orderFlags,
|
||||||
|
trustlineFlags
|
||||||
|
};
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const flags = utils.core.Remote.flags.offer;
|
const flags = require('./flags').orderFlags;
|
||||||
const parseAmount = require('./amount');
|
const parseAmount = require('./amount');
|
||||||
|
|
||||||
function parseOrderbookOrder(order: Object): Object {
|
function parseOrderbookOrder(order: Object): Object {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const transactionParser = require('ripple-lib-transactionparser');
|
const transactionParser = require('ripple-lib-transactionparser');
|
||||||
const toTimestamp = require('../../../core/utils').toTimestamp;
|
|
||||||
const utils = require('../utils');
|
const utils = require('../utils');
|
||||||
|
const rippleToUnixTimestamp = utils.common.rippleToUnixTimestamp;
|
||||||
const BigNumber = require('bignumber.js');
|
const BigNumber = require('bignumber.js');
|
||||||
|
|
||||||
function adjustQualityForXRP(
|
function adjustQualityForXRP(
|
||||||
@@ -19,7 +19,8 @@ function adjustQualityForXRP(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parseTimestamp(tx: {date: string}): string | void {
|
function parseTimestamp(tx: {date: string}): string | void {
|
||||||
return tx.date ? (new Date(toTimestamp(tx.date))).toISOString() : undefined;
|
return tx.date ? (new Date(rippleToUnixTimestamp(tx.date))).toISOString()
|
||||||
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeEmptyCounterparty(amount) {
|
function removeEmptyCounterparty(amount) {
|
||||||
@@ -87,6 +88,5 @@ module.exports = {
|
|||||||
dropsToXrp: utils.common.dropsToXrp,
|
dropsToXrp: utils.common.dropsToXrp,
|
||||||
constants: utils.common.constants,
|
constants: utils.common.constants,
|
||||||
txFlags: utils.common.txFlags,
|
txFlags: utils.common.txFlags,
|
||||||
core: utils.common.core,
|
|
||||||
removeUndefined: utils.common.removeUndefined
|
removeUndefined: utils.common.removeUndefined
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const async = require('async');
|
|
||||||
const BigNumber = require('bignumber.js');
|
const BigNumber = require('bignumber.js');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const parsePathfind = require('./parse/pathfind');
|
const parsePathfind = require('./parse/pathfind');
|
||||||
const {validate, composeAsync, convertErrors, toRippledAmount} = utils.common;
|
const {validate, toRippledAmount} = utils.common;
|
||||||
const NotFoundError = utils.common.errors.NotFoundError;
|
const NotFoundError = utils.common.errors.NotFoundError;
|
||||||
const ValidationError = utils.common.errors.ValidationError;
|
const ValidationError = utils.common.errors.ValidationError;
|
||||||
import type {Remote} from '../../core/remote';
|
import type {Connection} from '../common/connection';
|
||||||
import type {RippledAmount} from '../common/types.js';
|
import type {RippledAmount} from '../common/types.js';
|
||||||
import type {GetPaths, PathFind, RippledPathsResponse, PathFindRequest}
|
import type {GetPaths, PathFind, RippledPathsResponse, PathFindRequest}
|
||||||
from './pathfind-types.js';
|
from './pathfind-types.js';
|
||||||
@@ -21,7 +20,7 @@ function addParams(request: PathFindRequest, result: RippledPathsResponse) {
|
|||||||
}), {destination_amount: request.destination_amount});
|
}), {destination_amount: request.destination_amount});
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestPathFind(remote: Remote, pathfind: PathFind, callback) {
|
function requestPathFind(connection: Connection, pathfind: PathFind): Promise {
|
||||||
const destinationAmount = _.assign({value: -1}, pathfind.destination.amount);
|
const destinationAmount = _.assign({value: -1}, pathfind.destination.amount);
|
||||||
const request: PathFindRequest = {
|
const request: PathFindRequest = {
|
||||||
command: 'ripple_path_find',
|
command: 'ripple_path_find',
|
||||||
@@ -53,8 +52,7 @@ function requestPathFind(remote: Remote, pathfind: PathFind, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remote.rawRequest(request,
|
return connection.request(request).then(paths => addParams(request, paths));
|
||||||
composeAsync(_.partial(addParams, request), convertErrors(callback)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addDirectXrpPath(paths: RippledPathsResponse, xrpBalance: string
|
function addDirectXrpPath(paths: RippledPathsResponse, xrpBalance: string
|
||||||
@@ -76,16 +74,15 @@ function isRippledIOUAmount(amount: RippledAmount) {
|
|||||||
amount.currency && (amount.currency !== 'XRP');
|
amount.currency && (amount.currency !== 'XRP');
|
||||||
}
|
}
|
||||||
|
|
||||||
function conditionallyAddDirectXRPPath(remote: Remote, address: string,
|
function conditionallyAddDirectXRPPath(connection: Connection, address: string,
|
||||||
paths: RippledPathsResponse, callback
|
paths: RippledPathsResponse
|
||||||
) {
|
): Promise {
|
||||||
if (isRippledIOUAmount(paths.destination_amount)
|
if (isRippledIOUAmount(paths.destination_amount)
|
||||||
|| !_.includes(paths.destination_currencies, 'XRP')) {
|
|| !_.includes(paths.destination_currencies, 'XRP')) {
|
||||||
callback(null, paths);
|
return Promise.resolve(paths);
|
||||||
} else {
|
|
||||||
utils.getXRPBalance(remote, address, undefined,
|
|
||||||
composeAsync(_.partial(addDirectXrpPath, paths), callback));
|
|
||||||
}
|
}
|
||||||
|
return utils.getXRPBalance(connection, address, undefined).then(
|
||||||
|
xrpBalance => addDirectXrpPath(paths, xrpBalance));
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatResponse(pathfind: PathFind, paths: RippledPathsResponse) {
|
function formatResponse(pathfind: PathFind, paths: RippledPathsResponse) {
|
||||||
@@ -113,18 +110,13 @@ function formatResponse(pathfind: PathFind, paths: RippledPathsResponse) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPathsAsync(pathfind: PathFind, callback) {
|
function getPaths(pathfind: PathFind): Promise<GetPaths> {
|
||||||
validate.pathfind(pathfind);
|
validate.pathfind(pathfind);
|
||||||
|
|
||||||
const address = pathfind.source.address;
|
const address = pathfind.source.address;
|
||||||
async.waterfall([
|
return requestPathFind(this.connection, pathfind).then(paths =>
|
||||||
_.partial(requestPathFind, this.remote, pathfind),
|
conditionallyAddDirectXRPPath(this.connection, address, paths)
|
||||||
_.partial(conditionallyAddDirectXRPPath, this.remote, address)
|
).then(paths => formatResponse(pathfind, paths));
|
||||||
], composeAsync(_.partial(formatResponse, pathfind), callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPaths(pathfind: PathFind): Promise<GetPaths> {
|
|
||||||
return utils.promisify(getPathsAsync).call(this, pathfind);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getPaths;
|
module.exports = getPaths;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const parseFields = require('./parse/fields');
|
const parseFields = require('./parse/fields');
|
||||||
const {validate, composeAsync, convertErrors} = utils.common;
|
const {validate} = utils.common;
|
||||||
const AccountFlags = utils.common.constants.AccountFlags;
|
const AccountFlags = utils.common.constants.AccountFlags;
|
||||||
|
|
||||||
type SettingsOptions = {
|
type SettingsOptions = {
|
||||||
@@ -48,7 +48,8 @@ function formatSettings(response) {
|
|||||||
return _.assign({}, parsedFlags, parsedFields);
|
return _.assign({}, parsedFlags, parsedFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSettingsAsync(account: string, options: SettingsOptions, callback) {
|
function getSettings(account: string, options: SettingsOptions = {}
|
||||||
|
): Promise<GetSettings> {
|
||||||
validate.address(account);
|
validate.address(account);
|
||||||
validate.getSettingsOptions(options);
|
validate.getSettingsOptions(options);
|
||||||
|
|
||||||
@@ -58,13 +59,7 @@ function getSettingsAsync(account: string, options: SettingsOptions, callback) {
|
|||||||
ledger_index: options.ledgerVersion || 'validated'
|
ledger_index: options.ledgerVersion || 'validated'
|
||||||
};
|
};
|
||||||
|
|
||||||
this.remote.rawRequest(request,
|
return this.connection.request(request).then(formatSettings);
|
||||||
composeAsync(formatSettings, convertErrors(callback)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSettings(account: string, options: SettingsOptions = {}
|
|
||||||
): Promise<GetSettings> {
|
|
||||||
return utils.promisify(getSettingsAsync).call(this, account, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getSettings;
|
module.exports = getSettings;
|
||||||
|
|||||||
@@ -1,28 +1,22 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const async = require('async');
|
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const parseTransaction = require('./parse/transaction');
|
const parseTransaction = require('./parse/transaction');
|
||||||
const {validate, convertErrors, errors} = utils.common;
|
const {validate, errors} = utils.common;
|
||||||
const RippleError = require('../../core/rippleerror').RippleError;
|
import type {Connection} from '../common/connection.js';
|
||||||
|
import type {TransactionType, TransactionOptions} from './transaction-types';
|
||||||
|
|
||||||
import type {Remote} from '../../core/remote';
|
function attachTransactionDate(connection: Connection, tx: Object
|
||||||
|
): Promise<TransactionType> {
|
||||||
import type {CallbackType, TransactionType,
|
|
||||||
GetTransactionResponseCallback, TransactionOptions}
|
|
||||||
from './transaction-types';
|
|
||||||
|
|
||||||
function attachTransactionDate(remote: Remote, tx: Object,
|
|
||||||
callback: CallbackType
|
|
||||||
) {
|
|
||||||
if (tx.date) {
|
if (tx.date) {
|
||||||
callback(null, tx);
|
return Promise.resolve(tx);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tx.ledger_index) {
|
if (!tx.ledger_index) {
|
||||||
callback(new errors.NotFoundError('ledger_index not found in tx'));
|
return new Promise(() => {
|
||||||
return;
|
throw new errors.NotFoundError('ledger_index not found in tx');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const request = {
|
const request = {
|
||||||
@@ -30,14 +24,16 @@ function attachTransactionDate(remote: Remote, tx: Object,
|
|||||||
ledger_index: tx.ledger_index
|
ledger_index: tx.ledger_index
|
||||||
};
|
};
|
||||||
|
|
||||||
remote.rawRequest(request, (error, data) => {
|
return connection.request(request).then(data => {
|
||||||
if (error) {
|
if (typeof data.ledger.close_time === 'number') {
|
||||||
callback(new errors.NotFoundError('Transaction ledger not found'));
|
return _.assign({date: data.ledger.close_time}, tx);
|
||||||
} else if (typeof data.ledger.close_time === 'number') {
|
|
||||||
callback(null, _.assign({date: data.ledger.close_time}, tx));
|
|
||||||
} else {
|
|
||||||
callback(new errors.ApiError('Ledger missing close_time'));
|
|
||||||
}
|
}
|
||||||
|
throw new errors.ApiError('Ledger missing close_time');
|
||||||
|
}).catch(error => {
|
||||||
|
if (error instanceof errors.ApiError) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
throw new errors.NotFoundError('Transaction ledger not found');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,69 +44,59 @@ function isTransactionInRange(tx: Object, options: TransactionOptions) {
|
|||||||
|| tx.ledger_index <= options.maxLedgerVersion);
|
|| tx.ledger_index <= options.maxLedgerVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTransactionAsync(identifier: string, options: TransactionOptions,
|
function convertError(connection: Connection, options: TransactionOptions,
|
||||||
callback: GetTransactionResponseCallback
|
error: Error
|
||||||
) {
|
): Promise<Error> {
|
||||||
validate.identifier(identifier);
|
const _error = (error.message === 'txnNotFound') ?
|
||||||
validate.getTransactionOptions(options);
|
new errors.NotFoundError('Transaction not found') : error;
|
||||||
|
if (_error instanceof errors.NotFoundError) {
|
||||||
const remote = this.remote;
|
return utils.hasCompleteLedgerRange(connection, options.minLedgerVersion,
|
||||||
|
options.maxLedgerVersion).then(hasCompleteLedgerRange => {
|
||||||
function callbackWrapper(error_?: Error, tx?: Object,
|
if (!hasCompleteLedgerRange) {
|
||||||
maxLedgerVersion?: number
|
return utils.isPendingLedgerVersion(
|
||||||
) {
|
connection, options.maxLedgerVersion)
|
||||||
let error = error_;
|
.then(isPendingLedgerVersion => {
|
||||||
|
return isPendingLedgerVersion ?
|
||||||
if (!error && tx && tx.validated !== true) {
|
new errors.PendingLedgerVersionError() :
|
||||||
return callback(new errors.NotFoundError('Transaction not found'));
|
new errors.MissingLedgerHistoryError();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return _error;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve(_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error instanceof RippleError && error.remote &&
|
function formatResponse(options: TransactionOptions, tx: TransactionType
|
||||||
error.remote.error === 'txnNotFound') {
|
): TransactionType {
|
||||||
error = new errors.NotFoundError('Transaction not found');
|
if (tx.validated !== true || !isTransactionInRange(tx, options)) {
|
||||||
|
throw new errors.NotFoundError('Transaction not found');
|
||||||
}
|
}
|
||||||
|
return parseTransaction(tx);
|
||||||
// Missing complete ledger range
|
|
||||||
if (error instanceof errors.NotFoundError
|
|
||||||
&& !utils.hasCompleteLedgerRange(remote, options.minLedgerVersion,
|
|
||||||
maxLedgerVersion)) {
|
|
||||||
if (utils.isPendingLedgerVersion(remote, maxLedgerVersion)) {
|
|
||||||
callback(new errors.PendingLedgerVersionError());
|
|
||||||
} else {
|
|
||||||
callback(new errors.MissingLedgerHistoryError());
|
|
||||||
}
|
|
||||||
// Transaction is found, but not in specified range
|
|
||||||
} else if (!error && tx && !isTransactionInRange(tx, options)) {
|
|
||||||
callback(new errors.NotFoundError('Transaction not found'));
|
|
||||||
// Transaction is not found
|
|
||||||
} else if (error) {
|
|
||||||
convertErrors(callback)(error);
|
|
||||||
} else if (!tx) {
|
|
||||||
callback(new errors.ApiError('Internal error'));
|
|
||||||
} else {
|
|
||||||
callback(error, parseTransaction(tx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function maxLedgerGetter(error_?: Error, tx?: Object) {
|
|
||||||
this.getLedgerVersion().then((version) => {
|
|
||||||
const maxLedgerVersion = options.maxLedgerVersion || version;
|
|
||||||
callbackWrapper(error_, tx, maxLedgerVersion);
|
|
||||||
}, callbackWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
async.waterfall([
|
|
||||||
_.partial(remote.rawRequest.bind(remote),
|
|
||||||
{command: 'tx', transaction: identifier, binary: false}),
|
|
||||||
_.partial(attachTransactionDate, remote)
|
|
||||||
], maxLedgerGetter.bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTransaction(identifier: string,
|
function getTransaction(identifier: string,
|
||||||
options: TransactionOptions = {}
|
options: TransactionOptions = {}
|
||||||
): Promise<TransactionType> {
|
): Promise<TransactionType> {
|
||||||
return utils.promisify(getTransactionAsync).call(this, identifier, options);
|
validate.identifier(identifier);
|
||||||
|
validate.getTransactionOptions(options);
|
||||||
|
|
||||||
|
const request = {
|
||||||
|
command: 'tx',
|
||||||
|
transaction: identifier,
|
||||||
|
binary: false
|
||||||
|
};
|
||||||
|
|
||||||
|
return utils.ensureLedgerVersion.call(this, options).then(_options => {
|
||||||
|
return this.connection.request(request).then(tx =>
|
||||||
|
attachTransactionDate(this.connection, tx)
|
||||||
|
).then(_.partial(formatResponse, _options))
|
||||||
|
.catch(error => {
|
||||||
|
return convertError(this.connection, _options, error).then(_error => {
|
||||||
|
throw _error;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getTransaction;
|
module.exports = getTransaction;
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ const {computeTransactionHash} = require('ripple-hashes');
|
|||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const parseTransaction = require('./parse/transaction');
|
const parseTransaction = require('./parse/transaction');
|
||||||
const getTransaction = require('./transaction');
|
const getTransaction = require('./transaction');
|
||||||
const {validate, composeAsync, convertErrors} = utils.common;
|
const {validate} = utils.common;
|
||||||
import type {Remote} from '../../core/remote';
|
import type {Connection} from '../common/connection.js';
|
||||||
import type {TransactionType} from './transaction-types';
|
import type {TransactionType} from './transaction-types';
|
||||||
|
|
||||||
|
|
||||||
@@ -28,8 +28,6 @@ type TransactionsOptions = {
|
|||||||
|
|
||||||
type GetTransactionsResponse = Array<TransactionType>
|
type GetTransactionsResponse = Array<TransactionType>
|
||||||
|
|
||||||
type CallbackType = (err?: ?Error, data?: GetTransactionsResponse) => void
|
|
||||||
|
|
||||||
function parseBinaryTransaction(transaction) {
|
function parseBinaryTransaction(transaction) {
|
||||||
const tx = binary.decode(transaction.tx_blob);
|
const tx = binary.decode(transaction.tx_blob);
|
||||||
tx.hash = computeTransactionHash(tx);
|
tx.hash = computeTransactionHash(tx);
|
||||||
@@ -103,8 +101,8 @@ function formatPartialResponse(address: string,
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAccountTx(remote: Remote, address: string,
|
function getAccountTx(connection: Connection, address: string,
|
||||||
options: TransactionsOptions, marker: string, limit: number, callback
|
options: TransactionsOptions, marker: string, limit: number
|
||||||
) {
|
) {
|
||||||
const request = {
|
const request = {
|
||||||
command: 'account_tx',
|
command: 'account_tx',
|
||||||
@@ -119,13 +117,12 @@ function getAccountTx(remote: Remote, address: string,
|
|||||||
marker: marker
|
marker: marker
|
||||||
};
|
};
|
||||||
|
|
||||||
remote.rawRequest(request,
|
return connection.request(request).then(response =>
|
||||||
composeAsync(_.partial(formatPartialResponse, address, options),
|
formatPartialResponse(address, options, response));
|
||||||
convertErrors(callback)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkForLedgerGaps(remote: Remote, options: TransactionsOptions,
|
function checkForLedgerGaps(connection: Connection,
|
||||||
transactions: GetTransactionsResponse
|
options: TransactionsOptions, transactions: GetTransactionsResponse
|
||||||
) {
|
) {
|
||||||
let {minLedgerVersion, maxLedgerVersion} = options;
|
let {minLedgerVersion, maxLedgerVersion} = options;
|
||||||
|
|
||||||
@@ -140,54 +137,49 @@ function checkForLedgerGaps(remote: Remote, options: TransactionsOptions,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!utils.hasCompleteLedgerRange(remote, minLedgerVersion,
|
return utils.hasCompleteLedgerRange(connection, minLedgerVersion,
|
||||||
maxLedgerVersion)) {
|
maxLedgerVersion).then(hasCompleteLedgerRange => {
|
||||||
|
if (!hasCompleteLedgerRange) {
|
||||||
throw new utils.common.errors.MissingLedgerHistoryError();
|
throw new utils.common.errors.MissingLedgerHistoryError();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatResponse(remote: Remote, options: TransactionsOptions,
|
function formatResponse(connection: Connection, options: TransactionsOptions,
|
||||||
transactions: GetTransactionsResponse
|
transactions: GetTransactionsResponse
|
||||||
) {
|
) {
|
||||||
const compare = options.earliestFirst ? utils.compareTransactions :
|
const compare = options.earliestFirst ? utils.compareTransactions :
|
||||||
_.rearg(utils.compareTransactions, 1, 0);
|
_.rearg(utils.compareTransactions, 1, 0);
|
||||||
const sortedTransactions = transactions.sort(compare);
|
const sortedTransactions = transactions.sort(compare);
|
||||||
checkForLedgerGaps(remote, options, sortedTransactions);
|
return checkForLedgerGaps(connection, options, sortedTransactions).then(
|
||||||
return sortedTransactions;
|
() => sortedTransactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTransactionsInternal(remote: Remote, address: string,
|
function getTransactionsInternal(connection: Connection, address: string,
|
||||||
options: TransactionsOptions, callback
|
options: TransactionsOptions
|
||||||
) {
|
): Promise<GetTransactionsResponse> {
|
||||||
const getter = _.partial(getAccountTx, remote, address, options);
|
const getter = _.partial(getAccountTx, connection, address, options);
|
||||||
const format = _.partial(formatResponse, remote, options);
|
const format = _.partial(formatResponse, connection, options);
|
||||||
utils.getRecursive(getter, options.limit, composeAsync(format, callback));
|
return utils.getRecursive(getter, options.limit).then(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTransactionsAsync(account: string,
|
function getTransactions(account: string, options: TransactionsOptions = {}
|
||||||
options: TransactionsOptions, callback: CallbackType
|
): Promise<GetTransactionsResponse> {
|
||||||
) {
|
|
||||||
validate.address(account);
|
validate.address(account);
|
||||||
validate.getTransactionsOptions(options);
|
validate.getTransactionsOptions(options);
|
||||||
|
|
||||||
const defaults = {maxLedgerVersion: -1};
|
const defaults = {maxLedgerVersion: -1};
|
||||||
if (options.start) {
|
if (options.start) {
|
||||||
getTransaction.call(this, options.start).then(tx => {
|
return getTransaction.call(this, options.start).then(tx => {
|
||||||
const ledgerVersion = tx.outcome.ledgerVersion;
|
const ledgerVersion = tx.outcome.ledgerVersion;
|
||||||
const bound = options.earliestFirst ?
|
const bound = options.earliestFirst ?
|
||||||
{minLedgerVersion: ledgerVersion} : {maxLedgerVersion: ledgerVersion};
|
{minLedgerVersion: ledgerVersion} : {maxLedgerVersion: ledgerVersion};
|
||||||
const newOptions = _.assign(defaults, options, {startTx: tx}, bound);
|
const newOptions = _.assign(defaults, options, {startTx: tx}, bound);
|
||||||
getTransactionsInternal(this.remote, account, newOptions, callback);
|
return getTransactionsInternal(this.connection, account, newOptions);
|
||||||
}).catch(callback);
|
});
|
||||||
} else {
|
}
|
||||||
const newOptions = _.assign(defaults, options);
|
const newOptions = _.assign(defaults, options);
|
||||||
getTransactionsInternal(this.remote, account, newOptions, callback);
|
return getTransactionsInternal(this.connection, account, newOptions);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTransactions(account: string, options: TransactionsOptions = {}
|
|
||||||
): Promise<GetTransactionsResponse> {
|
|
||||||
return utils.promisify(getTransactionsAsync).call(this, account, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getTransactions;
|
module.exports = getTransactions;
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const async = require('async');
|
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const {validate, composeAsync, convertErrors} = utils.common;
|
const {validate} = utils.common;
|
||||||
const parseAccountTrustline = require('./parse/account-trustline');
|
const parseAccountTrustline = require('./parse/account-trustline');
|
||||||
|
import type {Connection} from '../common/connection.js';
|
||||||
import type {Remote} from '../../core/remote';
|
|
||||||
import type {TrustlinesOptions, Trustline} from './trustlines-types.js';
|
import type {TrustlinesOptions, Trustline} from './trustlines-types.js';
|
||||||
|
|
||||||
|
|
||||||
@@ -24,9 +22,10 @@ function formatResponse(options: TrustlinesOptions, data) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAccountLines(remote: Remote, address: string, ledgerVersion: number,
|
function getAccountLines(connection: Connection, address: string,
|
||||||
options: TrustlinesOptions, marker: string, limit: number, callback
|
ledgerVersion: number, options: TrustlinesOptions, marker: string,
|
||||||
) {
|
limit: number
|
||||||
|
): Promise<GetTrustlinesResponse> {
|
||||||
const request = {
|
const request = {
|
||||||
command: 'account_lines',
|
command: 'account_lines',
|
||||||
account: address,
|
account: address,
|
||||||
@@ -36,27 +35,19 @@ function getAccountLines(remote: Remote, address: string, ledgerVersion: number,
|
|||||||
peer: options.counterparty
|
peer: options.counterparty
|
||||||
};
|
};
|
||||||
|
|
||||||
remote.rawRequest(request,
|
return connection.request(request).then(_.partial(formatResponse, options));
|
||||||
composeAsync(_.partial(formatResponse, options),
|
|
||||||
convertErrors(callback)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTrustlinesAsync(account: string, options: TrustlinesOptions,
|
|
||||||
callback: () => void
|
|
||||||
): void {
|
|
||||||
validate.address(account);
|
|
||||||
validate.getTrustlinesOptions(options);
|
|
||||||
|
|
||||||
const getter = _.partial(getAccountLines, this.remote, account,
|
|
||||||
options.ledgerVersion, options);
|
|
||||||
utils.getRecursive(getter, options.limit, callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTrustlines(account: string, options: TrustlinesOptions = {}
|
function getTrustlines(account: string, options: TrustlinesOptions = {}
|
||||||
): Promise<GetTrustlinesResponse> {
|
): Promise<GetTrustlinesResponse> {
|
||||||
return utils.promisify(async.seq(
|
validate.address(account);
|
||||||
utils.getLedgerOptionsWithLedgerVersion,
|
validate.getTrustlinesOptions(options);
|
||||||
getTrustlinesAsync)).call(this, account, options);
|
|
||||||
|
return this.getLedgerVersion().then(ledgerVersion => {
|
||||||
|
const getter = _.partial(getAccountLines, this.connection, account,
|
||||||
|
options.ledgerVersion || ledgerVersion, options);
|
||||||
|
return utils.getRecursive(getter, options.limit);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getTrustlines;
|
module.exports = getTrustlines;
|
||||||
|
|||||||
@@ -4,63 +4,51 @@ const _ = require('lodash');
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const common = require('../common');
|
const common = require('../common');
|
||||||
const dropsToXrp = common.dropsToXrp;
|
const dropsToXrp = common.dropsToXrp;
|
||||||
const composeAsync = common.composeAsync;
|
|
||||||
import type {Remote} from '../../core/remote';
|
|
||||||
import type {TransactionType} from './transaction-types';
|
import type {TransactionType} from './transaction-types';
|
||||||
import type {Issue} from '../common/types.js';
|
import type {Issue} from '../common/types.js';
|
||||||
|
import type {Connection} from '../common/connection';
|
||||||
type Callback = (err: any, data: any) => void
|
|
||||||
|
|
||||||
type RecursiveData = {
|
type RecursiveData = {
|
||||||
marker: string,
|
marker: string,
|
||||||
results: Array<any>
|
results: Array<any>
|
||||||
}
|
}
|
||||||
|
|
||||||
type RecursiveCallback = (err: any, data: RecursiveData) => void
|
type Getter = (marker: ?string, limit: number) => Promise<RecursiveData>
|
||||||
|
|
||||||
function clamp(value: number, min: number, max: number): number {
|
function clamp(value: number, min: number, max: number): number {
|
||||||
assert(min <= max, 'Illegal clamp bounds');
|
assert(min <= max, 'Illegal clamp bounds');
|
||||||
return Math.min(Math.max(value, min), max);
|
return Math.min(Math.max(value, min), max);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getXRPBalance(remote: Remote, address: string, ledgerVersion?: number,
|
function getXRPBalance(connection: Connection, address: string,
|
||||||
callback: Callback
|
ledgerVersion?: number
|
||||||
): void {
|
): Promise<number> {
|
||||||
const request = {
|
const request = {
|
||||||
command: 'account_info',
|
command: 'account_info',
|
||||||
account: address,
|
account: address,
|
||||||
ledger_index: ledgerVersion
|
ledger_index: ledgerVersion
|
||||||
};
|
};
|
||||||
remote.rawRequest(request,
|
return connection.request(request).then(data =>
|
||||||
composeAsync((data) => dropsToXrp(data.account_data.Balance), callback));
|
dropsToXrp(data.account_data.Balance));
|
||||||
}
|
}
|
||||||
|
|
||||||
type Getter = (marker: ?string, limit: number,
|
|
||||||
callback: RecursiveCallback) => void
|
|
||||||
|
|
||||||
// If the marker is omitted from a response, you have reached the end
|
// If the marker is omitted from a response, you have reached the end
|
||||||
// getter(marker, limit, callback), callback(error, {marker, results})
|
// getter(marker, limit, callback), callback(error, {marker, results})
|
||||||
function getRecursiveRecur(getter: Getter, marker?: string, limit: number,
|
function getRecursiveRecur(getter: Getter, marker?: string, limit: number
|
||||||
callback: Callback
|
): Promise {
|
||||||
): void {
|
return getter(marker, limit).then(data => {
|
||||||
getter(marker, limit, (error, data) => {
|
|
||||||
if (error) {
|
|
||||||
return callback(error);
|
|
||||||
}
|
|
||||||
const remaining = limit - data.results.length;
|
const remaining = limit - data.results.length;
|
||||||
if (remaining > 0 && data.marker !== undefined) {
|
if (remaining > 0 && data.marker !== undefined) {
|
||||||
getRecursiveRecur(getter, data.marker, remaining, (_error, results) => {
|
return getRecursiveRecur(getter, data.marker, remaining).then(results =>
|
||||||
return _error ? callback(_error) :
|
data.results.concat(results)
|
||||||
callback(null, data.results.concat(results));
|
);
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return callback(null, data.results.slice(0, limit));
|
|
||||||
}
|
}
|
||||||
|
return data.results.slice(0, limit);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRecursive(getter: Getter, limit?: number, callback: Callback) {
|
function getRecursive(getter: Getter, limit?: number): Promise {
|
||||||
getRecursiveRecur(getter, undefined, limit || Infinity, callback);
|
return getRecursiveRecur(getter, undefined, limit || Infinity);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renameCounterpartyToIssuer(amount?: Issue): ?{issuer?: string} {
|
function renameCounterpartyToIssuer(amount?: Issue): ?{issuer?: string} {
|
||||||
@@ -109,46 +97,41 @@ function compareTransactions(first: TransactionType, second: TransactionType
|
|||||||
return first.outcome.ledgerVersion < second.outcome.ledgerVersion ? -1 : 1;
|
return first.outcome.ledgerVersion < second.outcome.ledgerVersion ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasCompleteLedgerRange(remote: Remote, minLedgerVersion?: number,
|
function hasCompleteLedgerRange(connection: Connection,
|
||||||
maxLedgerVersion?: number
|
minLedgerVersion?: number, maxLedgerVersion?: number
|
||||||
): boolean {
|
): Promise<boolean> {
|
||||||
|
|
||||||
const firstLedgerVersion = 32570; // earlier versions have been lost
|
const firstLedgerVersion = 32570; // earlier versions have been lost
|
||||||
return remote.getServer().hasLedgerRange(
|
return connection.hasLedgerVersions(
|
||||||
minLedgerVersion || firstLedgerVersion,
|
minLedgerVersion || firstLedgerVersion, maxLedgerVersion);
|
||||||
maxLedgerVersion || remote.getLedgerSequenceSync());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPendingLedgerVersion(remote: Remote, maxLedgerVersion: ?number
|
function isPendingLedgerVersion(connection: Connection,
|
||||||
): boolean {
|
maxLedgerVersion: ?number
|
||||||
const currentLedger = remote.getLedgerSequenceSync();
|
): Promise<boolean> {
|
||||||
return currentLedger < (maxLedgerVersion || 0);
|
return connection.getLedgerVersion().then(ledgerVersion =>
|
||||||
|
ledgerVersion < (maxLedgerVersion || 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLedgerOptionsWithLedgerVersion(account: string, options: Object,
|
function ensureLedgerVersion(options: Object
|
||||||
callback: (err?: ?Error, account?: string, options: Object) => void
|
): Promise<number> {
|
||||||
) {
|
|
||||||
if (Boolean(options) && options.ledgerVersion !== undefined &&
|
if (Boolean(options) && options.ledgerVersion !== undefined &&
|
||||||
options.ledgerVersion !== null
|
options.ledgerVersion !== null
|
||||||
) {
|
) {
|
||||||
callback(null, account, options);
|
return Promise.resolve(options);
|
||||||
} else {
|
|
||||||
this.getLedgerVersion().then((version) => {
|
|
||||||
callback(null, account, _.assign({}, options, {ledgerVersion: version}));
|
|
||||||
}, callback);
|
|
||||||
}
|
}
|
||||||
|
return this.getLedgerVersion().then(ledgerVersion =>
|
||||||
|
_.assign({}, options, {ledgerVersion}));
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getXRPBalance,
|
getXRPBalance,
|
||||||
getLedgerOptionsWithLedgerVersion,
|
ensureLedgerVersion,
|
||||||
compareTransactions,
|
compareTransactions,
|
||||||
renameCounterpartyToIssuer,
|
renameCounterpartyToIssuer,
|
||||||
renameCounterpartyToIssuerInOrder,
|
renameCounterpartyToIssuerInOrder,
|
||||||
getRecursive,
|
getRecursive,
|
||||||
hasCompleteLedgerRange,
|
hasCompleteLedgerRange,
|
||||||
isPendingLedgerVersion,
|
isPendingLedgerVersion,
|
||||||
promisify: common.promisify,
|
|
||||||
clamp: clamp,
|
clamp: clamp,
|
||||||
common: common
|
common: common
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,45 +4,32 @@ const common = require('../common');
|
|||||||
import type {GetServerInfoResponse} from '../common/serverinfo';
|
import type {GetServerInfoResponse} from '../common/serverinfo';
|
||||||
|
|
||||||
function isConnected(): boolean {
|
function isConnected(): boolean {
|
||||||
const server = this.remote.getServer();
|
return this.connection.isConnected();
|
||||||
return Boolean(server && server.isConnected());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLedgerVersion(): Promise<number> {
|
function getLedgerVersion(): Promise<number> {
|
||||||
return common.promisify(this.remote.getLedgerSequence).call(this.remote);
|
return this.connection.getLedgerVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
function connect(): Promise<void> {
|
function connect(): Promise<void> {
|
||||||
return common.promisify(callback => {
|
return this.connection.connect();
|
||||||
try {
|
|
||||||
this.remote.connect(() => callback(null));
|
|
||||||
} catch (error) {
|
|
||||||
callback(new common.errors.RippledNetworkError(error.message));
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function disconnect(): Promise<void> {
|
function disconnect(): Promise<void> {
|
||||||
return common.promisify(callback => {
|
return this.connection.disconnect();
|
||||||
try {
|
|
||||||
this.remote.disconnect(() => callback(null));
|
|
||||||
} catch (error) {
|
|
||||||
callback(new common.errors.RippledNetworkError(error.message));
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getServerInfo(): Promise<GetServerInfoResponse> {
|
function getServerInfo(): Promise<GetServerInfoResponse> {
|
||||||
return common.serverInfo.getServerInfo(this.remote);
|
return common.serverInfo.getServerInfo(this.connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFee(): Promise<number> {
|
function getFee(): Promise<number> {
|
||||||
const cushion = this._feeCushion || 1.2;
|
const cushion = this._feeCushion || 1.2;
|
||||||
return common.serverInfo.getFee(this.remote, cushion);
|
return common.serverInfo.getFee(this.connection, cushion);
|
||||||
}
|
}
|
||||||
|
|
||||||
function rippleTimeToISO8601(rippleTime: string): string {
|
function rippleTimeToISO8601(rippleTime: string): string {
|
||||||
return new Date(common.core.utils.toTimestamp(rippleTime)).toISOString();
|
return new Date(common.rippleToUnixTimestamp(rippleTime)).toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatLedgerClose(ledgerClose: Object): Object {
|
function formatLedgerClose(ledgerClose: Object): Object {
|
||||||
|
|||||||
@@ -37,18 +37,11 @@ function createOrderTransaction(account: string, order: Order): Object {
|
|||||||
return txJSON;
|
return txJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareOrderAsync(account: string, order: Order,
|
|
||||||
instructions: Instructions, callback
|
|
||||||
) {
|
|
||||||
const txJSON = createOrderTransaction(account, order);
|
|
||||||
utils.prepareTransaction(txJSON, this, instructions, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareOrder(account: string, order: Order,
|
function prepareOrder(account: string, order: Order,
|
||||||
instructions: Instructions = {}
|
instructions: Instructions = {}
|
||||||
): Promise<Prepare> {
|
): Promise<Prepare> {
|
||||||
return utils.promisify(prepareOrderAsync.bind(this))(
|
const txJSON = createOrderTransaction(account, order);
|
||||||
account, order, instructions);
|
return utils.prepareTransaction(txJSON, this, instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = prepareOrder;
|
module.exports = prepareOrder;
|
||||||
|
|||||||
@@ -17,18 +17,11 @@ function createOrderCancellationTransaction(account: string,
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareOrderCancellationAsync(account: string, sequence: number,
|
|
||||||
instructions: Instructions, callback
|
|
||||||
) {
|
|
||||||
const txJSON = createOrderCancellationTransaction(account, sequence);
|
|
||||||
utils.prepareTransaction(txJSON, this, instructions, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareOrderCancellation(account: string, sequence: number,
|
function prepareOrderCancellation(account: string, sequence: number,
|
||||||
instructions: Instructions = {}
|
instructions: Instructions = {}
|
||||||
): Promise<Prepare> {
|
): Promise<Prepare> {
|
||||||
return utils.promisify(prepareOrderCancellationAsync.bind(this))(
|
const txJSON = createOrderCancellationTransaction(account, sequence);
|
||||||
account, sequence, instructions);
|
return utils.prepareTransaction(txJSON, this, instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = prepareOrderCancellation;
|
module.exports = prepareOrderCancellation;
|
||||||
|
|||||||
@@ -141,18 +141,11 @@ function createPaymentTransaction(account: string, paymentArgument: Payment
|
|||||||
return txJSON;
|
return txJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
function preparePaymentAsync(account: string, payment: Payment,
|
|
||||||
instructions: Instructions, callback
|
|
||||||
) {
|
|
||||||
const txJSON = createPaymentTransaction(account, payment);
|
|
||||||
utils.prepareTransaction(txJSON, this, instructions, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function preparePayment(account: string, payment: Payment,
|
function preparePayment(account: string, payment: Payment,
|
||||||
instructions: Instructions = {}
|
instructions: Instructions
|
||||||
): Promise<Prepare> {
|
): Promise<Prepare> {
|
||||||
return utils.promisify(preparePaymentAsync.bind(this))(
|
const txJSON = createPaymentTransaction(account, payment);
|
||||||
account, payment, instructions);
|
return utils.prepareTransaction(txJSON, this, instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = preparePayment;
|
module.exports = preparePayment;
|
||||||
|
|||||||
@@ -95,18 +95,11 @@ function createSettingsTransaction(account: string, settings: Settings
|
|||||||
return txJSON;
|
return txJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareSettingsAsync(account: string, settings: Settings,
|
function prepareSettings(account: string, settings: Settings,
|
||||||
instructions: Instructions, callback
|
|
||||||
) {
|
|
||||||
const txJSON = createSettingsTransaction(account, settings);
|
|
||||||
utils.prepareTransaction(txJSON, this, instructions, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareSettings(account: string, settings: Object,
|
|
||||||
instructions: Instructions = {}
|
instructions: Instructions = {}
|
||||||
): Promise<Prepare> {
|
): Promise<Prepare> {
|
||||||
return utils.promisify(prepareSettingsAsync.bind(this))(
|
const txJSON = createSettingsTransaction(account, settings);
|
||||||
account, settings, instructions);
|
return utils.prepareTransaction(txJSON, this, instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = prepareSettings;
|
module.exports = prepareSettings;
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const validate = utils.common.validate;
|
const {validate, convertKeysFromSnakeCaseToCamelCase} = utils.common;
|
||||||
const Request = utils.common.core.Request;
|
|
||||||
const convertErrors = utils.common.convertErrors;
|
|
||||||
|
|
||||||
type Submit = {
|
type Submit = {
|
||||||
success: boolean,
|
success: boolean,
|
||||||
@@ -25,29 +23,20 @@ function isImmediateRejection(engineResult: string): boolean {
|
|||||||
return _.startsWith(engineResult, 'tem') || _.startsWith(engineResult, 'tej');
|
return _.startsWith(engineResult, 'tem') || _.startsWith(engineResult, 'tej');
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertSubmitErrors(callback) {
|
function formatResponse(response) {
|
||||||
return function(error, data) {
|
if (isImmediateRejection(response.engine_result)) {
|
||||||
if (!error && isImmediateRejection(data.engineResult)) {
|
throw new utils.common.errors.RippledError('Submit failed');
|
||||||
callback(new utils.common.errors.RippleError('Submit failed'), data);
|
|
||||||
} else {
|
|
||||||
callback(error, data);
|
|
||||||
}
|
}
|
||||||
};
|
return convertKeysFromSnakeCaseToCamelCase(response);
|
||||||
}
|
|
||||||
|
|
||||||
function submitAsync(txBlob: string, callback: (err: any, data: any) => void
|
|
||||||
): void {
|
|
||||||
validate.blob(txBlob);
|
|
||||||
const request = new Request(this.remote, 'submit');
|
|
||||||
request.message.tx_blob = txBlob;
|
|
||||||
request.request(null,
|
|
||||||
utils.common.composeAsync(
|
|
||||||
data => utils.common.convertKeysFromSnakeCaseToCamelCase(data),
|
|
||||||
convertSubmitErrors(convertErrors(callback))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function submit(txBlob: string): Promise<Submit> {
|
function submit(txBlob: string): Promise<Submit> {
|
||||||
return utils.promisify(submitAsync.bind(this))(txBlob);
|
validate.blob(txBlob);
|
||||||
|
const request = {
|
||||||
|
command: 'submit',
|
||||||
|
tx_blob: txBlob
|
||||||
|
};
|
||||||
|
return this.connection.request(request).then(formatResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = submit;
|
module.exports = submit;
|
||||||
|
|||||||
@@ -30,19 +30,12 @@ function createSuspendedPaymentCancellationTransaction(account: string,
|
|||||||
return txJSON;
|
return txJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareSuspendedPaymentCancellationAsync(account: string,
|
|
||||||
payment: SuspendedPaymentCancellation, instructions: Instructions, callback
|
|
||||||
) {
|
|
||||||
const txJSON =
|
|
||||||
createSuspendedPaymentCancellationTransaction(account, payment);
|
|
||||||
utils.prepareTransaction(txJSON, this, instructions, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareSuspendedPaymentCancellation(account: string,
|
function prepareSuspendedPaymentCancellation(account: string,
|
||||||
payment: SuspendedPaymentCancellation, instructions: Instructions = {}
|
payment: SuspendedPaymentCancellation, instructions: Instructions = {}
|
||||||
): Promise<Prepare> {
|
): Promise<Prepare> {
|
||||||
return utils.promisify(prepareSuspendedPaymentCancellationAsync)
|
const txJSON =
|
||||||
.call(this, account, payment, instructions);
|
createSuspendedPaymentCancellationTransaction(account, payment);
|
||||||
|
return utils.prepareTransaction(txJSON, this, instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = prepareSuspendedPaymentCancellation;
|
module.exports = prepareSuspendedPaymentCancellation;
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const validate = utils.common.validate;
|
const {validate, unixToRippleTimestamp, toRippledAmount} = utils.common;
|
||||||
const toRippledAmount = utils.common.toRippledAmount;
|
|
||||||
import type {Instructions, Prepare} from './types.js';
|
import type {Instructions, Prepare} from './types.js';
|
||||||
import type {Adjustment, MaxAdjustment, Memo} from '../common/types.js';
|
import type {Adjustment, MaxAdjustment, Memo} from '../common/types.js';
|
||||||
|
|
||||||
@@ -33,10 +32,10 @@ function createSuspendedPaymentCreationTransaction(account: string,
|
|||||||
txJSON.Digest = payment.digest;
|
txJSON.Digest = payment.digest;
|
||||||
}
|
}
|
||||||
if (payment.allowCancelAfter !== undefined) {
|
if (payment.allowCancelAfter !== undefined) {
|
||||||
txJSON.CancelAfter = utils.fromTimestamp(payment.allowCancelAfter);
|
txJSON.CancelAfter = unixToRippleTimestamp(payment.allowCancelAfter);
|
||||||
}
|
}
|
||||||
if (payment.allowExecuteAfter !== undefined) {
|
if (payment.allowExecuteAfter !== undefined) {
|
||||||
txJSON.FinishAfter = utils.fromTimestamp(payment.allowExecuteAfter);
|
txJSON.FinishAfter = unixToRippleTimestamp(payment.allowExecuteAfter);
|
||||||
}
|
}
|
||||||
if (payment.source.tag !== undefined) {
|
if (payment.source.tag !== undefined) {
|
||||||
txJSON.SourceTag = payment.source.tag;
|
txJSON.SourceTag = payment.source.tag;
|
||||||
@@ -50,18 +49,11 @@ function createSuspendedPaymentCreationTransaction(account: string,
|
|||||||
return txJSON;
|
return txJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareSuspendedPaymentCreationAsync(account: string,
|
|
||||||
payment: SuspendedPaymentCreation, instructions: Instructions, callback
|
|
||||||
) {
|
|
||||||
const txJSON = createSuspendedPaymentCreationTransaction(account, payment);
|
|
||||||
utils.prepareTransaction(txJSON, this, instructions, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareSuspendedPaymentCreation(account: string,
|
function prepareSuspendedPaymentCreation(account: string,
|
||||||
payment: SuspendedPaymentCreation, instructions: Instructions = {}
|
payment: SuspendedPaymentCreation, instructions: Instructions = {}
|
||||||
): Promise<Prepare> {
|
): Promise<Prepare> {
|
||||||
return utils.promisify(prepareSuspendedPaymentCreationAsync)
|
const txJSON = createSuspendedPaymentCreationTransaction(account, payment);
|
||||||
.call(this, account, payment, instructions);
|
return utils.prepareTransaction(txJSON, this, instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = prepareSuspendedPaymentCreation;
|
module.exports = prepareSuspendedPaymentCreation;
|
||||||
|
|||||||
@@ -43,18 +43,11 @@ function createSuspendedPaymentExecutionTransaction(account: string,
|
|||||||
return txJSON;
|
return txJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareSuspendedPaymentExecutionAsync(account: string,
|
|
||||||
payment: SuspendedPaymentExecution, instructions: Instructions, callback
|
|
||||||
) {
|
|
||||||
const txJSON = createSuspendedPaymentExecutionTransaction(account, payment);
|
|
||||||
utils.prepareTransaction(txJSON, this, instructions, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareSuspendedPaymentExecution(account: string,
|
function prepareSuspendedPaymentExecution(account: string,
|
||||||
payment: SuspendedPaymentExecution, instructions: Instructions = {}
|
payment: SuspendedPaymentExecution, instructions: Instructions = {}
|
||||||
): Promise<Prepare> {
|
): Promise<Prepare> {
|
||||||
return utils.promisify(prepareSuspendedPaymentExecutionAsync)
|
const txJSON = createSuspendedPaymentExecutionTransaction(account, payment);
|
||||||
.call(this, account, payment, instructions);
|
return utils.prepareTransaction(txJSON, this, instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = prepareSuspendedPaymentExecution;
|
module.exports = prepareSuspendedPaymentExecution;
|
||||||
|
|||||||
@@ -50,18 +50,11 @@ function createTrustlineTransaction(account: string,
|
|||||||
return txJSON;
|
return txJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareTrustlineAsync(account: string,
|
|
||||||
trustline: TrustLineSpecification, instructions: Instructions, callback
|
|
||||||
) {
|
|
||||||
const txJSON = createTrustlineTransaction(account, trustline);
|
|
||||||
utils.prepareTransaction(txJSON, this, instructions, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareTrustline(account: string,
|
function prepareTrustline(account: string,
|
||||||
trustline: TrustLineSpecification, instructions: Instructions = {}
|
trustline: TrustLineSpecification, instructions: Instructions = {}
|
||||||
): Promise<Prepare> {
|
): Promise<Prepare> {
|
||||||
return utils.promisify(prepareTrustlineAsync.bind(this))(
|
const txJSON = createTrustlineTransaction(account, trustline);
|
||||||
account, trustline, instructions);
|
return utils.prepareTransaction(txJSON, this, instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = prepareTrustline;
|
module.exports = prepareTrustline;
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const async = require('async');
|
|
||||||
const BigNumber = require('bignumber.js');
|
const BigNumber = require('bignumber.js');
|
||||||
const common = require('../common');
|
const common = require('../common');
|
||||||
const txFlags = common.txFlags;
|
const txFlags = common.txFlags;
|
||||||
import type {Instructions} from './types.js';
|
import type {Instructions, Prepare} from './types.js';
|
||||||
|
|
||||||
function removeUndefined(obj: Object): Object {
|
|
||||||
return _.omit(obj, _.isUndefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatPrepareResponse(txJSON: Object): Object {
|
function formatPrepareResponse(txJSON: Object): Object {
|
||||||
const instructions = {
|
const instructions = {
|
||||||
@@ -31,36 +26,34 @@ function setCanonicalFlag(txJSON) {
|
|||||||
txJSON.Flags = txJSON.Flags >>> 0;
|
txJSON.Flags = txJSON.Flags >>> 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Callback = (err: ?(typeof Error),
|
|
||||||
data: {txJSON: string, instructions: Instructions}) => void;
|
|
||||||
function prepareTransaction(txJSON: Object, api: Object,
|
function prepareTransaction(txJSON: Object, api: Object,
|
||||||
instructions: Instructions, callback: Callback
|
instructions: Instructions
|
||||||
): void {
|
): Promise<Prepare> {
|
||||||
common.validate.instructions(instructions);
|
common.validate.instructions(instructions);
|
||||||
|
|
||||||
const account = txJSON.Account;
|
const account = txJSON.Account;
|
||||||
setCanonicalFlag(txJSON);
|
setCanonicalFlag(txJSON);
|
||||||
|
|
||||||
function prepareMaxLedgerVersion(callback_) {
|
function prepareMaxLedgerVersion(): Promise<Object> {
|
||||||
if (instructions.maxLedgerVersion !== undefined) {
|
if (instructions.maxLedgerVersion !== undefined) {
|
||||||
txJSON.LastLedgerSequence = instructions.maxLedgerVersion;
|
txJSON.LastLedgerSequence = instructions.maxLedgerVersion;
|
||||||
callback_();
|
return Promise.resolve(txJSON);
|
||||||
} else {
|
}
|
||||||
const offset = instructions.maxLedgerVersionOffset !== undefined ?
|
const offset = instructions.maxLedgerVersionOffset !== undefined ?
|
||||||
instructions.maxLedgerVersionOffset : 3;
|
instructions.maxLedgerVersionOffset : 3;
|
||||||
api.remote.getLedgerSequence((error, ledgerVersion) => {
|
return api.connection.getLedgerVersion().then(ledgerVersion => {
|
||||||
txJSON.LastLedgerSequence = ledgerVersion + offset;
|
txJSON.LastLedgerSequence = ledgerVersion + offset;
|
||||||
callback_(error);
|
return txJSON;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function prepareFee(callback_) {
|
function prepareFee(): Promise<Object> {
|
||||||
if (instructions.fee !== undefined) {
|
if (instructions.fee !== undefined) {
|
||||||
txJSON.Fee = common.xrpToDrops(instructions.fee);
|
txJSON.Fee = common.xrpToDrops(instructions.fee);
|
||||||
callback_();
|
return Promise.resolve(txJSON);
|
||||||
} else {
|
}
|
||||||
common.serverInfo.getFee(api.remote, api._feeCushion).then(fee => {
|
const cushion = api._feeCushion;
|
||||||
|
return common.serverInfo.getFee(api.connection, cushion).then(fee => {
|
||||||
const feeDrops = common.xrpToDrops(fee);
|
const feeDrops = common.xrpToDrops(fee);
|
||||||
if (instructions.maxFee !== undefined) {
|
if (instructions.maxFee !== undefined) {
|
||||||
const maxFeeDrops = common.xrpToDrops(instructions.maxFee);
|
const maxFeeDrops = common.xrpToDrops(instructions.maxFee);
|
||||||
@@ -68,34 +61,30 @@ function prepareTransaction(txJSON: Object, api: Object,
|
|||||||
} else {
|
} else {
|
||||||
txJSON.Fee = feeDrops;
|
txJSON.Fee = feeDrops;
|
||||||
}
|
}
|
||||||
callback_();
|
return txJSON;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function prepareSequence(callback_) {
|
function prepareSequence(): Promise<Object> {
|
||||||
if (instructions.sequence !== undefined) {
|
if (instructions.sequence !== undefined) {
|
||||||
txJSON.Sequence = instructions.sequence;
|
txJSON.Sequence = instructions.sequence;
|
||||||
callback_(null, formatPrepareResponse(txJSON));
|
return Promise.resolve(txJSON);
|
||||||
} else {
|
}
|
||||||
const request = {
|
const request = {
|
||||||
command: 'account_info',
|
command: 'account_info',
|
||||||
account: account
|
account: account
|
||||||
};
|
};
|
||||||
api.remote.rawRequest(request, function(error, response) {
|
return api.connection.request(request).then(response => {
|
||||||
txJSON.Sequence = response.account_data.Sequence;
|
txJSON.Sequence = response.account_data.Sequence;
|
||||||
callback_(error, formatPrepareResponse(txJSON));
|
return txJSON;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async.series([
|
return Promise.all([
|
||||||
prepareMaxLedgerVersion,
|
prepareMaxLedgerVersion(),
|
||||||
prepareFee,
|
prepareFee(),
|
||||||
prepareSequence
|
prepareSequence()
|
||||||
], common.convertErrors(function(error, results) {
|
]).then(() => formatPrepareResponse(txJSON));
|
||||||
callback(error, results && results[2]);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertStringToHex(string: string) {
|
function convertStringToHex(string: string) {
|
||||||
@@ -105,7 +94,7 @@ function convertStringToHex(string: string) {
|
|||||||
|
|
||||||
function convertMemo(memo: Object): Object {
|
function convertMemo(memo: Object): Object {
|
||||||
return {
|
return {
|
||||||
Memo: removeUndefined({
|
Memo: common.removeUndefined({
|
||||||
MemoData: convertStringToHex(memo.data),
|
MemoData: convertStringToHex(memo.data),
|
||||||
MemoType: convertStringToHex(memo.type),
|
MemoType: convertStringToHex(memo.type),
|
||||||
MemoFormat: convertStringToHex(memo.format)
|
MemoFormat: convertStringToHex(memo.format)
|
||||||
@@ -113,33 +102,9 @@ function convertMemo(memo: Object): Object {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Number} rpepoch (seconds since 1/1/2000 GMT)
|
|
||||||
* @return {Number} ms since unix epoch
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function toTimestamp(rpepoch: number): number {
|
|
||||||
return (rpepoch + 0x386D4380) * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Number|Date} timestamp (ms since unix epoch)
|
|
||||||
* @return {Number} seconds since ripple epoch ( 1/1/2000 GMT)
|
|
||||||
*/
|
|
||||||
function fromTimestamp(timestamp: number | Date): number {
|
|
||||||
const timestamp_ = timestamp instanceof Date ?
|
|
||||||
timestamp.getTime() :
|
|
||||||
timestamp;
|
|
||||||
return Math.round(timestamp_ / 1000) - 0x386D4380;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
removeUndefined,
|
|
||||||
convertStringToHex,
|
convertStringToHex,
|
||||||
fromTimestamp,
|
|
||||||
toTimestamp,
|
|
||||||
convertMemo,
|
convertMemo,
|
||||||
prepareTransaction,
|
prepareTransaction,
|
||||||
common,
|
common
|
||||||
promisify: common.promisify
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,12 +4,6 @@ const _ = require('lodash');
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const Account = require('ripple-lib').Account;
|
const Account = require('ripple-lib').Account;
|
||||||
|
|
||||||
const addresses = require('./fixtures/addresses');
|
|
||||||
const fixtures = require('./fixtures/api');
|
|
||||||
const accountLinesResponse = require('./fixtures/api/rippled/account-lines');
|
|
||||||
|
|
||||||
const setupAPI = require('./setup-api');
|
|
||||||
|
|
||||||
|
|
||||||
function createRemote(remoteOptions = {}) {
|
function createRemote(remoteOptions = {}) {
|
||||||
return {
|
return {
|
||||||
@@ -58,150 +52,6 @@ function createRemote(remoteOptions = {}) {
|
|||||||
|
|
||||||
describe('Account', function() {
|
describe('Account', function() {
|
||||||
|
|
||||||
describe('mocked', function() {
|
|
||||||
beforeEach(setupAPI.setup);
|
|
||||||
afterEach(setupAPI.teardown);
|
|
||||||
|
|
||||||
// this test is artificial, just to increase coverage
|
|
||||||
// because code inside listenerRemoved function in Account object
|
|
||||||
// will never be called in normal situation
|
|
||||||
// (Account object is subscribed to own events, so _subs counter never
|
|
||||||
// reach zero)
|
|
||||||
it('unsubscribe ', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.ACCOUNT);
|
|
||||||
this.mockRippled.expect({
|
|
||||||
request_subscribe: 1,
|
|
||||||
request_unsubscribe: 1,
|
|
||||||
request_account_info: 1
|
|
||||||
});
|
|
||||||
function dumb() {}
|
|
||||||
account.on('entry', dumb);
|
|
||||||
account._subs -= 1;
|
|
||||||
account.removeListener('entry', dumb);
|
|
||||||
setTimeout(() => {
|
|
||||||
done();
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('toJson', function() {
|
|
||||||
const account = new Account(this.api.remote, addresses.ACCOUNT);
|
|
||||||
const json = account.toJson();
|
|
||||||
assert.strictEqual(json, addresses.ACCOUNT);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('entry', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.ACCOUNT);
|
|
||||||
account.entry((error, info) => {
|
|
||||||
assert.deepEqual(info, fixtures.rippled.account_info.normal.result);
|
|
||||||
done(error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('entry error', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.NOTFOUND);
|
|
||||||
account.entry((error) => {
|
|
||||||
assert(error);
|
|
||||||
error.remote.id = 0;
|
|
||||||
assert.deepEqual(error.remote, fixtures.rippled.account_info.notfound);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getNextSequence not found', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.NOTFOUND);
|
|
||||||
account.getNextSequence((error, sequence) => {
|
|
||||||
assert.strictEqual(sequence, 1);
|
|
||||||
done(error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('lines', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.ACCOUNT);
|
|
||||||
account.lines((error, lines) => {
|
|
||||||
assert(lines);
|
|
||||||
const expected = JSON.parse(accountLinesResponse.normal({}))
|
|
||||||
.result.lines;
|
|
||||||
assert.deepEqual(lines.lines, expected);
|
|
||||||
done(error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('line', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.ACCOUNT);
|
|
||||||
account.line('015841551A748AD2C1F76FF6ECB0CCCD00000000',
|
|
||||||
'rs9M85karFkCRjvc6KMWn8Coigm9cbcgcx', (error, line) => {
|
|
||||||
const expected = JSON.parse(accountLinesResponse.normal({}))
|
|
||||||
.result.lines[22];
|
|
||||||
assert.deepEqual(line, expected);
|
|
||||||
done(error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('line when account not found', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.NOTFOUND);
|
|
||||||
account.line('', 'rs9M85karFkCRjvc6KMWn8Coigm9cbcgcx', (error) => {
|
|
||||||
assert(error);
|
|
||||||
error.remote.id = 0;
|
|
||||||
assert.deepEqual(error.remote, fixtures.rippled.account_info.notfound);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('submit ', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.ACCOUNT);
|
|
||||||
account._transactionManager.submit = function() {
|
|
||||||
done();
|
|
||||||
};
|
|
||||||
account.submit({});
|
|
||||||
});
|
|
||||||
|
|
||||||
// this one just for coverage - _subs can't be zero
|
|
||||||
it('notify - no subscribers ', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.ACCOUNT);
|
|
||||||
let fired = false;
|
|
||||||
account.on('transaction', function() {
|
|
||||||
fired = true;
|
|
||||||
});
|
|
||||||
account._subs = 0;
|
|
||||||
account.notify({});
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
assert(!fired);
|
|
||||||
done();
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('notify - transaction without account field ', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.ACCOUNT);
|
|
||||||
let transactionFired;
|
|
||||||
let transactionInboundFired = false;
|
|
||||||
account.on('transaction', function(transaction) {
|
|
||||||
transactionFired = transaction;
|
|
||||||
});
|
|
||||||
account.on('transaction-inbound', function() {
|
|
||||||
transactionInboundFired = true;
|
|
||||||
});
|
|
||||||
account.notify({transaction: {}});
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
assert.deepEqual(transactionFired, {transaction: {}});
|
|
||||||
assert(!transactionInboundFired);
|
|
||||||
done();
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('notify - transaction-inbound', function(done) {
|
|
||||||
const account = new Account(this.api.remote, addresses.ACCOUNT);
|
|
||||||
account.on('transaction-inbound', function(transaction) {
|
|
||||||
assert.deepEqual(transaction,
|
|
||||||
{transaction: {Account: addresses.NOTFOUND}});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
account.notify({transaction: {Account: addresses.NOTFOUND}});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#_publicKeyToAddress()', function() {
|
describe('#_publicKeyToAddress()', function() {
|
||||||
|
|
||||||
it('should throw an error if the key is invalid', function() {
|
it('should throw an error if the key is invalid', function() {
|
||||||
@@ -271,7 +121,6 @@ describe('Account', function() {
|
|||||||
account.publicKeyIsActive(
|
account.publicKeyIsActive(
|
||||||
'025B32A54BFA33FB781581F49B235C0E2820C929FF41E677ADA5D3E53CFBA46332',
|
'025B32A54BFA33FB781581F49B235C0E2820C929FF41E677ADA5D3E53CFBA46332',
|
||||||
function(err, is_valid) {
|
function(err, is_valid) {
|
||||||
|
|
||||||
assert(err === null);
|
assert(err === null);
|
||||||
assert(is_valid === false);
|
assert(is_valid === false);
|
||||||
done();
|
done();
|
||||||
|
|||||||
@@ -193,10 +193,9 @@ describe('RippleAPI', function() {
|
|||||||
|
|
||||||
it('submit - failure', function() {
|
it('submit - failure', function() {
|
||||||
return this.api.submit('BAD').then(() => {
|
return this.api.submit('BAD').then(() => {
|
||||||
assert(false, 'Should throw RippleError');
|
assert(false, 'Should throw RippledError');
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
assert(error instanceof this.api.errors.RippleError);
|
assert(error instanceof this.api.errors.RippledError);
|
||||||
assert(error.data);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -361,7 +360,7 @@ describe('RippleAPI', function() {
|
|||||||
it('getTransaction - missing ledger history', function() {
|
it('getTransaction - missing ledger history', function() {
|
||||||
const hash = hashes.NOTFOUND_TRANSACTION_HASH;
|
const hash = hashes.NOTFOUND_TRANSACTION_HASH;
|
||||||
// make gaps in history
|
// make gaps in history
|
||||||
this.api.remote.getServer().emit('message', ledgerClosed);
|
this.api.connection._ws.emit('message', JSON.stringify(ledgerClosed));
|
||||||
return this.api.getTransaction(hash).then(() => {
|
return this.api.getTransaction(hash).then(() => {
|
||||||
assert(false, 'Should throw MissingLedgerHistoryError');
|
assert(false, 'Should throw MissingLedgerHistoryError');
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
@@ -601,8 +600,8 @@ describe('RippleAPI', function() {
|
|||||||
return this.api.getServerInfo().then(() => {
|
return this.api.getServerInfo().then(() => {
|
||||||
assert(false, 'Should throw NetworkError');
|
assert(false, 'Should throw NetworkError');
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
assert(error instanceof this.api.errors.NetworkError);
|
assert(error instanceof this.api.errors.RippledError);
|
||||||
assert(error.message.indexOf('too much load') !== -1);
|
assert(_.includes(error.message, 'slowDown'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -759,17 +758,20 @@ describe('RippleAPI', function() {
|
|||||||
assert.deepEqual(utils.renameCounterpartyToIssuer(amountArg), amountArg);
|
assert.deepEqual(utils.renameCounterpartyToIssuer(amountArg), amountArg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ledger utils - getRecursive', function(done) {
|
it('ledger utils - getRecursive', function() {
|
||||||
function getter(marker, limit, callback) {
|
function getter(marker, limit) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
if (marker === undefined) {
|
if (marker === undefined) {
|
||||||
callback(null, {marker: 'A', limit: limit, results: [1]});
|
resolve({marker: 'A', limit: limit, results: [1]});
|
||||||
} else {
|
} else {
|
||||||
callback(new Error(), null);
|
reject(new Error());
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
utils.getRecursive(getter, 10, (error) => {
|
return utils.getRecursive(getter, 10).then(() => {
|
||||||
|
assert(false, 'Should throw Error');
|
||||||
|
}).catch(error => {
|
||||||
assert(error instanceof Error);
|
assert(error instanceof Error);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -852,28 +854,6 @@ describe('RippleAPI', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('common utils', function() {
|
|
||||||
|
|
||||||
it('wrapCatch', function(done) {
|
|
||||||
common.wrapCatch(function() {
|
|
||||||
throw new Error('error');
|
|
||||||
})(function(error) {
|
|
||||||
assert(error instanceof Error);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('convertExceptions', function() {
|
|
||||||
assert.throws(common.convertExceptions(function() {
|
|
||||||
throw new Error('fall through');
|
|
||||||
}), this.api.errors.ApiError);
|
|
||||||
assert.throws(common.convertExceptions(function() {
|
|
||||||
throw new Error('fall through');
|
|
||||||
}), /fall through/);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('common errors', function() {
|
describe('common errors', function() {
|
||||||
|
|
||||||
it('TransactionError', function() {
|
it('TransactionError', function() {
|
||||||
@@ -909,7 +889,7 @@ describe('RippleAPI', function() {
|
|||||||
checkResult(responses.ledgerClosed, 'ledgerClosed', message);
|
checkResult(responses.ledgerClosed, 'ledgerClosed', message);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
this.api.remote.getServer().emit('message', ledgerClosed);
|
this.api.connection._ws.emit('message', JSON.stringify(ledgerClosed));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -965,9 +945,8 @@ describe('RippleAPI - offline', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('RippleAPI valid options', function() {
|
it('RippleAPI valid options', function() {
|
||||||
const api = new RippleAPI({trace: true, servers: ['wss://s:1']});
|
const api = new RippleAPI({servers: ['wss://s:1']});
|
||||||
assert(api.remote.trace);
|
assert.deepEqual(api.connection._url, 'wss://s:1');
|
||||||
assert.deepEqual(api.remote.servers, ['wss://s:1']);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('RippleAPI invalid server uri', function() {
|
it('RippleAPI invalid server uri', function() {
|
||||||
|
|||||||
@@ -107,8 +107,6 @@ module.exports = function(port) {
|
|||||||
assert.strictEqual(request.command, 'subscribe');
|
assert.strictEqual(request.command, 'subscribe');
|
||||||
if (request.accounts) {
|
if (request.accounts) {
|
||||||
assert(_.indexOf(_.values(addresses), request.accounts[0]) !== -1);
|
assert(_.indexOf(_.values(addresses), request.accounts[0]) !== -1);
|
||||||
} else {
|
|
||||||
assert.deepEqual(request.streams, ['ledger', 'server']);
|
|
||||||
}
|
}
|
||||||
conn.send(createResponse(request, fixtures.subscribe));
|
conn.send(createResponse(request, fixtures.subscribe));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ function setupMockRippledConnection(testcase, port, done) {
|
|||||||
testcase.mockRippled = createMockRippled(port);
|
testcase.mockRippled = createMockRippled(port);
|
||||||
testcase.api = new RippleAPI({servers: ['ws://localhost:' + port]});
|
testcase.api = new RippleAPI({servers: ['ws://localhost:' + port]});
|
||||||
testcase.api.connect().then(() => {
|
testcase.api.connect().then(() => {
|
||||||
testcase.api.remote.getServer().once('ledger_closed', () => done());
|
testcase.api.once('ledgerClosed', () => done());
|
||||||
testcase.api.remote.getServer().emit('message', ledgerClosed);
|
testcase.api.connection._ws.emit('message', JSON.stringify(ledgerClosed));
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user