Merge pull request #338 from ripple/fix-tx-summary

Fix transaction summary for transactions that fail format validation
This commit is contained in:
Geert Weening
2015-05-20 16:11:27 -07:00
5 changed files with 1483 additions and 963 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
'use strict';
var util = require('util');
var assert = require('assert');
var async = require('async');
var EventEmitter = require('events').EventEmitter;
var Transaction = require('./transaction').Transaction;
var RippleError = require('./rippleerror').RippleError;
var PendingQueue = require('./transactionqueue').TransactionQueue;
var log = require('./log').internal.sub('transactionmanager');
const util = require('util');
const assert = require('assert');
const async = require('async');
const EventEmitter = require('events').EventEmitter;
const Transaction = require('./transaction').Transaction;
const RippleError = require('./rippleerror').RippleError;
const PendingQueue = require('./transactionqueue').TransactionQueue;
const log = require('./log').internal.sub('transactionmanager');
/**
* @constructor TransactionManager
@@ -17,7 +17,7 @@ var log = require('./log').internal.sub('transactionmanager');
function TransactionManager(account) {
EventEmitter.call(this);
var self = this;
const self = this;
this._account = account;
this._accountID = account._account_id;
@@ -95,11 +95,11 @@ TransactionManager._isTooBusy = function(error) {
*/
TransactionManager.normalizeTransaction = function(tx) {
var transaction = { };
var keys = Object.keys(tx);
let transaction = { };
const keys = Object.keys(tx);
for (var i = 0; i < keys.length; i++) {
var k = keys[i];
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
switch (k) {
case 'transaction':
// Account transaction stream
@@ -141,7 +141,7 @@ TransactionManager.normalizeTransaction = function(tx) {
*/
TransactionManager.prototype._transactionReceived = function(tx) {
var transaction = TransactionManager.normalizeTransaction(tx);
const transaction = TransactionManager.normalizeTransaction(tx);
if (!transaction.validated) {
// Transaction has not been validated
@@ -159,8 +159,8 @@ TransactionManager.prototype._transactionReceived = function(tx) {
this._pending.addReceivedSequence(transaction.tx_json.Sequence);
var hash = transaction.tx_json.hash;
var submission = this._pending.getSubmission(hash);
const hash = transaction.tx_json.hash;
const submission = this._pending.getSubmission(hash);
if (!(submission instanceof Transaction)) {
// The received transaction does not correlate to one submitted
@@ -189,7 +189,7 @@ TransactionManager.prototype._transactionReceived = function(tx) {
*/
TransactionManager.prototype._adjustFees = function() {
var self = this;
const self = this;
if (!this._remote.local_fee) {
return;
@@ -207,8 +207,8 @@ TransactionManager.prototype._adjustFees = function() {
return;
}
var oldFee = transaction.tx_json.Fee;
var newFee = transaction._computeFee();
const oldFee = transaction.tx_json.Fee;
const newFee = transaction._computeFee();
if (Number(newFee) > self._maxFee) {
// Max transaction fee exceeded, abort submission
@@ -271,10 +271,10 @@ TransactionManager.prototype._updatePendingStatus = function(ledger) {
// Fill an account transaction sequence
TransactionManager.prototype._fillSequence = function(tx, callback) {
var self = this;
const self = this;
function submitFill(sequence, fCallback) {
var fillTransaction = self._remote.createTransaction('AccountSet', {
let fillTransaction = self._remote.createTransaction('AccountSet', {
account: self._accountID
});
fillTransaction.tx_json.Sequence = sequence;
@@ -294,8 +294,8 @@ TransactionManager.prototype._fillSequence = function(tx, callback) {
return callback();
}
var sequenceDiff = tx.tx_json.Sequence - sequence;
var submitted = 0;
const sequenceDiff = tx.tx_json.Sequence - sequence;
let submitted = 0;
async.whilst(
function() {
@@ -328,9 +328,11 @@ TransactionManager.prototype._fillSequence = function(tx, callback) {
* @api private
*/
TransactionManager.prototype._loadSequence = function(callback) {
var self = this;
callback = (typeof callback === 'function') ? callback : function() {};
TransactionManager.prototype._loadSequence = function(callback_) {
const self = this;
const callback = (typeof callback_ === 'function')
? callback_
: function() {};
function sequenceLoaded(err, sequence) {
if (err || typeof sequence !== 'number') {
@@ -356,9 +358,11 @@ TransactionManager.prototype._loadSequence = function(callback) {
* @api private
*/
TransactionManager.prototype._handleReconnect = function(callback) {
var self = this;
callback = (typeof callback === 'function') ? callback : function() {};
TransactionManager.prototype._handleReconnect = function(callback_) {
const self = this;
const callback = (typeof callback_ === 'function')
? callback_
: function() {};
if (!this._pending.length()) {
callback();
@@ -387,7 +391,7 @@ TransactionManager.prototype._handleReconnect = function(callback) {
});
}
var options = {
const options = {
account: this._accountID,
ledger_index_min: this._pending.getMinLedger(),
ledger_index_max: -1,
@@ -415,8 +419,8 @@ TransactionManager.prototype._waitLedgers = function(ledgers, callback) {
return callback();
}
var self = this;
var closes = 0;
const self = this;
let closes = 0;
function ledgerClosed() {
if (++closes === ledgers) {
@@ -437,10 +441,13 @@ TransactionManager.prototype._waitLedgers = function(ledgers, callback) {
* @api private
*/
TransactionManager.prototype._resubmit = function(ledgers, pending) {
var self = this;
TransactionManager.prototype._resubmit = function(ledgers_, pending_) {
const self = this;
if (ledgers && typeof ledgers !== 'number') {
let ledgers = ledgers_;
let pending = pending_;
if (arguments.length === 1) {
pending = ledgers;
ledgers = 0;
}
@@ -457,7 +464,7 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
}
// Find ID within cache of received (validated) transaction IDs
var received = transaction.findId(self._pending._idCache);
const received = transaction.findId(self._pending._idCache);
if (received) {
switch (received.engine_result) {
@@ -504,15 +511,15 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
*/
TransactionManager.prototype._prepareRequest = function(tx) {
var submitRequest = this._remote.requestSubmit();
const submitRequest = this._remote.requestSubmit();
if (this._remote.local_signing) {
tx.sign();
var serialized = tx.serialize();
const serialized = tx.serialize();
submitRequest.tx_blob(serialized.to_hex());
var hash = tx.hash(null, null, serialized);
const hash = tx.hash(null, null, serialized);
tx.addId(hash);
} else {
// ND: `build_path` is completely ignored when doing local signing as
@@ -536,8 +543,8 @@ TransactionManager.prototype._prepareRequest = function(tx) {
*/
TransactionManager.prototype._request = function(tx) {
var self = this;
var remote = this._remote;
const self = this;
const remote = this._remote;
if (tx.finalized) {
return;
@@ -549,7 +556,7 @@ TransactionManager.prototype._request = function(tx) {
}
if (tx.attempts > 0 && !remote.local_signing) {
var errMessage = 'Automatic resubmission requires local signing';
const errMessage = 'Automatic resubmission requires local signing';
tx.emit('error', new RippleError('tejLocalSigningRequired', errMessage));
return;
}
@@ -671,7 +678,7 @@ TransactionManager.prototype._request = function(tx) {
tx.sign();
}
var submitRequest = this._prepareRequest(tx);
const submitRequest = this._prepareRequest(tx);
submitRequest.once('error', submitted);
submitRequest.once('success', submitted);
@@ -692,7 +699,7 @@ TransactionManager.prototype._request = function(tx) {
*/
TransactionManager.prototype.submit = function(tx) {
var self = this;
const self = this;
if (typeof this._nextSequence !== 'number') {
// If sequence number is not yet known, defer until it is.

View File

@@ -56,24 +56,24 @@
"meta": {
"AffectedNodes": [
{
"ModifiedNode": {
"FinalFields": {
"Account": "rNP2Y5EZrVZdFKsow11NoKTE5FjXuBQd3d",
"Balance": "1000",
"Flags": 4849664,
"OwnerCount": 1,
"Sequence": 1
},
"LedgerEntryType": "AccountRoot",
"LedgerIndex": "A4B28FB972EF890DC39A8557DF8960D41DADA00D39B0F1EFCD4BBB85FCA13A30",
"PreviousFields": {
"Balance": "1000",
"Sequence": 3864
},
"PreviousTxnID": "F4910E55A39C42AB82071212D84119631DDE0B0F4F8F9040F252B0066898DBDF",
"PreviousTxnLgrSeq": 11693103
}
"ModifiedNode": {
"FinalFields": {
"Account": "rNP2Y5EZrVZdFKsow11NoKTE5FjXuBQd3d",
"Balance": "1000",
"Flags": 4849664,
"OwnerCount": 1,
"Sequence": 1
},
"LedgerEntryType": "AccountRoot",
"LedgerIndex": "A4B28FB972EF890DC39A8557DF8960D41DADA00D39B0F1EFCD4BBB85FCA13A30",
"PreviousFields": {
"Balance": "1000",
"Sequence": 3864
},
"PreviousTxnID": "F4910E55A39C42AB82071212D84119631DDE0B0F4F8F9040F252B0066898DBDF",
"PreviousTxnLgrSeq": 11693103
}
}
],
"TransactionIndex": 9,
"TransactionResult": "tesSUCCESS"
@@ -101,24 +101,24 @@
"TransactionIndex": 3,
"AffectedNodes": [
{
"ModifiedNode": {
"LedgerEntryType": "AccountRoot",
"PreviousTxnLgrSeq": 11693103,
"PreviousTxnID": "F4910E55A39C42AB82071212D84119631DDE0B0F4F8F9040F252B0066898DBDF",
"LedgerIndex": "A4B28FB972EF890DC39A8557DF8960D41DADA00D39B0F1EFCD4BBB85FCA13A30",
"PreviousFields": {
"Sequence": 3864,
"Balance": "1000"
},
"FinalFields": {
"Flags": 4849664,
"Sequence": 3865,
"OwnerCount": 1,
"Balance": "1000",
"Account": "rNP2Y5EZrVZdFKsow11NoKTE5FjXuBQd3d"
}
"ModifiedNode": {
"LedgerEntryType": "AccountRoot",
"PreviousTxnLgrSeq": 11693103,
"PreviousTxnID": "F4910E55A39C42AB82071212D84119631DDE0B0F4F8F9040F252B0066898DBDF",
"LedgerIndex": "A4B28FB972EF890DC39A8557DF8960D41DADA00D39B0F1EFCD4BBB85FCA13A30",
"PreviousFields": {
"Sequence": 3864,
"Balance": "1000"
},
"FinalFields": {
"Flags": 4849664,
"Sequence": 3865,
"OwnerCount": 1,
"Balance": "1000",
"Account": "rNP2Y5EZrVZdFKsow11NoKTE5FjXuBQd3d"
}
}
}
],
"TransactionResult": "tesSUCCESS"
},
@@ -290,5 +290,17 @@
},
"status": "success",
"type": "response"
},
"SUBMIT_REMOTE_ERROR": {
"error": "invalidTransaction",
"error_exception": "fails local checks: The MemoType and MemoFormat fields may only contain characters that are allowed in URLs under RFC 3986.",
"id": 1,
"request": {
"command": "submit",
"id": 1,
"tx_blob": "12000022800000002400000001201B00CCEAD0614000000000000001684000000000002EE0732102999FB4BC17144F83CDC2F17EA642519FF115EE7B0CC8C78DE9061F1A473F7BAC7447304502210098DC7E9ED1CE860FB6B0904E6E8140D5463D288BA633F36E69A68ACB3D6FCA06022014E76E22F5173B37239F9F56F904839B462F5019169C56A324D3F074FBA39A2A811492DECA2DC92352BE97C1F6347F7E6CCB9A8241C883143108B9AC27BF036EFE5CBE787921F54D622B7A5BF9EA7C0B6D79206D656D6F747970657E0C6D79206D656D6F5F64617461E1F1"
},
"status": "error",
"type": "response"
}
}

View File

@@ -1,46 +1,50 @@
/* eslint-disable max-len */
'use strict';
var ws = require('ws');
var lodash = require('lodash');
var assert = require('assert-diff');
var sjcl = require('ripple-lib').sjcl;
var Remote = require('ripple-lib').Remote;
var SerializedObject = require('ripple-lib').SerializedObject;
var Transaction = require('ripple-lib').Transaction;
var TransactionManager = require('ripple-lib')._test.TransactionManager;
const ws = require('ws');
const lodash = require('lodash');
const assert = require('assert-diff');
const sjcl = require('ripple-lib').sjcl;
const Remote = require('ripple-lib').Remote;
const SerializedObject = require('ripple-lib').SerializedObject;
const Transaction = require('ripple-lib').Transaction;
const TransactionManager = require('ripple-lib')._test.TransactionManager;
var LEDGER = require('./fixtures/transactionmanager').LEDGER;
var ACCOUNT = require('./fixtures/transactionmanager').ACCOUNT;
var ACCOUNT2 = require('./fixtures/transactionmanager').ACCOUNT2;
var SUBSCRIBE_RESPONSE = require('./fixtures/transactionmanager')
const LEDGER = require('./fixtures/transactionmanager').LEDGER;
const ACCOUNT = require('./fixtures/transactionmanager').ACCOUNT;
const ACCOUNT2 = require('./fixtures/transactionmanager').ACCOUNT2;
const SUBSCRIBE_RESPONSE = require('./fixtures/transactionmanager')
.SUBSCRIBE_RESPONSE;
var ACCOUNT_INFO_RESPONSE = require('./fixtures/transactionmanager')
const ACCOUNT_INFO_RESPONSE = require('./fixtures/transactionmanager')
.ACCOUNT_INFO_RESPONSE;
var TX_STREAM_TRANSACTION = require('./fixtures/transactionmanager')
const TX_STREAM_TRANSACTION = require('./fixtures/transactionmanager')
.TX_STREAM_TRANSACTION;
var ACCOUNT_TX_TRANSACTION = require('./fixtures/transactionmanager')
const ACCOUNT_TX_TRANSACTION = require('./fixtures/transactionmanager')
.ACCOUNT_TX_TRANSACTION;
var ACCOUNT_TX_RESPONSE = require('./fixtures/transactionmanager')
const ACCOUNT_TX_RESPONSE = require('./fixtures/transactionmanager')
.ACCOUNT_TX_RESPONSE;
var ACCOUNT_TX_ERROR = require('./fixtures/transactionmanager')
const ACCOUNT_TX_ERROR = require('./fixtures/transactionmanager')
.ACCOUNT_TX_ERROR;
var SUBMIT_RESPONSE = require('./fixtures/transactionmanager')
const SUBMIT_RESPONSE = require('./fixtures/transactionmanager')
.SUBMIT_RESPONSE;
var SUBMIT_TEC_RESPONSE = require('./fixtures/transactionmanager')
const SUBMIT_TEC_RESPONSE = require('./fixtures/transactionmanager')
.SUBMIT_TEC_RESPONSE;
var SUBMIT_TER_RESPONSE = require('./fixtures/transactionmanager')
const SUBMIT_TER_RESPONSE = require('./fixtures/transactionmanager')
.SUBMIT_TER_RESPONSE;
var SUBMIT_TEF_RESPONSE = require('./fixtures/transactionmanager')
const SUBMIT_TEF_RESPONSE = require('./fixtures/transactionmanager')
.SUBMIT_TEF_RESPONSE;
var SUBMIT_TEL_RESPONSE = require('./fixtures/transactionmanager')
const SUBMIT_TEL_RESPONSE = require('./fixtures/transactionmanager')
.SUBMIT_TEL_RESPONSE;
const SUBMIT_REMOTE_ERROR = require('./fixtures/transactionmanager')
.SUBMIT_REMOTE_ERROR;
describe('TransactionManager', function() {
var rippled;
var rippledConnection;
var remote;
var account;
var transactionManager;
let rippled;
let rippledConnection;
let remote;
let account;
let transactionManager;
before(function() {
sjcl.random.addEntropy(
@@ -51,7 +55,7 @@ describe('TransactionManager', function() {
rippled = new ws.Server({port: 5763});
rippled.on('connection', function(c) {
var ledger = lodash.extend({}, LEDGER);
const ledger = lodash.extend({}, LEDGER);
c.sendJSON = function(v) {
try {
c.send(JSON.stringify(v));
@@ -70,8 +74,8 @@ describe('TransactionManager', function() {
}));
};
c.on('message', function(m) {
m = JSON.parse(m);
rippled.emit('request_' + m.command, m, c);
const parsed = JSON.parse(m);
rippled.emit('request_' + parsed.command, parsed, c);
});
rippledConnection = c;
});
@@ -105,8 +109,8 @@ describe('TransactionManager', function() {
});
it('Normalize transaction', function() {
var t1 = TransactionManager.normalizeTransaction(TX_STREAM_TRANSACTION);
var t2 = TransactionManager.normalizeTransaction(ACCOUNT_TX_TRANSACTION);
const t1 = TransactionManager.normalizeTransaction(TX_STREAM_TRANSACTION);
const t2 = TransactionManager.normalizeTransaction(ACCOUNT_TX_TRANSACTION);
[t1, t2].forEach(function(t) {
assert(t.hasOwnProperty('metadata'));
@@ -121,7 +125,7 @@ describe('TransactionManager', function() {
});
it('Handle received transaction', function(done) {
var transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
const transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
transaction.once('success', function() {
done();
@@ -132,7 +136,7 @@ describe('TransactionManager', function() {
rippledConnection.sendJSON(TX_STREAM_TRANSACTION);
});
it('Handle received transaction -- failed', function(done) {
var transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
const transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
transaction.once('error', function(err) {
assert.strictEqual(err.engine_result, 'tecINSUFF_FEE_P');
@@ -155,7 +159,7 @@ describe('TransactionManager', function() {
});
});
it('Handle received transaction -- Account mismatch', function(done) {
var tx = lodash.extend({ }, TX_STREAM_TRANSACTION);
const tx = lodash.extend({ }, TX_STREAM_TRANSACTION);
lodash.extend(tx.transaction, {
Account: 'rMP2Y5EZrVZdFKsow11NoKTE5FjXuBQd3d'
});
@@ -168,7 +172,7 @@ describe('TransactionManager', function() {
});
});
it('Handle received transaction -- not validated', function(done) {
var tx = lodash.extend({ }, TX_STREAM_TRANSACTION, {
const tx = lodash.extend({ }, TX_STREAM_TRANSACTION, {
validated: false
});
rippledConnection.sendJSON(tx);
@@ -180,7 +184,7 @@ describe('TransactionManager', function() {
});
});
it('Handle received transaction -- from account_tx', function(done) {
var transaction = Transaction.from_json(ACCOUNT_TX_TRANSACTION.tx);
const transaction = Transaction.from_json(ACCOUNT_TX_TRANSACTION.tx);
transaction.once('success', function() {
done();
});
@@ -191,7 +195,7 @@ describe('TransactionManager', function() {
});
it('Adjust pending transaction fee', function(done) {
var transaction = new Transaction(remote);
const transaction = new Transaction(remote);
transaction.tx_json = ACCOUNT_TX_TRANSACTION.tx;
transaction.once('fee_adjusted', function(a, b) {
@@ -214,7 +218,7 @@ describe('TransactionManager', function() {
it('Adjust pending transaction fee -- max fee exceeded', function(done) {
transactionManager._maxFee = 10;
var transaction = new Transaction(remote);
const transaction = new Transaction(remote);
transaction.tx_json = ACCOUNT_TX_TRANSACTION.tx;
transaction.once('fee_adjusted', function() {
@@ -236,7 +240,7 @@ describe('TransactionManager', function() {
it('Adjust pending transaction fee -- no local fee', function(done) {
remote.local_fee = false;
var transaction = new Transaction(remote);
const transaction = new Transaction(remote);
transaction.tx_json = ACCOUNT_TX_TRANSACTION.tx;
transaction.once('fee_adjusted', function() {
@@ -258,7 +262,7 @@ describe('TransactionManager', function() {
it('Wait ledgers', function(done) {
transactionManager._waitLedgers(3, done);
for (var i = 1; i <= 3; i++) {
for (let i = 1; i <= 3; i++) {
rippledConnection.closeLedger();
}
});
@@ -268,12 +272,12 @@ describe('TransactionManager', function() {
});
it('Update pending status', function(done) {
var transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
const transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
transaction.submitIndex = 1;
transaction.tx_json.LastLedgerSequence = 10;
var receivedMissing = false;
var receivedLost = false;
let receivedMissing = false;
let receivedLost = false;
transaction.once('missing', function() {
receivedMissing = true;
@@ -291,20 +295,20 @@ describe('TransactionManager', function() {
transaction.addId(TX_STREAM_TRANSACTION.transaction.hash);
transactionManager.getPending().push(transaction);
for (var i = 1; i <= 10; i++) {
for (let i = 1; i <= 10; i++) {
rippledConnection.closeLedger();
}
});
it('Update pending status -- finalized before max ledger exceeded',
function(done) {
var transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
const transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
transaction.submitIndex = 1;
transaction.tx_json.LastLedgerSequence = 10;
transaction.finalized = true;
var receivedMissing = false;
var receivedLost = false;
let receivedMissing = false;
let receivedLost = false;
transaction.once('missing', function() {
receivedMissing = true;
@@ -319,7 +323,7 @@ describe('TransactionManager', function() {
transaction.addId(TX_STREAM_TRANSACTION.transaction.hash);
transactionManager.getPending().push(transaction);
for (var i = 1; i <= 10; i++) {
for (let i = 1; i <= 10; i++) {
rippledConnection.closeLedger();
}
@@ -331,15 +335,15 @@ describe('TransactionManager', function() {
});
it('Handle reconnect', function(done) {
var transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
const transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
var binaryTx = lodash.extend({}, ACCOUNT_TX_TRANSACTION, {
const binaryTx = lodash.extend({}, ACCOUNT_TX_TRANSACTION, {
ledger_index: ACCOUNT_TX_TRANSACTION.tx.ledger_index,
tx_blob: SerializedObject.from_json(ACCOUNT_TX_TRANSACTION.tx).to_hex(),
meta: SerializedObject.from_json(ACCOUNT_TX_TRANSACTION.meta).to_hex()
});
var hash = new SerializedObject(binaryTx.tx_blob).hash(0x54584E00).to_hex();
const hash = new SerializedObject(binaryTx.tx_blob).hash(0x54584E00).to_hex();
transaction.addId(hash);
@@ -351,7 +355,7 @@ describe('TransactionManager', function() {
transactionManager.getPending().push(transaction);
rippled.once('request_account_tx', function(m, req) {
var response = lodash.extend({}, ACCOUNT_TX_RESPONSE);
const response = lodash.extend({}, ACCOUNT_TX_RESPONSE);
response.result.transactions = [binaryTx];
req.sendResponse(response, {id: m.id});
});
@@ -360,9 +364,9 @@ describe('TransactionManager', function() {
});
it('Handle reconnect -- no matching transaction found', function(done) {
var transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
const transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
var binaryTx = lodash.extend({}, ACCOUNT_TX_TRANSACTION, {
const binaryTx = lodash.extend({}, ACCOUNT_TX_TRANSACTION, {
ledger_index: ACCOUNT_TX_TRANSACTION.tx.ledger_index,
tx_blob: SerializedObject.from_json(ACCOUNT_TX_TRANSACTION.tx).to_hex(),
meta: SerializedObject.from_json(ACCOUNT_TX_TRANSACTION.meta).to_hex()
@@ -376,7 +380,7 @@ describe('TransactionManager', function() {
transactionManager.getPending().push(transaction);
rippled.once('request_account_tx', function(m, req) {
var response = lodash.extend({}, ACCOUNT_TX_RESPONSE);
const response = lodash.extend({}, ACCOUNT_TX_RESPONSE);
response.result.transactions = [binaryTx];
req.sendResponse(response, {id: m.id});
});
@@ -385,7 +389,7 @@ describe('TransactionManager', function() {
});
it('Handle reconnect -- account_tx error', function(done) {
var transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
const transaction = Transaction.from_json(TX_STREAM_TRANSACTION.transaction);
transactionManager.getPending().push(transaction);
transactionManager._resubmit = function() {
@@ -401,12 +405,12 @@ describe('TransactionManager', function() {
});
it('Submit transaction', function(done) {
var transaction = remote.createTransaction('AccountSet', {
const transaction = remote.createTransaction('AccountSet', {
account: ACCOUNT.address
});
var receivedInitialSuccess = false;
var receivedProposed = false;
let receivedInitialSuccess = false;
let receivedProposed = false;
transaction.once('proposed', function(m) {
assert.strictEqual(m.engine_result, 'tesSUCCESS');
receivedProposed = true;
@@ -422,7 +426,7 @@ describe('TransactionManager', function() {
assert.strictEqual(transactionManager.getPending().length(), 1);
req.sendResponse(SUBMIT_RESPONSE, {id: m.id});
setImmediate(function() {
var txEvent = lodash.extend({}, TX_STREAM_TRANSACTION);
let txEvent = lodash.extend({}, TX_STREAM_TRANSACTION);
txEvent.transaction = transaction.tx_json;
txEvent.transaction.hash = transaction.hash();
rippledConnection.sendJSON(txEvent);
@@ -440,12 +444,12 @@ describe('TransactionManager', function() {
});
it('Submit transaction -- tec error', function(done) {
var transaction = remote.createTransaction('AccountSet', {
const transaction = remote.createTransaction('AccountSet', {
account: ACCOUNT.address,
set_flag: 'asfDisableMaster'
});
var receivedSubmitted = false;
let receivedSubmitted = false;
transaction.once('proposed', function() {
assert(false, 'Should not receive proposed event');
});
@@ -460,7 +464,7 @@ describe('TransactionManager', function() {
assert.strictEqual(transactionManager.getPending().length(), 1);
req.sendResponse(SUBMIT_TEC_RESPONSE, {id: m.id});
setImmediate(function() {
var txEvent = lodash.extend({}, TX_STREAM_TRANSACTION,
const txEvent = lodash.extend({}, TX_STREAM_TRANSACTION,
SUBMIT_TEC_RESPONSE.result);
txEvent.transaction = transaction.tx_json;
txEvent.transaction.hash = transaction.hash();
@@ -478,7 +482,7 @@ describe('TransactionManager', function() {
});
it('Submit transaction -- ter error', function(done) {
var transaction = remote.createTransaction('Payment', {
const transaction = remote.createTransaction('Payment', {
account: ACCOUNT.address,
destination: ACCOUNT2.address,
amount: '1'
@@ -486,17 +490,17 @@ describe('TransactionManager', function() {
transaction.tx_json.Sequence = ACCOUNT_INFO_RESPONSE.result
.account_data.Sequence + 1;
var receivedSubmitted = false;
let receivedSubmitted = false;
transaction.once('proposed', function() {
assert(false, 'Should not receive proposed event');
});
transaction.once('submitted', function(m) {
assert.strictEqual(m.engine_result, 'terNO_ACCOUNT');
assert.strictEqual(m.engine_result, SUBMIT_TER_RESPONSE.result.engine_result);
receivedSubmitted = true;
});
rippled.on('request_submit', function(m, req) {
var deserialized = new SerializedObject(m.tx_blob).to_json();
const deserialized = new SerializedObject(m.tx_blob).to_json();
switch (deserialized.TransactionType) {
case 'Payment':
@@ -523,20 +527,36 @@ describe('TransactionManager', function() {
assert.strictEqual(err.engine_result, 'tejMaxLedger');
assert(receivedSubmitted);
assert.strictEqual(transactionManager.getPending().length(), 0);
assert.strictEqual(transactionManager.getPending().length(), 0);
const summary = transaction.summary();
assert.strictEqual(summary.submissionAttempts, 1);
assert.strictEqual(summary.submitIndex, 2);
assert.strictEqual(summary.initialSubmitIndex, 2);
assert.strictEqual(summary.lastLedgerSequence, 5);
assert.strictEqual(summary.state, 'failed');
assert.strictEqual(summary.finalized, true);
assert.deepEqual(summary.result, {
engine_result: SUBMIT_TER_RESPONSE.result.engine_result,
engine_result_message: SUBMIT_TER_RESPONSE.result.engine_result_message,
ledger_hash: undefined,
ledger_index: undefined,
transaction_hash: SUBMIT_TER_RESPONSE.result.tx_json.hash
});
transactionManager.once('sequence_filled', done);
});
});
it('Submit transaction -- tef error', function(done) {
var transaction = remote.createTransaction('AccountSet', {
const transaction = remote.createTransaction('AccountSet', {
account: ACCOUNT.address
});
transaction.tx_json.Sequence = ACCOUNT_INFO_RESPONSE.result
.account_data.Sequence - 1;
var receivedSubmitted = false;
var receivedResubmitted = false;
let receivedSubmitted = false;
let receivedResubmitted = false;
transaction.once('proposed', function() {
assert(false, 'Should not receive proposed event');
});
@@ -569,17 +589,32 @@ describe('TransactionManager', function() {
assert(receivedResubmitted);
assert.strictEqual(err.engine_result, 'tejMaxLedger');
assert.strictEqual(transactionManager.getPending().length(), 0);
const summary = transaction.summary();
assert.strictEqual(summary.submissionAttempts, 2);
assert.strictEqual(summary.submitIndex, 3);
assert.strictEqual(summary.initialSubmitIndex, 2);
assert.strictEqual(summary.lastLedgerSequence, 5);
assert.strictEqual(summary.state, 'failed');
assert.strictEqual(summary.finalized, true);
assert.deepEqual(summary.result, {
engine_result: SUBMIT_TEF_RESPONSE.result.engine_result,
engine_result_message: SUBMIT_TEF_RESPONSE.result.engine_result_message,
ledger_hash: undefined,
ledger_index: undefined,
transaction_hash: SUBMIT_TEF_RESPONSE.result.tx_json.hash
});
done();
});
});
it('Submit transaction -- tel error', function(done) {
var transaction = remote.createTransaction('AccountSet', {
const transaction = remote.createTransaction('AccountSet', {
account: ACCOUNT.address
});
var receivedSubmitted = false;
var receivedResubmitted = false;
let receivedSubmitted = false;
let receivedResubmitted = false;
transaction.once('proposed', function() {
assert(false, 'Should not receive proposed event');
});
@@ -612,6 +647,21 @@ describe('TransactionManager', function() {
assert(receivedResubmitted);
assert.strictEqual(err.engine_result, 'tejMaxLedger');
assert.strictEqual(transactionManager.getPending().length(), 0);
const summary = transaction.summary();
assert.strictEqual(summary.submissionAttempts, 2);
assert.strictEqual(summary.submitIndex, 3);
assert.strictEqual(summary.initialSubmitIndex, 2);
assert.strictEqual(summary.lastLedgerSequence, 5);
assert.strictEqual(summary.state, 'failed');
assert.strictEqual(summary.finalized, true);
assert.deepEqual(summary.result, {
engine_result: SUBMIT_TEL_RESPONSE.result.engine_result,
engine_result_message: SUBMIT_TEL_RESPONSE.result.engine_result_message,
ledger_hash: undefined,
ledger_index: undefined,
transaction_hash: SUBMIT_TEL_RESPONSE.result.tx_json.hash
});
done();
});
});
@@ -619,7 +669,7 @@ describe('TransactionManager', function() {
it('Submit transaction -- invalid secret', function(done) {
remote.setSecret(ACCOUNT.address, ACCOUNT.secret + 'z');
var transaction = remote.createTransaction('AccountSet', {
const transaction = remote.createTransaction('AccountSet', {
account: ACCOUNT.address
});
@@ -630,6 +680,89 @@ describe('TransactionManager', function() {
transaction.submit(function(err) {
assert.strictEqual(err.engine_result, 'tejSecretInvalid');
assert.strictEqual(transactionManager.getPending().length(), 0);
const summary = transaction.summary();
assert.deepEqual(summary.tx_json, transaction.tx_json);
assert.strictEqual(summary.submissionAttempts, 0);
assert.strictEqual(summary.submitIndex, undefined);
assert.strictEqual(summary.initialSubmitIndex, undefined);
assert.strictEqual(summary.lastLedgerSequence, undefined);
assert.strictEqual(summary.state, 'failed');
assert.strictEqual(summary.finalized, true);
assert.deepEqual(summary.result, {
engine_result: 'tejSecretInvalid',
engine_result_message: 'Invalid secret',
ledger_hash: undefined,
ledger_index: undefined,
transaction_hash: undefined
});
done();
});
});
it('Submit transaction -- remote error', function(done) {
const transaction = remote.createTransaction('Payment', {
account: ACCOUNT.address,
destination: ACCOUNT2.address,
amount: '1'
});
// MemoType must contain only valid URL characters (RFC 3986). This
// transaction is invalid
// transaction.addMemo('my memotype','my_memo_data');
transaction.tx_json.Memos = [{
Memo: {
MemoType: '6D79206D656D6F74797065',
MemoData: '6D795F6D656D6F5F64617461'
}
}];
let receivedSubmitted = false;
transaction.once('proposed', function() {
assert(false, 'Should not receive proposed event');
});
transaction.once('submitted', function(m) {
assert.strictEqual(m.error, 'remoteError');
receivedSubmitted = true;
});
rippled.on('request_submit', function(m, req) {
assert.strictEqual(transactionManager.getPending().length(), 1);
assert.strictEqual(m.tx_blob, SerializedObject.from_json(
transaction.tx_json).to_hex());
/* eslint-disable max-len */
// rippled returns an exception here rather than an engine result
// https://github.com/ripple/rippled/blob/c61d0c663e410c3d3622f20092535710243b55af/src/ripple/rpc/handlers/Submit.cpp#L66-L75
/* eslint-enable max-len */
req.sendResponse(SUBMIT_REMOTE_ERROR, {id: m.id});
});
transaction.submit(function(err) {
assert(err, 'Transaction submission should not succeed');
assert(receivedSubmitted);
assert.strictEqual(err.error, 'remoteError');
assert.strictEqual(err.remote.error, 'invalidTransaction');
assert.strictEqual(transactionManager.getPending().length(), 0);
const summary = transaction.summary();
assert.deepEqual(summary.tx_json, transaction.tx_json);
assert.strictEqual(summary.submissionAttempts, 1);
assert.strictEqual(summary.submitIndex, 2);
assert.strictEqual(summary.initialSubmitIndex, 2);
assert.strictEqual(summary.lastLedgerSequence, 5);
assert.strictEqual(summary.state, 'failed');
assert.strictEqual(summary.finalized, true);
assert.deepEqual(summary.result, {
engine_result: undefined,
engine_result_message: undefined,
ledger_hash: undefined,
ledger_index: undefined,
transaction_hash: undefined
});
done();
});
});

File diff suppressed because it is too large Load Diff