From 47a87f3a92c25101e216a7772ff87bbb8928a4e4 Mon Sep 17 00:00:00 2001 From: Chris Clark Date: Wed, 24 Jun 2015 12:18:56 -0700 Subject: [PATCH] Update getBalances to use getTrustlines --- src/api/common/index.js | 3 +- src/api/common/utils.js | 13 +- src/api/ledger/balances.js | 183 ++++--------------- test/fixtures/balances-response.json | 257 +++++++++++++-------------- 4 files changed, 171 insertions(+), 285 deletions(-) diff --git a/src/api/common/index.js b/src/api/common/index.js index f922e4fc..5c8c7266 100644 --- a/src/api/common/index.js +++ b/src/api/common/index.js @@ -10,5 +10,6 @@ module.exports = { dropsToXrp: utils.dropsToXrp, xrpToDrops: utils.xrpToDrops, toRippledAmount: utils.toRippledAmount, - wrapCatch: utils.wrapCatch + wrapCatch: utils.wrapCatch, + composeAsync: utils.composeAsync }; diff --git a/src/api/common/utils.js b/src/api/common/utils.js index 2ea76bd5..7ada879c 100644 --- a/src/api/common/utils.js +++ b/src/api/common/utils.js @@ -31,9 +31,20 @@ function wrapCatch(asyncFunction: () => void): () => void { }; } +function composeAsync(wrapper, callback) { + return function(error, data) { + if (error) { + callback(error); + return; + } + callback(null, wrapper(data)); + }; +} + module.exports = { dropsToXrp, xrpToDrops, toRippledAmount, - wrapCatch + wrapCatch, + composeAsync }; diff --git a/src/api/ledger/balances.js b/src/api/ledger/balances.js index 9c1989ba..f3bd9bf6 100644 --- a/src/api/ledger/balances.js +++ b/src/api/ledger/balances.js @@ -1,164 +1,43 @@ -/* globals Promise: true */ -/* eslint-disable valid-jsdoc */ 'use strict'; +const _ = require('lodash'); +const async = require('async'); const utils = require('./utils'); +const getTrustlines = require('./trustlines').getTrustlines; const validate = utils.common.validate; +const composeAsync = utils.common.composeAsync; +const dropsToXrp = utils.common.dropsToXrp; -const DefaultPageLimit = 200; +function getXRPBalance(remote, address, ledgerVersion, callback) { + remote.requestAccountInfo({account: address, ledger: ledgerVersion}, + composeAsync((data) => dropsToXrp(data.account_data.Balance), callback)); +} + +function parseBalanceAmount(trustline) { + return { + currency: trustline.specification.currency, + counterparty: trustline.specification.counterparty, + value: trustline.state.balance + }; +} + +function formatBalances(balances) { + const xrpBalance = { + currency: 'XRP', + value: balances[0] + }; + return [xrpBalance].concat(balances[1].map(parseBalanceAmount)); +} -/** - * Request the balances for a given account - * - * Notes: - * In order to use paging, you must provide at least ledger as a query - * parameter. Additionally, any limit lower than 10 will be bumped up to 10. - * - * @url - * @param {RippleAddress} request.params.account - * - account to retrieve balances for - * - * @query - * @param {String ISO 4217 Currency Code} [request.query.currency] - * - only request balances with given currency - * @param {RippleAddress} [request.query.counterparty] - * - only request balances with given counterparty - * @param {String} [request.query.marker] - start position in response paging - * @param {Number String} [request.query.limit] - max results per response - * @param {Number String} [request.query.ledger] - identifier - * - */ function getBalances(account, options, callback) { validate.address(account); validate.options(options); - const self = this; - - const currencyRE = new RegExp(options.currency ? - ('^' + options.currency.toUpperCase() + '$') : /./); - - function getXRPBalance() { - const promise = new Promise(function(resolve, reject) { - const accountInfoRequest = self.remote.requestAccountInfo({ - account: account, - ledger: utils.parseLedger(options.ledger) - }); - - const lines = []; - accountInfoRequest.once('error', reject); - accountInfoRequest.once('success', function(result) { - lines.push({ - value: utils.common.dropsToXrp(result.account_data.Balance), - currency: 'XRP', - counterparty: '' - }); - - result.lines = lines; - resolve(result); - }); - - accountInfoRequest.request(); - }); - - return promise; - } - - function getLineBalances(prevResult) { - const isAggregate = options.limit === undefined; - if (prevResult && (!isAggregate || !prevResult.marker)) { - return Promise.resolve(prevResult); - } - - const promise = new Promise(function(resolve, reject) { - let accountLinesRequest; - let marker; - let ledger; - let limit; - - if (prevResult) { - marker = prevResult.marker; - limit = prevResult.limit; - ledger = prevResult.ledger_index; - } else { - marker = options.marker; - limit = options.limit || DefaultPageLimit; - ledger = utils.parseLedger(options.ledger); - } - - accountLinesRequest = self.remote.requestAccountLines({ - account: account, - marker: marker, - limit: limit, - ledger: ledger - }); - - if (options.counterparty) { - accountLinesRequest.message.peer = options.counterparty; - } - - accountLinesRequest.once('error', reject); - accountLinesRequest.once('success', function(nextResult) { - const lines = []; - nextResult.lines.forEach(function(line) { - if (options.frozen && !line.freeze) { - return; - } - - if (currencyRE.test(line.currency)) { - lines.push({ - value: line.balance, - currency: line.currency, - counterparty: line.account - }); - } - }); - - nextResult.lines = prevResult ? prevResult.lines.concat(lines) : lines; - resolve(nextResult); - }); - accountLinesRequest.request(); - }); - - return promise.then(getLineBalances); - } - - function getAccountBalances() { - if (options.counterparty || options.frozen) { - return getLineBalances(); - } - - if (options.currency) { - if (options.currency === 'XRP') { - return getXRPBalance(); - } - return getLineBalances(); - } - - return Promise.all([getXRPBalance(), getLineBalances()]) - .then(function(values) { - const xrpBalance = values[0].lines[0]; - const lineBalances = values[1]; - lineBalances.lines.unshift(xrpBalance); - return Promise.resolve(lineBalances); - }); - } - - function respondWithBalances(result) { - let balances = {}; - - if (result.marker) { - balances.marker = result.marker; - } - - balances.limit = result.limit; - balances.ledger = result.ledger_index; - balances.balances = result.lines; - - callback(null, balances); - } - - getAccountBalances() - .then(respondWithBalances) - .catch(callback); + const ledgerVersion = options.ledgerVersion + || this.remote.getLedgerSequence(); + async.parallel([ + _.partial(getXRPBalance, this.remote, account, ledgerVersion), + _.partial(getTrustlines.bind(this), account, options) + ], composeAsync(formatBalances, callback)); } module.exports.getBalances = getBalances; diff --git a/test/fixtures/balances-response.json b/test/fixtures/balances-response.json index daed312a..9625e989 100644 --- a/test/fixtures/balances-response.json +++ b/test/fixtures/balances-response.json @@ -1,131 +1,126 @@ -{ - "limit": 200, - "ledger": 8819951, - "balances": [ - { - "value": "922.913243", - "currency": "XRP", - "counterparty": "" - }, - { - "value": "0", - "currency": "ASP", - "counterparty": "r3vi7mWxru9rJCxETCyA1CHvzL96eZWx5z" - }, - { - "value": "0", - "currency": "XAU", - "counterparty": "r3vi7mWxru9rJCxETCyA1CHvzL96eZWx5z" - }, - { - "value": "2.497605752725159", - "currency": "USD", - "counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q" - }, - { - "value": "481.992867407479", - "currency": "MXN", - "counterparty": "rHpXfibHgSb64n8kK9QWDpdbfqSpYbM9a4" - }, - { - "value": "0.793598266778297", - "currency": "EUR", - "counterparty": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun" - }, - { - "value": "0", - "currency": "CNY", - "counterparty": "rnuF96W4SZoCJmbHYBFoJZpR8eCaxNvekK" - }, - { - "value": "1.294889190631542", - "currency": "DYM", - "counterparty": "rGwUWgN5BEg3QGNY3RX2HfYowjUTZdid3E" - }, - { - "value": "0.3488146605801446", - "currency": "CHF", - "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" - }, - { - "value": "2.114103174931847", - "currency": "BTC", - "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" - }, - { - "value": "0", - "currency": "USD", - "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" - }, - { - "value": "-0.00111", - "currency": "BTC", - "counterparty": "rpgKWEmNqSDAGFhy5WDnsyPqfQxbWxKeVd" - }, - { - "value": "-0.1010780000080207", - "currency": "BTC", - "counterparty": "rBJ3YjwXi2MGbg7GVLuTXUWQ8DjL7tDXh4" - }, - { - "value": "1", - "currency": "USD", - "counterparty": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun" - }, - { - "value": "8.07619790068559", - "currency": "CNY", - "counterparty": "razqQKzJRdB4UxFPWf5NEpEG3WMkmwgcXA" - }, - { - "value": "7.292695098901099", - "currency": "JPY", - "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" - }, - { - "value": "0", - "currency": "AUX", - "counterparty": "r3vi7mWxru9rJCxETCyA1CHvzL96eZWx5z" - }, - { - "value": "0", - "currency": "USD", - "counterparty": "r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X" - }, - { - "value": "12.41688780720394", - "currency": "EUR", - "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" - }, - { - "value": "35", - "currency": "USD", - "counterparty": "rfF3PNkwkq1DygW2wum2HK3RGfgkJjdPVD" - }, - { - "value": "-5", - "currency": "JOE", - "counterparty": "rwUVoVMSURqNyvocPCcvLu3ygJzZyw8qwp" - }, - { - "value": "0", - "currency": "USD", - "counterparty": "rE6R3DWF9fBD7CyiQciePF9SqK58Ubp8o2" - }, - { - "value": "0", - "currency": "JOE", - "counterparty": "rE6R3DWF9fBD7CyiQciePF9SqK58Ubp8o2" - }, - { - "value": "0", - "currency": "015841551A748AD2C1F76FF6ECB0CCCD00000000", - "counterparty": "rs9M85karFkCRjvc6KMWn8Coigm9cbcgcx" - }, - { - "value": "0", - "currency": "USD", - "counterparty": "rEhDDUUNxpXgEHVJtC2cjXAgyx5VCFxdMF" - } - ] -} +[ + { + "value": "922.913243", + "currency": "XRP" + }, + { + "value": "0", + "currency": "ASP", + "counterparty": "r3vi7mWxru9rJCxETCyA1CHvzL96eZWx5z" + }, + { + "value": "0", + "currency": "XAU", + "counterparty": "r3vi7mWxru9rJCxETCyA1CHvzL96eZWx5z" + }, + { + "value": "2.497605752725159", + "currency": "USD", + "counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q" + }, + { + "value": "481.992867407479", + "currency": "MXN", + "counterparty": "rHpXfibHgSb64n8kK9QWDpdbfqSpYbM9a4" + }, + { + "value": "0.793598266778297", + "currency": "EUR", + "counterparty": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun" + }, + { + "value": "0", + "currency": "CNY", + "counterparty": "rnuF96W4SZoCJmbHYBFoJZpR8eCaxNvekK" + }, + { + "value": "1.294889190631542", + "currency": "DYM", + "counterparty": "rGwUWgN5BEg3QGNY3RX2HfYowjUTZdid3E" + }, + { + "value": "0.3488146605801446", + "currency": "CHF", + "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" + }, + { + "value": "2.114103174931847", + "currency": "BTC", + "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" + }, + { + "value": "0", + "currency": "USD", + "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" + }, + { + "value": "-0.00111", + "currency": "BTC", + "counterparty": "rpgKWEmNqSDAGFhy5WDnsyPqfQxbWxKeVd" + }, + { + "value": "-0.1010780000080207", + "currency": "BTC", + "counterparty": "rBJ3YjwXi2MGbg7GVLuTXUWQ8DjL7tDXh4" + }, + { + "value": "1", + "currency": "USD", + "counterparty": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun" + }, + { + "value": "8.07619790068559", + "currency": "CNY", + "counterparty": "razqQKzJRdB4UxFPWf5NEpEG3WMkmwgcXA" + }, + { + "value": "7.292695098901099", + "currency": "JPY", + "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" + }, + { + "value": "0", + "currency": "AUX", + "counterparty": "r3vi7mWxru9rJCxETCyA1CHvzL96eZWx5z" + }, + { + "value": "0", + "currency": "USD", + "counterparty": "r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X" + }, + { + "value": "12.41688780720394", + "currency": "EUR", + "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" + }, + { + "value": "35", + "currency": "USD", + "counterparty": "rfF3PNkwkq1DygW2wum2HK3RGfgkJjdPVD" + }, + { + "value": "-5", + "currency": "JOE", + "counterparty": "rwUVoVMSURqNyvocPCcvLu3ygJzZyw8qwp" + }, + { + "value": "0", + "currency": "USD", + "counterparty": "rE6R3DWF9fBD7CyiQciePF9SqK58Ubp8o2" + }, + { + "value": "0", + "currency": "JOE", + "counterparty": "rE6R3DWF9fBD7CyiQciePF9SqK58Ubp8o2" + }, + { + "value": "0", + "currency": "015841551A748AD2C1F76FF6ECB0CCCD00000000", + "counterparty": "rs9M85karFkCRjvc6KMWn8Coigm9cbcgcx" + }, + { + "value": "0", + "currency": "USD", + "counterparty": "rEhDDUUNxpXgEHVJtC2cjXAgyx5VCFxdMF" + } +]