Filter insufficient source funds paths from pathfind results

When pathfinding with source amount, we need to filter out paths where source
amount is not equal to the specified source amount. This is due to the behavior
of rippled when specifying a source amount during pathfinding.

Example:

 {
  "command": "ripple_path_find",
  "source_account": "rhFQQ4ATC6MDF9ghTq3qAoCsGbGtjnhcXF",
  "destination_account": "rp91GUd5R3Rk3ipqW7XBdtrUJcX8epzGyb",
  "destination_amount": {
    "currency": "EUR",
    "issuer": "rp91GUd5R3Rk3ipqW7XBdtrUJcX8epzGyb",
    "value": -1
  },
  "send_max": {
    "currency": "USD",
    "issuer": "rhFQQ4ATC6MDF9ghTq3qAoCsGbGtjnhcXF",
    "value": "1234567891"
  },
  "id": 2
}
{
  "id": 2,
  "result": {
    "alternatives": [
      {
        "destination_amount": {
          "currency": "EUR",
          "issuer": "rp91GUd5R3Rk3ipqW7XBdtrUJcX8epzGyb",
          "value": "3999889.62127857"
        },
        "paths_canonical": [],
        "paths_computed": [
          [
            {
              "account": "rcsxQxEqU2qquAKp3tBUJy8Z2t19ioQPJ",
              "type": 1,
              "type_hex": "0000000000000001"
            },
            {
              "currency": "EUR",
              "issuer": "rp91GUd5R3Rk3ipqW7XBdtrUJcX8epzGyb",
              "type": 48,
              "type_hex": "0000000000000030"
            }
          ]
        ],
        "source_amount": {
          "currency": "USD",
          "issuer": "rhFQQ4ATC6MDF9ghTq3qAoCsGbGtjnhcXF",
          "value": "4170759.906037564"
        }
      }
    ],
    "destination_account": "rp91GUd5R3Rk3ipqW7XBdtrUJcX8epzGyb",
    "destination_amount": {
      "currency": "EUR",
      "issuer": "rp91GUd5R3Rk3ipqW7XBdtrUJcX8epzGyb",
      "value": "-1"
    },
    "destination_currencies": [
      "EUR",
      "XRP"
    ],
    "full_reply": true,
    "id": 2,
    "source_account": "rhFQQ4ATC6MDF9ghTq3qAoCsGbGtjnhcXF",
    "status": "success"
  },
  "status": "success",
  "type": "response"
}
This commit is contained in:
Alan Cohen
2016-01-15 13:03:42 -08:00
parent 0d6aaee12a
commit 6b8cd6151d
8 changed files with 143 additions and 3 deletions

View File

@@ -85,6 +85,20 @@ function conditionallyAddDirectXRPPath(connection: Connection, address: string,
xrpBalance => addDirectXrpPath(paths, xrpBalance)); xrpBalance => addDirectXrpPath(paths, xrpBalance));
} }
function filterSourceFundsLowPaths(pathfind: PathFind,
paths: RippledPathsResponse
): RippledPathsResponse {
if (pathfind.source.amount &&
pathfind.destination.amount.value === undefined && paths.alternatives) {
paths.alternatives = _.filter(paths.alternatives, alt => {
return alt.source_amount &&
pathfind.source.amount &&
alt.source_amount.value === pathfind.source.amount.value;
});
}
return paths;
}
function formatResponse(pathfind: PathFind, paths: RippledPathsResponse) { function formatResponse(pathfind: PathFind, paths: RippledPathsResponse) {
if (paths.alternatives && paths.alternatives.length > 0) { if (paths.alternatives && paths.alternatives.length > 0) {
return parsePathfind(paths); return parsePathfind(paths);
@@ -116,7 +130,9 @@ function getPaths(pathfind: PathFind): Promise<GetPaths> {
const address = pathfind.source.address; const address = pathfind.source.address;
return requestPathFind(this.connection, pathfind).then(paths => return requestPathFind(this.connection, pathfind).then(paths =>
conditionallyAddDirectXRPPath(this.connection, address, paths) conditionallyAddDirectXRPPath(this.connection, address, paths)
).then(paths => formatResponse(pathfind, paths)); )
.then(paths => filterSourceFundsLowPaths(pathfind, paths))
.then(paths => formatResponse(pathfind, paths));
} }
module.exports = getPaths; module.exports = getPaths;

View File

@@ -1049,6 +1049,15 @@ describe('RippleAPI', function() {
}); });
}); });
it('getPaths - no paths source amount', function() {
return this.api.getPaths(requests.getPaths.NoPathsSource).then(() => {
assert(false, 'Should throw NotFoundError');
}).catch(error => {
assert(error instanceof this.api.errors.NotFoundError);
});
});
it('getPaths - no paths with source currencies', function() { it('getPaths - no paths with source currencies', function() {
const pathfind = requests.getPaths.NoPathsWithCurrencies; const pathfind = requests.getPaths.NoPathsWithCurrencies;
return this.api.getPaths(pathfind).then(() => { return this.api.getPaths(pathfind).then(() => {

View File

@@ -6,5 +6,6 @@ module.exports = {
FOURTH_ACCOUNT: 'rJnZ4YHCUsHvQu7R6mZohevKJDHFzVD6Zr', FOURTH_ACCOUNT: 'rJnZ4YHCUsHvQu7R6mZohevKJDHFzVD6Zr',
ISSUER: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM', ISSUER: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM',
NOTFOUND: 'rajTAg3hon5Lcu1RxQQPxTgHvqfhc1EaUS', NOTFOUND: 'rajTAg3hon5Lcu1RxQQPxTgHvqfhc1EaUS',
SECRET: 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' SECRET: 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV',
SOURCE_LOW_FUNDS: 'rhVgDEfS1r1fLyRUZCpab4TdowZcAJwHy2'
}; };

View File

@@ -0,0 +1,13 @@
{
"source": {
"address": "rhVgDEfS1r1fLyRUZCpab4TdowZcAJwHy2",
"amount": {
"value": "1000002",
"currency": "USD"
}
},
"destination": {
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"amount": {"currency": "USD"}
}
}

View File

@@ -53,6 +53,7 @@ module.exports = {
XrpToXrpNotEnough: require('./getpaths/xrp2xrp-not-enough'), XrpToXrpNotEnough: require('./getpaths/xrp2xrp-not-enough'),
NotAcceptCurrency: require('./getpaths/not-accept-currency'), NotAcceptCurrency: require('./getpaths/not-accept-currency'),
NoPaths: require('./getpaths/no-paths'), NoPaths: require('./getpaths/no-paths'),
NoPathsSource: require('./getpaths/no-paths-source-amount'),
NoPathsWithCurrencies: require('./getpaths/no-paths-with-currencies'), NoPathsWithCurrencies: require('./getpaths/no-paths-with-currencies'),
sendAll: require('./getpaths/send-all'), sendAll: require('./getpaths/send-all'),
invalid: require('./getpaths/invalid'), invalid: require('./getpaths/invalid'),

View File

@@ -38,7 +38,8 @@ module.exports = {
sendUSD: require('./path-find-send-usd'), sendUSD: require('./path-find-send-usd'),
sendAll: require('./path-find-send-all'), sendAll: require('./path-find-send-all'),
XrpToXrp: require('./path-find-xrp-to-xrp'), XrpToXrp: require('./path-find-xrp-to-xrp'),
srcActNotFound: require('./path-find-srcActNotFound') srcActNotFound: require('./path-find-srcActNotFound'),
sourceAmountLow: require('./path-find-srcAmtLow')
}, },
tx: { tx: {
Payment: require('./tx/payment.json'), Payment: require('./tx/payment.json'),

View File

@@ -0,0 +1,97 @@
{
"id": 0,
"result": {
"full_reply": true,
"alternatives": [
{
"paths_canonical": [],
"paths_computed": [
[
{
"account": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"type": 1,
"type_hex": "0000000000000001"
}
],
[
{
"account": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"type": 1,
"type_hex": "0000000000000001"
},
{
"account": "rLMJ4db4uwHcd6NHg6jvTaYb8sH5Gy4tg5",
"type": 1,
"type_hex": "0000000000000001"
},
{
"account": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun",
"type": 1,
"type_hex": "0000000000000001"
}
],
[
{
"account": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"type": 1,
"type_hex": "0000000000000001"
},
{
"currency": "USD",
"issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun",
"type": 48,
"type_hex": "0000000000000030"
},
{
"account": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun",
"type": 1,
"type_hex": "0000000000000001"
}
],
[
{
"account": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"type": 1,
"type_hex": "0000000000000001"
},
{
"account": "rLMJ4db4uwHcd6NHg6jvTaYb8sH5Gy4tg5",
"type": 1,
"type_hex": "0000000000000001"
},
{
"account": "r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X",
"type": 1,
"type_hex": "0000000000000001"
}
]
],
"source_amount": {
"currency": "USD",
"issuer": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"value": "0.000001002"
}
}
],
"source_account": "rhVgDEfS1r1fLyRUZCpab4TdowZcAJwHy2",
"destination_amount": {
"currency": "USD",
"value": "-1",
"issuer": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59"
},
"destination_account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"destination_currencies": [
"JOE",
"BTC",
"DYM",
"CNY",
"EUR",
"015841551A748AD2C1F76FF6ECB0CCCD00000000",
"MXN",
"USD",
"XRP"
]
},
"status": "success",
"type": "response"
}

View File

@@ -323,6 +323,8 @@ module.exports = function(port) {
} }
if (request.source_account === addresses.NOTFOUND) { if (request.source_account === addresses.NOTFOUND) {
response = createResponse(request, fixtures.path_find.srcActNotFound); response = createResponse(request, fixtures.path_find.srcActNotFound);
} else if (request.source_account === addresses.SOURCE_LOW_FUNDS) {
response = createResponse(request, fixtures.path_find.sourceAmountLow);
} else if (request.source_account === addresses.OTHER_ACCOUNT) { } else if (request.source_account === addresses.OTHER_ACCOUNT) {
response = createResponse(request, fixtures.path_find.sendUSD); response = createResponse(request, fixtures.path_find.sendUSD);
} else if (request.source_account === addresses.THIRD_ACCOUNT) { } else if (request.source_account === addresses.THIRD_ACCOUNT) {