diff --git a/src/api/common/constants.js b/src/api/common/constants.js index d6f88c0a..655e0b53 100644 --- a/src/api/common/constants.js +++ b/src/api/common/constants.js @@ -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 = { diff --git a/src/api/common/core.js b/src/api/common/core.js deleted file mode 100644 index c0d333b0..00000000 --- a/src/api/common/core.js +++ /dev/null @@ -1,2 +0,0 @@ -'use strict'; -module.exports = require('../../core'); diff --git a/src/api/common/index.js b/src/api/common/index.js index 5c8c7266..d0f65988 100644 --- a/src/api/common/index.js +++ b/src/api/common/index.js @@ -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, diff --git a/src/api/common/schema-validator.js b/src/api/common/schema-validator.js index 4dabcbea..35c9dbc1 100644 --- a/src/api/common/schema-validator.js +++ b/src/api/common/schema-validator.js @@ -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 = {}; diff --git a/src/api/common/server.js b/src/api/common/server.js deleted file mode 100644 index 3897583c..00000000 --- a/src/api/common/server.js +++ /dev/null @@ -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 -}; diff --git a/src/api/common/utils.js b/src/api/common/utils.js index 7ada879c..71f9b1f6 100644 --- a/src/api/common/utils.js +++ b/src/api/common/utils.js @@ -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, diff --git a/src/api/common/validate.js b/src/api/common/validate.js index 004450f8..e1f5a3f8 100644 --- a/src/api/common/validate.js +++ b/src/api/common/validate.js @@ -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); diff --git a/src/api/index.js b/src/api/index.js index d38d0f61..27520f85 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -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, diff --git a/src/api/ledger/utils.js b/src/api/ledger/utils.js index b6048853..3e805e4d 100644 --- a/src/api/ledger/utils.js +++ b/src/api/ledger/utils.js @@ -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 diff --git a/src/api/server/server.js b/src/api/server/server.js index cfed1d42..8c3d54f3 100644 --- a/src/api/server/server.js +++ b/src/api/server/server.js @@ -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 }; diff --git a/src/api/transaction/settings.js b/src/api/transaction/settings.js index d8cb791c..84811943 100644 --- a/src/api/transaction/settings.js +++ b/src/api/transaction/settings.js @@ -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. diff --git a/src/api/transaction/utils.js b/src/api/transaction/utils.js index df25c3ff..0568e211 100644 --- a/src/api/transaction/utils.js +++ b/src/api/transaction/utils.js @@ -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) { diff --git a/test/api-test.js b/test/api-test.js index 24541a9e..38cc0fc2 100644 --- a/test/api-test.js +++ b/test/api-test.js @@ -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(); + }); + }); }); diff --git a/test/fixtures/get-server-info-response.json b/test/fixtures/get-server-info-response.json new file mode 100644 index 00000000..b45b337d --- /dev/null +++ b/test/fixtures/get-server-info-response.json @@ -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 + } +}