From f74e11bce0c3f9abffd05e3a6f40c6740a8a11f1 Mon Sep 17 00:00:00 2001 From: Chris Clark Date: Thu, 5 May 2016 12:49:28 -0700 Subject: [PATCH] Add support for parsing SetFee and EnableAmendment pseudo-transactions --- circle.yml | 1 + package.json | 4 +- src/ledger/parse/amendment.js | 9 ++++ src/ledger/parse/fee-update.js | 15 +++++++ src/ledger/parse/transaction.js | 12 ++++-- src/ledger/transaction.js | 11 +++-- test/api-test.js | 17 +++++++- .../responses/get-transaction-amendment.json | 17 ++++++++ .../responses/get-transaction-fee-update.json | 21 +++++++++ test/fixtures/responses/index.js | 6 ++- test/fixtures/rippled/index.js | 4 +- test/fixtures/rippled/tx/amendment.json | 40 +++++++++++++++++ test/fixtures/rippled/tx/set-fee.json | 43 +++++++++++++++++++ test/mock-rippled.js | 8 +++- 14 files changed, 194 insertions(+), 14 deletions(-) create mode 100644 src/ledger/parse/amendment.js create mode 100644 src/ledger/parse/fee-update.js create mode 100644 test/fixtures/responses/get-transaction-amendment.json create mode 100644 test/fixtures/responses/get-transaction-fee-update.json create mode 100644 test/fixtures/rippled/tx/amendment.json create mode 100644 test/fixtures/rippled/tx/set-fee.json diff --git a/circle.yml b/circle.yml index 430957ac..2e46f661 100644 --- a/circle.yml +++ b/circle.yml @@ -5,6 +5,7 @@ machine: testripple.circleci.com: 127.0.0.1 dependencies: pre: + - npm -g install npm@latest-2 - wget https://s3-us-west-2.amazonaws.com/ripple-debs/rippled_0.30.1-b11-1.deb - sudo dpkg -i rippled_0.30.1-b11-1.deb test: diff --git a/package.json b/package.json index 9b29e177..80bee191 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "assert-diff": "^1.0.1", "babel-cli": "^6.4.0", "babel-core": "^6.4.0", - "babel-eslint": "^4.1.8", + "babel-eslint": "^6.0.4", "babel-loader": "^6.2.1", "babel-plugin-syntax-flow": "^6.3.13", "babel-plugin-transform-flow-strip-types": "^6.4.0", @@ -43,7 +43,7 @@ "coveralls": "^2.10.0", "doctoc": "^0.15.0", "ejs": "^2.3.4", - "eslint": "^2.1.0", + "eslint": "^2.9.0", "eventemitter2": "^0.4.14", "flow-bin": "^0.14", "gulp": "^3.8.10", diff --git a/src/ledger/parse/amendment.js b/src/ledger/parse/amendment.js new file mode 100644 index 00000000..d3c4011b --- /dev/null +++ b/src/ledger/parse/amendment.js @@ -0,0 +1,9 @@ +'use strict'; // eslint-disable-line strict + +function parseAmendment(tx: Object) { + return { + amendment: tx.Amendment + }; +} + +module.exports = parseAmendment; diff --git a/src/ledger/parse/fee-update.js b/src/ledger/parse/fee-update.js new file mode 100644 index 00000000..b386a44b --- /dev/null +++ b/src/ledger/parse/fee-update.js @@ -0,0 +1,15 @@ +'use strict'; // eslint-disable-line strict +const BigNumber = require('bignumber.js'); +const {dropsToXrp} = require('./utils'); + +function parseFeeUpdate(tx: Object) { + const baseFeeDrops = (new BigNumber(tx.BaseFee, 16)).toString(); + return { + baseFeeXRP: dropsToXrp(baseFeeDrops), + referenceFeeUnits: tx.ReferenceFeeUnits, + reserveBaseXRP: dropsToXrp(tx.ReserveBase), + reserveIncrementXRP: dropsToXrp(tx.ReserveIncrement) + }; +} + +module.exports = parseFeeUpdate; diff --git a/src/ledger/parse/transaction.js b/src/ledger/parse/transaction.js index ee56795f..5aef7029 100644 --- a/src/ledger/parse/transaction.js +++ b/src/ledger/parse/transaction.js @@ -1,5 +1,5 @@ /* @flow */ -'use strict'; +'use strict'; // eslint-disable-line strict const assert = require('assert'); const utils = require('./utils'); const parsePayment = require('./payment'); @@ -11,6 +11,8 @@ const parseSuspendedPaymentCreation = require('./suspended-payment-creation'); const parseSuspendedPaymentExecution = require('./suspended-payment-execution'); const parseSuspendedPaymentCancellation = require('./suspended-payment-cancellation'); +const parseFeeUpdate = require('./fee-update'); +const parseAmendment = require('./amendment'); function parseTransactionType(type) { const mapping = { @@ -23,7 +25,9 @@ function parseTransactionType(type) { SuspendedPaymentCreate: 'suspendedPaymentCreation', SuspendedPaymentFinish: 'suspendedPaymentExecution', SuspendedPaymentCancel: 'suspendedPaymentCancellation', - SignerListSet: 'settings' + SignerListSet: 'settings', + SetFee: 'feeUpdate', // pseudo-transaction + EnableAmendment: 'amendment' // pseudo-transaction }; return mapping[type] || null; } @@ -38,7 +42,9 @@ function parseTransaction(tx: Object): Object { 'settings': parseSettings, 'suspendedPaymentCreation': parseSuspendedPaymentCreation, 'suspendedPaymentExecution': parseSuspendedPaymentExecution, - 'suspendedPaymentCancellation': parseSuspendedPaymentCancellation + 'suspendedPaymentCancellation': parseSuspendedPaymentCancellation, + 'feeUpdate': parseFeeUpdate, + 'amendment': parseAmendment }; const parser = mapping[type]; assert(parser !== undefined, 'Unrecognized transaction type'); diff --git a/src/ledger/transaction.js b/src/ledger/transaction.js index 731536c6..561d0130 100644 --- a/src/ledger/transaction.js +++ b/src/ledger/transaction.js @@ -1,5 +1,5 @@ /* @flow */ -'use strict'; +'use strict'; // eslint-disable-line strict const _ = require('lodash'); const utils = require('./utils'); const parseTransaction = require('./parse/transaction'); @@ -13,15 +13,18 @@ function attachTransactionDate(connection: Connection, tx: Object return Promise.resolve(tx); } - if (!tx.ledger_index) { + const ledgerVersion = tx.ledger_index || tx.LedgerSequence; + + if (!ledgerVersion) { return new Promise(() => { - throw new errors.NotFoundError('ledger_index not found in tx'); + throw new errors.NotFoundError( + 'ledger_index and LedgerSequence not found in tx'); }); } const request = { command: 'ledger', - ledger_index: tx.ledger_index + ledger_index: ledgerVersion }; return connection.request(request).then(data => { diff --git a/test/api-test.js b/test/api-test.js index 2facd6d1..bbc4e1a7 100644 --- a/test/api-test.js +++ b/test/api-test.js @@ -1,5 +1,5 @@ /* eslint-disable max-nested-callbacks */ -'use strict'; // eslint-disable-line +'use strict'; // eslint-disable-line const _ = require('lodash'); const assert = require('assert-diff'); const setupAPI = require('./setup-api'); @@ -708,6 +708,21 @@ describe('RippleAPI', function() { }); }); + it('getTransaction - amendment', function() { + const hash = + 'A971B83ABED51D83749B73F3C1AAA627CD965AFF74BE8CD98299512D6FB0658F'; + return this.api.getTransaction(hash).then(result => { + assert.deepEqual(result, responses.getTransaction.amendment); + }); + }); + + it('getTransaction - feeUpdate', function() { + const hash = + 'C6A40F56127436DCD830B1B35FF939FD05B5747D30D6542572B7A835239817AF'; + return this.api.getTransaction(hash).then(result => { + assert.deepEqual(result, responses.getTransaction.feeUpdate); + }); + }); }); it('getTransactions', function() { diff --git a/test/fixtures/responses/get-transaction-amendment.json b/test/fixtures/responses/get-transaction-amendment.json new file mode 100644 index 00000000..10d754dc --- /dev/null +++ b/test/fixtures/responses/get-transaction-amendment.json @@ -0,0 +1,17 @@ +{ + "type": "amendment", + "address": "rrrrrrrrrrrrrrrrrrrrrhoLvTp", + "sequence": 0, + "id": "A971B83ABED51D83749B73F3C1AAA627CD965AFF74BE8CD98299512D6FB0658F", + "specification": { + "amendment": "42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE" + }, + "outcome": { + "result": "tesSUCCESS", + "timestamp": "2016-05-05T16:33:30.000Z", + "fee": "0", + "balanceChanges": {}, + "orderbookChanges": {}, + "indexInLedger": 0 + } +} diff --git a/test/fixtures/responses/get-transaction-fee-update.json b/test/fixtures/responses/get-transaction-fee-update.json new file mode 100644 index 00000000..f9556e1c --- /dev/null +++ b/test/fixtures/responses/get-transaction-fee-update.json @@ -0,0 +1,21 @@ +{ + "type": "feeUpdate", + "address": "rrrrrrrrrrrrrrrrrrrrrhoLvTp", + "sequence": 0, + "id": "C6A40F56127436DCD830B1B35FF939FD05B5747D30D6542572B7A835239817AF", + "specification": { + "baseFeeXRP": "0.00001", + "referenceFeeUnits": 10, + "reserveBaseXRP": "50", + "reserveIncrementXRP": "12.5" + }, + "outcome": { + "result": "tesSUCCESS", + "timestamp": "2014-08-08T16:57:50.000Z", + "fee": "0", + "balanceChanges": {}, + "orderbookChanges": {}, + "ledgerVersion": 3717633, + "indexInLedger": 3 + } +} diff --git a/test/fixtures/responses/index.js b/test/fixtures/responses/index.js index 2281f43a..a78015ab 100644 --- a/test/fixtures/responses/index.js +++ b/test/fixtures/responses/index.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict'; // eslint-disable-line strict module.exports = { generateAddress: require('./generate-address.json'), @@ -43,7 +43,9 @@ module.exports = { suspendedPaymentExecution: require('./get-transaction-suspended-payment-execution.json'), suspendedPaymentExecutionSimple: - require('./get-transaction-suspended-payment-execution-simple.json') + require('./get-transaction-suspended-payment-execution-simple.json'), + amendment: require('./get-transaction-amendment.json'), + feeUpdate: require('./get-transaction-fee-update.json') }, getTransactions: { normal: require('./get-transactions.json'), diff --git a/test/fixtures/rippled/index.js b/test/fixtures/rippled/index.js index 76638514..0073e9fa 100644 --- a/test/fixtures/rippled/index.js +++ b/test/fixtures/rippled/index.js @@ -72,6 +72,8 @@ module.exports = { require('./tx/suspended-payment-execution-simple.json'), Unrecognized: require('./tx/unrecognized.json'), NoMeta: require('./tx/no-meta.json'), - LedgerZero: require('./tx/ledger-zero.json') + LedgerZero: require('./tx/ledger-zero.json'), + Amendment: require('./tx/amendment.json'), + SetFee: require('./tx/set-fee.json') } }; diff --git a/test/fixtures/rippled/tx/amendment.json b/test/fixtures/rippled/tx/amendment.json new file mode 100644 index 00000000..7c51648a --- /dev/null +++ b/test/fixtures/rippled/tx/amendment.json @@ -0,0 +1,40 @@ +{ + "id": 0, + "status": "success", + "type": "response", + "result": { + "Account": "rrrrrrrrrrrrrrrrrrrrrhoLvTp", + "Amendment": "42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE", + "Fee": "0", + "Flags": 65536, + "date": 515781210, + "LedgerSequence": 20889601, + "Sequence": 0, + "SigningPubKey": "", + "TransactionType": "EnableAmendment", + "hash": "A971B83ABED51D83749B73F3C1AAA627CD965AFF74BE8CD98299512D6FB0658F", + "meta": { + "AffectedNodes": [ + { + "CreatedNode": { + "LedgerEntryType": "Amendments", + "LedgerIndex": "7DB0788C020F02780A673DC74757F23823FA3014C1866E72CC4CD8B226CD6EF4", + "NewFields": { + "Majorities": [ + { + "Majority": { + "Amendment": "42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE", + "CloseTime": 515781202 + } + } + ] + } + } + } + ], + "TransactionIndex": 0, + "TransactionResult": "tesSUCCESS" + }, + "validated": true + } +} diff --git a/test/fixtures/rippled/tx/set-fee.json b/test/fixtures/rippled/tx/set-fee.json new file mode 100644 index 00000000..f6a1b258 --- /dev/null +++ b/test/fixtures/rippled/tx/set-fee.json @@ -0,0 +1,43 @@ +{ + "id": 0, + "status": "success", + "type": "response", + "result": { + "hash": "C6A40F56127436DCD830B1B35FF939FD05B5747D30D6542572B7A835239817AF", + "ledger_index": 3717633, + "date": 460832270, + "TransactionType": "SetFee", + "Sequence": 0, + "ReferenceFeeUnits": 10, + "ReserveBase": 50000000, + "ReserveIncrement": 12500000, + "BaseFee": "000000000000000A", + "Fee": "0", + "SigningPubKey": "", + "Account": "rrrrrrrrrrrrrrrrrrrrrhoLvTp", + "meta": { + "TransactionIndex": 3, + "AffectedNodes": [ + { + "ModifiedNode": { + "LedgerEntryType": "FeeSettings", + "LedgerIndex": "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A651", + "PreviousFields": { + "ReserveBase": 20000000, + "ReserveIncrement": 5000000 + }, + "FinalFields": { + "Flags": 0, + "ReferenceFeeUnits": 10, + "ReserveBase": 50000000, + "ReserveIncrement": 12500000, + "BaseFee": "000000000000000A" + } + } + } + ], + "TransactionResult": "tesSUCCESS" + }, + "validated": true + } +} diff --git a/test/mock-rippled.js b/test/mock-rippled.js index b0af10f0..a8738bc0 100644 --- a/test/mock-rippled.js +++ b/test/mock-rippled.js @@ -1,4 +1,4 @@ -'use strict'; // eslint-disable-line +'use strict'; // eslint-disable-line const _ = require('lodash'); const assert = require('assert'); const WebSocketServer = require('ws').Server; @@ -292,6 +292,12 @@ module.exports = function createMockRippled(port) { } else if (request.transaction === '4FB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA13') { conn.send(createResponse(request, fixtures.tx.LedgerZero)); + } else if (request.transaction === + 'A971B83ABED51D83749B73F3C1AAA627CD965AFF74BE8CD98299512D6FB0658F') { + conn.send(createResponse(request, fixtures.tx.Amendment)); + } else if (request.transaction === + 'C6A40F56127436DCD830B1B35FF939FD05B5747D30D6542572B7A835239817AF') { + conn.send(createResponse(request, fixtures.tx.SetFee)); } else { assert(false, 'Unrecognized transaction hash: ' + request.transaction); }