From 65f7485497e561d4b2873ac886ccfdcfed4c4c54 Mon Sep 17 00:00:00 2001 From: wltsmrz Date: Wed, 20 May 2015 05:00:08 -0700 Subject: [PATCH] Lint --- src/transaction.js | 1015 ++++++++++++++++++------------ src/transactionmanager.js | 95 +-- test/transaction-manager-test.js | 179 +++--- test/transaction-test.js | 571 ++++++++++------- 4 files changed, 1093 insertions(+), 767 deletions(-) diff --git a/src/transaction.js b/src/transaction.js index 90bd1ede7c..f36ce9fed3 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -1,18 +1,18 @@ 'use strict'; -var util = require('util'); -var lodash = require('lodash'); -var EventEmitter = require('events').EventEmitter; -var utils = require('./utils'); -var sjcl = require('./utils').sjcl; -var Amount = require('./amount').Amount; -var Currency = require('./amount').Currency; -var UInt160 = require('./amount').UInt160; -var Seed = require('./seed').Seed; -var SerializedObject = require('./serializedobject').SerializedObject; -var RippleError = require('./rippleerror').RippleError; -var hashprefixes = require('./hashprefixes'); -var log = require('./log').internal.sub('transaction'); +const util = require('util'); +const lodash = require('lodash'); +const EventEmitter = require('events').EventEmitter; +const utils = require('./utils'); +const sjcl = require('./utils').sjcl; +const Amount = require('./amount').Amount; +const Currency = require('./amount').Currency; +const UInt160 = require('./amount').UInt160; +const Seed = require('./seed').Seed; +const SerializedObject = require('./serializedobject').SerializedObject; +const RippleError = require('./rippleerror').RippleError; +const hashprefixes = require('./hashprefixes'); +const log = require('./log').internal.sub('transaction'); /** * @constructor Transaction @@ -32,8 +32,8 @@ var log = require('./log').internal.sub('transaction'); function Transaction(remote) { EventEmitter.call(this); - var self = this; - var remoteExists = (typeof remote === 'object'); + const self = this; + const remoteExists = (typeof remote === 'object'); this.remote = remote; this.tx_json = {Flags: 0}; @@ -141,8 +141,7 @@ Transaction.set_clear_flags = { } }; -Transaction.MEMO_TYPES = { -}; +Transaction.MEMO_TYPES = {}; /* eslint-disable max-len */ @@ -258,6 +257,7 @@ Transaction.prototype.getAccount = function() { * @return {String} */ +Transaction.prototype.getType = Transaction.prototype.getTransactionType = function() { return this.tx_json.TransactionType; }; @@ -269,15 +269,12 @@ Transaction.prototype.getTransactionType = function() { * @return {TransactionManager] */ -Transaction.prototype.getManager = function(account) { +Transaction.prototype.getManager = function(account_) { if (!this.remote) { return undefined; } - if (!account) { - account = this.tx_json.Account; - } - + let account = account_ || this.tx_json.Account; return this.remote.account(account)._transactionManager; }; @@ -288,15 +285,12 @@ Transaction.prototype.getManager = function(account) { */ Transaction.prototype.getSecret = -Transaction.prototype._accountSecret = function(account) { +Transaction.prototype._accountSecret = function(account_) { if (!this.remote) { return undefined; } - if (!account) { - account = this.tx_json.Account; - } - + let account = account_ || this.tx_json.Account; return this.remote.secrets[account]; }; @@ -328,12 +322,12 @@ Transaction.prototype._computeFee = function() { return undefined; } - var servers = this.remote._servers; - var fees = [ ]; + const servers = this.remote._servers; + const fees = [ ]; - for (var i = 0; i < servers.length; i++) { - var server = servers[i]; - if (server._connected) { + for (let i = 0; i < servers.length; i++) { + let server = servers[i]; + if (server.isConnected()) { fees.push(Number(server._computeFee(this._getFeeUnits()))); } } @@ -352,9 +346,9 @@ Transaction.prototype._computeFee = function() { return 0; }); - var midInd = Math.floor(fees.length / 2); + const midInd = Math.floor(fees.length / 2); - var median = fees.length % 2 === 0 + const median = fees.length % 2 === 0 ? Math.floor(0.5 + (fees[midInd] + fees[midInd - 1]) / 2) : fees[midInd]; @@ -393,8 +387,8 @@ Transaction.prototype.complete = function() { if (typeof this.tx_json.SigningPubKey === 'undefined') { try { - var seed = Seed.from_json(this._secret); - var key = seed.get_key(this.tx_json.Account); + const seed = Seed.from_json(this._secret); + const key = seed.get_key(this.tx_json.Account); this.tx_json.SigningPubKey = key.to_hex_pub(); } catch(e) { this.emit('error', new RippleError( @@ -441,28 +435,29 @@ Transaction.prototype.signingHash = function(testnet) { return this.hash(testnet ? 'HASH_TX_SIGN_TESTNET' : 'HASH_TX_SIGN'); }; -Transaction.prototype.hash = function(prefix, asUINT256, serialized) { - if (typeof prefix === 'string') { - if (typeof hashprefixes[prefix] === 'undefined') { - throw new Error('Unknown hashing prefix requested.'); - } - prefix = hashprefixes[prefix]; - } else if (!prefix) { +Transaction.prototype.hash = function(prefix_, asUINT256, serialized) { + let prefix; + + if (typeof prefix_ !== 'string') { prefix = hashprefixes.HASH_TX_ID; + } else if (!hashprefixes.hasOwnProperty(prefix_)) { + throw new Error('Unknown hashing prefix requested: ' + prefix_); + } else { + prefix = hashprefixes[prefix_]; } - var hash = (serialized || this.serialize()).hash(prefix); + const hash = (serialized || this.serialize()).hash(prefix); return asUINT256 ? hash : hash.to_hex(); }; Transaction.prototype.sign = function(testnet) { - var seed = Seed.from_json(this._secret); + const seed = Seed.from_json(this._secret); + const prev_sig = this.tx_json.TxnSignature; - var prev_sig = this.tx_json.TxnSignature; delete this.tx_json.TxnSignature; - var hash = this.signingHash(testnet); + const hash = this.signingHash(testnet); // If the hash is the same, we can re-use the previous signature if (prev_sig && hash === this.previousSigningHash) { @@ -470,9 +465,9 @@ Transaction.prototype.sign = function(testnet) { return this; } - var key = seed.get_key(this.tx_json.Account); - var sig = key.sign(hash); - var hex = sjcl.codec.hex.fromBits(sig).toUpperCase(); + const key = seed.get_key(this.tx_json.Account); + const sig = key.sign(hash); + const hex = sjcl.codec.hex.fromBits(sig).toUpperCase(); this.tx_json.TxnSignature = hex; this.previousSigningHash = hash; @@ -488,7 +483,7 @@ Transaction.prototype.sign = function(testnet) { */ Transaction.prototype.addId = function(id) { - if (this.submittedIDs.indexOf(id) === -1) { + if (!lodash.contains(this.submittedIDs, id)) { this.submittedIDs.unshift(id); } }; @@ -504,87 +499,10 @@ Transaction.prototype.addId = function(id) { */ Transaction.prototype.findId = function(cache) { - var result; - - for (var i = 0; i < this.submittedIDs.length; i++) { - var hash = this.submittedIDs[i]; - if ((result = cache[hash])) { - break; - } - } - - return result; -}; - -/** - * Set build_path to have server blindly construct a path for Payment - * - * "blindly" because the sender has no idea of the actual cost must be less - * than send max. - * - * XXX Abort if not a Payment - * - * @param {Boolean} build path - */ - -Transaction.prototype.setBuildPath = -Transaction.prototype.buildPath = function(build) { - this._build_path = build; - return this; -}; - -/** - * Set SourceTag - * - * tag should be undefined or a 32 bit integer. - * YYY Add range checking for tag - * - * @param {Number} source tag - */ - -Transaction.prototype.sourceTag = function(tag) { - if (typeof tag === 'number' && isFinite(tag)) { - this.tx_json.SourceTag = tag; - } - return this; -}; - -/** - * Set DestinationTag for Payment transaction - * - * tag should be undefined or a 32 bit integer. - * YYY Add range checking for tag. - * - * XXX Abort if not a Payment - * - * @param {Number} destination tag - */ - -Transaction.prototype.setDestinationTag = -Transaction.prototype.destinationTag = function(tag) { - if (typeof tag === 'number' && isFinite(tag)) { - this.tx_json.DestinationTag = tag; - } - return this; -}; - -/** - * Set InvoiceID for Payment transaction - * - * XXX Abort if not a Payment - * - * @param {String} id - */ - -Transaction.prototype.setInvoiceID = -Transaction.prototype.invoiceID = function(id) { - if (typeof id === 'string') { - while (id.length < 64) { - id += '0'; - } - this.tx_json.InvoiceID = id; - } - return this; + const cachedTransactionID = lodash.detect(this.submittedIDs, function(id) { + return cache.hasOwnProperty(id); + }); + return cache[cachedTransactionID]; }; /** @@ -615,13 +533,11 @@ Transaction.prototype.clientID = function(id) { * @param {Number} ledger index */ +Transaction.prototype.setLastLedgerSequence = Transaction.prototype.setLastLedger = Transaction.prototype.lastLedger = function(sequence) { - if (typeof sequence === 'number' && isFinite(sequence)) { - this._setLastLedger = true; - this.tx_json.LastLedgerSequence = sequence; - } - + this._setUInt32('LastLedgerSequence', sequence); + this._setLastLedger = true; return this; }; @@ -632,6 +548,7 @@ Transaction.prototype.lastLedger = function(sequence) { * @param {Number} fee The proposed fee */ +Transaction.prototype.setMaxFee = Transaction.prototype.maxFee = function(fee) { if (typeof fee === 'number' && fee >= 0) { this._setMaxFee = true; @@ -658,125 +575,127 @@ Transaction.prototype.setFixedFee = function(fee) { }; /** - * Filter invalid properties from path objects in a path array - * - * Valid properties are: - * - account - * - currency - * - issuer - * - type_hex + * Set secret If the secret has been set with Remote.setSecret, it does not + * need to be provided * - * @param {Array} path - * @return {Array} filtered path + * @param {String} secret */ -Transaction._rewritePath = function(path) { - if (!Array.isArray(path)) { - throw new Error('Path must be an array'); +Transaction.prototype.setSecret = +Transaction.prototype.secret = function(secret) { + if (typeof secret === 'string') { + this._secret = secret; } + return this; +}; - var newPath = path.map(function(node) { - var newNode = { }; +Transaction.prototype.setType = function(type) { + if (lodash.isUndefined(Transaction.formats, type)) { + throw new Error('TransactionType must be a valid transaction type'); + } - if (node.hasOwnProperty('account')) { - newNode.account = UInt160.json_rewrite(node.account); - } + this.tx_json.TransactionType = type; - if (node.hasOwnProperty('issuer')) { - newNode.issuer = UInt160.json_rewrite(node.issuer); - } + return this; +}; - if (node.hasOwnProperty('currency')) { - newNode.currency = Currency.json_rewrite(node.currency); - } +Transaction.prototype._setUInt32 = function(name, value, options_) { + const options = lodash.merge({}, options_); + const isValidUInt32 = typeof value === 'number' + && value >= 0 && value < Math.pow(256, 4); - if (node.hasOwnProperty('type_hex')) { - newNode.type_hex = node.type_hex; - } + if (!isValidUInt32) { + throw new Error(name + ' must be a valid UInt32'); + } + if (!lodash.isUndefined(options.min_value) && value < options.min_value) { + throw new Error(name + ' must be >= ' + options.min_value); + } - return newNode; - }); + this.tx_json[name] = value; - return newPath; + return this; }; /** - * Add a path for Payment transaction - * - * XXX Abort if not a Payment + * Set SourceTag * - * @param {Array} path + * @param {Number} source tag */ -Transaction.prototype.addPath = -Transaction.prototype.pathAdd = function(path) { - if (Array.isArray(path)) { - this.tx_json.Paths = this.tx_json.Paths || [ ]; - this.tx_json.Paths.push(Transaction._rewritePath(path)); - } - return this; +Transaction.prototype.setSourceTag = +Transaction.prototype.sourceTag = function(tag) { + return this._setUInt32('SourceTag', tag); }; -/** - * Set paths for Payment transaction - * - * XXX Abort if not a Payment - * - * @param {Array} paths - */ +Transaction.prototype._setAccount = function(name, value) { + const uInt160 = UInt160.from_json(value); -Transaction.prototype.setPaths = -Transaction.prototype.paths = function(paths) { - if (Array.isArray(paths)) { - for (var i = 0, l = paths.length; i < l; i++) { - this.addPath(paths[i]); - } + if (!uInt160.is_valid()) { + throw new Error(name + ' must be a valid account'); } + + this.tx_json[name] = uInt160.to_json(); + return this; }; -/** - * Set secret If the secret has been set with Remote.setSecret, it does not - * need to be provided - * - * @param {String} secret - */ +Transaction.prototype.setAccount = function(account) { + return this._setAccount('Account', account); +}; -Transaction.prototype.setSecret = -Transaction.prototype.secret = function(secret) { - if (typeof secret === 'string') { - this._secret = secret; +Transaction.prototype._setAmount = function(name, amount, options_) { + const options = lodash.merge({no_native: false}, options_); + const parsedAmount = Amount.from_json(amount); + + if (parsedAmount.is_negative()) { + throw new Error(name + ' value must be non-negative'); } - return this; -}; -/** - * Set SendMax for Payment - * - * @param {String|Object} send max amount - */ + const isNative = parsedAmount.currency().is_native(); -Transaction.prototype.setSendMax = -Transaction.prototype.sendMax = function(send_max) { - if (send_max) { - this.tx_json.SendMax = Amount.json_rewrite(send_max); + if (isNative && options.no_native) { + throw new Error(name + ' must be a non-native amount'); + } + if (!(isNative || parsedAmount.currency().is_valid())) { + throw new Error(name + ' must have a valid currency'); } + if (!(isNative || parsedAmount.issuer().is_valid())) { + throw new Error(name + ' must have a valid issuer'); + } + + this.tx_json[name] = parsedAmount.to_json(); + return this; }; -/** - * Set TransferRate for AccountSet - * - * @param {Number} transfer raate - */ +Transaction.prototype._setHash256 = function(name, value, options_) { + if (typeof value !== 'string') { + throw new Error(name + ' must be a valid Hash256'); + } -Transaction.prototype.transferRate = function(rate) { - if (typeof rate === 'number' && rate >= 1e9) { - this.tx_json.TransferRate = rate; + const options = lodash.merge({pad: false}, options_); + let hash256 = value; + + if (options.pad) { + while (hash256.length < 64) { + hash256 += '0'; + } + } + + if (!/^[0-9A-Fa-f]{64}$/.test(hash256)) { + throw new Error(name + ' must be a valid Hash256'); } + + this.tx_json[name] = hash256; + return this; }; +Transaction.prototype.setAccountTxnID = +Transaction.prototype.accountTxnID = function(id) { + return this._setHash256('AccountTxnID', id); +}; + /** * Set Flags. You may specify flags as a number, as the string name of the * flag, or as an array of strings. @@ -799,16 +718,18 @@ Transaction.prototype.setFlags = function(flags) { return this; } - var transaction_flags = Transaction.flags[this.getTransactionType()] || { }; - var flag_set = Array.isArray(flags) ? flags : [].slice.call(arguments); + const transaction_flags = Transaction.flags[this.getType()] || { }; + const flag_set = Array.isArray(flags) ? flags : [].slice.call(arguments); - for (var i = 0, l = flag_set.length; i < l; i++) { - var flag = flag_set[i]; + for (let i = 0, l = flag_set.length; i < l; i++) { + const flag = flag_set[i]; if (transaction_flags.hasOwnProperty(flag)) { this.tx_json.Flags += transaction_flags[flag]; } else { - return this.emit('error', new RippleError('tejInvalidFlag')); + // XXX Should throw? + this.emit('error', new RippleError('tejInvalidFlag')); + return this; } } @@ -828,21 +749,29 @@ Transaction.prototype.setFlags = function(flags) { * be stringified (JSON) for transport */ -Transaction.prototype.addMemo = function(memoType, memoFormat, memoData) { - if (typeof memoType === 'object') { - var opts = memoType; - memoType = opts.memoType; - memoFormat = opts.memoFormat; - memoData = opts.memoData; +Transaction.prototype.addMemo = function(options_) { + let options; + + if (typeof options_ === 'object') { + options = lodash.merge({}, options_); + } else { + options = { + memoType: arguments[0], + memoFormat: arguments[1], + memoData: arguments[2] + }; } function convertStringToHex(string) { - var utf8String = sjcl.codec.utf8String.toBits(string); + const utf8String = sjcl.codec.utf8String.toBits(string); return sjcl.codec.hex.fromBits(utf8String).toUpperCase(); } - var memo = {}; - var memoRegex = Transaction.MEMO_REGEX; + const memo = {}; + const memoRegex = Transaction.MEMO_REGEX; + let memoType = options.memoType; + let memoFormat = options.memoFormat; + let memoData = options.memoData; if (memoType) { if (!(lodash.isString(memoType) && memoRegex.test(memoType))) { @@ -868,7 +797,7 @@ Transaction.prototype.addMemo = function(memoType, memoFormat, memoData) { if (memoData) { if (typeof memoData !== 'string') { - if (memoFormat === 'json') { + if (memoFormat.toLowerCase() === 'json') { try { memoData = JSON.stringify(memoData); } catch (e) { @@ -889,15 +818,6 @@ Transaction.prototype.addMemo = function(memoType, memoFormat, memoData) { return this; }; -Transaction.prototype.setAccountTxnID = -Transaction.prototype.accountTxnID = function(id) { - if (typeof id === 'string') { - this.tx_json.AccountTxnID = id; - } - - return this; -}; - /** * Construct an 'AccountSet' transaction * @@ -917,170 +837,209 @@ Transaction.prototype.accountTxnID = function(id) { * @param [String] clear flag */ -Transaction.prototype.accountSet = function(src, set_flag, clear_flag) { - if (typeof src === 'object') { - var options = src; - src = options.source || options.from || options.account; - set_flag = options.set_flag || options.set; - clear_flag = options.clear_flag || options.clear; - } +Transaction.prototype.accountSet = function(options_) { + let options; - if (!UInt160.is_valid(src)) { - throw new Error('Source address invalid'); - } + if (typeof options_ === 'object') { + options = lodash.merge({}, options_); - this.tx_json.TransactionType = 'AccountSet'; - this.tx_json.Account = UInt160.json_rewrite(src); + if (lodash.isUndefined(options.account)) { + options.account = options.src; + } + if (lodash.isUndefined(options.set_flag)) { + options.set_flag = options.set; + } + if (lodash.isUndefined(options.clear_flag)) { + options.clear_flag = options.clear; + } + } else { + options = { + account: arguments[0], + set_flag: arguments[1], + clear_flag: arguments[2] + }; + } - var SetClearFlags = Transaction.set_clear_flags.AccountSet; + this.setType('AccountSet'); + this.setAccount(options.account); - function prepareFlag(flag) { - return (typeof flag === 'number') - ? flag - : (SetClearFlags[flag] || SetClearFlags['asf' + flag]); + if (!lodash.isUndefined(options.set_flag)) { + this.setSetFlag(options.set_flag); + } + if (!lodash.isUndefined(options.clear_flag)) { + this.setClearFlag(options.clear_flag); } - var prepared; + return this; +}; - if (set_flag) { - prepared = prepareFlag(set_flag); +Transaction.prototype.setAccountSetFlag = function(name, value) { + // if (this.getType() !== 'AccountSet') { + // throw new Error('TransactionType must be AccountSet to use ' + name); + // } - if (prepared) { - this.tx_json.SetFlag = prepared; - } - } + const accountSetFlags = Transaction.set_clear_flags.AccountSet; + let flagValue = value; - if (clear_flag) { - prepared = prepareFlag(clear_flag); + if (typeof flagValue === 'string') { + flagValue = /^asf/.test(flagValue) + ? accountSetFlags[flagValue] + : accountSetFlags['asf' + flagValue]; + } - if (prepared) { - this.tx_json.ClearFlag = prepared; - } + if (!lodash.contains(lodash.values(accountSetFlags), flagValue)) { + throw new Error(name + ' must be a valid AccountSet flag'); } + this.tx_json[name] = flagValue; + return this; }; +Transaction.prototype.setSetFlag = function(flag) { + return this.setAccountSetFlag('SetFlag', flag); +}; + +Transaction.prototype.setClearFlag = function(flag) { + return this.setAccountSetFlag('ClearFlag', flag); +}; + /** - * Construct a 'Claim' transaction + * Set TransferRate for AccountSet + * + * @param {Number} transfer rate */ -Transaction.prototype.claim = function(src, generator, public_key, signature) { - if (typeof src === 'object') { - var options = src; - signature = options.signature; - public_key = options.public_key; - generator = options.generator; - src = options.source || options.from || options.account; +Transaction.prototype.setTransferRate = +Transaction.prototype.transferRate = function(rate) { + /* eslint-disable max-len */ + // if (this.getType() !== 'AccountSet') { + // throw new Error('TransactionType must be AccountSet to use TransferRate'); + // } + /* eslint-enable max-len */ + + let transferRate = rate; + + if (transferRate === 0) { + // Clear TransferRate + this.tx_json.TransferRate = transferRate; + return this; } - this.tx_json.TransactionType = 'Claim'; - this.tx_json.Generator = generator; - this.tx_json.PublicKey = public_key; - this.tx_json.Signature = signature; + // if (rate >= 1 && rate < 2) { + // transferRate *= 1e9; + // } - return this; + return this._setUInt32('TransferRate', transferRate, {min_value: 1e9}); }; /** - * Construct an 'OfferCancel' transaction + * Construct a 'SetRegularKey' transaction + * + * If the RegularKey is set, the private key that corresponds to it can be + * used to sign transactions instead of the master key + * + * The RegularKey must be a valid Ripple Address, or a Hash160 of the public + * key corresponding to the new private signing key. * * @param {String} account - * @param [Number] sequence of an existing offer + * @param {String} regular key */ -Transaction.prototype.offerCancel = function(src, sequence) { - if (typeof src === 'object') { - var options = src; - sequence = options.sequence; - src = options.source || options.from || options.account; - } +Transaction.prototype.setRegularKey = function(options_) { + let options; + + if (typeof options_ === 'object') { + options = lodash.merge({}, options_); - if (!UInt160.is_valid(src)) { - throw new Error('Source address invalid'); + if (lodash.isUndefined(options.account)) { + options.account = options.src; + } + } else { + options = { + account: arguments[0], + regular_key: arguments[1] + }; } - this.tx_json.TransactionType = 'OfferCancel'; - this.tx_json.Account = UInt160.json_rewrite(src); - this.tx_json.OfferSequence = Number(sequence); + this.setType('SetRegularKey'); + this.setAccount(options.account); + + if (!lodash.isUndefined(options.regular_key)) { + this._setAccount('RegularKey', options.regular_key); + } return this; }; /** - * Construct an 'OfferCreate transaction + * Construct a 'TrustSet' transaction * * @param {String} account - * @param {Amount} taker pays amount - * @param {Amount} taker gets amount - * @param [Number|Date] - * @param [Number] sequence of an existing offer to replace + * @param [Amount] limit + * @param [Number] quality in + * @param [Number] quality out */ -Transaction.prototype.offerCreate = function(src, taker_pays, taker_gets, - expiration, cancel_sequence) { - if (typeof src === 'object') { - var options = src; - cancel_sequence = options.cancel_sequence || options.sequence; - expiration = options.expiration; - taker_gets = options.taker_gets || options.sell; - taker_pays = options.taker_pays || options.buy; - src = options.source || options.from || options.account; - } +Transaction.prototype.trustSet = +Transaction.prototype.rippleLineSet = function(options_) { + let options; - if (!UInt160.is_valid(src)) { - throw new Error('Source address invalid'); + if (typeof options_ === 'object') { + options = lodash.merge({}, options_); + + if (lodash.isUndefined(options.account)) { + options.account = options.src; + } + } else { + options = { + account: arguments[0], + limit: arguments[1], + quality_in: arguments[2], + quality_out: arguments[3] + }; } - this.tx_json.TransactionType = 'OfferCreate'; - this.tx_json.Account = UInt160.json_rewrite(src); - this.tx_json.TakerPays = Amount.json_rewrite(taker_pays); - this.tx_json.TakerGets = Amount.json_rewrite(taker_gets); + this.setType('TrustSet'); + this.setAccount(options.account); - if (expiration) { - this.tx_json.Expiration = utils.time.toRipple(expiration); + if (!lodash.isUndefined(options.limit)) { + this.setLimit(options.limit); } - - if (cancel_sequence) { - this.tx_json.OfferSequence = Number(cancel_sequence); + if (!lodash.isUndefined(options.quality_in)) { + this.setQualityIn(options.quality_in); + } + if (!lodash.isUndefined(options.quality_out)) { + this.setQualityOut(options.quality_out); } + // XXX Throw an error if nothing is set. + return this; }; -/** - * Construct a 'SetRegularKey' transaction - * - * If the RegularKey is set, the private key that corresponds to it can be - * used to sign transactions instead of the master key - * - * The RegularKey must be a valid Ripple Address, or a Hash160 of the public - * key corresponding to the new private signing key. - * - * @param {String} account - * @param {String} regular key - */ +Transaction.prototype.setLimit = function(amount) { + // if (this.getType() !== 'TrustSet') { + // throw new Error('TransactionType must be TrustSet to use LimitAmount'); + // } -Transaction.prototype.setRegularKey = function(src, regular_key) { - if (typeof src === 'object') { - var options = src; - src = options.address || options.account || options.from; - regular_key = options.regular_key; - } + return this._setAmount('LimitAmount', amount, {no_native: true}); +}; - if (!UInt160.is_valid(src)) { - throw new Error('Source address invalid'); - } +Transaction.prototype.setQualityIn = function(quality) { + // if (this.getType() !== 'TrustSet') { + // throw new Error('TransactionType must be TrustSet to use QualityIn'); + // } - if (!UInt160.is_valid(regular_key)) { - throw new Error('RegularKey must be a valid Ripple Address'); - } + return this._setUInt32('QualityIn', quality); +}; - this.tx_json.TransactionType = 'SetRegularKey'; - this.tx_json.Account = UInt160.json_rewrite(src); - this.tx_json.RegularKey = UInt160.json_rewrite(regular_key); +Transaction.prototype.setQualityOut = function(quality) { + // if (this.getType() !== 'TrustSet') { + // throw new Error('TransactionType must be TrustSet to use QualityOut'); + // } - return this; + return this._setUInt32('QualityOut', quality); }; /** @@ -1096,76 +1055,322 @@ Transaction.prototype.setRegularKey = function(src, regular_key) { * - setFlags() * * @param {String} source account - * @param {StrinG} destination account + * @param {String} destination account * @param {Amount} payment amount */ -Transaction.prototype.payment = function(src, dst, amount) { - if (typeof src === 'object') { - var options = src; - amount = options.amount; - dst = options.destination || options.to; - src = options.source || options.from || options.account; +Transaction.prototype.payment = function(options_) { + let options; + + if (typeof options_ === 'object') { + options = lodash.merge({}, options_); + + if (lodash.isUndefined(options.account)) { + options.account = options.src || options.from; + } + if (lodash.isUndefined(options.destination)) { + options.destination = options.dst || options.to; + } + } else { + options = { + account: arguments[0], + destination: arguments[1], + amount: arguments[2] + }; } - if (!UInt160.is_valid(src)) { - throw new Error('Payment source address invalid'); + this.setType('Payment'); + this.setAccount(options.account); + this.setDestination(options.destination); + this.setAmount(options.amount); + + return this; +}; + +Transaction.prototype.setAmount = function(amount) { + // if (this.getType() !== 'Payment') { + // throw new Error('TransactionType must be Payment to use SendMax'); + // } + + return this._setAmount('Amount', amount); +}; + +Transaction.prototype.setDestination = function(destination) { + // if (this.getType() !== 'Payment') { + // throw new Error('TransactionType must be Payment to use Destination'); + // } + + return this._setAccount('Destination', destination); +}; + +/** + * Set SendMax for Payment + * + * @param {String|Object} send max amount + */ + +Transaction.prototype.setSendMax = +Transaction.prototype.sendMax = function(send_max) { + // if (this.getType() !== 'Payment') { + // throw new Error('TransactionType must be Payment to use SendMax'); + // } + + return this._setAmount('SendMax', send_max); +}; + +/** + * Filter invalid properties from path objects in a path array + * + * Valid properties are: + * - account + * - currency + * - issuer + * - type_hex + * + * @param {Array} path + * @return {Array} filtered path + */ + +Transaction._rewritePath = function(path) { + const newPath = path.map(function(node) { + const newNode = { }; + + if (node.hasOwnProperty('account')) { + newNode.account = UInt160.json_rewrite(node.account); + } + + if (node.hasOwnProperty('issuer')) { + newNode.issuer = UInt160.json_rewrite(node.issuer); + } + + if (node.hasOwnProperty('currency')) { + newNode.currency = Currency.json_rewrite(node.currency); + } + + if (node.hasOwnProperty('type_hex')) { + newNode.type_hex = node.type_hex; + } + + return newNode; + }); + + return newPath; +}; + +/** + * Add a path for Payment transaction + * + * @param {Array} path + */ + +Transaction.prototype.addPath = +Transaction.prototype.pathAdd = function(path) { + if (!Array.isArray(path)) { + throw new Error('Path must be an array'); } + // if (this.getType() !== 'Payment') { + // throw new Error('TransactionType must be Payment to use Paths'); + // } + + this.tx_json.Paths = this.tx_json.Paths || []; + this.tx_json.Paths.push(Transaction._rewritePath(path)); + + return this; +}; + +/** + * Set paths for Payment transaction + * + * @param {Array} paths + */ - if (!UInt160.is_valid(dst)) { - throw new Error('Payment destination address invalid'); +Transaction.prototype.setPaths = +Transaction.prototype.paths = function(paths) { + if (!Array.isArray(paths)) { + throw new Error('Paths must be an array'); } + // if (this.getType() !== 'Payment') { + // throw new Error('TransactionType must be Payment to use Paths'); + // } - this.tx_json.TransactionType = 'Payment'; - this.tx_json.Account = UInt160.json_rewrite(src); - this.tx_json.Amount = Amount.json_rewrite(amount); - this.tx_json.Destination = UInt160.json_rewrite(dst); + this.tx_json.Paths = []; + paths.forEach(this.addPath, this); return this; }; /** - * Construct a 'TrustSet' transaction + * Set build_path to have server blindly construct a path for Payment + * + * "blindly" because the sender has no idea of the actual cost must be less + * than send max. + * + * @param {Boolean} build path + */ + +Transaction.prototype.setBuildPath = +Transaction.prototype.buildPath = function(build) { + // if (this.getType() !== 'Payment') { + // throw new Error('TransactionType must be Payment to use build_path'); + // } + + this._build_path = build === undefined || build; + + return this; +}; + +/** + * Set DestinationTag for Payment transaction + * + * @param {Number} destination tag + */ + +Transaction.prototype.setDestinationTag = +Transaction.prototype.destinationTag = function(tag) { + // if (this.getType() !== 'Payment') { + // throw new Error('TransactionType must be Payment to use DestinationTag'); + // } + + return this._setUInt32('DestinationTag', tag); +}; + +/** + * Set InvoiceID for Payment transaction + * + * @param {String} id + */ + +Transaction.prototype.setInvoiceID = +Transaction.prototype.invoiceID = function(id) { + // if (this.getType() !== 'Payment') { + // throw new Error('TransactionType must be Payment to use InvoiceID'); + // } + + return this._setHash256('InvoiceID', id, {pad: true}); +}; + +/** + * Construct an 'OfferCreate transaction * * @param {String} account - * @param {Amount} limit - * @param {Number} quality in - * @param {Number} quality out + * @param {Amount} taker pays amount + * @param {Amount} taker gets amount + * @param [Number|Date] expiration + * @param [Number] sequence of an existing offer to replace */ -Transaction.prototype.trustSet = -Transaction.prototype.rippleLineSet = function(src, - limit, - quality_in, - quality_out) { - if (typeof src === 'object') { - var options = src; - quality_out = options.quality_out; - quality_in = options.quality_in; - limit = options.limit; - src = options.source || options.from || options.account; - } +Transaction.prototype.offerCreate = function(options_) { + let options; - if (!UInt160.is_valid(src)) { - throw new Error('Source address invalid'); + if (typeof options_ === 'object') { + options = lodash.merge({}, options_); + + if (lodash.isUndefined(options.account)) { + options.account = options.src; + } + if (lodash.isUndefined(options.taker_pays)) { + options.taker_pays = options.buy; + } + if (lodash.isUndefined(options.taker_gets)) { + options.taker_gets = options.sell; + } + if (lodash.isUndefined(options.offer_sequence)) { + options.offer_sequence = options.cancel_sequence || options.sequence; + } + } else { + options = { + account: arguments[0], + taker_pays: arguments[1], + taker_gets: arguments[2], + expiration: arguments[3], + offer_sequence: arguments[4] + }; } - this.tx_json.TransactionType = 'TrustSet'; - this.tx_json.Account = UInt160.json_rewrite(src); + this.setType('OfferCreate'); + this.setAccount(options.account); + this.setTakerGets(options.taker_gets); + this.setTakerPays(options.taker_pays); - if (limit !== undefined) { - this.tx_json.LimitAmount = Amount.json_rewrite(limit); + if (!lodash.isUndefined(options.expiration)) { + this.setExpiration(options.expiration); } - - if (quality_in) { - this.tx_json.QualityIn = quality_in; + if (!lodash.isUndefined(options.offer_sequence)) { + this.setOfferSequence(options.offer_sequence); } - if (quality_out) { - this.tx_json.QualityOut = quality_out; + return this; +}; + +Transaction.prototype.setTakerGets = function(amount) { + // if (this.getType() !== 'OfferCreate') { + // throw new Error('TransactionType must be OfferCreate to use TakerGets'); + // } + + return this._setAmount('TakerGets', amount); +}; + +Transaction.prototype.setTakerPays = function(amount) { + // if (this.getType() !== 'OfferCreate') { + // throw new Error('TransactionType must be OfferCreate to use TakerPays'); + // } + + return this._setAmount('TakerPays', amount); +}; + +Transaction.prototype.setExpiration = function(expiration) { + // if (this.getType() !== 'OfferCreate') { + // throw new Error('TransactionType must be OfferCreate to use Expiration'); + // } + + let timeOffset = expiration instanceof Date + ? expiration.getTime() + : expiration; + + return this._setUInt32('Expiration', utils.time.toRipple(timeOffset)); +}; + +Transaction.prototype.setOfferSequence = function(offerSequence) { + /* eslint-disable max-len */ + // if (!/^Offer(Cancel|Create)$/.test(this.getType())) { + // throw new Error( + // 'TransactionType must be OfferCreate or OfferCancel to use OfferSequence' + // ); + // } + /* eslint-enable max-len */ + + return this._setUInt32('OfferSequence', offerSequence); +}; + +/** + * Construct an 'OfferCancel' transaction + * + * @param {String} account + * @param [Number] sequence of an existing offer + */ + +Transaction.prototype.offerCancel = function(options_) { + let options; + + if (typeof options_ === 'object') { + options = lodash.merge({}, options_); + + if (lodash.isUndefined(options.account)) { + options.account = options.src; + } + if (lodash.isUndefined(options.offer_sequence)) { + options.offer_sequence = options.sequence || options.cancel_sequence; + } + } else { + options = { + account: arguments[0], + offer_sequence: arguments[1] + }; } - // XXX Throw an error if nothing is set. + this.setType('OfferCancel'); + this.setAccount(options.account); + this.setOfferSequence(options.offer_sequence); return this; }; @@ -1177,14 +1382,17 @@ Transaction.prototype.rippleLineSet = function(src, */ Transaction.prototype.submit = function(callback) { - var self = this; + const self = this; this.callback = (typeof callback === 'function') ? callback : function() {}; - this._errorHandler = function transactionError(error, message) { + this._errorHandler = function transactionError(error_, message) { + let error = error_; + if (!(error instanceof RippleError)) { error = new RippleError(error, message); } + self.callback(error); }; @@ -1197,6 +1405,13 @@ Transaction.prototype.submit = function(callback) { return this; } + /* eslint-disable max-len */ + // if (this.state !== 'unsubmitted') { + // this.emit('error', new Error('Attempt to submit transaction more than once')); + // return; + // } + /* eslint-enable max-len */ + this.getManager().submit(this); return this; @@ -1206,6 +1421,8 @@ Transaction.prototype.abort = function() { if (!this.finalized) { this.emit('error', new RippleError('tejAbort', 'Transaction aborted')); } + + return this; }; /** @@ -1216,7 +1433,7 @@ Transaction.prototype.abort = function() { Transaction.prototype.getSummary = Transaction.prototype.summary = function() { - var txSummary = { + let txSummary = { tx_json: this.tx_json, clientID: this._clientID, submittedIDs: this.submittedIDs, @@ -1229,7 +1446,7 @@ Transaction.prototype.summary = function() { }; if (this.result) { - var transaction_hash = this.result.tx_json + const transaction_hash = this.result.tx_json ? this.result.tx_json.hash : undefined; diff --git a/src/transactionmanager.js b/src/transactionmanager.js index ca6332f5d4..1785e0a449 100644 --- a/src/transactionmanager.js +++ b/src/transactionmanager.js @@ -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. diff --git a/test/transaction-manager-test.js b/test/transaction-manager-test.js index 53e223f7d0..82c772af8f 100644 --- a/test/transaction-manager-test.js +++ b/test/transaction-manager-test.js @@ -1,51 +1,50 @@ /* eslint-disable max-len */ -/* eslint-disable comma-spacing */ '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; - -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 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; + +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; -var SUBMIT_REMOTE_ERROR = require('./fixtures/transactionmanager') +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( @@ -56,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)); @@ -75,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; }); @@ -110,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')); @@ -126,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(); @@ -137,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'); @@ -160,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' }); @@ -173,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); @@ -185,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(); }); @@ -196,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) { @@ -219,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() { @@ -241,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() { @@ -263,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(); } }); @@ -273,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; @@ -296,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; @@ -324,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(); } @@ -336,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); @@ -356,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}); }); @@ -365,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() @@ -381,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}); }); @@ -390,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() { @@ -406,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; @@ -427,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); @@ -445,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'); }); @@ -465,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(); @@ -483,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' @@ -491,7 +490,7 @@ 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'); }); @@ -501,7 +500,7 @@ describe('TransactionManager', function() { }); 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': @@ -530,7 +529,7 @@ describe('TransactionManager', function() { assert.strictEqual(transactionManager.getPending().length(), 0); assert.strictEqual(transactionManager.getPending().length(), 0); - var summary = transaction.summary(); + const summary = transaction.summary(); assert.strictEqual(summary.submissionAttempts, 1); assert.strictEqual(summary.submitIndex, 2); assert.strictEqual(summary.initialSubmitIndex, 2); @@ -549,15 +548,15 @@ describe('TransactionManager', function() { }); 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'); }); @@ -591,7 +590,7 @@ describe('TransactionManager', function() { assert.strictEqual(err.engine_result, 'tejMaxLedger'); assert.strictEqual(transactionManager.getPending().length(), 0); - var summary = transaction.summary(); + const summary = transaction.summary(); assert.strictEqual(summary.submissionAttempts, 2); assert.strictEqual(summary.submitIndex, 3); assert.strictEqual(summary.initialSubmitIndex, 2); @@ -610,12 +609,12 @@ describe('TransactionManager', function() { }); 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'); }); @@ -649,7 +648,7 @@ describe('TransactionManager', function() { assert.strictEqual(err.engine_result, 'tejMaxLedger'); assert.strictEqual(transactionManager.getPending().length(), 0); - var summary = transaction.summary(); + const summary = transaction.summary(); assert.strictEqual(summary.submissionAttempts, 2); assert.strictEqual(summary.submitIndex, 3); assert.strictEqual(summary.initialSubmitIndex, 2); @@ -670,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 }); @@ -682,7 +681,7 @@ describe('TransactionManager', function() { assert.strictEqual(err.engine_result, 'tejSecretInvalid'); assert.strictEqual(transactionManager.getPending().length(), 0); - var summary = transaction.summary(); + const summary = transaction.summary(); assert.deepEqual(summary.tx_json, transaction.tx_json); assert.strictEqual(summary.submissionAttempts, 0); assert.strictEqual(summary.submitIndex, undefined); @@ -702,7 +701,7 @@ describe('TransactionManager', function() { }); it('Submit transaction -- remote error', function(done) { - var transaction = remote.createTransaction('Payment', { + const transaction = remote.createTransaction('Payment', { account: ACCOUNT.address, destination: ACCOUNT2.address, amount: '1' @@ -710,7 +709,7 @@ describe('TransactionManager', function() { // MemoType must contain only valid URL characters (RFC 3986). This // transaction is invalid - //transaction.addMemo('my memotype','my_memo_data'); + // transaction.addMemo('my memotype','my_memo_data'); transaction.tx_json.Memos = [{ Memo: { MemoType: '6D79206D656D6F74797065', @@ -718,7 +717,7 @@ describe('TransactionManager', function() { } }]; - var receivedSubmitted = false; + let receivedSubmitted = false; transaction.once('proposed', function() { assert(false, 'Should not receive proposed event'); }); @@ -732,14 +731,14 @@ describe('TransactionManager', function() { assert.strictEqual(m.tx_blob, SerializedObject.from_json( transaction.tx_json).to_hex()); - /* eslint-disable max-len */ + /* 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 + // 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 */ + /* eslint-enable max-len */ - req.sendResponse(SUBMIT_REMOTE_ERROR, {id: m.id}); + req.sendResponse(SUBMIT_REMOTE_ERROR, {id: m.id}); }); transaction.submit(function(err) { @@ -749,7 +748,7 @@ describe('TransactionManager', function() { assert.strictEqual(err.remote.error, 'invalidTransaction'); assert.strictEqual(transactionManager.getPending().length(), 0); - var summary = transaction.summary(); + const summary = transaction.summary(); assert.deepEqual(summary.tx_json, transaction.tx_json); assert.strictEqual(summary.submissionAttempts, 1); assert.strictEqual(summary.submitIndex, 2); diff --git a/test/transaction-test.js b/test/transaction-test.js index ca38cce815..8ed048e31e 100644 --- a/test/transaction-test.js +++ b/test/transaction-test.js @@ -2,15 +2,15 @@ 'use strict'; -var assert = require('assert'); -var lodash = require('lodash'); -var Transaction = require('ripple-lib').Transaction; -var TransactionQueue = require('ripple-lib').TransactionQueue; -var Remote = require('ripple-lib').Remote; -var Server = require('ripple-lib').Server; -var sjcl = require('ripple-lib').sjcl; - -var transactionResult = { +const assert = require('assert'); +const lodash = require('lodash'); +const Transaction = require('ripple-lib').Transaction; +const TransactionQueue = require('ripple-lib').TransactionQueue; +const Remote = require('ripple-lib').Remote; +const Server = require('ripple-lib').Server; +const sjcl = require('ripple-lib').sjcl; + +const transactionResult = { engine_result: 'tesSUCCESS', engine_result_code: 0, engine_result_message: 'The transaction was applied.', @@ -41,13 +41,13 @@ var transactionResult = { }; // https://github.com/ripple/rippled/blob/c61d0c663e410c3d3622f20092535710243b55af/src/ripple/protocol/impl/STTx.cpp#L342-L370 -var allowed_memo_chars = ('0123456789-._~:/?#[]@!$&\'()*+,;=%ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz').split(''); +const allowed_memo_chars = ('0123456789-._~:/?#[]@!$&\'()*+,;=%ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz').split(''); // Disallowed ASCII characters -var disallowed_memo_chars = []; +const disallowed_memo_chars = []; -for (var i = 0; i <= 127; i++) { - var char = String.fromCharCode(i); +for (let i = 0; i <= 127; i++) { + const char = String.fromCharCode(i); if (!lodash.contains(allowed_memo_chars, char)) { disallowed_memo_chars.push(char); } @@ -60,7 +60,7 @@ describe('Transaction', function() { }); it('Success listener', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.once('final', function(message) { assert.deepEqual(message, transactionResult); @@ -73,7 +73,7 @@ describe('Transaction', function() { }); it('Error listener', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.once('final', function(message) { assert.deepEqual(message, transactionResult); @@ -86,19 +86,19 @@ describe('Transaction', function() { }); it('Submitted listener', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.emit('submitted'); assert.strictEqual(transaction.state, 'submitted'); }); it('Proposed listener', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.emit('proposed'); assert.strictEqual(transaction.state, 'pending'); }); it('Check response code is tel', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); assert(!transaction.isTelLocal(-400)); assert(transaction.isTelLocal(-399)); assert(transaction.isTelLocal(-300)); @@ -106,7 +106,7 @@ describe('Transaction', function() { }); it('Check response code is tem', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); assert(!transaction.isTemMalformed(-300)); assert(transaction.isTemMalformed(-299)); assert(transaction.isTemMalformed(-200)); @@ -114,7 +114,7 @@ describe('Transaction', function() { }); it('Check response code is tef', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); assert(!transaction.isTefFailure(-200)); assert(transaction.isTefFailure(-199)); assert(transaction.isTefFailure(-100)); @@ -122,7 +122,7 @@ describe('Transaction', function() { }); it('Check response code is ter', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); assert(!transaction.isTerRetry(-100)); assert(transaction.isTerRetry(-99)); assert(transaction.isTerRetry(-1)); @@ -130,21 +130,21 @@ describe('Transaction', function() { }); it('Check response code is tep', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); assert(!transaction.isTepSuccess(-1)); assert(transaction.isTepSuccess(0)); assert(transaction.isTepSuccess(1e3)); }); it('Check response code is tec', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); assert(!transaction.isTecClaimed(99)); assert(transaction.isTecClaimed(100)); assert(transaction.isTecClaimed(1e3)); }); it('Check response code is rejected', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); assert(!transaction.isRejected(0)); assert(!transaction.isRejected(-99)); assert(transaction.isRejected(-100)); @@ -153,12 +153,12 @@ describe('Transaction', function() { }); it('Set state', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); assert.strictEqual(transaction.state, 'unsubmitted'); - var receivedEvents = 0; - var events = [ + let receivedEvents = 0; + const events = [ 'submitted', 'pending', 'validated' @@ -180,9 +180,9 @@ describe('Transaction', function() { }); it('Finalize submission', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); - var tx = transactionResult; + const tx = transactionResult; tx.ledger_hash = '2031E311FD28A6BZ76Z7BD6ECF8E6661521902E7A6A8EF069A2F3C628E76A322'; tx.ledger_index = 7106150; @@ -194,7 +194,7 @@ describe('Transaction', function() { }); it('Finalize unsubmitted', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.finalize(transactionResult); assert.strictEqual(transaction.result.ledger_index, transactionResult.ledger_index); @@ -202,14 +202,14 @@ describe('Transaction', function() { }); it('Get account secret', function() { - var remote = new Remote(); + const remote = new Remote(); remote.secrets = { rpzT237Ctpaa58KieifoK8RyBmmRwEcfhK: 'shY1njzHAXp8Qt3bpxYW6RpoZtMKP', rpdxPs9CR93eLAc5DTvAgv4S9XJ1CzKj1a: 'ssboTJezioTq8obyvDU9tVo95NGGQ' }; - var transaction = new Transaction(remote); + const transaction = new Transaction(remote); assert.strictEqual(transaction._accountSecret('rpzT237Ctpaa58KieifoK8RyBmmRwEcfhK'), 'shY1njzHAXp8Qt3bpxYW6RpoZtMKP'); assert.strictEqual(transaction._accountSecret('rpdxPs9CR93eLAc5DTvAgv4S9XJ1CzKj1a'), 'ssboTJezioTq8obyvDU9tVo95NGGQ'); @@ -217,30 +217,30 @@ describe('Transaction', function() { }); it('Get fee units', function() { - var remote = new Remote(); - var transaction = new Transaction(remote); + const remote = new Remote(); + const transaction = new Transaction(remote); assert.strictEqual(transaction.feeUnits(), 10); }); it('Compute fee', function() { - var remote = new Remote(); + const remote = new Remote(); - var s1 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s1 = new Server(remote, 'wss://s-west.ripple.com:443'); s1._connected = true; - var s2 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s2 = new Server(remote, 'wss://s-west.ripple.com:443'); s2._connected = true; s2._load_factor = 256 * 4; - var s3 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s3 = new Server(remote, 'wss://s-west.ripple.com:443'); s3._connected = true; s3._load_factor = 256 * 8; - var s4 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s4 = new Server(remote, 'wss://s-west.ripple.com:443'); s4._connected = true; s4._load_factor = 256 * 8; - var s5 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s5 = new Server(remote, 'wss://s-west.ripple.com:443'); s5._connected = true; s5._load_factor = 256 * 7; @@ -252,27 +252,27 @@ describe('Transaction', function() { assert.strictEqual(s4._computeFee(10), '96'); assert.strictEqual(s5._computeFee(10), '84'); - var transaction = new Transaction(remote); + const transaction = new Transaction(remote); assert.strictEqual(transaction._computeFee(), '72'); }); it('Compute fee, no remote', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); assert.strictEqual(transaction._computeFee(10), undefined); }); it('Compute fee - no connected server', function() { - var remote = new Remote(); + const remote = new Remote(); - var s1 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s1 = new Server(remote, 'wss://s-west.ripple.com:443'); s1._connected = false; - var s2 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s2 = new Server(remote, 'wss://s-west.ripple.com:443'); s2._connected = false; s2._load_factor = 256 * 4; - var s3 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s3 = new Server(remote, 'wss://s-west.ripple.com:443'); s3._connected = false; s3._load_factor = 256 * 8; @@ -282,22 +282,22 @@ describe('Transaction', function() { assert.strictEqual(s2._computeFee(10), '48'); assert.strictEqual(s3._computeFee(10), '96'); - var transaction = new Transaction(remote); + const transaction = new Transaction(remote); assert.strictEqual(transaction._computeFee(), undefined); }); it('Compute fee - one connected server', function() { - var remote = new Remote(); + const remote = new Remote(); - var s1 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s1 = new Server(remote, 'wss://s-west.ripple.com:443'); s1._connected = false; - var s2 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s2 = new Server(remote, 'wss://s-west.ripple.com:443'); s2._connected = false; s2._load_factor = 256 * 4; - var s3 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s3 = new Server(remote, 'wss://s-west.ripple.com:443'); s3._connected = true; s3._load_factor = 256 * 8; @@ -307,27 +307,27 @@ describe('Transaction', function() { assert.strictEqual(s2._computeFee(10), '48'); assert.strictEqual(s3._computeFee(10), '96'); - var transaction = new Transaction(remote); + const transaction = new Transaction(remote); assert.strictEqual(transaction._computeFee(), '96'); }); it('Does not compute a median fee with floating point', function() { - var remote = new Remote(); + const remote = new Remote(); - var s1 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s1 = new Server(remote, 'wss://s-west.ripple.com:443'); s1._connected = true; - var s2 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s2 = new Server(remote, 'wss://s-west.ripple.com:443'); s2._connected = true; s2._load_factor = 256 * 4; - var s3 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s3 = new Server(remote, 'wss://s-west.ripple.com:443'); s3._connected = true; s3._load_factor = (256 * 7) + 1; - var s4 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s4 = new Server(remote, 'wss://s-west.ripple.com:443'); s4._connected = true; s4._load_factor = 256 * 16; @@ -339,35 +339,35 @@ describe('Transaction', function() { assert.strictEqual(s3._computeFee(10), '85'); assert.strictEqual(s4._computeFee(10), '192'); - var transaction = new Transaction(remote); + const transaction = new Transaction(remote); transaction.tx_json.Sequence = 1; - var src = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'; - var dst = 'rGihwhaqU8g7ahwAvTq6iX5rvsfcbgZw6v'; + const src = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'; + const dst = 'rGihwhaqU8g7ahwAvTq6iX5rvsfcbgZw6v'; transaction.payment(src, dst, '100'); remote.set_secret(src, 'masterpassphrase'); assert(transaction.complete()); - var json = transaction.serialize().to_json(); + const json = transaction.serialize().to_json(); assert.notStrictEqual(json.Fee, '66500000', 'Fee == 66500000, i.e. 66.5 XRP!'); }); it('Compute fee - even server count', function() { - var remote = new Remote(); + const remote = new Remote(); - var s1 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s1 = new Server(remote, 'wss://s-west.ripple.com:443'); s1._connected = true; - var s2 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s2 = new Server(remote, 'wss://s-west.ripple.com:443'); s2._connected = true; s2._load_factor = 256 * 4; - var s3 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s3 = new Server(remote, 'wss://s-west.ripple.com:443'); s3._connected = true; s3._load_factor = 256 * 8; - var s4 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s4 = new Server(remote, 'wss://s-west.ripple.com:443'); s4._connected = true; s4._load_factor = 256 * 16; @@ -379,22 +379,22 @@ describe('Transaction', function() { assert.strictEqual(s3._computeFee(10), '96'); assert.strictEqual(s4._computeFee(10), '192'); - var transaction = new Transaction(remote); + const transaction = new Transaction(remote); assert.strictEqual(transaction._computeFee(), '72'); }); it('Complete transaction', function(done) { - var remote = new Remote(); + const remote = new Remote(); - var s1 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s1 = new Server(remote, 'wss://s-west.ripple.com:443'); s1._connected = true; remote._servers = [s1]; remote.trusted = true; remote.local_signing = true; - var transaction = new Transaction(remote); + const transaction = new Transaction(remote); transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij'; transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ'; transaction.tx_json.Flags = 0; @@ -405,7 +405,7 @@ describe('Transaction', function() { }); it('Complete transaction, local signing, no remote', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij'; transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ'; @@ -415,8 +415,8 @@ describe('Transaction', function() { }); it('Complete transaction - untrusted', function(done) { - var remote = new Remote(); - var transaction = new Transaction(remote); + const remote = new Remote(); + const transaction = new Transaction(remote); remote.trusted = false; remote.local_signing = false; @@ -430,8 +430,8 @@ describe('Transaction', function() { }); it('Complete transaction - no secret', function(done) { - var remote = new Remote(); - var transaction = new Transaction(remote); + const remote = new Remote(); + const transaction = new Transaction(remote); remote.trusted = true; remote.local_signing = true; @@ -445,8 +445,8 @@ describe('Transaction', function() { }); it('Complete transaction - invalid secret', function(done) { - var remote = new Remote(); - var transaction = new Transaction(remote); + const remote = new Remote(); + const transaction = new Transaction(remote); remote.trusted = true; remote.local_signing = true; @@ -464,8 +464,8 @@ describe('Transaction', function() { }); it('Complete transaction - cached SigningPubKey', function(done) { - var remote = new Remote(); - var transaction = new Transaction(remote); + const remote = new Remote(); + const transaction = new Transaction(remote); remote.trusted = true; remote.local_signing = true; @@ -483,10 +483,10 @@ describe('Transaction', function() { }); it('Complete transaction - compute fee', function(done) { - var remote = new Remote(); - var transaction = new Transaction(remote); + const remote = new Remote(); + const transaction = new Transaction(remote); - var s1 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s1 = new Server(remote, 'wss://s-west.ripple.com:443'); s1._connected = true; remote._servers = [s1]; @@ -507,9 +507,9 @@ describe('Transaction', function() { }); it('Complete transaction - compute fee exceeds max fee', function(done) { - var remote = new Remote({max_fee: 10}); + const remote = new Remote({max_fee: 10}); - var s1 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s1 = new Server(remote, 'wss://s-west.ripple.com:443'); s1._connected = true; s1._load_factor = 256 * 16; @@ -517,7 +517,7 @@ describe('Transaction', function() { remote.trusted = true; remote.local_signing = true; - var transaction = new Transaction(remote); + const transaction = new Transaction(remote); transaction.tx_json.SigningPubKey = '021FED5FD081CE5C4356431267D04C6E2167E4112C897D5E10335D4E22B4DA49ED'; transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ'; transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij'; @@ -531,9 +531,9 @@ describe('Transaction', function() { }); it('Complete transaction - canonical flags', function(done) { - var remote = new Remote(); + const remote = new Remote(); - var s1 = new Server(remote, 'wss://s-west.ripple.com:443'); + const s1 = new Server(remote, 'wss://s-west.ripple.com:443'); s1._connected = true; s1._load_factor = 256; @@ -541,7 +541,7 @@ describe('Transaction', function() { remote.trusted = true; remote.local_signing = true; - var transaction = new Transaction(remote); + const transaction = new Transaction(remote); transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij'; transaction.tx_json.SigningPubKey = '021FED5FD081CE5C4356431267D04C6E2167E4112C897D5E10335D4E22B4DA49ED'; transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ'; @@ -554,7 +554,7 @@ describe('Transaction', function() { }); it('Get signing hash', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij'; transaction.tx_json.SigningPubKey = '021FED5FD081CE5C4356431267D04C6E2167E4112C897D5E10335D4E22B4DA49ED'; transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ'; @@ -569,7 +569,7 @@ describe('Transaction', function() { }); it('Get hash - no prefix', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij'; transaction.tx_json.SigningPubKey = '021FED5FD081CE5C4356431267D04C6E2167E4112C897D5E10335D4E22B4DA49ED'; transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ'; @@ -584,7 +584,7 @@ describe('Transaction', function() { }); it('Get hash - prefix', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij'; transaction.tx_json.SigningPubKey = '021FED5FD081CE5C4356431267D04C6E2167E4112C897D5E10335D4E22B4DA49ED'; transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ'; @@ -600,7 +600,7 @@ describe('Transaction', function() { }); it('Get hash - invalid prefix', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij'; transaction.tx_json.SigningPubKey = '021FED5FD081CE5C4356431267D04C6E2167E4112C897D5E10335D4E22B4DA49ED'; transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ'; @@ -617,7 +617,7 @@ describe('Transaction', function() { }); it('Get hash - complex transaction', function() { - var input_json = { + const input_json = { Account: 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS', Amount: { currency: 'LTC', @@ -662,14 +662,14 @@ describe('Transaction', function() { TxnSignature: '304602210096C2F385530587DE573936CA51CB86B801A28F777C944E268212BE7341440B7F022100EBF0508A9145A56CDA7FAF314DF3BBE51C6EE450BA7E74D88516891A3608644E' }; - var expected_hash = '87366146D381AD971B97DD41CFAC1AE4670B0E996AB574B0CE18CE6467811868'; - var transaction = Transaction.from_json(input_json); + const expected_hash = '87366146D381AD971B97DD41CFAC1AE4670B0E996AB574B0CE18CE6467811868'; + const transaction = Transaction.from_json(input_json); assert.deepEqual(transaction.hash(), expected_hash); }); it('Get hash - complex transaction including Memo', function() { - var input_json = { + const input_json = { Account: 'rfe8yiZUymRPx35BEwGjhfkaLmgNsTytxT', Amount: '1', Destination: 'r9kiSEUEw6iSCNksDVKf9k3AyxjW3r1qPf', @@ -746,7 +746,7 @@ describe('Transaction', function() { }); it('Serialize transaction', function() { - var input_json = { + const input_json = { Account: 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS', Amount: { currency: 'LTC', @@ -791,15 +791,15 @@ describe('Transaction', function() { TxnSignature: '304602210096C2F385530587DE573936CA51CB86B801A28F777C944E268212BE7341440B7F022100EBF0508A9145A56CDA7FAF314DF3BBE51C6EE450BA7E74D88516891A3608644E' }; - var expected_hex = '1200002200000000240000019F61D4A3794DFA1510000000000000000000000000004C54430000000000EF7ED76B77750D79EC92A59389952E0E8054407668400000000000000F69D4CAC4AC112283000000000000000000000000005553440000000000EF7ED76B77750D79EC92A59389952E0E80544076732102854B06CE8F3E65323F89260E9E19B33DA3E01B30EA4CA172612DE77973FAC58A7448304602210096C2F385530587DE573936CA51CB86B801A28F777C944E268212BE7341440B7F022100EBF0508A9145A56CDA7FAF314DF3BBE51C6EE450BA7E74D88516891A3608644E8114EF7ED76B77750D79EC92A59389952E0E805440768314EF7ED76B77750D79EC92A59389952E0E80544076011231DD39C650A96EDA48334E70CC4A85B8B2E8502CD30000000000000000000000005553440000000000DD39C650A96EDA48334E70CC4A85B8B2E8502CD3300000000000000000000000004C5443000000000047DA9E2E00ECF224A52329793F1BB20FB1B5EA643147DA9E2E00ECF224A52329793F1BB20FB1B5EA640000000000000000000000004C5443000000000047DA9E2E00ECF224A52329793F1BB20FB1B5EA6400'; + const expected_hex = '1200002200000000240000019F61D4A3794DFA1510000000000000000000000000004C54430000000000EF7ED76B77750D79EC92A59389952E0E8054407668400000000000000F69D4CAC4AC112283000000000000000000000000005553440000000000EF7ED76B77750D79EC92A59389952E0E80544076732102854B06CE8F3E65323F89260E9E19B33DA3E01B30EA4CA172612DE77973FAC58A7448304602210096C2F385530587DE573936CA51CB86B801A28F777C944E268212BE7341440B7F022100EBF0508A9145A56CDA7FAF314DF3BBE51C6EE450BA7E74D88516891A3608644E8114EF7ED76B77750D79EC92A59389952E0E805440768314EF7ED76B77750D79EC92A59389952E0E80544076011231DD39C650A96EDA48334E70CC4A85B8B2E8502CD30000000000000000000000005553440000000000DD39C650A96EDA48334E70CC4A85B8B2E8502CD3300000000000000000000000004C5443000000000047DA9E2E00ECF224A52329793F1BB20FB1B5EA643147DA9E2E00ECF224A52329793F1BB20FB1B5EA640000000000000000000000004C5443000000000047DA9E2E00ECF224A52329793F1BB20FB1B5EA6400'; - var transaction = Transaction.from_json(input_json); + const transaction = Transaction.from_json(input_json); assert.deepEqual(transaction.serialize().to_hex(), expected_hex); }); it('Sign transaction', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij'; transaction.tx_json.SigningPubKey = '021FED5FD081CE5C4356431267D04C6E2167E4112C897D5E10335D4E22B4DA49ED'; transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ'; @@ -810,7 +810,7 @@ describe('Transaction', function() { transaction.sign(); - var signature = transaction.tx_json.TxnSignature; + const signature = transaction.tx_json.TxnSignature; assert.strictEqual(transaction.previousSigningHash, 'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE'); assert(/^[A-Z0-9]+$/.test(signature)); @@ -826,7 +826,7 @@ describe('Transaction', function() { }); it('Add transaction ID', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.addId('D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE'); transaction.addId('F1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE'); @@ -842,7 +842,7 @@ describe('Transaction', function() { }); it('Find transaction IDs in cache', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); assert.deepEqual(transaction.findId({ F1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE: transaction @@ -862,34 +862,73 @@ describe('Transaction', function() { }); it('Set build_path', function() { - var transaction = new Transaction(); - transaction.buildPath(true); + const transaction = new Transaction(); + +// assert.throws(function() { +// transaction.buildPath(); +// }, /Error: TransactionType must be Payment to use build_path/); +// assert.throws(function() { +// transaction.setBuildPath(); +// }, /Error: TransactionType must be Payment to use build_path/); + + assert.strictEqual(transaction._build_path, false); + + transaction.setType('Payment'); + transaction.setBuildPath(); assert.strictEqual(transaction._build_path, true); + transaction.setBuildPath(false); + assert.strictEqual(transaction._build_path, false); }); it('Set DestinationTag', function() { - var transaction = new Transaction(); - transaction.destinationTag('tag'); + const transaction = new Transaction(); + +// assert.throws(function() { +// transaction.destinationTag(1); +// }, /Error: TransactionType must be Payment to use DestinationTag/); +// assert.throws(function() { +// transaction.setDestinationTag(1); +// }, /Error: TransactionType must be Payment to use DestinationTag/); + assert.strictEqual(transaction.tx_json.DestinationTag, undefined); - transaction.destinationTag(1); + + transaction.setType('Payment'); + + assert.throws(function() { + transaction.setDestinationTag('tag'); + }, /Error: DestinationTag must be a valid UInt32/); + + transaction.setDestinationTag(1); assert.strictEqual(transaction.tx_json.DestinationTag, 1); }); it('Set InvoiceID', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); + +// assert.throws(function() { +// transaction.invoiceID('DEADBEEF'); +// }, /Error: TransactionType must be Payment to use InvoiceID/); +// assert.strictEqual(transaction.tx_json.InvoiceID, undefined); + + transaction.setType('Payment'); + + assert.throws(function() { + transaction.setInvoiceID(1); + }, /Error: InvoiceID must be a valid Hash256/); - transaction.invoiceID(1); assert.strictEqual(transaction.tx_json.InvoiceID, undefined); - transaction.invoiceID('DEADBEEF'); + transaction.setType('Payment'); + + transaction.setInvoiceID('DEADBEEF'); assert.strictEqual(transaction.tx_json.InvoiceID, 'DEADBEEF00000000000000000000000000000000000000000000000000000000'); - transaction.invoiceID('FEADBEEF00000000000000000000000000000000000000000000000000000000'); + transaction.setInvoiceID('FEADBEEF00000000000000000000000000000000000000000000000000000000'); assert.strictEqual(transaction.tx_json.InvoiceID, 'FEADBEEF00000000000000000000000000000000000000000000000000000000'); }); it('Set ClientID', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.clientID(1); assert.strictEqual(transaction._clientID, undefined); @@ -899,23 +938,28 @@ describe('Transaction', function() { }); it('Set LastLedgerSequence', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); - transaction.lastLedger('a'); - assert.strictEqual(transaction.tx_json.LastLedgerSequence, undefined); - assert(!transaction._setLastLedger); + assert.throws(function() { + transaction.lastLedger('a'); + }, /Error: LastLedgerSequence must be a valid UInt32/); + assert.throws(function() { + transaction.setLastLedgerSequence('a'); + }, /Error: LastLedgerSequence must be a valid UInt32/); + assert.throws(function() { + transaction.setLastLedgerSequence(NaN); + }, /Error: LastLedgerSequence must be a valid UInt32/); - transaction.lastLedger(NaN); assert.strictEqual(transaction.tx_json.LastLedgerSequence, undefined); assert(!transaction._setLastLedger); - transaction.lastLedger(12); + transaction.setLastLedgerSequence(12); assert.strictEqual(transaction.tx_json.LastLedgerSequence, 12); assert(transaction._setLastLedger); }); it('Set Max Fee', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.maxFee('a'); assert(!transaction._setMaxFee); @@ -929,7 +973,7 @@ describe('Transaction', function() { }); it('Set Fixed Fee', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.setFixedFee('a'); assert(!transaction._setFixedFee); @@ -946,7 +990,7 @@ describe('Transaction', function() { }); it('Rewrite transaction path', function() { - var path = [ + const path = [ { account: 'rP51ycDJw5ZhgvdKiRjBYZKYjsyoCcHmnY', issuer: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', @@ -992,13 +1036,9 @@ describe('Transaction', function() { }); it('Add transaction path', function() { - var transaction = new Transaction(); - - transaction.pathAdd(1); + const transaction = new Transaction(); - assert.strictEqual(transaction.tx_json.Paths, undefined); - - var path = [ + const path = [ { account: 'rP51ycDJw5ZhgvdKiRjBYZKYjsyoCcHmnY', issuer: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', @@ -1007,7 +1047,7 @@ describe('Transaction', function() { } ]; - var path2 = [ + const path2 = [ { account: 'rP51ycDJw5ZhgvdKiRjBYZKYjsyoCcHmnY', issuer: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', @@ -1016,7 +1056,25 @@ describe('Transaction', function() { } ]; - transaction.pathAdd(path); +// assert.throws(function() { +// transaction.pathAdd(path); +// }, /^Error: TransactionType must be Payment to use Paths$/); +// assert.throws(function() { +// transaction.addPath(path); +// }, /^Error: TransactionType must be Payment to use Paths$/); + + assert.strictEqual(transaction.tx_json.Paths, undefined); + + transaction.setType('Payment'); + + assert.throws(function() { + transaction.pathAdd(1); + }, /^Error: Path must be an array$/); + assert.throws(function() { + transaction.addPath(1); + }, /^Error: Path must be an array$/); + + transaction.addPath(path); assert.deepEqual(transaction.tx_json.Paths, [ [{ @@ -1026,7 +1084,7 @@ describe('Transaction', function() { }] ]); - transaction.pathAdd(path2); + transaction.addPath(path2); assert.deepEqual(transaction.tx_json.Paths, [ [{ @@ -1043,26 +1101,43 @@ describe('Transaction', function() { }); it('Add transaction paths', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); + + const paths = [ + [{ + account: 'rP51ycDJw5ZhgvdKiRjBYZKYjsyoCcHmnY', + issuer: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', + test: 1, + currency: 'USD' + }], + [{ + account: 'rP51ycDJw5ZhgvdKiRjBYZKYjsyoCcHmnY', + issuer: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', + test: 2, + currency: 'USD' + }] + ]; - transaction.paths(1); +// assert.throws(function() { +// transaction.paths(paths); +// }, /Error: TransactionType must be Payment to use Paths/); +// assert.throws(function() { +// transaction.setPaths(paths); +// }, /Error: TransactionType must be Payment to use Paths/); assert.strictEqual(transaction.tx_json.Paths, undefined); - transaction.paths([ - [{ - account: 'rP51ycDJw5ZhgvdKiRjBYZKYjsyoCcHmnY', - issuer: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', - test: 1, - currency: 'USD' - }], - [{ - account: 'rP51ycDJw5ZhgvdKiRjBYZKYjsyoCcHmnY', - issuer: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', - test: 2, - currency: 'USD' - }] - ]); + transaction.setType('Payment'); + + assert.throws(function() { + transaction.paths(1); + }, /Error: Paths must be an array/); + assert.throws(function() { + transaction.setPaths(1); + }, /Error: Paths must be an array/); + + transaction.setPaths(paths); + transaction.setPaths(paths); assert.deepEqual(transaction.tx_json.Paths, [ [{ @@ -1079,14 +1154,24 @@ describe('Transaction', function() { }); it('Set secret', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.secret('shHXjwp9m3MDQNcUrTekXcdzFsCjM'); assert.strictEqual(transaction._secret, 'shHXjwp9m3MDQNcUrTekXcdzFsCjM'); }); it('Set SendMax', function() { - var transaction = new Transaction(); - transaction.sendMax('1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'); + const transaction = new Transaction(); + +// assert.throws(function() { +// transaction.sendMax('1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'); +// }, /^Error: TransactionType must be Payment to use SendMax$/); +// assert.throws(function() { +// transaction.setSendMax('1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'); +// }, /^Error: TransactionType must be Payment to use SendMax$/); + + transaction.setType('Payment'); + transaction.setSendMax('1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'); + assert.deepEqual(transaction.tx_json.SendMax, { value: '1', currency: 'USD', @@ -1095,48 +1180,67 @@ describe('Transaction', function() { }); it('Set SourceTag', function() { - var transaction = new Transaction(); - transaction.sourceTag('tag'); + const transaction = new Transaction(); + + assert.throws(function() { + transaction.sourceTag('tag'); + }, /Error: SourceTag must be a valid UInt32/); + assert.strictEqual(transaction.tx_json.SourceTag, undefined); transaction.sourceTag(1); assert.strictEqual(transaction.tx_json.SourceTag, 1); + transaction.setSourceTag(2); + assert.strictEqual(transaction.tx_json.SourceTag, 2); }); it('Set TransferRate', function() { - var transaction = new Transaction(); - transaction.transferRate(1); + const transaction = new Transaction(); + transaction.setType('AccountSet'); + + assert.throws(function() { + transaction.transferRate(1); + }, /^Error: TransferRate must be >= 1000000000$/); + assert.throws(function() { + transaction.setTransferRate(1); + }, /^Error: TransferRate must be >= 1000000000$/); + assert.throws(function() { + transaction.setTransferRate('a'); + }, /^Error: TransferRate must be a valid UInt32$/); + assert.strictEqual(transaction.tx_json.TransferRate, undefined); - transaction.transferRate(1.5 * 1e9); + transaction.setTransferRate(1.5 * 1e9); assert.strictEqual(transaction.tx_json.TransferRate, 1.5 * 1e9); + transaction.setTransferRate(0); + assert.strictEqual(transaction.tx_json.TransferRate, 0); }); it('Set Flags', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.tx_json.TransactionType = 'Payment'; transaction.setFlags(); assert.strictEqual(transaction.tx_json.Flags, 0); - var transaction2 = new Transaction(); + const transaction2 = new Transaction(); transaction2.tx_json.TransactionType = 'Payment'; transaction2.setFlags(Transaction.flags.Payment.PartialPayment); assert.strictEqual(transaction2.tx_json.Flags, 131072); - var transaction3 = new Transaction(); + const transaction3 = new Transaction(); transaction3.tx_json.TransactionType = 'Payment'; transaction3.setFlags('NoRippleDirect'); assert.strictEqual(transaction3.tx_json.Flags, 65536); - var transaction4 = new Transaction(); + const transaction4 = new Transaction(); transaction4.tx_json.TransactionType = 'Payment'; transaction4.setFlags('PartialPayment', 'NoRippleDirect'); assert.strictEqual(transaction4.tx_json.Flags, 196608); - var transaction5 = new Transaction(); - transaction5.tx_json.TransactionType = 'Payment'; + const transaction5 = new Transaction(); + transaction5.setType('Payment'); transaction5.setFlags(['LimitQuality', 'PartialPayment']); assert.strictEqual(transaction5.tx_json.Flags, 393216); - var transaction6 = new Transaction(); + const transaction6 = new Transaction(); transaction6.tx_json.TransactionType = 'Payment'; transaction6.once('error', function(err) { assert.strictEqual(err.result, 'tejInvalidFlag'); @@ -1146,12 +1250,12 @@ describe('Transaction', function() { }); it('Add Memo', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.tx_json.TransactionType = 'Payment'; - var memoType = 'message'; - var memoFormat = 'json'; - var memoData = { + const memoType = 'message'; + const memoFormat = 'json'; + const memoData = { string: 'value', bool: true, integer: 1 @@ -1159,7 +1263,7 @@ describe('Transaction', function() { transaction.addMemo(memoType, memoFormat, memoData); - var expected = [ + const expected = [ { Memo: { @@ -1173,8 +1277,8 @@ describe('Transaction', function() { assert.deepEqual(transaction.tx_json.Memos, expected); allowed_memo_chars.forEach(function(c) { - var hexStr = new Buffer(c).toString('hex').toUpperCase(); - var tx = new Transaction(); + const hexStr = new Buffer(c).toString('hex').toUpperCase(); + const tx = new Transaction(); tx.addMemo(c, c, c); @@ -1189,20 +1293,19 @@ describe('Transaction', function() { }); it('Add Memo - by object', function() { - var transaction = new Transaction(); - transaction.tx_json.TransactionType = 'Payment'; + const transaction = new Transaction(); + transaction.setType('Payment'); - var memo = { + const memo = { memoType: 'type', memoData: 'data' }; transaction.addMemo(memo); - var expected = [ + const expected = [ { - Memo: - { + Memo: { MemoType: '74797065', MemoData: '64617461' } @@ -1213,7 +1316,7 @@ describe('Transaction', function() { }); it('Add Memos', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.tx_json.TransactionType = 'Payment'; transaction.addMemo('testkey', undefined, 'testvalue'); @@ -1222,7 +1325,7 @@ describe('Transaction', function() { transaction.addMemo(undefined, undefined, 'testvalue4'); transaction.addMemo('testkey4', 'text/html', ''); - var expected = [ + const expected = [ { Memo: { MemoType: '746573746B6579', @@ -1259,10 +1362,10 @@ describe('Transaction', function() { }); it('Add Memo - invalid MemoType', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.tx_json.TransactionType = 'Payment'; - var error_regex = /^Error: MemoType must be a string containing only valid URL characters$/; + const error_regex = /^Error: MemoType must be a string containing only valid URL characters$/; assert.throws(function() { transaction.addMemo(1); @@ -1282,10 +1385,10 @@ describe('Transaction', function() { }); it('Add Memo - invalid MemoFormat', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.tx_json.TransactionType = 'Payment'; - var error_regex = /^Error: MemoFormat must be a string containing only valid URL characters$/; + const error_regex = /^Error: MemoFormat must be a string containing only valid URL characters$/; assert.throws(function() { transaction.addMemo(undefined, 1); @@ -1305,7 +1408,7 @@ describe('Transaction', function() { }); it('Add Memo - MemoData string', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.tx_json.TransactionType = 'Payment'; transaction.addMemo({memoData: 'some_string'}); @@ -1320,10 +1423,10 @@ describe('Transaction', function() { }); it('Add Memo - MemoData complex object', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.tx_json.TransactionType = 'Payment'; - var memo = { + const memo = { memoFormat: 'json', memoData: { string: 'string', @@ -1352,7 +1455,7 @@ describe('Transaction', function() { }); it('Set AccountTxnID', function() { - var transaction = new Transaction(); + const transaction = new Transaction(); assert(transaction instanceof Transaction); transaction.accountTxnID('75C5A92212AA82A89C3824F6F071FE49C95C45DE9113EB51763A217DBACB5B4F'); @@ -1364,7 +1467,7 @@ describe('Transaction', function() { }); it('Construct AccountSet transaction - with setFlag, clearFlag', function() { - var transaction = new Transaction().accountSet('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 'asfRequireDest', 'asfRequireAuth'); + const transaction = new Transaction().accountSet('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 'asfRequireDest', 'asfRequireAuth'); assert(transaction instanceof Transaction); assert.deepEqual(transaction.tx_json, { @@ -1377,7 +1480,7 @@ describe('Transaction', function() { }); it('Construct AccountSet transaction - with AccountTxnID SetFlag', function() { - var transaction = new Transaction().accountSet('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 'asfAccountTxnID'); + const transaction = new Transaction().accountSet('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 'asfAccountTxnID'); assert(transaction instanceof Transaction); assert.deepEqual(transaction.tx_json, { @@ -1389,7 +1492,7 @@ describe('Transaction', function() { }); it('Construct AccountSet transaction - params object', function() { - var transaction = new Transaction().accountSet({ + const transaction = new Transaction().accountSet({ account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', set: 'asfRequireDest', clear: 'asfRequireAuth' @@ -1412,7 +1515,7 @@ describe('Transaction', function() { }); it('Construct OfferCancel transaction', function() { - var transaction = new Transaction().offerCancel('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 1); + const transaction = new Transaction().offerCancel('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 1); assert(transaction instanceof Transaction); assert.deepEqual(transaction.tx_json, { @@ -1424,7 +1527,7 @@ describe('Transaction', function() { }); it('Construct OfferCancel transaction - params object', function() { - var transaction = new Transaction().offerCancel({ + const transaction = new Transaction().offerCancel({ account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', sequence: 1 }); @@ -1445,10 +1548,10 @@ describe('Transaction', function() { }); it('Construct OfferCreate transaction', function() { - var bid = '1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; - var ask = '1/EUR/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; + const bid = '1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; + const ask = '1/EUR/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; - var transaction = new Transaction().offerCreate('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', bid, ask); + const transaction = new Transaction().offerCreate('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', bid, ask); assert(transaction instanceof Transaction); assert.deepEqual(transaction.tx_json, { @@ -1469,14 +1572,14 @@ describe('Transaction', function() { }); it('Construct OfferCreate transaction - with expiration, cancelSequence', function() { - var bid = '1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; - var ask = '1/EUR/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; - var expiration = new Date(); + const bid = '1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; + const ask = '1/EUR/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; + const expiration = new Date(); expiration.setHours(expiration.getHours() + 1); - var rippleExpiration = Math.round(expiration.getTime() / 1000) - 0x386D4380; + const rippleExpiration = Math.round(expiration.getTime() / 1000) - 0x386D4380; - var transaction = new Transaction().offerCreate('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', bid, ask, expiration, 1); + const transaction = new Transaction().offerCreate('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', bid, ask, expiration, 1); assert(transaction instanceof Transaction); assert.deepEqual(transaction.tx_json, { @@ -1499,14 +1602,14 @@ describe('Transaction', function() { }); it('Construct OfferCreate transaction - params object', function() { - var bid = '1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; - var ask = '1/EUR/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; - var expiration = new Date(); + const bid = '1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; + const ask = '1/EUR/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; + const expiration = new Date(); expiration.setHours(expiration.getHours() + 1); - var rippleExpiration = Math.round(expiration.getTime() / 1000) - 0x386D4380; + const rippleExpiration = Math.round(expiration.getTime() / 1000) - 0x386D4380; - var transaction = new Transaction().offerCreate({ + const transaction = new Transaction().offerCreate({ account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', taker_gets: ask, taker_pays: bid, @@ -1535,15 +1638,15 @@ describe('Transaction', function() { }); it('Construct OfferCreate transaction - invalid account', function() { - var bid = '1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; - var ask = '1/EUR/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; + const bid = '1/USD/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; + const ask = '1/EUR/rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm'; assert.throws(function() { new Transaction().offerCreate('xrsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', bid, ask); }); }); it('Construct SetRegularKey transaction', function() { - var transaction = new Transaction().setRegularKey('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 'r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'); + const transaction = new Transaction().setRegularKey('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 'r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'); assert(transaction instanceof Transaction); assert.deepEqual(transaction.tx_json, { @@ -1555,7 +1658,7 @@ describe('Transaction', function() { }); it('Construct SetRegularKey transaction - params object', function() { - var transaction = new Transaction().setRegularKey({ + const transaction = new Transaction().setRegularKey({ account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', regular_key: 'r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe' }); @@ -1582,7 +1685,7 @@ describe('Transaction', function() { }); it('Construct Payment transaction', function() { - var transaction = new Transaction().payment( + const transaction = new Transaction().payment( 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 'r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe', '1' @@ -1599,7 +1702,7 @@ describe('Transaction', function() { }); it('Construct Payment transaction - complex amount', function() { - var transaction = new Transaction().payment( + const transaction = new Transaction().payment( 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 'r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe', '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe' @@ -1620,7 +1723,7 @@ describe('Transaction', function() { }); it('Construct Payment transaction - params object', function() { - var transaction = new Transaction().payment({ + const transaction = new Transaction().payment({ account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', destination: 'r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe', amount: '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe' @@ -1661,8 +1764,8 @@ describe('Transaction', function() { }); it('Construct TrustSet transaction', function() { - var limit = '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'; - var transaction = new Transaction().trustSet('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', limit); + const limit = '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'; + const transaction = new Transaction().trustSet('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', limit); assert(transaction instanceof Transaction); assert.deepEqual(transaction.tx_json, { Flags: 0, @@ -1677,8 +1780,8 @@ describe('Transaction', function() { }); it('Construct TrustSet transaction - with qualityIn, qualityOut', function() { - var limit = '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'; - var transaction = new Transaction().trustSet('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', limit, 1.0, 1.0); + const limit = '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'; + const transaction = new Transaction().trustSet('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', limit, 1.0, 1.0); assert(transaction instanceof Transaction); assert.deepEqual(transaction.tx_json, { Flags: 0, @@ -1695,8 +1798,8 @@ describe('Transaction', function() { }); it('Construct TrustSet transaction - params object', function() { - var limit = '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'; - var transaction = new Transaction().trustSet({ + const limit = '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'; + const transaction = new Transaction().trustSet({ account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', limit: limit, quality_in: 1.0, @@ -1720,21 +1823,21 @@ describe('Transaction', function() { it('Construct TrustSet transaction - invalid account', function() { assert.throws(function() { - var limit = '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'; + const limit = '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'; new Transaction().trustSet('xrsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', limit, 1.0, 1.0); }); }); it('Submit transaction', function(done) { - var remote = new Remote(); - var transaction = new Transaction(remote).accountSet('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'); + const remote = new Remote(); + const transaction = new Transaction(remote).accountSet('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'); assert.strictEqual(transaction.callback, undefined); assert.strictEqual(transaction._errorHandler, undefined); assert.strictEqual(transaction._successHandler, undefined); assert.strictEqual(transaction.listeners('error').length, 1); - var account = remote.addAccount('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'); + const account = remote.addAccount('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'); account._transactionManager._nextSequence = 1; @@ -1746,7 +1849,7 @@ describe('Transaction', function() { return this; }; - var receivedSuccess = false; + let receivedSuccess = false; transaction.once('success', function() { receivedSuccess = true; @@ -1769,11 +1872,11 @@ describe('Transaction', function() { }); it('Submit transaction - submission error', function(done) { - var remote = new Remote(); + const remote = new Remote(); - var transaction = new Transaction(remote).accountSet('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'); + const transaction = new Transaction(remote).accountSet('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'); - var account = remote.addAccount('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'); + const account = remote.addAccount('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'); account._transactionManager._nextSequence = 1; @@ -1785,7 +1888,7 @@ describe('Transaction', function() { return this; }; - var receivedError = false; + let receivedError = false; transaction.once('error', function() { receivedError = true; @@ -1804,7 +1907,7 @@ describe('Transaction', function() { }); it('Submit transaction - submission error, no remote', function(done) { - var transaction = new Transaction(); + const transaction = new Transaction(); transaction.once('error', function(error) { assert(error); @@ -1816,7 +1919,7 @@ describe('Transaction', function() { }); it('Submit transaction - invalid account', function(done) { - var remote = new Remote(); + const remote = new Remote(); assert.throws(function() { new Transaction(remote).accountSet('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWeZ'); }); @@ -1824,10 +1927,10 @@ describe('Transaction', function() { }); it('Abort submission on presubmit', function(done) { - var remote = new Remote(); + const remote = new Remote(); remote.setSecret('rJaT8TafQfYJqDm8aC5n3Yx5yWEL2Ery79', 'snPwFATthTkKnGjEW73q3TL4yci1Q'); - var server = new Server(remote, 'wss://s1.ripple.com:443'); + const server = new Server(remote, 'wss://s1.ripple.com:443'); server._computeFee = function() { return '12'; }; @@ -1837,8 +1940,8 @@ describe('Transaction', function() { remote._connected = true; remote._ledger_current_index = 1; - var transaction = new Transaction(remote).accountSet('rJaT8TafQfYJqDm8aC5n3Yx5yWEL2Ery79'); - var account = remote.account('rJaT8TafQfYJqDm8aC5n3Yx5yWEL2Ery79'); + const transaction = new Transaction(remote).accountSet('rJaT8TafQfYJqDm8aC5n3Yx5yWEL2Ery79'); + const account = remote.account('rJaT8TafQfYJqDm8aC5n3Yx5yWEL2Ery79'); account._transactionManager._nextSequence = 1; @@ -1856,7 +1959,7 @@ describe('Transaction', function() { }); it('Get min ledger', function() { - var queue = new TransactionQueue(); + let queue = new TransactionQueue(); // Randomized submit indexes [ @@ -1872,13 +1975,13 @@ describe('Transaction', function() { 543305 ] .forEach(function(index) { - var tx = new Transaction(); + let tx = new Transaction(); tx.initialSubmitIndex = index; queue.push(tx); }); // Pending queue sorted by submit index - var sorted = queue._queue.slice().sort(function(a, b) { + const sorted = queue._queue.slice().sort(function(a, b) { return a.initialSubmitIndex - b.initialSubmitIndex; });