mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 12:15:51 +00:00
1519 lines
52 KiB
JavaScript
1519 lines
52 KiB
JavaScript
/* eslint-disable max-nested-callbacks */
|
|
'use strict';
|
|
const _ = require('lodash');
|
|
const net = require('net');
|
|
const assert = require('assert-diff');
|
|
const setupAPI = require('./setup-api');
|
|
const RippleAPI = require('ripple-api').RippleAPI;
|
|
const validate = RippleAPI._PRIVATE.validate;
|
|
const fixtures = require('./fixtures');
|
|
const requests = fixtures.requests;
|
|
const responses = fixtures.responses;
|
|
const addresses = require('./fixtures/addresses');
|
|
const hashes = require('./fixtures/hashes');
|
|
const address = addresses.ACCOUNT;
|
|
const utils = RippleAPI._PRIVATE.ledgerUtils;
|
|
const ledgerClosed = require('./fixtures/rippled/ledger-close-newer');
|
|
const schemaValidator = RippleAPI._PRIVATE.schemaValidator;
|
|
|
|
function unused() {
|
|
}
|
|
|
|
function closeLedger(connection) {
|
|
connection._ws.emit('message', JSON.stringify(ledgerClosed));
|
|
}
|
|
|
|
function checkResult(expected, schemaName, response) {
|
|
if (expected.txJSON) {
|
|
assert(response.txJSON);
|
|
assert.deepEqual(JSON.parse(response.txJSON), JSON.parse(expected.txJSON));
|
|
}
|
|
assert.deepEqual(_.omit(response, 'txJSON'), _.omit(expected, 'txJSON'));
|
|
if (schemaName) {
|
|
schemaValidator.schemaValidate(schemaName, response);
|
|
}
|
|
return response;
|
|
}
|
|
|
|
function createServer() {
|
|
return new Promise((resolve, reject) => {
|
|
const server = net.createServer();
|
|
server.on('listening', function() {
|
|
resolve(server);
|
|
});
|
|
server.on('error', function(error) {
|
|
reject(error);
|
|
});
|
|
server.listen(0, '0.0.0.0');
|
|
});
|
|
}
|
|
|
|
|
|
describe('RippleAPI', function() {
|
|
const instructions = {maxLedgerVersionOffset: 100};
|
|
beforeEach(setupAPI.setup);
|
|
afterEach(setupAPI.teardown);
|
|
|
|
describe('Connection', function() {
|
|
|
|
it('connection default options', function() {
|
|
const connection = new utils.common.Connection('url');
|
|
assert.strictEqual(connection._url, 'url');
|
|
assert(_.isUndefined(connection._proxyURL));
|
|
assert(_.isUndefined(connection._authorization));
|
|
});
|
|
|
|
it('with proxy', function(done) {
|
|
createServer().then((server) => {
|
|
const port = server.address().port;
|
|
const expect = 'CONNECT localhost';
|
|
server.on('connection', (socket) => {
|
|
socket.on('data', (data) => {
|
|
const got = data.toString('ascii', 0, expect.length);
|
|
assert.strictEqual(got, expect);
|
|
server.close();
|
|
done();
|
|
});
|
|
});
|
|
|
|
const options = {
|
|
proxy: 'ws://localhost:' + port,
|
|
authorization: 'authorization',
|
|
trustedCertificates: 'something'
|
|
};
|
|
const connection =
|
|
new utils.common.Connection(this.api.connection._url, options);
|
|
connection.connect().catch(done);
|
|
connection.connect().catch(done);
|
|
}, done);
|
|
});
|
|
|
|
it('Multiply disconnect calls', function() {
|
|
this.api.disconnect();
|
|
return this.api.disconnect();
|
|
});
|
|
|
|
it('reconnect', function() {
|
|
return this.api.connection.reconnect();
|
|
});
|
|
|
|
it('NotConnectedError', function() {
|
|
const connection = new utils.common.Connection('url');
|
|
return connection.getLedgerVersion().then(() => {
|
|
assert(false, 'Should throw NotConnectedError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotConnectedError);
|
|
});
|
|
});
|
|
|
|
it('DisconnectedError', function() {
|
|
this.api.connection._send = function() {
|
|
this._ws.close();
|
|
};
|
|
return this.api.getServerInfo().then(() => {
|
|
assert(false, 'Should throw DisconnectedError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.DisconnectedError);
|
|
});
|
|
});
|
|
|
|
it('TimeoutError', function() {
|
|
this.api.connection._send = function() {
|
|
return Promise.resolve({});
|
|
};
|
|
const request = {command: 'server_info'};
|
|
return this.api.connection.request(request, 1).then(() => {
|
|
assert(false, 'Should throw TimeoutError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.TimeoutError);
|
|
});
|
|
});
|
|
|
|
it('DisconnectedError on send', function() {
|
|
this.api.connection._ws.send = function(message, options, callback) {
|
|
unused(message, options);
|
|
callback({message: 'not connected'});
|
|
};
|
|
return this.api.getServerInfo().then(() => {
|
|
assert(false, 'Should throw DisconnectedError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.DisconnectedError);
|
|
assert.strictEqual(error.message, 'not connected');
|
|
});
|
|
});
|
|
|
|
it('ResponseFormatError', function() {
|
|
this.api.connection._send = function(message) {
|
|
const parsed = JSON.parse(message);
|
|
setTimeout(() => {
|
|
this._ws.emit('message', JSON.stringify({
|
|
id: parsed.id,
|
|
type: 'response',
|
|
status: 'unrecognized'
|
|
}));
|
|
}, 2);
|
|
return new Promise(() => {});
|
|
};
|
|
return this.api.getServerInfo().then(() => {
|
|
assert(false, 'Should throw ResponseFormatError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.ResponseFormatError);
|
|
});
|
|
});
|
|
|
|
it('reconnect on unexpected close ', function(done) {
|
|
this.api.connection.on('connected', () => {
|
|
done();
|
|
});
|
|
|
|
setTimeout(() => {
|
|
this.api.connection._ws.close();
|
|
}, 1);
|
|
});
|
|
|
|
it('Multiply connect calls', function() {
|
|
return this.api.connect().then(() => {
|
|
return this.api.connect();
|
|
});
|
|
});
|
|
|
|
it('hasLedgerVersion', function() {
|
|
return this.api.connection.hasLedgerVersion(8819951).then((result) => {
|
|
assert(result);
|
|
});
|
|
});
|
|
|
|
it('Cannot connect because no server', function() {
|
|
const connection = new utils.common.Connection();
|
|
return connection.connect().then(() => {
|
|
assert(false, 'Should throw ConnectionError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.ConnectionError);
|
|
});
|
|
});
|
|
|
|
it('connect multiserver error', function() {
|
|
const options = {
|
|
servers: ['wss://server1.com', 'wss://server2.com']
|
|
};
|
|
assert.throws(function() {
|
|
const api = new RippleAPI(options);
|
|
unused(api);
|
|
}, this.api.errors.RippleError);
|
|
});
|
|
|
|
it('connect throws error', function(done) {
|
|
this.api.once('error', (type, info) => {
|
|
assert.strictEqual(type, 'type');
|
|
assert.strictEqual(info, 'info');
|
|
done();
|
|
});
|
|
this.api.connection.emit('error', 'type', 'info');
|
|
});
|
|
|
|
it('connection emit stream messages', function(done) {
|
|
let transactionCount = 0;
|
|
let pathFindCount = 0;
|
|
this.api.connection.on('transaction', () => {
|
|
transactionCount++;
|
|
});
|
|
this.api.connection.on('path_find', () => {
|
|
pathFindCount++;
|
|
});
|
|
this.api.connection.on('1', () => {
|
|
assert.strictEqual(transactionCount, 1);
|
|
assert.strictEqual(pathFindCount, 1);
|
|
done();
|
|
});
|
|
|
|
this.api.connection._onMessage(JSON.stringify({
|
|
type: 'transaction'
|
|
}));
|
|
this.api.connection._onMessage(JSON.stringify({
|
|
type: 'path_find'
|
|
}));
|
|
this.api.connection._onMessage(JSON.stringify({
|
|
type: 'response', id: 1
|
|
}));
|
|
});
|
|
|
|
it('connection - invalid message id', function(done) {
|
|
this.api.on('error', (type, message) => {
|
|
assert.strictEqual(type, 'badMessage');
|
|
assert.strictEqual(message,
|
|
'{"type":"response","id":"must be integer"}');
|
|
done();
|
|
});
|
|
this.api.connection._onMessage(JSON.stringify({
|
|
type: 'response', id: 'must be integer'
|
|
}));
|
|
});
|
|
|
|
it('connection - error message', function(done) {
|
|
this.api.on('error', (type, message) => {
|
|
assert.strictEqual(type, 'slowDown');
|
|
assert.strictEqual(message, 'slow down');
|
|
done();
|
|
});
|
|
this.api.connection._onMessage(JSON.stringify({
|
|
error: 'slowDown', error_message: 'slow down'
|
|
}));
|
|
});
|
|
|
|
it('connection - unrecognized message type', function(done) {
|
|
this.api.on('error', (type, message) => {
|
|
assert.strictEqual(type, 'badMessage');
|
|
assert.strictEqual(message, '{"type":"unknown"}');
|
|
done();
|
|
});
|
|
|
|
this.api.connection._onMessage(JSON.stringify({type: 'unknown'}));
|
|
});
|
|
});
|
|
|
|
it('error inspect', function() {
|
|
const error = new this.api.errors.RippleError('mess', {data: 1});
|
|
assert.strictEqual(error.inspect(), '[RippleError(mess, { data: 1 })]');
|
|
});
|
|
|
|
it('preparePayment', function() {
|
|
const localInstructions = _.defaults({
|
|
maxFee: '0.000012'
|
|
}, instructions);
|
|
return this.api.preparePayment(
|
|
address, requests.preparePayment, localInstructions).then(
|
|
_.partial(checkResult, responses.preparePayment.normal, 'prepare'));
|
|
});
|
|
|
|
it('preparePayment - min amount xrp', function() {
|
|
const localInstructions = _.defaults({
|
|
maxFee: '0.000012'
|
|
}, instructions);
|
|
return this.api.preparePayment(
|
|
address, requests.preparePaymentMinAmountXRP, localInstructions).then(
|
|
_.partial(checkResult, responses.preparePayment.minAmountXRP, 'prepare'));
|
|
});
|
|
|
|
it('preparePayment - min amount xrp2xrp', function() {
|
|
return this.api.preparePayment(
|
|
address, requests.preparePaymentMinAmount, instructions).then(
|
|
_.partial(checkResult,
|
|
responses.preparePayment.minAmountXRPXRP, 'prepare'));
|
|
});
|
|
|
|
it('preparePayment - XRP to XRP no partial', function() {
|
|
assert.throws(() => {
|
|
this.api.preparePayment(address, requests.preparePaymentWrongPartial);
|
|
}, /XRP to XRP payments cannot be partial payments/);
|
|
});
|
|
|
|
it('preparePayment - address must match payment.source.address', function() {
|
|
assert.throws(() => {
|
|
this.api.preparePayment(address, requests.preparePaymentWrongAddress);
|
|
}, /address must match payment.source.address/);
|
|
});
|
|
|
|
it('preparePayment - wrong amount', function() {
|
|
assert.throws(() => {
|
|
this.api.preparePayment(address, requests.preparePaymentWrongAmount);
|
|
}, this.api.errors.ValidationError);
|
|
});
|
|
|
|
it('preparePayment with all options specified', function() {
|
|
return this.api.getLedgerVersion().then((ver) => {
|
|
const localInstructions = {
|
|
maxLedgerVersion: ver + 100,
|
|
fee: '0.000012'
|
|
};
|
|
return this.api.preparePayment(
|
|
address, requests.preparePaymentAllOptions, localInstructions).then(
|
|
_.partial(checkResult, responses.preparePayment.allOptions, 'prepare'));
|
|
});
|
|
});
|
|
|
|
it('preparePayment without counterparty set', function() {
|
|
const localInstructions = _.defaults({sequence: 23}, instructions);
|
|
return this.api.preparePayment(
|
|
address, requests.preparePaymentNoCounterparty, localInstructions).then(
|
|
_.partial(checkResult, responses.preparePayment.noCounterparty,
|
|
'prepare'));
|
|
});
|
|
|
|
it('preparePayment - destination.minAmount', function() {
|
|
return this.api.preparePayment(address, responses.getPaths.sendAll[0],
|
|
instructions).then(_.partial(checkResult,
|
|
responses.preparePayment.minAmount, 'prepare'));
|
|
});
|
|
|
|
it('prepareOrder - buy order', function() {
|
|
const request = requests.prepareOrder.buy;
|
|
return this.api.prepareOrder(address, request)
|
|
.then(_.partial(checkResult, responses.prepareOrder.buy, 'prepare'));
|
|
});
|
|
|
|
it('prepareOrder - buy order with expiration', function() {
|
|
const request = requests.prepareOrder.expiration;
|
|
const response = responses.prepareOrder.expiration;
|
|
return this.api.prepareOrder(address, request, instructions)
|
|
.then(_.partial(checkResult, response, 'prepare'));
|
|
});
|
|
|
|
it('prepareOrder - sell order', function() {
|
|
const request = requests.prepareOrder.sell;
|
|
return this.api.prepareOrder(address, request, instructions).then(
|
|
_.partial(checkResult, responses.prepareOrder.sell, 'prepare'));
|
|
});
|
|
|
|
it('prepareOrderCancellation', function() {
|
|
const request = requests.prepareOrderCancellation;
|
|
return this.api.prepareOrderCancellation(address, request, instructions)
|
|
.then(_.partial(checkResult, responses.prepareOrder.cancellation,
|
|
'prepare'));
|
|
});
|
|
|
|
it('prepareOrderCancellation - no instructions', function() {
|
|
const request = requests.prepareOrderCancellation;
|
|
return this.api.prepareOrderCancellation(address, request)
|
|
.then(_.partial(checkResult,
|
|
responses.prepareOrder.cancellationNoInstructions,
|
|
'prepare'));
|
|
});
|
|
|
|
it('prepareTrustline - simple', function() {
|
|
return this.api.prepareTrustline(
|
|
address, requests.prepareTrustline.simple, instructions).then(
|
|
_.partial(checkResult, responses.prepareTrustline.simple, 'prepare'));
|
|
});
|
|
|
|
it('prepareTrustline - frozen', function() {
|
|
return this.api.prepareTrustline(
|
|
address, requests.prepareTrustline.frozen).then(
|
|
_.partial(checkResult, responses.prepareTrustline.frozen, 'prepare'));
|
|
});
|
|
|
|
it('prepareTrustline - complex', function() {
|
|
return this.api.prepareTrustline(
|
|
address, requests.prepareTrustline.complex, instructions).then(
|
|
_.partial(checkResult, responses.prepareTrustline.complex, 'prepare'));
|
|
});
|
|
|
|
it('prepareSettings', function() {
|
|
return this.api.prepareSettings(
|
|
address, requests.prepareSettings, instructions).then(
|
|
_.partial(checkResult, responses.prepareSettings.flags, 'prepare'));
|
|
});
|
|
|
|
it('prepareSettings - no instructions', function() {
|
|
return this.api.prepareSettings(
|
|
address, requests.prepareSettings).then(
|
|
_.partial(
|
|
checkResult,
|
|
responses.prepareSettings.noInstructions,
|
|
'prepare'));
|
|
});
|
|
|
|
it('prepareSettings - regularKey', function() {
|
|
const regularKey = {regularKey: 'rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD'};
|
|
return this.api.prepareSettings(address, regularKey, instructions).then(
|
|
_.partial(checkResult, responses.prepareSettings.regularKey, 'prepare'));
|
|
});
|
|
|
|
it('prepareSettings - remove regularKey', function() {
|
|
const regularKey = {regularKey: null};
|
|
return this.api.prepareSettings(address, regularKey, instructions).then(
|
|
_.partial(checkResult, responses.prepareSettings.removeRegularKey,
|
|
'prepare'));
|
|
});
|
|
|
|
it('prepareSettings - flag set', function() {
|
|
const settings = {requireDestinationTag: true};
|
|
return this.api.prepareSettings(address, settings, instructions).then(
|
|
_.partial(checkResult, responses.prepareSettings.flagSet, 'prepare'));
|
|
});
|
|
|
|
it('prepareSettings - flag clear', function() {
|
|
const settings = {requireDestinationTag: false};
|
|
return this.api.prepareSettings(address, settings, instructions).then(
|
|
_.partial(checkResult, responses.prepareSettings.flagClear, 'prepare'));
|
|
});
|
|
|
|
it('prepareSettings - integer field clear', function() {
|
|
const settings = {transferRate: null};
|
|
return this.api.prepareSettings(address, settings, instructions)
|
|
.then(data => {
|
|
assert(data);
|
|
assert.strictEqual(JSON.parse(data.txJSON).TransferRate, 0);
|
|
});
|
|
});
|
|
|
|
it('prepareSettings - set transferRate', function() {
|
|
const settings = {transferRate: 1};
|
|
return this.api.prepareSettings(address, settings, instructions).then(
|
|
_.partial(checkResult, responses.prepareSettings.setTransferRate,
|
|
'prepare'));
|
|
});
|
|
|
|
it('prepareSuspendedPaymentCreation', function() {
|
|
const localInstructions = _.defaults({
|
|
maxFee: '0.000012'
|
|
}, instructions);
|
|
return this.api.prepareSuspendedPaymentCreation(
|
|
address, requests.prepareSuspendedPaymentCreation,
|
|
localInstructions).then(
|
|
_.partial(checkResult, responses.prepareSuspendedPaymentCreation,
|
|
'prepare'));
|
|
});
|
|
|
|
it('prepareSuspendedPaymentCreation full', function() {
|
|
return this.api.prepareSuspendedPaymentCreation(
|
|
address, requests.prepareSuspendedPaymentCreationFull).then(
|
|
_.partial(checkResult, responses.prepareSuspendedPaymentCreationFull,
|
|
'prepare'));
|
|
});
|
|
|
|
it('prepareSuspendedPaymentExecution', function() {
|
|
return this.api.prepareSuspendedPaymentExecution(
|
|
address, requests.prepareSuspendedPaymentExecution, instructions).then(
|
|
_.partial(checkResult, responses.prepareSuspendedPaymentExecution,
|
|
'prepare'));
|
|
});
|
|
|
|
it('prepareSuspendedPaymentExecution - simple', function() {
|
|
return this.api.prepareSuspendedPaymentExecution(
|
|
address, requests.prepareSuspendedPaymentExecutionSimple).then(
|
|
_.partial(checkResult, responses.prepareSuspendedPaymentExecutionSimple,
|
|
'prepare'));
|
|
});
|
|
|
|
it('prepareSuspendedPaymentCancellation', function() {
|
|
return this.api.prepareSuspendedPaymentCancellation(
|
|
address, requests.prepareSuspendedPaymentCancellation, instructions).then(
|
|
_.partial(checkResult, responses.prepareSuspendedPaymentCancellation,
|
|
'prepare'));
|
|
});
|
|
|
|
it('prepareSuspendedPaymentCancellation with memos', function() {
|
|
return this.api.prepareSuspendedPaymentCancellation(
|
|
address, requests.prepareSuspendedPaymentCancellationMemos).then(
|
|
_.partial(checkResult, responses.prepareSuspendedPaymentCancellationMemos,
|
|
'prepare'));
|
|
});
|
|
|
|
it('sign', function() {
|
|
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV';
|
|
const result = this.api.sign(requests.sign.txJSON, secret);
|
|
assert.deepEqual(result, responses.sign);
|
|
schemaValidator.schemaValidate('sign', result);
|
|
});
|
|
|
|
it('sign - SuspendedPaymentExecution', function() {
|
|
const secret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb';
|
|
const result = this.api.sign(requests.signSuspended.txJSON, secret);
|
|
assert.deepEqual(result, responses.signSuspended);
|
|
schemaValidator.schemaValidate('sign', result);
|
|
});
|
|
|
|
it('submit', function() {
|
|
return this.api.submit(responses.sign.signedTransaction).then(
|
|
_.partial(checkResult, responses.submit, 'submit'));
|
|
});
|
|
|
|
it('submit - failure', function() {
|
|
return this.api.submit('BAD').then(() => {
|
|
assert(false, 'Should throw RippledError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.RippledError);
|
|
assert.strictEqual(error.data.resultCode, 'temBAD_FEE');
|
|
});
|
|
});
|
|
|
|
describe('RippleAPI', function() {
|
|
|
|
it('getBalances', function() {
|
|
return this.api.getBalances(address).then(
|
|
_.partial(checkResult, responses.getBalances, 'getBalances'));
|
|
});
|
|
|
|
it('getBalances - limit', function() {
|
|
const options = {
|
|
limit: 3,
|
|
ledgerVersion: 123456
|
|
};
|
|
const expectedResponse = responses.getBalances.slice(0, 3);
|
|
return this.api.getBalances(address, options).then(
|
|
_.partial(checkResult, expectedResponse, 'getBalances'));
|
|
});
|
|
|
|
it('getBalances - limit & currency', function() {
|
|
const options = {
|
|
currency: 'USD',
|
|
limit: 3
|
|
};
|
|
const expectedResponse = _.filter(responses.getBalances,
|
|
item => item.currency === 'USD').slice(0, 3);
|
|
return this.api.getBalances(address, options).then(
|
|
_.partial(checkResult, expectedResponse, 'getBalances'));
|
|
});
|
|
|
|
it('getBalances - limit & currency & issuer', function() {
|
|
const options = {
|
|
currency: 'USD',
|
|
counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B',
|
|
limit: 3
|
|
};
|
|
const expectedResponse = _.filter(responses.getBalances,
|
|
item => item.currency === 'USD' &&
|
|
item.counterparty === 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B').slice(0, 3);
|
|
return this.api.getBalances(address, options).then(
|
|
_.partial(checkResult, expectedResponse, 'getBalances'));
|
|
});
|
|
});
|
|
|
|
it('getBalanceSheet', function() {
|
|
return this.api.getBalanceSheet(address).then(
|
|
_.partial(checkResult, responses.getBalanceSheet, 'getBalanceSheet'));
|
|
});
|
|
|
|
it('getBalanceSheet - invalid options', function() {
|
|
assert.throws(() => {
|
|
this.api.getBalanceSheet(address, {invalid: 'options'});
|
|
}, this.api.errors.ValidationError);
|
|
});
|
|
|
|
it('getBalanceSheet - empty', function() {
|
|
const options = {ledgerVersion: 123456};
|
|
return this.api.getBalanceSheet(address, options).then(
|
|
_.partial(checkResult, {}, 'getBalanceSheet'));
|
|
});
|
|
|
|
describe('getTransaction', () => {
|
|
it('getTransaction - payment', function() {
|
|
return this.api.getTransaction(hashes.VALID_TRANSACTION_HASH).then(
|
|
_.partial(checkResult, responses.getTransaction.payment,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - settings', function() {
|
|
const hash =
|
|
'4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA1B';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult, responses.getTransaction.settings,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - order', function() {
|
|
const hash =
|
|
'10A6FB4A66EE80BED46AAE4815D7DC43B97E944984CCD5B93BCF3F8538CABC51';
|
|
closeLedger(this.api.connection);
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult, responses.getTransaction.order,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - sell order', function() {
|
|
const hash =
|
|
'458101D51051230B1D56E9ACAFAA34451BF65FA000F95DF6F0FF5B3A62D83FC2';
|
|
closeLedger(this.api.connection);
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult, responses.getTransaction.orderSell,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - order cancellation', function() {
|
|
const hash =
|
|
'809335DD3B0B333865096217AA2F55A4DF168E0198080B3A090D12D88880FF0E';
|
|
closeLedger(this.api.connection);
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult, responses.getTransaction.orderCancellation,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - order with expiration cancellation', function() {
|
|
const hash =
|
|
'097B9491CC76B64831F1FEA82EAA93BCD728106D90B65A072C933888E946C40B';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult,
|
|
responses.getTransaction.orderWithExpirationCancellation,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - trustline set', function() {
|
|
const hash =
|
|
'635A0769BD94710A1F6A76CDE65A3BC661B20B798807D1BBBDADCEA26420538D';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult, responses.getTransaction.trustline,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - trustline frozen off', function() {
|
|
const hash =
|
|
'FE72FAD0FA7CA904FB6C633A1666EDF0B9C73B2F5A4555D37EEF2739A78A531B';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult, responses.getTransaction.trustlineFrozenOff,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - trustline no quality', function() {
|
|
const hash =
|
|
'BAF1C678323C37CCB7735550C379287667D8288C30F83148AD3C1CB019FC9002';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult, responses.getTransaction.trustlineNoQuality,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - not validated', function() {
|
|
const hash =
|
|
'4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA10';
|
|
return this.api.getTransaction(hash).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
});
|
|
});
|
|
|
|
it('getTransaction - tracking on', function() {
|
|
const hash =
|
|
'8925FC8844A1E930E2CC76AD0A15E7665AFCC5425376D548BB1413F484C31B8C';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult, responses.getTransaction.trackingOn,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - tracking off', function() {
|
|
const hash =
|
|
'C8C5E20DFB1BF533D0D81A2ED23F0A3CBD1EF2EE8A902A1D760500473CC9C582';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult, responses.getTransaction.trackingOff,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - set regular key', function() {
|
|
const hash =
|
|
'278E6687C1C60C6873996210A6523564B63F2844FB1019576C157353B1813E60';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult, responses.getTransaction.setRegularKey,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - not found in range', function() {
|
|
const hash =
|
|
'809335DD3B0B333865096217AA2F55A4DF168E0198080B3A090D12D88880FF0E';
|
|
const options = {
|
|
minLedgerVersion: 32570,
|
|
maxLedgerVersion: 32571
|
|
};
|
|
return this.api.getTransaction(hash, options).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
});
|
|
});
|
|
|
|
it('getTransaction - not found by hash', function() {
|
|
const hash = hashes.NOTFOUND_TRANSACTION_HASH;
|
|
return this.api.getTransaction(hash).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
});
|
|
});
|
|
|
|
it('getTransaction - missing ledger history', function() {
|
|
const hash = hashes.NOTFOUND_TRANSACTION_HASH;
|
|
// make gaps in history
|
|
closeLedger(this.api.connection);
|
|
return this.api.getTransaction(hash).then(() => {
|
|
assert(false, 'Should throw MissingLedgerHistoryError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.MissingLedgerHistoryError);
|
|
});
|
|
});
|
|
|
|
it('getTransaction - missing ledger history with ledger range', function() {
|
|
const hash = hashes.NOTFOUND_TRANSACTION_HASH;
|
|
const options = {
|
|
minLedgerVersion: 32569,
|
|
maxLedgerVersion: 32571
|
|
};
|
|
return this.api.getTransaction(hash, options).then(() => {
|
|
assert(false, 'Should throw MissingLedgerHistoryError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.MissingLedgerHistoryError);
|
|
});
|
|
});
|
|
|
|
it('getTransaction - not found - future maxLedgerVersion', function() {
|
|
const hash = hashes.NOTFOUND_TRANSACTION_HASH;
|
|
const options = {
|
|
maxLedgerVersion: 99999999999
|
|
};
|
|
return this.api.getTransaction(hash, options).then(() => {
|
|
assert(false, 'Should throw PendingLedgerVersionError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.PendingLedgerVersionError);
|
|
});
|
|
});
|
|
|
|
it('getTransaction - ledger_index not found', function() {
|
|
const hash =
|
|
'4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA11';
|
|
return this.api.getTransaction(hash).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
assert(error.message.indexOf('ledger_index') !== -1);
|
|
});
|
|
});
|
|
|
|
it('getTransaction - transaction ledger not found', function() {
|
|
const hash =
|
|
'4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA12';
|
|
return this.api.getTransaction(hash).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
assert(error.message.indexOf('ledger not found') !== -1);
|
|
});
|
|
});
|
|
|
|
it('getTransaction - ledger missing close time', function() {
|
|
const hash =
|
|
'0F7ED9F40742D8A513AE86029462B7A6768325583DF8EE21B7EC663019DD6A04';
|
|
closeLedger(this.api.connection);
|
|
return this.api.getTransaction(hash).then(() => {
|
|
assert(false, 'Should throw UnexpectedError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.UnexpectedError);
|
|
});
|
|
});
|
|
|
|
it('getTransaction - SuspendedPaymentCreation', function() {
|
|
const hash =
|
|
'144F272380BDB4F1BD92329A2178BABB70C20F59042C495E10BF72EBFB408EE1';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult,
|
|
responses.getTransaction.suspendedPaymentCreation,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - SuspendedPaymentCreation iou', function() {
|
|
const hash =
|
|
'144F272380BDB4F1BD92329A2178BABB70C20F59042C495E10BF72EBFB408EE2';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult,
|
|
responses.getTransaction.SuspendedPaymentCreationIOU,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - SuspendedPaymentCancellation', function() {
|
|
const hash =
|
|
'F346E542FFB7A8398C30A87B952668DAB48B7D421094F8B71776DA19775A3B22';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult,
|
|
responses.getTransaction.suspendedPaymentCancellation,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - SuspendedPaymentExecution', function() {
|
|
const options = {
|
|
minLedgerVersion: 10,
|
|
maxLedgerVersion: 15
|
|
};
|
|
const hash =
|
|
'CC5277137B3F25EE8B86259C83CB0EAADE818505E4E9BCBF19B1AC6FD136993B';
|
|
return this.api.getTransaction(hash, options).then(
|
|
_.partial(checkResult,
|
|
responses.getTransaction.suspendedPaymentExecution,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - SuspendedPaymentExecution simple', function() {
|
|
const hash =
|
|
'CC5277137B3F25EE8B86259C83CB0EAADE818505E4E9BCBF19B1AC6FD1369931';
|
|
return this.api.getTransaction(hash).then(
|
|
_.partial(checkResult,
|
|
responses.getTransaction.suspendedPaymentExecutionSimple,
|
|
'getTransaction'));
|
|
});
|
|
|
|
it('getTransaction - no Meta', function() {
|
|
const hash =
|
|
'AFB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA1B';
|
|
return this.api.getTransaction(hash).then(result => {
|
|
assert.deepEqual(result, responses.getTransaction.noMeta);
|
|
});
|
|
});
|
|
|
|
it('getTransaction - Unrecognized transaction type', function() {
|
|
const hash =
|
|
'AFB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA11';
|
|
closeLedger(this.api.connection);
|
|
return this.api.getTransaction(hash).then(() => {
|
|
assert(false, 'Unrecognized transaction type');
|
|
}).catch(error => {
|
|
assert.strictEqual(error.message, 'Unrecognized transaction type');
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
it('getTransactions', function() {
|
|
const options = {types: ['payment', 'order'], initiated: true, limit: 2};
|
|
return this.api.getTransactions(address, options).then(
|
|
_.partial(checkResult, responses.getTransactions,
|
|
'getTransactions'));
|
|
});
|
|
|
|
it('getTransactions - earliest first', function() {
|
|
const options = {types: ['payment', 'order'], initiated: true, limit: 2,
|
|
earliestFirst: true
|
|
};
|
|
const expected = _.cloneDeep(responses.getTransactions)
|
|
.sort(utils.compareTransactions);
|
|
return this.api.getTransactions(address, options).then(
|
|
_.partial(checkResult, expected, 'getTransactions'));
|
|
});
|
|
|
|
|
|
it('getTransactions - earliest first with start option', function() {
|
|
const options = {types: ['payment', 'order'], initiated: true, limit: 2,
|
|
start: hashes.VALID_TRANSACTION_HASH,
|
|
earliestFirst: true
|
|
};
|
|
return this.api.getTransactions(address, options).then(data => {
|
|
assert.strictEqual(data.length, 0);
|
|
});
|
|
});
|
|
|
|
it('getTransactions - gap', function() {
|
|
const options = {types: ['payment', 'order'], initiated: true, limit: 2,
|
|
maxLedgerVersion: 348858000
|
|
};
|
|
return this.api.getTransactions(address, options).then(() => {
|
|
assert(false, 'Should throw MissingLedgerHistoryError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.MissingLedgerHistoryError);
|
|
});
|
|
});
|
|
|
|
it('getTransactions - tx not found', function() {
|
|
const options = {types: ['payment', 'order'], initiated: true, limit: 2,
|
|
start: hashes.NOTFOUND_TRANSACTION_HASH,
|
|
counterparty: address
|
|
};
|
|
return this.api.getTransactions(address, options).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
});
|
|
});
|
|
|
|
it('getTransactions - filters', function() {
|
|
const options = {types: ['payment', 'order'], initiated: true, limit: 10,
|
|
excludeFailures: true,
|
|
counterparty: addresses.ISSUER
|
|
};
|
|
return this.api.getTransactions(address, options).then(data => {
|
|
assert.strictEqual(data.length, 10);
|
|
assert(_.every(data, t => t.type === 'payment' || t.type === 'order'));
|
|
assert(_.every(data, t => t.outcome.result === 'tesSUCCESS'));
|
|
});
|
|
});
|
|
|
|
it('getTransactions - filters for incoming', function() {
|
|
const options = {types: ['payment', 'order'], initiated: false, limit: 10,
|
|
excludeFailures: true,
|
|
counterparty: addresses.ISSUER
|
|
};
|
|
return this.api.getTransactions(address, options).then(data => {
|
|
assert.strictEqual(data.length, 10);
|
|
assert(_.every(data, t => t.type === 'payment' || t.type === 'order'));
|
|
assert(_.every(data, t => t.outcome.result === 'tesSUCCESS'));
|
|
});
|
|
});
|
|
|
|
// this is the case where core.RippleError just falls
|
|
// through the api to the user
|
|
it('getTransactions - error', function() {
|
|
const options = {types: ['payment', 'order'], initiated: true, limit: 13};
|
|
return this.api.getTransactions(address, options).then(() => {
|
|
assert(false, 'Should throw RippleError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.RippleError);
|
|
});
|
|
});
|
|
|
|
// TODO: this doesn't test much, just that it doesn't crash
|
|
it('getTransactions with start option', function() {
|
|
const options = {
|
|
start: hashes.VALID_TRANSACTION_HASH,
|
|
earliestFirst: false,
|
|
limit: 2
|
|
};
|
|
return this.api.getTransactions(address, options).then(
|
|
_.partial(checkResult, responses.getTransactions, 'getTransactions'));
|
|
});
|
|
|
|
it('getTransactions - start transaction with zero ledger version', function(
|
|
) {
|
|
const options = {
|
|
start: '4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA13',
|
|
limit: 1
|
|
};
|
|
return this.api.getTransactions(address, options).then(
|
|
_.partial(checkResult, [], 'getTransactions'));
|
|
});
|
|
|
|
it('getTransactions - no options', function() {
|
|
return this.api.getTransactions(addresses.OTHER_ACCOUNT).then(
|
|
_.partial(checkResult, responses.getTransactionsOne, 'getTransactions'));
|
|
});
|
|
|
|
it('getTrustlines', function() {
|
|
const options = {currency: 'USD'};
|
|
return this.api.getTrustlines(address, options).then(
|
|
_.partial(checkResult, responses.getTrustlines, 'getTrustlines'));
|
|
});
|
|
|
|
it('getTrustlines - ono options', function() {
|
|
return this.api.getTrustlines(address).then(
|
|
_.partial(checkResult, responses.getTrustlinesAll, 'getTrustlines'));
|
|
});
|
|
|
|
it('generateAddress', function() {
|
|
function random() {
|
|
return _.fill(Array(16), 0);
|
|
}
|
|
assert.deepEqual(this.api.generateAddress({entropy: random()}),
|
|
responses.generateAddress);
|
|
});
|
|
|
|
it('generateAddress invalid', function() {
|
|
assert.throws(() => {
|
|
function random() {
|
|
return _.fill(Array(1), 0);
|
|
}
|
|
this.api.generateAddress({entropy: random()});
|
|
}, this.api.errors.UnexpectedError);
|
|
});
|
|
|
|
it('getSettings', function() {
|
|
return this.api.getSettings(address).then(
|
|
_.partial(checkResult, responses.getSettings, 'getSettings'));
|
|
});
|
|
|
|
it('getSettings - options undefined', function() {
|
|
return this.api.getSettings(address, undefined).then(
|
|
_.partial(checkResult, responses.getSettings, 'getSettings'));
|
|
});
|
|
|
|
it('getSettings - invalid options', function() {
|
|
assert.throws(() => {
|
|
this.api.getSettings(address, {invalid: 'options'});
|
|
}, this.api.errors.ValidationError);
|
|
});
|
|
|
|
it('getAccountInfo', function() {
|
|
return this.api.getAccountInfo(address).then(
|
|
_.partial(checkResult, responses.getAccountInfo, 'getAccountInfo'));
|
|
});
|
|
|
|
it('getAccountInfo - options undefined', function() {
|
|
return this.api.getAccountInfo(address, undefined).then(
|
|
_.partial(checkResult, responses.getAccountInfo, 'getAccountInfo'));
|
|
});
|
|
|
|
it('getAccountInfo - invalid options', function() {
|
|
assert.throws(() => {
|
|
this.api.getAccountInfo(address, {invalid: 'options'});
|
|
}, this.api.errors.ValidationError);
|
|
});
|
|
|
|
it('getOrders', function() {
|
|
return this.api.getOrders(address).then(
|
|
_.partial(checkResult, responses.getOrders, 'getOrders'));
|
|
});
|
|
|
|
it('getOrders', function() {
|
|
return this.api.getOrders(address, undefined).then(
|
|
_.partial(checkResult, responses.getOrders, 'getOrders'));
|
|
});
|
|
|
|
it('getOrders - invalid options', function() {
|
|
assert.throws(() => {
|
|
this.api.getOrders(address, {invalid: 'options'});
|
|
}, this.api.errors.ValidationError);
|
|
});
|
|
|
|
it('getOrderbook', function() {
|
|
return this.api.getOrderbook(address, requests.getOrderbook, undefined)
|
|
.then(
|
|
_.partial(checkResult, responses.getOrderbook, 'getOrderbook'));
|
|
});
|
|
|
|
it('getOrderbook - invalid options', function() {
|
|
assert.throws(() => {
|
|
this.api.getOrderbook(address, requests.getOrderbook,
|
|
{invalid: 'options'});
|
|
}, this.api.errors.ValidationError);
|
|
});
|
|
|
|
it('getOrderbook with XRP', function() {
|
|
return this.api.getOrderbook(address, requests.getOrderbookWithXRP).then(
|
|
_.partial(checkResult, responses.getOrderbookWithXRP, 'getOrderbook'));
|
|
});
|
|
|
|
it('getOrderbook - sorted so that best deals come first', function() {
|
|
return this.api.getOrderbook(address, requests.getOrderbook)
|
|
.then(data => {
|
|
const bidRates = data.bids.map(bid => bid.properties.makerExchangeRate);
|
|
const askRates = data.asks.map(ask => ask.properties.makerExchangeRate);
|
|
// makerExchangeRate = quality = takerPays.value/takerGets.value
|
|
// so the best deal for the taker is the lowest makerExchangeRate
|
|
// bids and asks should be sorted so that the best deals come first
|
|
assert.deepEqual(_.sortBy(bidRates, x => Number(x)), bidRates);
|
|
assert.deepEqual(_.sortBy(askRates, x => Number(x)), askRates);
|
|
});
|
|
});
|
|
|
|
it('getOrderbook - currency & counterparty are correct', function() {
|
|
return this.api.getOrderbook(address, requests.getOrderbook)
|
|
.then(data => {
|
|
const orders = _.flatten([data.bids, data.asks]);
|
|
_.forEach(orders, order => {
|
|
const quantity = order.specification.quantity;
|
|
const totalPrice = order.specification.totalPrice;
|
|
const {base, counter} = requests.getOrderbook;
|
|
assert.strictEqual(quantity.currency, base.currency);
|
|
assert.strictEqual(quantity.counterparty, base.counterparty);
|
|
assert.strictEqual(totalPrice.currency, counter.currency);
|
|
assert.strictEqual(totalPrice.counterparty, counter.counterparty);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('getOrderbook - direction is correct for bids and asks', function() {
|
|
return this.api.getOrderbook(address, requests.getOrderbook)
|
|
.then(data => {
|
|
assert(_.every(data.bids, bid => bid.specification.direction === 'buy'));
|
|
assert(_.every(data.asks, ask => ask.specification.direction === 'sell'));
|
|
});
|
|
});
|
|
|
|
it('getServerInfo', function() {
|
|
return this.api.getServerInfo().then(
|
|
_.partial(checkResult, responses.getServerInfo, 'getServerInfo'));
|
|
});
|
|
|
|
it('getServerInfo - error', function() {
|
|
this.mockRippled.returnErrorOnServerInfo = true;
|
|
return this.api.getServerInfo().then(() => {
|
|
assert(false, 'Should throw NetworkError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.RippledError);
|
|
assert(_.includes(error.message, 'slowDown'));
|
|
});
|
|
});
|
|
|
|
it('getFee', function() {
|
|
return this.api.getFee().then(fee => {
|
|
assert.strictEqual(fee, '0.000012');
|
|
});
|
|
});
|
|
|
|
it('getFee default', function() {
|
|
this.api._feeCushion = undefined;
|
|
return this.api.getFee().then(fee => {
|
|
assert.strictEqual(fee, '0.000012');
|
|
});
|
|
});
|
|
|
|
it('disconnect & isConnected', function() {
|
|
assert.strictEqual(this.api.isConnected(), true);
|
|
return this.api.disconnect().then(() => {
|
|
assert.strictEqual(this.api.isConnected(), false);
|
|
});
|
|
});
|
|
|
|
it('getPaths', function() {
|
|
return this.api.getPaths(requests.getPaths.normal).then(
|
|
_.partial(checkResult, responses.getPaths.XrpToUsd, 'getPaths'));
|
|
});
|
|
|
|
it('getPaths - queuing', function() {
|
|
return Promise.all([
|
|
this.api.getPaths(requests.getPaths.normal),
|
|
this.api.getPaths(requests.getPaths.UsdToUsd),
|
|
this.api.getPaths(requests.getPaths.XrpToXrp)
|
|
]).then(results => {
|
|
checkResult(responses.getPaths.XrpToUsd, 'getPaths', results[0]);
|
|
checkResult(responses.getPaths.UsdToUsd, 'getPaths', results[1]);
|
|
checkResult(responses.getPaths.XrpToXrp, 'getPaths', results[2]);
|
|
});
|
|
});
|
|
|
|
// @TODO
|
|
// need decide what to do with currencies/XRP:
|
|
// if add 'XRP' in currencies, then there will be exception in
|
|
// xrpToDrops function (called from toRippledAmount)
|
|
it('getPaths USD 2 USD', function() {
|
|
return this.api.getPaths(requests.getPaths.UsdToUsd).then(
|
|
_.partial(checkResult, responses.getPaths.UsdToUsd, 'getPaths'));
|
|
});
|
|
|
|
it('getPaths XRP 2 XRP', function() {
|
|
return this.api.getPaths(requests.getPaths.XrpToXrp).then(
|
|
_.partial(checkResult, responses.getPaths.XrpToXrp, 'getPaths'));
|
|
});
|
|
|
|
it('getPaths - source with issuer', function() {
|
|
return this.api.getPaths(requests.getPaths.issuer).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
});
|
|
});
|
|
|
|
it('getPaths - XRP 2 XRP - not enough', function() {
|
|
return this.api.getPaths(requests.getPaths.XrpToXrpNotEnough).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
});
|
|
});
|
|
|
|
it('getPaths - invalid PathFind', function() {
|
|
assert.throws(() => {
|
|
this.api.getPaths(requests.getPaths.invalid);
|
|
}, /Cannot specify both source.amount/);
|
|
});
|
|
|
|
it('getPaths - does not accept currency', function() {
|
|
return this.api.getPaths(requests.getPaths.NotAcceptCurrency).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
});
|
|
});
|
|
|
|
it('getPaths - no paths', function() {
|
|
return this.api.getPaths(requests.getPaths.NoPaths).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
});
|
|
});
|
|
|
|
it('getPaths - no paths with source currencies', function() {
|
|
const pathfind = requests.getPaths.NoPathsWithCurrencies;
|
|
return this.api.getPaths(pathfind).then(() => {
|
|
assert(false, 'Should throw NotFoundError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.NotFoundError);
|
|
});
|
|
});
|
|
|
|
it('getPaths - error: srcActNotFound', function() {
|
|
const pathfind = _.assign({}, requests.getPaths.normal,
|
|
{source: {address: addresses.NOTFOUND}});
|
|
return this.api.getPaths(pathfind).catch(error => {
|
|
assert(error instanceof this.api.errors.RippleError);
|
|
});
|
|
});
|
|
|
|
it('getPaths - send all', function() {
|
|
return this.api.getPaths(requests.getPaths.sendAll).then(
|
|
_.partial(checkResult, responses.getPaths.sendAll, 'getPaths'));
|
|
});
|
|
|
|
it('getLedgerVersion', function(done) {
|
|
this.api.getLedgerVersion().then((ver) => {
|
|
assert.strictEqual(ver, 8819951);
|
|
done();
|
|
}, done);
|
|
});
|
|
|
|
it('getLedger', function() {
|
|
return this.api.getLedger().then(
|
|
_.partial(checkResult, responses.getLedger.header, 'getLedger'));
|
|
});
|
|
|
|
it('getLedger - future ledger version', function() {
|
|
return this.api.getLedger({ledgerVersion: 14661789}).then(() => {
|
|
assert(false, 'Should throw LedgerVersionError');
|
|
}).catch(error => {
|
|
assert(error instanceof this.api.errors.LedgerVersionError);
|
|
});
|
|
});
|
|
|
|
it('getLedger - with state as hashes', function() {
|
|
const request = {
|
|
includeTransactions: true,
|
|
includeAllData: false,
|
|
includeState: true,
|
|
ledgerVersion: 6
|
|
};
|
|
return this.api.getLedger(request).then(
|
|
_.partial(checkResult, responses.getLedger.withStateAsHashes,
|
|
'getLedger'));
|
|
});
|
|
|
|
it('getLedger - with settings transaction', function() {
|
|
const request = {
|
|
includeTransactions: true,
|
|
includeAllData: true,
|
|
ledgerVersion: 4181996
|
|
};
|
|
return this.api.getLedger(request).then(
|
|
_.partial(checkResult, responses.getLedger.withSettingsTx, 'getLedger'));
|
|
});
|
|
|
|
it('getLedger - full, then computeLedgerHash', function() {
|
|
const request = {
|
|
includeTransactions: true,
|
|
includeState: true,
|
|
includeAllData: true,
|
|
ledgerVersion: 38129
|
|
};
|
|
return this.api.getLedger(request).then(
|
|
_.partial(checkResult, responses.getLedger.full, 'getLedger'))
|
|
.then(response => {
|
|
const ledger = _.assign({}, response,
|
|
{parentCloseTime: response.closeTime});
|
|
const hash = this.api.computeLedgerHash(ledger);
|
|
assert.strictEqual(hash,
|
|
'E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E');
|
|
});
|
|
});
|
|
|
|
it('computeLedgerHash - wrong hash', function() {
|
|
const request = {
|
|
includeTransactions: true,
|
|
includeState: true,
|
|
includeAllData: true,
|
|
ledgerVersion: 38129
|
|
};
|
|
return this.api.getLedger(request).then(
|
|
_.partial(checkResult, responses.getLedger.full, 'getLedger'))
|
|
.then(response => {
|
|
const ledger = _.assign({}, response, {
|
|
parentCloseTime: response.closeTime, stateHash:
|
|
'D9ABF622DA26EEEE48203085D4BC23B0F77DC6F8724AC33D975DA3CA492D2E44'});
|
|
assert.throws(() => {
|
|
const hash = this.api.computeLedgerHash(ledger);
|
|
unused(hash);
|
|
}, /does not match computed hash of state/);
|
|
});
|
|
});
|
|
|
|
it('RippleError with data', function() {
|
|
const error = new this.api.errors.RippleError('_message_', '_data_');
|
|
assert.strictEqual(error.toString(),
|
|
'[RippleError(_message_, \'_data_\')]');
|
|
});
|
|
|
|
it('NotFoundError default message', function() {
|
|
const error = new this.api.errors.NotFoundError();
|
|
assert.strictEqual(error.toString(),
|
|
'[NotFoundError(Not found)]');
|
|
});
|
|
|
|
it('common utils - toRippledAmount', function() {
|
|
const amount = {issuer: 'is', currency: 'c', value: 'v'};
|
|
|
|
assert.deepEqual(utils.common.toRippledAmount(amount), {
|
|
issuer: 'is', currency: 'c', value: 'v'
|
|
});
|
|
});
|
|
|
|
it('ledger utils - renameCounterpartyToIssuerInOrder', function() {
|
|
const order = {taker_gets: {issuer: '1'}};
|
|
const expected = {taker_gets: {issuer: '1'}};
|
|
|
|
assert.deepEqual(utils.renameCounterpartyToIssuerInOrder(order), expected);
|
|
});
|
|
|
|
it('ledger utils - compareTransactions', function() {
|
|
assert.strictEqual(utils.compareTransactions({}, {}), 0);
|
|
let first = {outcome: {ledgerVersion: 1, indexInLedger: 100}};
|
|
let second = {outcome: {ledgerVersion: 1, indexInLedger: 200}};
|
|
|
|
assert.strictEqual(utils.compareTransactions(first, second), -1);
|
|
|
|
first = {outcome: {ledgerVersion: 1, indexInLedger: 100}};
|
|
second = {outcome: {ledgerVersion: 1, indexInLedger: 100}};
|
|
|
|
assert.strictEqual(utils.compareTransactions(first, second), 0);
|
|
|
|
first = {outcome: {ledgerVersion: 1, indexInLedger: 200}};
|
|
second = {outcome: {ledgerVersion: 1, indexInLedger: 100}};
|
|
|
|
assert.strictEqual(utils.compareTransactions(first, second), 1);
|
|
});
|
|
|
|
it('ledger utils - getRecursive', function() {
|
|
function getter(marker, limit) {
|
|
return new Promise((resolve, reject) => {
|
|
if (marker === undefined) {
|
|
resolve({marker: 'A', limit: limit, results: [1]});
|
|
} else {
|
|
reject(new Error());
|
|
}
|
|
});
|
|
}
|
|
return utils.getRecursive(getter, 10).then(() => {
|
|
assert(false, 'Should throw Error');
|
|
}).catch(error => {
|
|
assert(error instanceof Error);
|
|
});
|
|
});
|
|
|
|
describe('schema-validator', function() {
|
|
it('valid', function() {
|
|
assert.doesNotThrow(function() {
|
|
schemaValidator.schemaValidate('hash256',
|
|
'0F7ED9F40742D8A513AE86029462B7A6768325583DF8EE21B7EC663019DD6A0F');
|
|
});
|
|
});
|
|
|
|
it('invalid', function() {
|
|
assert.throws(function() {
|
|
schemaValidator.schemaValidate('hash256', 'invalid');
|
|
}, this.api.errors.ValidationError);
|
|
});
|
|
|
|
it('invalid - empty value', function() {
|
|
assert.throws(function() {
|
|
schemaValidator.schemaValidate('hash256', '');
|
|
}, this.api.errors.ValidationError);
|
|
});
|
|
|
|
it('schema not found error', function() {
|
|
assert.throws(function() {
|
|
schemaValidator.schemaValidate('unexisting', 'anything');
|
|
}, /no schema/);
|
|
});
|
|
|
|
});
|
|
|
|
describe('validator', function() {
|
|
|
|
it('validateLedgerRange', function() {
|
|
const options = {
|
|
minLedgerVersion: 20000,
|
|
maxLedgerVersion: 10000
|
|
};
|
|
const thunk = _.partial(validate.getTransactions,
|
|
{address, options});
|
|
assert.throws(thunk, this.api.errors.ValidationError);
|
|
assert.throws(thunk,
|
|
/minLedgerVersion must not be greater than maxLedgerVersion/);
|
|
});
|
|
|
|
it('secret', function() {
|
|
function validateSecret(secret) {
|
|
validate.sign({txJSON: '', secret});
|
|
}
|
|
assert.doesNotThrow(_.partial(validateSecret,
|
|
'shzjfakiK79YQdMjy4h8cGGfQSV6u'));
|
|
assert.throws(_.partial(validateSecret,
|
|
'shzjfakiK79YQdMjy4h8cGGfQSV6v'), this.api.errors.ValidationError);
|
|
assert.throws(_.partial(validateSecret, 1),
|
|
this.api.errors.ValidationError);
|
|
assert.throws(_.partial(validateSecret, ''),
|
|
this.api.errors.ValidationError);
|
|
assert.throws(_.partial(validateSecret, 's!!!'),
|
|
this.api.errors.ValidationError);
|
|
assert.throws(_.partial(validateSecret, 'passphrase'),
|
|
this.api.errors.ValidationError);
|
|
// 32 0s is a valid hex repr of seed bytes
|
|
const hex = new Array(33).join('0');
|
|
assert.throws(_.partial(validateSecret, hex),
|
|
this.api.errors.ValidationError);
|
|
});
|
|
|
|
});
|
|
|
|
it('ledger event', function(done) {
|
|
this.api.on('ledger', message => {
|
|
checkResult(responses.ledgerEvent, 'ledgerEvent', message);
|
|
done();
|
|
});
|
|
closeLedger(this.api.connection);
|
|
});
|
|
});
|
|
|
|
describe('RippleAPI - offline', function() {
|
|
it('prepareSettings and sign', function() {
|
|
const api = new RippleAPI();
|
|
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV';
|
|
const settings = requests.prepareSettings;
|
|
const instructions = {
|
|
sequence: 23,
|
|
maxLedgerVersion: 8820051,
|
|
fee: '0.000012'
|
|
};
|
|
return api.prepareSettings(address, settings, instructions).then(data => {
|
|
checkResult(responses.prepareSettings.flags, 'prepare', data);
|
|
assert.deepEqual(api.sign(data.txJSON, secret), responses.sign);
|
|
});
|
|
});
|
|
|
|
it('getServerInfo - offline', function() {
|
|
const api = new RippleAPI();
|
|
return api.getServerInfo().then(() => {
|
|
assert(false, 'Should throw error');
|
|
}).catch(error => {
|
|
assert(error instanceof api.errors.NotConnectedError);
|
|
});
|
|
});
|
|
|
|
it('computeLedgerHash', function() {
|
|
const api = new RippleAPI();
|
|
const header = requests.computeLedgerHash.header;
|
|
const ledgerHash = api.computeLedgerHash(header);
|
|
assert.strictEqual(ledgerHash,
|
|
'F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349');
|
|
});
|
|
|
|
it('computeLedgerHash - with transactions', function() {
|
|
const api = new RippleAPI();
|
|
const header = _.omit(requests.computeLedgerHash.header,
|
|
'transactionHash');
|
|
header.rawTransactions = JSON.stringify(
|
|
requests.computeLedgerHash.transactions);
|
|
const ledgerHash = api.computeLedgerHash(header);
|
|
assert.strictEqual(ledgerHash,
|
|
'F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349');
|
|
});
|
|
|
|
it('computeLedgerHash - incorrent transaction_hash', function() {
|
|
const api = new RippleAPI();
|
|
const header = _.assign({}, requests.computeLedgerHash.header,
|
|
{transactionHash:
|
|
'325EACC5271322539EEEC2D6A5292471EF1B3E72AE7180533EFC3B8F0AD435C9'});
|
|
header.rawTransactions = JSON.stringify(
|
|
requests.computeLedgerHash.transactions);
|
|
assert.throws(() => api.computeLedgerHash(header));
|
|
});
|
|
|
|
/* eslint-disable no-unused-vars */
|
|
it('RippleAPI - implicit server port', function() {
|
|
const api = new RippleAPI({servers: ['wss://s1.ripple.com']});
|
|
});
|
|
/* eslint-enable no-unused-vars */
|
|
it('RippleAPI invalid options', function() {
|
|
assert.throws(() => new RippleAPI({invalid: true}));
|
|
});
|
|
|
|
it('RippleAPI valid options', function() {
|
|
const api = new RippleAPI({servers: ['wss://s:1']});
|
|
assert.deepEqual(api.connection._url, 'wss://s:1');
|
|
});
|
|
|
|
it('RippleAPI invalid server uri', function() {
|
|
assert.throws(() => new RippleAPI({servers: ['wss//s:1']}));
|
|
});
|
|
|
|
});
|