diff --git a/src/api/ledger/pathfind.js b/src/api/ledger/pathfind.js index f895d75f..e3a1084d 100644 --- a/src/api/ledger/pathfind.js +++ b/src/api/ledger/pathfind.js @@ -46,7 +46,7 @@ function requestPathFind(remote, pathfind: PathFind, callback) { _.omit(utils.common.toRippledAmount(amount), 'value')); } - remote.requestRipplePathFind(params, + remote.createPathFind(params, composeAsync(_.partial(addParams, params), callback)); } diff --git a/src/core/pathfind.js b/src/core/pathfind.js index a1e994d1..afae384a 100644 --- a/src/core/pathfind.js +++ b/src/core/pathfind.js @@ -59,7 +59,8 @@ PathFind.prototype.create = function() { }; PathFind.prototype.close = function() { - this.remote.request_path_find_close().broadcast().request(); + this.removeAllListeners('update'); + this.remote.requestPathFindClose().broadcast().request(); this.emit('end'); this.emit('close'); }; @@ -73,7 +74,7 @@ PathFind.prototype.notify_update = function(message) { // looking for. if (this.src_account === src_account && this.dst_account === dst_account && - this.dst_amount.equals(dst_amount)) { + dst_amount.equals(this.dst_amount)) { this.emit('update', message); } }; diff --git a/src/core/remote.js b/src/core/remote.js index bb67588e..9bd762b5 100644 --- a/src/core/remote.js +++ b/src/core/remote.js @@ -65,6 +65,7 @@ function Remote(options = {}) { this._transaction_listeners = 0; this._received_tx = new LRU({max: 100}); this._cur_path_find = null; + this._queued_path_finds = []; if (this.local_signing) { // Local signing implies local fees and sequences @@ -1934,9 +1935,14 @@ Remote.prototype.findAccount = function(accountID) { * @return {PathFind} */ -function createPathFind(options_) { +function createPathFind(options_, callback) { const options = {}; + if (this._cur_path_find !== null) { + this._queued_path_finds.push({options: options_, callback: callback}); + return null; + } + if (_.isPlainObject(options_)) { _.merge(options, options_); } else { @@ -1955,10 +1961,21 @@ function createPathFind(options_) { this._cur_path_find.notify_superceded(); } - pathFind.create(); + if (callback) { + pathFind.on('update', (data) => { + if (data.full_reply) { + pathFind.close(); + callback(null, data); + } + }); + pathFind.on('error', (error) => { + pathFind.close(); + callback(error); + }); + } this._cur_path_find = pathFind; - + pathFind.create(); return pathFind; } @@ -2369,6 +2386,11 @@ Remote.prototype.requestPathFindClose = function(callback) { request.message.subcommand = 'close'; request.callback(callback); + this._cur_path_find = null; + if (this._queued_path_finds.length > 0) { + const pathfind = this._queued_path_finds.shift(); + this.createPathFind(pathfind.options, pathfind.callback); + } return request; }; diff --git a/test/fixtures/api/requests/getpaths/xrp2xrp-not-enough.json b/test/fixtures/api/requests/getpaths/xrp2xrp-not-enough.json index 202f136c..e912e0ff 100644 --- a/test/fixtures/api/requests/getpaths/xrp2xrp-not-enough.json +++ b/test/fixtures/api/requests/getpaths/xrp2xrp-not-enough.json @@ -1,12 +1,12 @@ -{ - "source": { - "address": "rwBYyfufTzk77zUSKEu4MvixfarC35av1J" - }, - "destination": { - "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", - "amount": { - "value": "1000002", - "currency": "XRP" - } - } -} \ No newline at end of file +{ + "source": { + "address": "rwBYyfufTzk77zUSKEu4MvixfarC35av1J" + }, + "destination": { + "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "amount": { + "value": "1000002", + "currency": "XRP" + } + } +} diff --git a/test/fixtures/api/requests/getpaths/xrp2xrp.json b/test/fixtures/api/requests/getpaths/xrp2xrp.json index a9cc116c..51709a93 100644 --- a/test/fixtures/api/requests/getpaths/xrp2xrp.json +++ b/test/fixtures/api/requests/getpaths/xrp2xrp.json @@ -9,4 +9,4 @@ "currency": "XRP" } } -} \ No newline at end of file +} diff --git a/test/fixtures/api/rippled/index.js b/test/fixtures/api/rippled/index.js index 714318ee..88312022 100644 --- a/test/fixtures/api/rippled/index.js +++ b/test/fixtures/api/rippled/index.js @@ -16,10 +16,10 @@ module.exports = { book_offers: require('./book-offers'), server_info: require('./server-info'), server_info_error: require('./server-info-error'), - ripple_path_find: { - generate: require('./ripple-path-find'), - sendUSD: require('./ripple-path-find-send-usd'), - XrpToXrp: require('./ripple-path-find-xrp-to-xrp') + path_find: { + generate: require('./path-find'), + sendUSD: require('./path-find-send-usd'), + XrpToXrp: require('./path-find-xrp-to-xrp') }, tx: { Payment: require('./tx/payment.json'), diff --git a/test/fixtures/api/rippled/ripple-path-find-send-usd.json b/test/fixtures/api/rippled/path-find-send-usd.json similarity index 91% rename from test/fixtures/api/rippled/ripple-path-find-send-usd.json rename to test/fixtures/api/rippled/path-find-send-usd.json index 47a50dc8..aab3cf9c 100644 --- a/test/fixtures/api/rippled/ripple-path-find-send-usd.json +++ b/test/fixtures/api/rippled/path-find-send-usd.json @@ -1,6 +1,7 @@ { "id": 0, "result": { + "full_reply": true, "alternatives": [ { "paths_canonical": [], @@ -72,6 +73,12 @@ } } ], + "source_account": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + "destination_amount": { + "currency": "USD", + "value": "0.000001", + "issuer": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59" + }, "destination_account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", "destination_currencies": [ "JOE", diff --git a/test/fixtures/api/rippled/ripple-path-find-xrp-to-xrp.json b/test/fixtures/api/rippled/path-find-xrp-to-xrp.json similarity index 75% rename from test/fixtures/api/rippled/ripple-path-find-xrp-to-xrp.json rename to test/fixtures/api/rippled/path-find-xrp-to-xrp.json index 797500c2..6ca3ab54 100644 --- a/test/fixtures/api/rippled/ripple-path-find-xrp-to-xrp.json +++ b/test/fixtures/api/rippled/path-find-xrp-to-xrp.json @@ -1,7 +1,10 @@ { "id": 1, "result": { + "full_reply": true, "alternatives": [], + "source_account": "rwBYyfufTzk77zUSKEu4MvixfarC35av1J", + "destination_amount": "2", "destination_account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", "destination_currencies": [ "JOE", diff --git a/test/fixtures/api/rippled/ripple-path-find.js b/test/fixtures/api/rippled/path-find.js similarity index 98% rename from test/fixtures/api/rippled/ripple-path-find.js rename to test/fixtures/api/rippled/path-find.js index 3868725a..670e9c22 100644 --- a/test/fixtures/api/rippled/ripple-path-find.js +++ b/test/fixtures/api/rippled/path-find.js @@ -7,6 +7,9 @@ function(request_id, sendingAccount, destinationAccount, destinationAmount) { 'status': 'success', 'type': 'response', 'result': { + 'full_reply': true, + 'source_account': sendingAccount, + 'destination_amount': destinationAmount, 'alternatives': [ { 'paths_canonical': [], @@ -308,6 +311,7 @@ function(request_id, sendingAccount, destinationAccount) { 'status': 'success', 'type': 'response', 'result': { + 'full_reply': true, 'alternatives': [ { 'paths_canonical': [], diff --git a/test/mock-rippled.js b/test/mock-rippled.js index a6d95335..75f3bff6 100644 --- a/test/mock-rippled.js +++ b/test/mock-rippled.js @@ -17,8 +17,11 @@ function isBTC(json) { return json === 'BTC' || json === '0000000000000000000000004254430000000000'; } -function createResponse(request, response) { - return JSON.stringify(_.assign({}, response, {id: request.id})); +function createResponse(request, response, overrides={}) { + const result = _.assign({}, response.result, overrides); + const change = response.result && !_.isEmpty(overrides) ? + {id: request.id, result: result} : {id: request.id}; + return JSON.stringify(_.assign({}, response, change)); } module.exports = function(port) { @@ -216,14 +219,20 @@ module.exports = function(port) { } }); - mock.on('request_ripple_path_find', function(request, conn) { + mock.on('request_path_find', function(request, conn) { let response = null; + if (request.subcommand === 'close') { + return; + } if (request.source_account === addresses.OTHER_ACCOUNT) { - response = createResponse(request, fixtures.ripple_path_find.sendUSD); + response = createResponse(request, fixtures.path_find.sendUSD); } else if (request.source_account === addresses.THIRD_ACCOUNT) { - response = createResponse(request, fixtures.ripple_path_find.XrpToXrp); + response = createResponse(request, fixtures.path_find.XrpToXrp, { + destination_amount: request.destination_amount, + destination_address: request.destination_address + }); } else { - response = fixtures.ripple_path_find.generate.generateIOUPaymentPaths( + response = fixtures.path_find.generate.generateIOUPaymentPaths( request.id, request.source_account, request.destination_account, request.destination_amount); }