Convert server methods, add unit tests, and cleanup

This commit is contained in:
Chris Clark
2015-07-01 15:42:32 -07:00
parent 4efe0b920e
commit 32ca23a00b
14 changed files with 77 additions and 223 deletions

View File

@@ -1,5 +1,5 @@
'use strict';
const Transaction = require('./core').Transaction;
const Transaction = require('./utils').core.Transaction;
const flagIndices = Transaction.set_clear_flags.AccountSet;
const AccountFlagIndices = {

View File

@@ -1,2 +0,0 @@
'use strict';
module.exports = require('../../core');

View File

@@ -2,11 +2,10 @@
const utils = require('./utils');
module.exports = {
core: require('./core'),
core: utils.core,
constants: require('./constants'),
errors: require('./errors'),
validate: require('./validate'),
server: require('./server'),
dropsToXrp: utils.dropsToXrp,
xrpToDrops: utils.xrpToDrops,
toRippledAmount: utils.toRippledAmount,

View File

@@ -3,7 +3,7 @@ const _ = require('lodash');
const fs = require('fs');
const path = require('path');
const validator = require('is-my-json-valid');
const ripple = require('./core');
const ripple = require('./utils').core;
const ValidationError = require('./errors').ValidationError;
let SCHEMAS = {};

View File

@@ -1,116 +0,0 @@
/* eslint-disable valid-jsdoc */
'use strict';
const async = require('async');
/**
* If a ledger is not received in this time, consider the connection offline
*/
const CONNECTION_TIMEOUT = 1000 * 30;
/**
* Determine if remote is connected based on time of last ledger closed
*
* @param {Server} server
* @return {Boolean}
*/
function isConnected(remote) {
if (isNaN(remote._ledger_current_index)) {
// Remote is missing the index of last ledger closed. Unprepared to submit
// transactions
return false;
}
const server = remote.getServer();
if (!server) {
return false;
}
if (remote._stand_alone) {
// If rippled is in standalone mode we can assume there will not be a
// ledger close within 30 seconds.
return true;
}
return (Date.now() - server._lastLedgerClose) <= CONNECTION_TIMEOUT;
}
/**
* Check if remote is connected and attempt to reconnect if not
*
* @param {Remote} remote
* @param {Function} callback
*/
function ensureConnected(remote, callback) {
if (remote.getServer()) {
callback(null, isConnected(remote));
} else {
callback(null, false);
}
}
/**
* @param {Remote} remote
* @param {Function} callback
*/
function getStatus(remote, callback) {
function checkConnectivity(_callback) {
ensureConnected(remote, _callback);
}
function requestServerInfo(connected, _callback) {
remote.requestServerInfo(_callback);
}
function prepareResponse(server_info, _callback) {
const results = { };
results.rippled_server_url = remote.getServer()._url;
results.rippled_server_status = server_info.info;
_callback(null, results);
}
const steps = [
checkConnectivity,
requestServerInfo,
prepareResponse
];
async.waterfall(steps, callback);
}
/**
* @param {Remote} remote
* @param {Number|String} ledger
* @param {Function} callback
*/
function remoteHasLedger(remote, ledger, callback) {
const ledger_index = Number(ledger);
function handleStatus(err, status) {
if (err) {
return callback(err);
}
const ledger_range = status.rippled_server_status.complete_ledgers;
const match = ledger_range.match(/([0-9]+)-([0-9]+)$/);
const min = Number(match[1]);
const max = Number(match[2]);
if (ledger_index >= min && ledger_index <= max) {
callback(null, true);
} else {
callback(null, false);
}
}
getStatus(remote, handleStatus);
}
module.exports = {
CONNECTION_TIMEOUT: CONNECTION_TIMEOUT,
getStatus: getStatus,
isConnected: isConnected,
ensureConnected: ensureConnected,
remoteHasLedger: remoteHasLedger
};

View File

@@ -1,5 +1,6 @@
'use strict';
const BigNumber = require('bignumber.js');
const core = require('../../core');
function dropsToXrp(drops) {
return (new BigNumber(drops)).dividedBy(1000000.0).toString();
@@ -42,6 +43,7 @@ function composeAsync(wrapper, callback) {
}
module.exports = {
core,
dropsToXrp,
xrpToDrops,
toRippledAmount,

View File

@@ -2,7 +2,7 @@
const _ = require('lodash');
const ValidationError = require('./errors').ValidationError;
const schemaValidate = require('./schema-validator');
const ripple = require('./core');
const ripple = require('./utils').core;
function error(text) {
return new ValidationError(text);

View File

@@ -2,9 +2,10 @@
const ripple = require('./common').core;
const server = require('./server/server');
const connect = server.connect;
// const getServerStatus = server.getServerStatus;
// const getFee = server.getFee;
// const isConnected = server.isConnected;
const disconnect = server.disconnect;
const getServerInfo = server.getServerInfo;
const getFee = server.getFee;
const isConnected = server.isConnected;
const getTransaction = require('./ledger/transaction');
const getAccountTransactions = require('./ledger/transactions');
const getTrustlines = require('./ledger/trustlines');
@@ -29,9 +30,10 @@ function RippleAPI(options) {
RippleAPI.prototype = {
connect,
// getServerStatus,
// getFee,
// isConnected,
disconnect,
isConnected,
getServerInfo,
getFee,
getTransaction,
getAccountTransactions,

View File

@@ -1,10 +1,6 @@
/* eslint-disable valid-jsdoc */
'use strict';
const _ = require('lodash');
const async = require('async');
const asyncify = require('simple-asyncify');
const common = require('../common');
const ripple = common.core;
// If the marker is omitted from a response, you have reached the end
// getter(marker, limit, callback), callback(error, {marker, results})
@@ -46,26 +42,6 @@ function renameCounterpartyToIssuerInOrder(order) {
return _.assign({}, order, _.omit(changes, _.isUndefined));
}
function isValidHash256(hash) {
return ripple.UInt256.is_valid(hash);
}
function parseLedger(ledger) {
if (/^current$|^closed$|^validated$/.test(ledger)) {
return ledger;
}
if (ledger && Number(ledger) >= 0 && isFinite(Number(ledger))) {
return Number(ledger);
}
if (isValidHash256(ledger)) {
return ledger;
}
return 'validated';
}
function signum(num) {
return (num === 0) ? 0 : (num > 0 ? 1 : -1);
}
@@ -87,41 +63,10 @@ function compareTransactions(first, second) {
return Number(first.ledgerVersion) < Number(second.ledgerVersion) ? -1 : 1;
}
function attachDate(api, baseTransactions, callback) {
const groupedTx = _.groupBy(baseTransactions, function(tx) {
return tx.ledger_index;
});
function attachDateToTransactions(transactions, data) {
return _.map(transactions, function(tx) {
return _.assign(tx, {date: data.ledger.close_time});
});
}
function getLedger(ledgerIndex, _callback) {
api.remote.requestLedger({ledger_index: ledgerIndex}, _callback);
}
function attachDateToLedgerTransactions(_groupedTx, ledger, _callback) {
const transactions = _groupedTx[ledger];
async.waterfall([
_.partial(getLedger, Number(ledger)),
asyncify(_.partial(attachDateToTransactions, transactions))
], _callback);
}
const ledgers = _.keys(groupedTx);
const flatMap = async.seq(async.map, asyncify(_.flatten));
const iterator = _.partial(attachDateToLedgerTransactions, groupedTx);
flatMap(ledgers, iterator, callback);
}
module.exports = {
parseLedger: parseLedger,
compareTransactions: compareTransactions,
renameCounterpartyToIssuer: renameCounterpartyToIssuer,
renameCounterpartyToIssuerInOrder: renameCounterpartyToIssuerInOrder,
attachDate: attachDate,
getRecursive: getRecursive,
wrapCatch: common.wrapCatch,
common: common

View File

@@ -1,33 +1,45 @@
'use strict';
const common = require('../common');
// If a ledger is not received in this time, consider the connection offline
const CONNECTION_TIMEOUT = 1000 * 30;
function connect(callback) {
this.remote.connect(callback);
}
function isConnected() {
return common.server.isConnected(this.remote);
function disconnect(callback) {
this.remote.disconnect(callback);
}
function getServerStatus(callback) {
common.server.getStatus(this.remote, function(error, status) {
function isUpToDate(remote) {
const server = remote.getServer();
return Boolean(server) && (remote._stand_alone
|| (Date.now() - server._lastLedgerClose) <= CONNECTION_TIMEOUT);
}
function isConnected() {
return Boolean(this.remote._ledger_current_index) && isUpToDate(this.remote);
}
function getServerInfo(callback) {
this.remote.requestServerInfo((error, info) => {
if (error) {
callback(new common.errors.RippledNetworkError(error.message));
} else {
callback(null, status);
callback(null, info);
}
});
}
function getFee(callback) {
const fee = this.remote.createTransaction()._computeFee();
callback(null, {fee: common.dropsToXrp(fee)});
function getFee() {
return common.dropsToXrp(this.remote.createTransaction()._computeFee());
}
module.exports = {
connect: connect,
disconnect: disconnect,
isConnected: isConnected,
getServerStatus: getServerStatus,
getServerInfo: getServerInfo,
getFee: getFee
};

View File

@@ -1,5 +1,4 @@
/* @flow */
/* eslint-disable valid-jsdoc */
'use strict';
const _ = require('lodash');
const assert = require('assert');
@@ -28,16 +27,6 @@ function setTransactionFlags(transaction, values) {
}
}
/**
* Set fields on a transaction based on input and fields schema object
*
* @param {Transaction} transaction
* @param {Object} input - Object whose properties are used to set fields on
* the transaction
* @param {Object} fieldSchema - Object that holds the schema of each field
*
* @returns undefined
*/
function setTransactionFields(transaction, input) {
const fieldSchema = AccountFields;
for (const fieldName in fieldSchema) {
@@ -78,8 +67,6 @@ function setTransactionFields(transaction, input) {
}
/**
* Convert a numerical transfer rate in ripple-rest format to ripple-lib
*
* Note: A fee of 1% requires 101% of the destination to be sent for the
* destination to receive 100%.
* The transfer rate is specified as the input amount as fraction of 1.

View File

@@ -1,24 +1,8 @@
/* @flow */
/* eslint-disable valid-jsdoc */
'use strict';
const BigNumber = require('bignumber.js');
const common = require('../common');
/**
* Helper that sets bit flags on transactions
*
* @param {Transaction} transaction - Transaction object that is used to submit
* requests to ripple
* @param {Object} options
* @param {Object} options.flags - Holds flag names to set on transaction when
* parameter values are true or false on input
* @param {Object} options.input - Holds parameter values
* @param {String} options.clear_setting - Used to check if parameter values
* besides false mean false
*
*
* @returns undefined
*/
function setTransactionBitFlags(transaction: any, values: any, flags: any):
void {
for (const flagName in flags) {

View File

@@ -29,6 +29,7 @@ const walletResponse = require('./fixtures/wallet.json');
const getSettingsResponse = require('./fixtures/get-settings-response');
const getOrdersResponse = require('./fixtures/get-orders-response');
const getOrderBookResponse = require('./fixtures/get-orderbook-response');
const getServerInfoResponse = require('./fixtures/get-server-info-response');
function checkResult(expected, done, error, response) {
if (error) {
@@ -153,4 +154,20 @@ describe('RippleAPI', function() {
this.api.getOrderBook(address, orderbook, {},
_.partial(checkResult, getOrderBookResponse, done));
});
it('getServerInfo', function(done) {
this.api.getServerInfo(_.partial(checkResult, getServerInfoResponse, done));
});
it('getFee', function() {
assert.strictEqual(this.api.getFee(), '0.000012');
});
it('disconnect & isConnected', function(done) {
assert.strictEqual(this.api.isConnected(), true);
this.api.disconnect(() => {
assert.strictEqual(this.api.isConnected(), false);
done();
});
});
});

View File

@@ -0,0 +1,24 @@
{
"info": {
"build_version": "0.24.0-rc1",
"complete_ledgers": "32570-6595042",
"hostid": "ARTS",
"last_close": {
"converge_time_s": 2.007,
"proposers": 4
},
"load_factor": 1,
"peers": 53,
"pubkey_node": "n94wWvFUmaKGYrKUGgpv1DyYgDeXRGdACkNQaSe7zJiy5Znio7UC",
"server_state": "full",
"validated_ledger": {
"age": 5,
"base_fee_xrp": 0.00001,
"hash": "4482DEE5362332F54A4036ED57EE1767C9F33CF7CE5A6670355C16CECE381D46",
"reserve_base_xrp": 20,
"reserve_inc_xrp": 5,
"seq": 6595042
},
"validation_quorum": 3
}
}