From 80494ad8136e1012080a2abb572cbce91ccbb9f3 Mon Sep 17 00:00:00 2001 From: Chris Clark Date: Fri, 28 Aug 2015 14:47:03 -0700 Subject: [PATCH] Return promise error if submit result is an immediate failure --- src/api/transaction/submit.js | 19 ++++++++++++++++++- test/api-test.js | 8 ++++++++ test/fixtures/api/rippled/index.js | 5 ++++- test/fixtures/api/rippled/submit-failed.json | 13 +++++++++++++ test/mock-rippled.js | 6 +++++- 5 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/api/rippled/submit-failed.json diff --git a/src/api/transaction/submit.js b/src/api/transaction/submit.js index 57780263..d6795f0d 100644 --- a/src/api/transaction/submit.js +++ b/src/api/transaction/submit.js @@ -1,10 +1,27 @@ /* @flow */ 'use strict'; +const _ = require('lodash'); const utils = require('./utils'); const validate = utils.common.validate; const Request = utils.common.core.Request; const convertErrors = utils.common.convertErrors; +function isImmediateRejection(engineResult) { + return _.startsWith(engineResult, 'tel') + || _.startsWith(engineResult, 'tem') + || _.startsWith(engineResult, 'tej'); +} + +function convertSubmitErrors(callback) { + return function(error, data) { + if (isImmediateRejection(data.engineResult)) { + callback(new utils.common.errors.RippleError('Submit failed'), data); + } else { + callback(error, data); + } + }; +} + function submitAsync(txBlob: string, callback: (err: any, data: any) => void ): void { validate.blob(txBlob); @@ -13,7 +30,7 @@ function submitAsync(txBlob: string, callback: (err: any, data: any) => void request.request(null, utils.common.composeAsync( data => utils.common.convertKeysFromSnakeCaseToCamelCase(data), - convertErrors(callback))); + convertSubmitErrors(convertErrors(callback)))); } function submit(txBlob: string) { diff --git a/test/api-test.js b/test/api-test.js index 5c207fb0..95489a51 100644 --- a/test/api-test.js +++ b/test/api-test.js @@ -155,6 +155,14 @@ describe('RippleAPI', function() { _.partial(checkResult, responses.submit, 'submit')); }); + it('submit - failure', function() { + return this.api.submit('BAD').then(() => { + assert(false, 'Should throw RippleError'); + }).catch(error => { + assert(error instanceof this.api.errors.RippleError); + }); + }); + it('getBalances', function() { return this.api.getBalances(address).then( _.partial(checkResult, responses.getBalances, 'getBalances')); diff --git a/test/fixtures/api/rippled/index.js b/test/fixtures/api/rippled/index.js index d0e95b63..fc7d44b4 100644 --- a/test/fixtures/api/rippled/index.js +++ b/test/fixtures/api/rippled/index.js @@ -1,7 +1,10 @@ 'use strict'; module.exports = { - submit: require('./submit'), + submit: { + success: require('./submit'), + failure: require('./submit-failed') + }, ledger: require('./ledger'), ledgerNotFound: require('./ledger-not-found'), ledgerWithoutCloseTime: require('./ledger-without-close-time'), diff --git a/test/fixtures/api/rippled/submit-failed.json b/test/fixtures/api/rippled/submit-failed.json new file mode 100644 index 00000000..e2d02754 --- /dev/null +++ b/test/fixtures/api/rippled/submit-failed.json @@ -0,0 +1,13 @@ +{ + "id": 0, + "status": "success", + "type": "response", + "result": { + "success": false, + "engine_result": "temBAD_FEE", + "engine_result_code": 1, + "engine_result_message": "", + "tx_blob": "12000322000000002400000017201B0086955468400000000000000C732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402207660BDEF67105CE1EBA9AD35DC7156BAB43FF1D47633199EE257D70B6B9AAFBF02207F5517BC8AEF2ADC1325897ECDBA8C673838048BCA62F4E98B252F19BE88796D770A726970706C652E636F6D81144FBFF73DA4ECF9B701940F27341FA8020C313443", + "tx_json": {} + } +} diff --git a/test/mock-rippled.js b/test/mock-rippled.js index 598f1376..bf662d05 100644 --- a/test/mock-rippled.js +++ b/test/mock-rippled.js @@ -205,7 +205,11 @@ module.exports = function(port) { mock.on('request_submit', function(request, conn) { assert.strictEqual(request.command, 'submit'); - conn.send(createResponse(request, fixtures.submit)); + if (request.tx_blob === 'BAD') { + conn.send(createResponse(request, fixtures.submit.failure)); + } else { + conn.send(createResponse(request, fixtures.submit.success)); + } }); mock.on('request_account_lines', function(request, conn) {