From b9c953fce685af0fa451be27e8a4daf9d85a733a Mon Sep 17 00:00:00 2001 From: Elliot Lee Date: Thu, 23 Aug 2018 17:37:02 -0700 Subject: [PATCH] Fix getPaths (#930) * getPaths: * Filter paths correctly * Use correct value when XRP is the destination currency --- src/ledger/pathfind.ts | 36 +++++++++++++++++++------- test/api-test.js | 39 +++++++++++++++++++++++++++++ test/mock-rippled.js | 57 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 120 insertions(+), 12 deletions(-) diff --git a/src/ledger/pathfind.ts b/src/ledger/pathfind.ts index be27a15b..ac127549 100644 --- a/src/ledger/pathfind.ts +++ b/src/ledger/pathfind.ts @@ -1,7 +1,13 @@ import * as _ from 'lodash' import BigNumber from 'bignumber.js' import {getXRPBalance, renameCounterpartyToIssuer} from './utils' -import {validate, toRippledAmount, errors} from '../common' +import { + validate, + toRippledAmount, + errors, + xrpToDrops, + dropsToXrp +} from '../common' import {Connection} from '../common' import parsePathfind from './parse/pathfind' import {RippledAmount, Amount} from '../common/types/objects' @@ -23,7 +29,11 @@ function addParams(request: PathFindRequest, result: RippledPathsResponse function requestPathFind(connection: Connection, pathfind: PathFind ): Promise { const destinationAmount: Amount = _.assign( - {value: '-1'}, + { + // This is converted back to drops by toRippledAmount() + value: pathfind.destination.amount.currency === 'XRP' ? + dropsToXrp('-1') : '-1' + }, pathfind.destination.amount ) const request: PathFindRequest = { @@ -95,13 +105,21 @@ function filterSourceFundsLowPaths(pathfind: PathFind, ): RippledPathsResponse { if (pathfind.source.amount && pathfind.destination.amount.value === undefined && paths.alternatives) { - paths.alternatives = _.filter(paths.alternatives, alt => - !!alt.source_amount && - !!pathfind.source.amount && - // TODO: Returns false when alt.source_amount is a string. Fix? - typeof alt.source_amount !== 'string' && - new BigNumber(alt.source_amount.value).eq(pathfind.source.amount.value) - ) + paths.alternatives = _.filter(paths.alternatives, alt => { + if (!alt.source_amount) { + return false + } + const pathfindSourceAmountValue = new BigNumber( + pathfind.source.amount.currency === 'XRP' ? + xrpToDrops(pathfind.source.amount.value) : + pathfind.source.amount.value) + const altSourceAmountValue = new BigNumber( + typeof alt.source_amount === 'string' ? + alt.source_amount : + alt.source_amount.value + ) + return altSourceAmountValue.eq(pathfindSourceAmountValue) + }) } return paths } diff --git a/test/api-test.js b/test/api-test.js index 5f895f9f..68340a21 100644 --- a/test/api-test.js +++ b/test/api-test.js @@ -2328,6 +2328,45 @@ describe('RippleAPI', function () { _.partial(checkResult, responses.getPaths.XrpToUsd, 'getPaths')); }); + it('getPaths - result path has source_amount in drops', function () { + return this.api.getPaths({ + source: { + address: 'rB2NTuTTS3eNCsWxZYzJ4wqRqxNLZqA9Vx', + amount: { + value: this.api.dropsToXrp(1000000), + currency: 'XRP' + } + }, + destination: { + address: 'rhpJkBfZGQyT1xeDbwtKEuSrSXw3QZSAy5', + amount: { + counterparty: 'rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u', + currency: 'EUR' + } + } + }).then( + _.partial(checkResult, [ + { + "source": { + "address": "rB2NTuTTS3eNCsWxZYzJ4wqRqxNLZqA9Vx", + "amount": { + "currency": "XRP", + "value": "1" + } + }, + "destination": { + "address": "rhpJkBfZGQyT1xeDbwtKEuSrSXw3QZSAy5", + "minAmount": { + "currency": "EUR", + "value": "1", + "counterparty": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u" + } + }, + "paths": "[[{\"currency\":\"USD\",\"issuer\":\"rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u\"},{\"currency\":\"EUR\",\"issuer\":\"rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u\"}]]" + } + ], 'getPaths')); + }); + it('getPaths - queuing', function () { return Promise.all([ this.api.getPaths(requests.getPaths.normal), diff --git a/test/mock-rippled.js b/test/mock-rippled.js index a99de120..2458bba2 100644 --- a/test/mock-rippled.js +++ b/test/mock-rippled.js @@ -485,7 +485,57 @@ module.exports = function createMockRippled(port) { if (request.subcommand === 'close') { // for path_find command return; } - if (request.source_account === addresses.NOTFOUND) { + if (request.source_account === 'rB2NTuTTS3eNCsWxZYzJ4wqRqxNLZqA9Vx') { + // getPaths - result path has source_amount in drops + response = createResponse(request, { + "id": 0, + "type": "response", + "status": "success", + "result": { + "alternatives": [ + { + "destination_amount": { + "currency": "EUR", + "issuer": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u", + "value": "1" + }, + "paths_canonical": [], + "paths_computed": [ + [ + { + "currency": "USD", + "issuer": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u", + "type": 48, + "type_hex": "0000000000000030" + }, + { + "currency": "EUR", + "issuer": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u", + "type": 48, + "type_hex": "0000000000000030" + } + ] + ], + "source_amount": "1000000" + } + ], + "destination_account": "rhpJkBfZGQyT1xeDbwtKEuSrSXw3QZSAy5", + "destination_amount": { + "currency": "EUR", + "issuer": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u", + "value": "-1" + }, + "destination_currencies": [ + "EUR", + "XRP" + ], + "full_reply": true, + "id": 2, + "source_account": "rB2NTuTTS3eNCsWxZYzJ4wqRqxNLZqA9Vx", + "status": "success" + } + }) + } else if (request.source_account === addresses.NOTFOUND) { response = createResponse(request, fixtures.path_find.srcActNotFound); } else if (request.source_account === addresses.SOURCE_LOW_FUNDS) { response = createResponse(request, fixtures.path_find.sourceAmountLow); @@ -497,8 +547,9 @@ module.exports = function createMockRippled(port) { destination_address: request.destination_address }); } else if (request.source_account === addresses.ACCOUNT) { - if (request.destination_account === - 'ra5nK24KXen9AHvsdFTKHSANinZseWnPcX') { + if (request.destination_account === 'ra5nK24KXen9AHvsdFTKHSANinZseWnPcX' && + // Important: Ensure that destination_amount.value is correct + request.destination_amount.value === "-1") { response = createResponse(request, fixtures.path_find.sendAll); } else { response = fixtures.path_find.generate.generateIOUPaymentPaths(