diff --git a/src/api/common/schemas/pathfind.json b/src/api/common/schemas/pathfind.json index 2302f2c7..2a1cfd1d 100644 --- a/src/api/common/schemas/pathfind.json +++ b/src/api/common/schemas/pathfind.json @@ -24,7 +24,32 @@ "additionalProperties": false, "required": ["address"] }, - "destination": {"$ref": "adjustment"} + "destination": { + "type": "object", + "properties": { + "address": {"$ref": "address"}, + "amount": { + "type": "object", + "properties": { + "value": { + "description": "The quantity of the currency, denoted as a string to retain floating point precision", + "$ref": "value" + }, + "currency": { + "description": "The three-character code or hex string used to denote currencies", + "$ref": "currency" + }, + "counterparty": { + "description": "The Ripple account address of the currency's issuer or gateway", + "$ref": "address" + }, + "required": ["currency", "value"] + }, + "additionalProperties": false + } + }, + "required": ["address", "amount"] + } }, "required": ["source", "destination"], "additionalProperties": false diff --git a/test/api-test.js b/test/api-test.js index 3abfb903..4fa2de53 100644 --- a/test/api-test.js +++ b/test/api-test.js @@ -46,19 +46,29 @@ describe('RippleAPI', function() { afterEach(setupAPI.teardown); it('preparePayment', function(done) { - this.api.preparePayment(address, requests.preparePayment, instructions, + const localInstructions = _.defaults({ + maxFee: '0.000012' + }, instructions); + this.api.preparePayment(address, requests.preparePayment, localInstructions, _.partial(checkResult, responses.preparePayment, done)); }); it('preparePayment with all options specified', function(done) { + const localInstructions = { + maxLedgerVersion: this.api.getLedgerVersion() + 100, + fee: '0.000012' + }; this.api.preparePayment(address, requests.preparePaymentAllOptions, - instructions, + localInstructions, _.partial(checkResult, responses.preparePaymentAllOptions, done)); }); it('preparePayment without counterparty set', function(done) { + const localInstructions = _.defaults({ + sequence: 23 + }, instructions); this.api.preparePayment(address, requests.preparePaymentNoCounterparty, - instructions, + localInstructions, _.partial(checkResult, responses.preparePaymentNoCounterparty, done)); }); @@ -258,7 +268,8 @@ describe('RippleAPI', function() { it('getOrderbook - direction is correct for bids and asks', function(done) { this.api.getOrderbook(address, orderbook, {}, (error, data) => { assert(_.every(data.bids, bid => bid.specification.direction === 'buy')); - assert(_.every(data.asks, ask => ask.specification.direction === 'sell')); + assert( + _.every(data.asks, ask => ask.specification.direction === 'sell')); done(); }); }); @@ -281,21 +292,50 @@ describe('RippleAPI', function() { }); it('getPaths', function(done) { - const pathfind = { - source: { - address: address - }, - destination: { - address: addresses.OTHER_ACCOUNT, - amount: { - currency: 'USD', - counterparty: addresses.ISSUER, - value: '100' - } - } - }; - this.api.getPaths(pathfind, - _.partial(checkResult, responses.getPaths, done)); + this.api.getPaths(requests.getPaths.normal, + _.partial(checkResult, responses.getPaths.XrpToUsd, done)); + }); + + // @TODO + // need decide what to do with currencies/XRP: + // if add 'XRP' in currencies, then there will be exception in + // xrpToDrops function (called from toRippledAmount) + it('getPaths USD 2 USD', function(done) { + this.api.getPaths(requests.getPaths.UsdToUsd, + _.partial(checkResult, responses.getPaths.UsdToUsd, done)); + }); + + it('getPaths XRP 2 XRP', function(done) { + this.api.getPaths(requests.getPaths.XrpToXrp, + _.partial(checkResult, responses.getPaths.XrpToXrp, done)); + }); + + it('getPaths - XRP 2 XRP - not enough', function(done) { + this.api.getPaths(requests.getPaths.XrpToXrpNotEnough, (error) => { + assert(error instanceof this.api.errors.NotFoundError); + done(); + }); + }); + + it('getPaths - does not accept currency', function(done) { + this.api.getPaths(requests.getPaths.NotAcceptCurrency, (error) => { + assert(error instanceof this.api.errors.NotFoundError); + done(); + }); + }); + + it('getPaths - no paths', function(done) { + this.api.getPaths(requests.getPaths.NoPaths, (error) => { + assert(error instanceof this.api.errors.NotFoundError); + done(); + }); + }); + + it('getPaths - no paths with source currencies', function(done) { + this.api.getPaths(requests.getPaths.NoPathsWithCurrencies, (error) => { + assert(error instanceof this.api.errors.NotFoundError); + done(); + }); }); it('getLedgerVersion', function() { diff --git a/test/fixtures/api/requests/getpaths/no-paths-with-currencies.json b/test/fixtures/api/requests/getpaths/no-paths-with-currencies.json new file mode 100644 index 00000000..b723a296 --- /dev/null +++ b/test/fixtures/api/requests/getpaths/no-paths-with-currencies.json @@ -0,0 +1,17 @@ +{ + "source": { + "address": "rwBYyfufTzk77zUSKEu4MvixfarC35av1J", + "currencies": [ + { + "currency": "USD" + } + ] + }, + "destination": { + "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "amount": { + "value": "1000002", + "currency": "USD" + } + } +} diff --git a/test/fixtures/api/requests/getpaths/no-paths.json b/test/fixtures/api/requests/getpaths/no-paths.json new file mode 100644 index 00000000..269d2e5e --- /dev/null +++ b/test/fixtures/api/requests/getpaths/no-paths.json @@ -0,0 +1,12 @@ +{ + "source": { + "address": "rwBYyfufTzk77zUSKEu4MvixfarC35av1J" + }, + "destination": { + "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "amount": { + "value": "1000002", + "currency": "USD" + } + } +} diff --git a/test/fixtures/api/requests/getpaths/normal.json b/test/fixtures/api/requests/getpaths/normal.json new file mode 100644 index 00000000..01c4980a --- /dev/null +++ b/test/fixtures/api/requests/getpaths/normal.json @@ -0,0 +1,13 @@ +{ + "source": { + "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59" + }, + "destination": { + "address": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + "amount": { + "currency": "USD", + "counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + "value": "100" + } + } +} \ No newline at end of file diff --git a/test/fixtures/api/requests/getpaths/not-accept-currency.json b/test/fixtures/api/requests/getpaths/not-accept-currency.json new file mode 100644 index 00000000..68ecfc83 --- /dev/null +++ b/test/fixtures/api/requests/getpaths/not-accept-currency.json @@ -0,0 +1,12 @@ +{ + "source": { + "address": "rwBYyfufTzk77zUSKEu4MvixfarC35av1J" + }, + "destination": { + "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "amount": { + "value": "0.000002", + "currency": "GBP" + } + } +} diff --git a/test/fixtures/api/requests/getpaths/usd2usd.json b/test/fixtures/api/requests/getpaths/usd2usd.json new file mode 100644 index 00000000..30af3080 --- /dev/null +++ b/test/fixtures/api/requests/getpaths/usd2usd.json @@ -0,0 +1,20 @@ +{ + "source": { + "address": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + "currencies": [ + { + "currency": "LTC" + }, + { + "currency": "USD" + } + ] + }, + "destination": { + "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "amount": { + "currency": "USD", + "value": "0.000001" + } + } +} \ No newline at end of file diff --git a/test/fixtures/api/requests/getpaths/xrp2xrp-not-enough.json b/test/fixtures/api/requests/getpaths/xrp2xrp-not-enough.json new file mode 100644 index 00000000..202f136c --- /dev/null +++ b/test/fixtures/api/requests/getpaths/xrp2xrp-not-enough.json @@ -0,0 +1,12 @@ +{ + "source": { + "address": "rwBYyfufTzk77zUSKEu4MvixfarC35av1J" + }, + "destination": { + "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "amount": { + "value": "1000002", + "currency": "XRP" + } + } +} \ No newline at end of file diff --git a/test/fixtures/api/requests/getpaths/xrp2xrp.json b/test/fixtures/api/requests/getpaths/xrp2xrp.json new file mode 100644 index 00000000..a9cc116c --- /dev/null +++ b/test/fixtures/api/requests/getpaths/xrp2xrp.json @@ -0,0 +1,12 @@ +{ + "source": { + "address": "rwBYyfufTzk77zUSKEu4MvixfarC35av1J" + }, + "destination": { + "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "amount": { + "value": "0.000002", + "currency": "XRP" + } + } +} \ No newline at end of file diff --git a/test/fixtures/api/requests/index.js b/test/fixtures/api/requests/index.js index 3f56779a..1caab3fb 100644 --- a/test/fixtures/api/requests/index.js +++ b/test/fixtures/api/requests/index.js @@ -8,5 +8,14 @@ module.exports = { preparePaymentNoCounterparty: require('./prepare-payment-no-counterparty'), prepareSettings: require('./prepare-settings'), prepareTrustline: require('./prepare-trustline'), - sign: require('./sign') + sign: require('./sign'), + getPaths: { + normal: require('./getpaths/normal'), + UsdToUsd: require('./getpaths/usd2usd'), + XrpToXrp: require('./getpaths/xrp2xrp'), + XrpToXrpNotEnough: require('./getpaths/xrp2xrp-not-enough'), + NotAcceptCurrency: require('./getpaths/not-accept-currency'), + NoPaths: require('./getpaths/no-paths'), + NoPathsWithCurrencies: require('./getpaths/no-paths-with-currencies') + } }; diff --git a/test/fixtures/api/responses/get-paths-send-usd.json b/test/fixtures/api/responses/get-paths-send-usd.json new file mode 100644 index 00000000..ea177562 --- /dev/null +++ b/test/fixtures/api/responses/get-paths-send-usd.json @@ -0,0 +1,20 @@ +[ + { + "source": { + "address": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + "amount": { + "currency": "USD", + "value": "0.000001002", + "counterparty": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo" + } + }, + "destination": { + "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "amount": { + "value": "0.000001", + "currency": "USD" + } + }, + "paths": "[[{\"account\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\"}],[{\"account\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\"},{\"account\":\"rLMJ4db4uwHcd6NHg6jvTaYb8sH5Gy4tg5\"},{\"account\":\"rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun\"}],[{\"account\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\"},{\"currency\":\"USD\",\"issuer\":\"rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun\"},{\"account\":\"rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun\"}],[{\"account\":\"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\"},{\"account\":\"rLMJ4db4uwHcd6NHg6jvTaYb8sH5Gy4tg5\"},{\"account\":\"r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X\"}]]" + } +] diff --git a/test/fixtures/api/responses/get-paths-xrp-to-xrp.json b/test/fixtures/api/responses/get-paths-xrp-to-xrp.json new file mode 100644 index 00000000..146b2ae3 --- /dev/null +++ b/test/fixtures/api/responses/get-paths-xrp-to-xrp.json @@ -0,0 +1,19 @@ +[ + { + "source": { + "address": "rwBYyfufTzk77zUSKEu4MvixfarC35av1J", + "amount": { + "currency": "XRP", + "value": "0.000002" + } + }, + "destination": { + "address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "amount": { + "value": "0.000002", + "currency": "XRP" + } + }, + "paths": "[]" + } +] diff --git a/test/fixtures/api/responses/index.js b/test/fixtures/api/responses/index.js index ac2de441..f51e5fb9 100644 --- a/test/fixtures/api/responses/index.js +++ b/test/fixtures/api/responses/index.js @@ -6,7 +6,11 @@ module.exports = { getBalances: require('./get-balances.json'), getOrderbook: require('./get-orderbook.json'), getOrders: require('./get-orders.json'), - getPaths: require('./get-paths.json'), + getPaths: { + XrpToUsd: require('./get-paths.json'), + UsdToUsd: require('./get-paths-send-usd.json'), + XrpToXrp: require('./get-paths-xrp-to-xrp.json') + }, getServerInfo: require('./get-server-info.json'), getSettings: require('./get-settings.json'), getTransaction: { diff --git a/test/fixtures/api/rippled/index.js b/test/fixtures/api/rippled/index.js index 8c76af8c..5c999e58 100644 --- a/test/fixtures/api/rippled/index.js +++ b/test/fixtures/api/rippled/index.js @@ -13,7 +13,11 @@ module.exports = { account_tx: require('./account-tx'), book_offers: require('./book-offers'), server_info: require('./server-info'), - ripple_path_find: require('./ripple-path-find'), + ripple_path_find: { + generate: require('./ripple-path-find'), + sendUSD: require('./ripple-path-find-send-usd'), + XrpToXrp: require('./ripple-path-find-xrp-to-xrp') + }, tx: { Payment: require('./tx/payment.json'), AccountSet: require('./tx/account-set.json'), diff --git a/test/fixtures/api/rippled/ripple-path-find-send-usd.json b/test/fixtures/api/rippled/ripple-path-find-send-usd.json new file mode 100644 index 00000000..47a50dc8 --- /dev/null +++ b/test/fixtures/api/rippled/ripple-path-find-send-usd.json @@ -0,0 +1,90 @@ +{ + "id": 0, + "result": { + "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" + } + } + ], + "destination_account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "destination_currencies": [ + "JOE", + "BTC", + "DYM", + "CNY", + "EUR", + "015841551A748AD2C1F76FF6ECB0CCCD00000000", + "MXN", + "USD", + "XRP" + ] + }, + "status": "success", + "type": "response" +} diff --git a/test/fixtures/api/rippled/ripple-path-find-xrp-to-xrp.json b/test/fixtures/api/rippled/ripple-path-find-xrp-to-xrp.json new file mode 100644 index 00000000..797500c2 --- /dev/null +++ b/test/fixtures/api/rippled/ripple-path-find-xrp-to-xrp.json @@ -0,0 +1,20 @@ +{ + "id": 1, + "result": { + "alternatives": [], + "destination_account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "destination_currencies": [ + "JOE", + "BTC", + "DYM", + "CNY", + "EUR", + "015841551A748AD2C1F76FF6ECB0CCCD00000000", + "MXN", + "USD", + "XRP" + ] + }, + "status": "success", + "type": "response" +} diff --git a/test/mock-rippled.js b/test/mock-rippled.js index 372d2d86..f4e80f35 100644 --- a/test/mock-rippled.js +++ b/test/mock-rippled.js @@ -100,6 +100,10 @@ module.exports = function(port) { conn.send(createResponse(request, fixtures.account_info.normal)); } else if (request.account === addresses.NOTFOUND) { conn.send(createResponse(request, fixtures.account_info.notfound)); + } else if (request.account === addresses.THIRD_ACCOUNT) { + const response = _.assign({}, fixtures.account_info.normal); + response.Account = addresses.THIRD_ACCOUNT; + conn.send(createResponse(request, response)); } else { assert(false, 'Unrecognized account address: ' + request.account); } @@ -179,9 +183,16 @@ module.exports = function(port) { }); mock.on('request_ripple_path_find', function(request, conn) { - const response = fixtures.ripple_path_find.generateIOUPaymentPaths( - request.id, request.source_account, request.destination_account, - request.destination_amount); + let response = null; + if (request.source_account === addresses.OTHER_ACCOUNT) { + response = createResponse(request, fixtures.ripple_path_find.sendUSD); + } else if (request.source_account === addresses.THIRD_ACCOUNT) { + response = createResponse(request, fixtures.ripple_path_find.XrpToXrp); + } else { + response = fixtures.ripple_path_find.generate.generateIOUPaymentPaths( + request.id, request.source_account, request.destination_account, + request.destination_amount); + } conn.send(response); });