From 806547dd154e1b0bf252e8a74ad3ac6aa8a97660 Mon Sep 17 00:00:00 2001 From: Ivan Tivonenko Date: Tue, 1 Sep 2015 01:29:37 +0300 Subject: [PATCH 1/3] fix Amount compare bug return 0 if values not comparable --- src/amount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/amount.js b/src/amount.js index 41a41512..8a4813fc 100644 --- a/src/amount.js +++ b/src/amount.js @@ -388,7 +388,7 @@ Amount.prototype._copy = function(value) { Amount.prototype.compareTo = function(to) { var toAmount = Amount.from_json(to); if (!this.is_comparable(toAmount)) { - return new Amount(NaN); + return 0; } return this._value.comparedTo(toAmount._value); }; From 0c62fa21123b220b066871e1c41a3b4fe6f51885 Mon Sep 17 00:00:00 2001 From: Ivan Tivonenko Date: Tue, 1 Sep 2015 01:34:59 +0300 Subject: [PATCH 2/3] remove Firefox warning about prototype overwrite --- src/currency.js | 2 +- src/seed.js | 2 +- src/uint128.js | 2 +- src/uint160.js | 2 +- src/uint256.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/currency.js b/src/currency.js index 66a7e603..d40c4a9a 100644 --- a/src/currency.js +++ b/src/currency.js @@ -22,7 +22,7 @@ var Currency = extend(function() { this._update(); }, UInt160); -Currency.prototype = extend({}, UInt160.prototype); +Currency.prototype = Object.create(extend({}, UInt160.prototype)); Currency.prototype.constructor = Currency; Currency.HEX_CURRENCY_BAD = '0000000000000000000000005852500000000000'; diff --git a/src/seed.js b/src/seed.js index 8266c496..ba66e718 100644 --- a/src/seed.js +++ b/src/seed.js @@ -19,7 +19,7 @@ const Seed = extend(function() { }, UInt); Seed.width = 16; -Seed.prototype = extend({}, UInt.prototype); +Seed.prototype = Object.create(extend({}, UInt.prototype)); Seed.prototype.constructor = Seed; // value = NaN on error. diff --git a/src/uint128.js b/src/uint128.js index f3de0f96..13974730 100644 --- a/src/uint128.js +++ b/src/uint128.js @@ -13,7 +13,7 @@ var UInt128 = extend(function() { }, UInt); UInt128.width = 16; -UInt128.prototype = extend({}, UInt.prototype); +UInt128.prototype = Object.create(extend({}, UInt.prototype)); UInt128.prototype.constructor = UInt128; var HEX_ZERO = UInt128.HEX_ZERO = '00000000000000000000000000000000'; diff --git a/src/uint160.js b/src/uint160.js index 70cd4e97..94031bdf 100644 --- a/src/uint160.js +++ b/src/uint160.js @@ -17,7 +17,7 @@ var UInt160 = extend(function() { }, UInt); UInt160.width = 20; -UInt160.prototype = extend({}, UInt.prototype); +UInt160.prototype = Object.create(extend({}, UInt.prototype)); UInt160.prototype.constructor = UInt160; var HEX_ZERO = UInt160.HEX_ZERO = '0000000000000000000000000000000000000000'; diff --git a/src/uint256.js b/src/uint256.js index 47cd1cd0..b9a04236 100644 --- a/src/uint256.js +++ b/src/uint256.js @@ -13,7 +13,7 @@ var UInt256 = extend(function() { }, UInt); UInt256.width = 32; -UInt256.prototype = extend({}, UInt.prototype); +UInt256.prototype = Object.create(extend({}, UInt.prototype)); UInt256.prototype.constructor = UInt256; var HEX_ZERO = UInt256.HEX_ZERO = '00000000000000000000000000000000' + From c745faaaf0956ca98448a754b4fe97fb50574fc7 Mon Sep 17 00:00:00 2001 From: Ivan Tivonenko Date: Tue, 1 Sep 2015 01:39:47 +0300 Subject: [PATCH 3/3] optimize baseconverter , OrderBook and AutobridgeCalculator for speed --- circle.yml | 3 + npm-shrinkwrap.json | 10 - package.json | 8 +- src/autobridgecalculator.js | 29 +- src/baseconverter.js | 31 +- src/orderbook.js | 369 +++++++++++++----- src/orderbookutils.js | 60 ++- test/fixtures/orderbook.js | 22 +- test/orderbook-autobridge-test.js | 232 +++++++----- test/orderbook-test.js | 610 +++++++++++++++--------------- 10 files changed, 816 insertions(+), 558 deletions(-) create mode 100644 circle.yml diff --git a/circle.yml b/circle.yml new file mode 100644 index 00000000..1ef2b5e5 --- /dev/null +++ b/circle.yml @@ -0,0 +1,3 @@ +machine: + node: + version: 0.12.0 diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 7463705c..8fea68b6 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -8,16 +8,6 @@ "version": "0.9.2", "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz" }, - "babel-runtime": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.3.tgz", - "dependencies": { - "core-js": { - "version": "0.9.18", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-0.9.18.tgz" - } - } - }, "bignumber.js": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.0.7.tgz" diff --git a/package.json b/package.json index 7693b811..e445d9e2 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "async": "~0.9.0", - "babel-runtime": "^5.3.2", + "babel-runtime": "^5.8.20", "bignumber.js": "^2.0.3", "extend": "~1.2.1", "lodash": "^3.1.0", @@ -27,10 +27,10 @@ "devDependencies": { "assert-diff": "^1.0.1", "babel": "^5.3.3", - "babel-core": "^5.3.2", - "babel-loader": "^5.0.0", + "babel-core": "^5.8.23", + "babel-loader": "^5.3.2", "coveralls": "~2.10.0", - "eslint": "^0.18.0", + "eslint": "^1.3.1", "gulp": "~3.8.10", "gulp-bump": "~0.1.13", "gulp-clean-dest": "^0.1.0", diff --git a/src/autobridgecalculator.js b/src/autobridgecalculator.js index 746a085d..9448e925 100644 --- a/src/autobridgecalculator.js +++ b/src/autobridgecalculator.js @@ -20,7 +20,8 @@ function assertValidLegOneOffer(legOneOffer, message) { function AutobridgeCalculator(currencyGets, currencyPays, legOneOffers, legTwoOffers, issuerGets, issuerPays) { this._currencyGets = currencyGets; - this._currencyPays = currencyPays; + this._currencyGetsHex = currencyGets.to_hex(); + this._currencyPaysHex = currencyPays.to_hex(); this._issuerGets = issuerGets; this._issuerPays = issuerPays; this.legOneOffers = _.cloneDeep(legOneOffers); @@ -29,6 +30,8 @@ function AutobridgeCalculator(currencyGets, currencyPays, this._ownerFundsLeftover = {}; } +AutobridgeCalculator.NULL_AMOUNT = Utils.normalizeAmount('0'); + /** * Calculates an ordered array of autobridged offers by quality * @@ -39,7 +42,7 @@ AutobridgeCalculator.prototype.calculate = function() { let legOnePointer = 0; let legTwoPointer = 0; - let offersAutobridged = []; + const offersAutobridged = []; this.clearOwnerFundsLeftover(); @@ -70,14 +73,17 @@ AutobridgeCalculator.prototype.calculate = function() { continue; } - if (legOneTakerGetsFunded.compareTo(legTwoTakerPaysFunded) > 0) { + // using private fields for speed + if (legOneTakerGetsFunded._value.comparedTo( + legTwoTakerPaysFunded._value) > 0) { autobridgedOffer = this.getAutobridgedOfferWithClampedLegOne( legOneOffer, legTwoOffer ); legTwoPointer++; - } else if (legTwoTakerPaysFunded.compareTo(legOneTakerGetsFunded) > 0) { + } else if (legTwoTakerPaysFunded._value.comparedTo( + legOneTakerGetsFunded._value) > 0) { autobridgedOffer = this.getAutobridgedOfferWithClampedLegTwo( legOneOffer, legTwoOffer @@ -210,8 +216,6 @@ AutobridgeCalculator.prototype.clearOwnerFundsLeftover = function() { */ AutobridgeCalculator.prototype.resetOwnerFundsLeftover = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); - this._ownerFundsLeftover[account] = Utils.normalizeAmount('0'); return this._ownerFundsLeftover[account]; @@ -226,12 +230,10 @@ AutobridgeCalculator.prototype.resetOwnerFundsLeftover = function(account) { */ AutobridgeCalculator.prototype.getLeftoverOwnerFunds = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); - let amount = this._ownerFundsLeftover[account]; if (!amount) { - amount = Utils.normalizeAmount('0'); + amount = AutobridgeCalculator.NULL_AMOUNT.clone(); } return amount; @@ -248,7 +250,6 @@ AutobridgeCalculator.prototype.getLeftoverOwnerFunds = function(account) { AutobridgeCalculator.prototype.addLeftoverOwnerFunds = function(account, amount) { - assert(UInt160.is_valid(account), 'Account is invalid'); assert(amount instanceof Amount, 'Amount is invalid'); this._ownerFundsLeftover[account] = this.getLeftoverOwnerFunds(account) @@ -266,7 +267,6 @@ function(account, amount) { AutobridgeCalculator.prototype.setLeftoverOwnerFunds = function(account, amount) { - assert(UInt160.is_valid(account), 'Account is invalid'); assert(amount instanceof Amount, 'Amount is invalid'); this._ownerFundsLeftover[account] = amount; @@ -291,13 +291,13 @@ function(takerGets, takerPays) { autobridgedOffer.TakerGets = { value: takerGets.to_text(), - currency: this._currencyGets.to_hex(), + currency: this._currencyGetsHex, issuer: this._issuerGets }; autobridgedOffer.TakerPays = { value: takerPays.to_text(), - currency: this._currencyPays.to_hex(), + currency: this._currencyPaysHex, issuer: this._issuerPays }; @@ -308,7 +308,8 @@ function(takerGets, takerPays) { autobridgedOffer.autobridged = true; - autobridgedOffer.BookDirectory = Utils.convertOfferQualityToHex(quality); + autobridgedOffer.BookDirectory = Utils.convertOfferQualityToHexFromText(autobridgedOffer.quality); + autobridgedOffer.qualityHex = autobridgedOffer.BookDirectory; return autobridgedOffer; }; diff --git a/src/baseconverter.js b/src/baseconverter.js index 6c0bc541..ef16e64a 100644 --- a/src/baseconverter.js +++ b/src/baseconverter.js @@ -1,28 +1,39 @@ 'use strict'; + function normalize(digitArray) { - while (digitArray[0] === 0) { - digitArray.shift(); + let i = 0; + while (digitArray[i] === 0) { + ++i; + } + if (i > 0) { + digitArray.splice(0, i); } return digitArray; } function divmod(digitArray, base, divisor) { - var remainder = 0; - var quotient = []; - for (var j = 0; j < digitArray.length; j++) { - var temp = remainder * base + parseInt(digitArray[j], 10); - quotient.push(Math.floor(temp / divisor)); + let remainder = 0; + let temp, divided; + let j = -1; + + const length = digitArray.length; + const quotient = new Array(length); + + while (++j < length) { + temp = remainder * base + digitArray[j]; + divided = temp / divisor; + quotient[j] = divided << 0; remainder = temp % divisor; } return {quotient: normalize(quotient), remainder: remainder}; } function convertBase(digitArray, fromBase, toBase) { - var result = []; - var dividend = digitArray; + const result = []; + let dividend = digitArray, qr; while (dividend.length > 0) { - var qr = divmod(dividend, fromBase, toBase); + qr = divmod(dividend, fromBase, toBase); result.unshift(qr.remainder); dividend = qr.quotient; } diff --git a/src/orderbook.js b/src/orderbook.js index b71a3b8a..5fde78c5 100644 --- a/src/orderbook.js +++ b/src/orderbook.js @@ -23,10 +23,6 @@ const AutobridgeCalculator = require('./autobridgecalculator'); const OrderBookUtils = require('./orderbookutils'); const log = require('./log').internal.sub('orderbook'); -function assertValidNumber(number, message) { - assert(!_.isNull(number) && !isNaN(number), message); -} - /** * @constructor OrderBook * @param {Remote} remote @@ -35,11 +31,12 @@ function assertValidNumber(number, message) { * @param {String} bid currency * @param {String} bid issuer * @param {String} orderbook key + * @param {Boolean} fire 'model' event after receiving transaction + only once in 10 seconds */ function OrderBook(remote, - currencyGets, issuerGets, currencyPays, issuerPays, - key) { + currencyGets, issuerGets, currencyPays, issuerPays, key) { EventEmitter.call(this); const self = this; @@ -60,6 +57,8 @@ function OrderBook(remote, this._ownerFundsUnadjusted = {}; this._ownerFunds = {}; this._ownerOffersTotal = {}; + this._validAccounts = {}; + this._validAccountsCount = 0; // We consider ourselves synchronized if we have a current // copy of the offers, we are online and subscribed to updates @@ -72,13 +71,44 @@ function OrderBook(remote, // books that we must keep track of to compute autobridged offers this._legOneBook = null; this._legTwoBook = null; + this._gotOffersFromLegOne = false; + this._gotOffersFromLegTwo = false; + + this.sortOffers = this._currencyGets.has_interest() ? + _sortOffers.bind(this) : _sortOffersQuick; + + this.notifyDirectOffersChanged = + _.debounce( + this.notifyDirectOffersChangedInternal, + OrderBook.NOTIFY_TIMEOUT, + {maxWait: OrderBook.NOTIFY_MAXWAIT}); this._isAutobridgeable = !this._currencyGets.is_native() && !this._currencyPays.is_native(); - function computeAutobridgedOffersWrapper() { - self.computeAutobridgedOffers(); - self.mergeDirectAndAutobridgedBooks(); + this._autobridgeThrottleTimeMultiplier = 1; + this.createDebouncedOffersWrapper(); + + function computeAutobridgedOffersWrapperOne() { + self._gotOffersFromLegOne = true; + self.computeAutobridgedOffersThrottled(); + } + + function computeAutobridgedOffersWrapperTwo() { + self._gotOffersFromLegTwo = true; + self.computeAutobridgedOffersThrottled(); + } + + function onDisconnect() { + self.resetCache(); + self._gotOffersFromLegOne = false; + self._gotOffersFromLegTwo = false; + if (!self._destroyed) { + self._remote.once('disconnect', onDisconnect); + self._remote.once('connect', function() { + self.subscribe(); + }); + } } if (this._isAutobridgeable) { @@ -88,15 +118,15 @@ function OrderBook(remote, issuer_pays: issuerPays }); - this._legOneBook.on('model', computeAutobridgedOffersWrapper); - this._legTwoBook = remote.createOrderBook({ currency_gets: currencyGets, issuer_gets: issuerGets, currency_pays: 'XRP' }); + } - this._legTwoBook.on('model', computeAutobridgedOffersWrapper); + function updateFundedAmountsWrapper(transaction) { + self.updateFundedAmounts(transaction); } function listenersModified(action, event) { @@ -106,7 +136,16 @@ function OrderBook(remote, switch (action) { case 'add': if (++self._listeners === 1) { + self._shouldSubscribe = true; self.subscribe(); + + self._remote.on('transaction', updateFundedAmountsWrapper); + self._remote.once('disconnect', onDisconnect); + + if (self._isAutobridgeable) { + self._legOneBook.on('model', computeAutobridgedOffersWrapperOne); + self._legTwoBook.on('model', computeAutobridgedOffersWrapperTwo); + } } break; case 'remove': @@ -118,10 +157,6 @@ function OrderBook(remote, } } - function updateFundedAmountsWrapper(transaction) { - self.updateFundedAmounts(transaction); - } - this.on('newListener', function(event) { listenersModified('add', event); }); @@ -130,23 +165,21 @@ function OrderBook(remote, listenersModified('remove', event); }); - this._remote.on('transaction', updateFundedAmountsWrapper); - this.on('unsubscribe', function() { self.resetCache(); self._remote.removeListener('transaction', updateFundedAmountsWrapper); - }); + self._remote.removeListener('disconnect', onDisconnect); - this._remote.once('prepare_subscribe', function() { - self.subscribe(); - }); + self._gotOffersFromLegOne = false; + self._gotOffersFromLegTwo = false; - this._remote.on('disconnect', function() { - self.resetCache(); - self._remote.once('prepare_subscribe', function() { - self.subscribe(); - }); + if (self._isAutobridgeable) { + self._legOneBook.removeListener('model', + computeAutobridgedOffersWrapperOne); + self._legTwoBook.removeListener('model', + computeAutobridgedOffersWrapperTwo); + } }); return this; @@ -164,7 +197,21 @@ OrderBook.EVENTS = [ 'offer_changed', 'offer_funds_changed' ]; -OrderBook.DEFAULT_TRANSFER_RATE = 1000000000; +OrderBook.DEFAULT_TRANSFER_RATE = Amount.from_json(1000000000); + +OrderBook.NOTIFY_TIMEOUT = 100; + +OrderBook.NOTIFY_MAXWAIT = 250; + +OrderBook.AUTOBRIDGE_CALCULATE_THROTTLE_TIME = 1000; + +OrderBook.AUTOBRIDGE_CALCULATE_DEBOUNCE_TIME = 250; + +OrderBook.AUTOBRIDGE_CALCULATE_DEBOUNCE_MAXWAIT = 500; + +OrderBook.ZERO_NATIVE_AMOUNT = Amount.from_json('0'); + +OrderBook.ZERO_NORMALIZED_AMOUNT = OrderBookUtils.normalizeAmount('0'); /** * Normalize offers from book_offers and transaction stream @@ -191,18 +238,20 @@ OrderBook.offerRewrite = function(offer) { result.Flags = result.Flags || 0; result.OwnerNode = result.OwnerNode || new Array(16 + 1).join('0'); result.BookNode = result.BookNode || new Array(16 + 1).join('0'); + result.qualityHex = result.BookDirectory.slice(-16); return result; }; /** * Initialize orderbook. Get orderbook offers and subscribe to transactions + * @api private */ OrderBook.prototype.subscribe = function() { const self = this; - if (!this._shouldSubscribe) { + if (!this._shouldSubscribe || this._destroyed) { return; } @@ -215,7 +264,7 @@ OrderBook.prototype.subscribe = function() { self.requestTransferRate(callback); }, function(callback) { - self.requestOffers(callback); + self.requestOffers(callback, true); }, function(callback) { self.subscribeTransactions(callback); @@ -228,6 +277,7 @@ OrderBook.prototype.subscribe = function() { /** * Unhook event listeners and prevent ripple-lib from further work on this * orderbook. There is no more orderbook stream, so "unsubscribe" is nominal + * @api private */ OrderBook.prototype.unsubscribe = function() { @@ -249,33 +299,75 @@ OrderBook.prototype.unsubscribe = function() { this.emit('unsubscribe'); }; +/** + * After that you can't use this object. + */ + +OrderBook.prototype.destroy = function() { + this._destroyed = true; + if (this._subscribed) { + this.unsubscribe(); + } + + if (this._remote._books.hasOwnProperty(this._key)) { + delete this._remote._books[this._key]; + } + + if (this._isAutobridgeable) { + this._legOneBook.destroy(); + this._legTwoBook.destroy(); + } +}; + /** * Request orderbook entries from server * * @param {Function} callback */ -OrderBook.prototype.requestOffers = function(callback) { +OrderBook.prototype.requestOffers = function(callback = function() {}, + internal = false) { const self = this; + if (!this._remote.isConnected()) { + // do not make request if not online. + // that requests will be queued and + // eventually all of them will fire back + return undefined; + } + if (!this._shouldSubscribe) { - return callback(new Error('Should not request offers')); + callback(new Error('Should not request offers')); + return undefined; } if (this._remote.trace) { log.info('requesting offers', this._key); } + if (this._isAutobridgeable && !internal) { + this._gotOffersFromLegOne = false; + this._gotOffersFromLegTwo = false; + + this._legOneBook.requestOffers(); + this._legTwoBook.requestOffers(); + } + + function handleOffers(res) { + if (self._destroyed) { + return; + } + if (!Array.isArray(res.offers)) { // XXX What now? - return callback(new Error('Invalid response')); + callback(new Error('Invalid response')); + return; } if (self._remote.trace) { log.info('requested offers', self._key, 'offers: ' + res.offers.length); } - self.setOffers(res.offers); self._synchronized = true; self.notifyDirectOffersChanged(); @@ -330,8 +422,9 @@ OrderBook.prototype.requestTransferRate = function(callback) { // When transfer rate is not explicitly set on account, it implies the // default transfer rate - self._issuerTransferRate = info.account_data.TransferRate || - OrderBook.DEFAULT_TRANSFER_RATE; + self._issuerTransferRate = + Amount.from_json(info.account_data.TransferRate || + OrderBook.DEFAULT_TRANSFER_RATE); callback(null, self._issuerTransferRate); } @@ -391,7 +484,7 @@ OrderBook.prototype.subscribeTransactions = function(callback) { * books, an additional merge step is also performed */ -OrderBook.prototype.notifyDirectOffersChanged = function() { +OrderBook.prototype.notifyDirectOffersChangedInternal = function() { if (this._isAutobridgeable) { this.mergeDirectAndAutobridgedBooks(); } else { @@ -407,7 +500,13 @@ OrderBook.prototype.resetCache = function() { this._ownerFunds = {}; this._ownerOffersTotal = {}; this._offerCounts = {}; + this._offers = []; this._synchronized = false; + + if (this._validAccountsCount > 3000) { + this._validAccounts = {}; + this._validAccountsCount = 0; + } }; /** @@ -417,7 +516,6 @@ OrderBook.prototype.resetCache = function() { */ OrderBook.prototype.hasOwnerFunds = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); return this._ownerFunds[account] !== undefined; }; @@ -429,7 +527,6 @@ OrderBook.prototype.hasOwnerFunds = function(account) { */ OrderBook.prototype.setOwnerFunds = function(account, fundedAmount) { - assert(UInt160.is_valid(account), 'Account is invalid'); assert(!isNaN(fundedAmount), 'Funded amount is invalid'); this._ownerFundsUnadjusted[account] = fundedAmount; @@ -446,11 +543,11 @@ OrderBook.prototype.setOwnerFunds = function(account, fundedAmount) { OrderBook.prototype.applyTransferRate = function(balance) { assert(!isNaN(balance), 'Balance is invalid'); - assertValidNumber(this._issuerTransferRate, 'Transfer rate is invalid'); + assert(this._issuerTransferRate.is_valid(), 'Transfer rate is invalid'); const adjustedBalance = OrderBookUtils.normalizeAmount(balance) .divide(this._issuerTransferRate) - .multiply(Amount.from_json(OrderBook.DEFAULT_TRANSFER_RATE)) + .multiply(OrderBook.DEFAULT_TRANSFER_RATE) .to_json() .value; @@ -465,7 +562,6 @@ OrderBook.prototype.applyTransferRate = function(balance) { */ OrderBook.prototype.getOwnerFunds = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); if (this.hasOwnerFunds(account)) { if (this._currencyGets.is_native()) { return Amount.from_json(this._ownerFunds[account]); @@ -482,7 +578,6 @@ OrderBook.prototype.getOwnerFunds = function(account) { */ OrderBook.prototype.getUnadjustedOwnerFunds = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); return this._ownerFundsUnadjusted[account]; }; @@ -493,7 +588,6 @@ OrderBook.prototype.getUnadjustedOwnerFunds = function(account) { */ OrderBook.prototype.deleteOwnerFunds = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); this._ownerFunds[account] = undefined; }; @@ -505,7 +599,6 @@ OrderBook.prototype.deleteOwnerFunds = function(account) { */ OrderBook.prototype.getOwnerOfferCount = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); return this._offerCounts[account] || 0; }; @@ -517,7 +610,6 @@ OrderBook.prototype.getOwnerOfferCount = function(account) { */ OrderBook.prototype.incrementOwnerOfferCount = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); const result = (this._offerCounts[account] || 0) + 1; this._offerCounts[account] = result; return result; @@ -532,7 +624,6 @@ OrderBook.prototype.incrementOwnerOfferCount = function(account) { */ OrderBook.prototype.decrementOwnerOfferCount = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); const result = (this._offerCounts[account] || 1) - 1; this._offerCounts[account] = result; @@ -553,8 +644,6 @@ OrderBook.prototype.decrementOwnerOfferCount = function(account) { */ OrderBook.prototype.addOwnerOfferTotal = function(account, amount) { - assert(UInt160.is_valid(account), 'Account is invalid'); - const previousAmount = this.getOwnerOfferTotal(account); const currentAmount = previousAmount.add(Amount.from_json(amount)); @@ -573,14 +662,12 @@ OrderBook.prototype.addOwnerOfferTotal = function(account, amount) { */ OrderBook.prototype.subtractOwnerOfferTotal = function(account, amount) { - assert(UInt160.is_valid(account), 'Account is invalid'); - const previousAmount = this.getOwnerOfferTotal(account); const newAmount = previousAmount.subtract(Amount.from_json(amount)); + this._ownerOffersTotal[account] = newAmount; assert(!newAmount.is_negative(), 'Offer total cannot be negative'); - return newAmount; }; @@ -592,15 +679,14 @@ OrderBook.prototype.subtractOwnerOfferTotal = function(account, amount) { */ OrderBook.prototype.getOwnerOfferTotal = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); const amount = this._ownerOffersTotal[account]; if (amount) { return amount; } if (this._currencyGets.is_native()) { - return Amount.from_json('0'); + return OrderBook.ZERO_NATIVE_AMOUNT.clone(); } - return OrderBookUtils.normalizeAmount('0'); + return OrderBook.ZERO_NORMALIZED_AMOUNT.clone(); }; /** @@ -611,11 +697,10 @@ OrderBook.prototype.getOwnerOfferTotal = function(account) { */ OrderBook.prototype.resetOwnerOfferTotal = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); if (this._currencyGets.is_native()) { - this._ownerOffersTotal[account] = Amount.from_json('0'); + this._ownerOffersTotal[account] = OrderBook.ZERO_NATIVE_AMOUNT.clone(); } else { - this._ownerOffersTotal[account] = OrderBookUtils.normalizeAmount('0'); + this._ownerOffersTotal[account] = OrderBook.ZERO_NORMALIZED_AMOUNT.clone(); } }; @@ -633,17 +718,18 @@ OrderBook.prototype.resetOwnerOfferTotal = function(account) { OrderBook.prototype.setOfferFundedAmount = function(offer) { assert.strictEqual(typeof offer, 'object', 'Offer is invalid'); + const takerGets = Amount.from_json(offer.TakerGets); const fundedAmount = this.getOwnerFunds(offer.Account); const previousOfferSum = this.getOwnerOfferTotal(offer.Account); - const currentOfferSum = previousOfferSum.add( - Amount.from_json(offer.TakerGets)); + const currentOfferSum = previousOfferSum.add(takerGets); offer.owner_funds = this.getUnadjustedOwnerFunds(offer.Account); - offer.is_fully_funded = fundedAmount.compareTo(currentOfferSum) >= 0; + offer.is_fully_funded = fundedAmount.is_comparable(currentOfferSum) && + fundedAmount.compareTo(currentOfferSum) >= 0; if (offer.is_fully_funded) { - offer.taker_gets_funded = Amount.from_json(offer.TakerGets).to_text(); + offer.taker_gets_funded = takerGets.to_text(); offer.taker_pays_funded = Amount.from_json(offer.TakerPays).to_text(); } else if (previousOfferSum.compareTo(fundedAmount) < 0) { offer.taker_gets_funded = fundedAmount.subtract(previousOfferSum).to_text(); @@ -699,7 +785,11 @@ OrderBook.prototype.parseAccountBalanceFromNode = function(node) { } assert(!isNaN(result.balance), 'node has an invalid balance'); - assert(UInt160.is_valid(result.account), 'node has an invalid account'); + if (this._validAccounts[result.Account] === undefined) { + assert(UInt160.is_valid(result.account), 'node has an invalid account'); + this._validAccounts[result.Account] = true; + this._validAccountsCount++; + } return result; }; @@ -781,6 +871,7 @@ OrderBook.prototype.updateFundedAmounts = function(transaction) { }); }; + /** * Update offers' funded amount with their owner's funds * @@ -788,10 +879,15 @@ OrderBook.prototype.updateFundedAmounts = function(transaction) { */ OrderBook.prototype.updateOwnerOffersFundedAmount = function(account) { - assert(UInt160.is_valid(account), 'Account is invalid'); + // assert(UInt160.is_valid(account), 'Account is invalid'); const self = this; + if (!this.hasOwnerFunds(account)) { + // We are only updating owner funds that are already cached + return; + } + if (this._remote.trace) { const ownerFunds = this.getOwnerFunds(account); log.info('updating offer funds', this._key, account, @@ -843,7 +939,7 @@ OrderBook.prototype.updateOwnerOffersFundedAmount = function(account) { OrderBook.prototype.notify = function(transaction) { const self = this; - if (!this._subscribed) { + if (!this._subscribed || this._destroyed) { return; } @@ -879,6 +975,12 @@ OrderBook.prototype.notify = function(transaction) { function handleNode(node) { switch (node.nodeType) { case 'DeletedNode': + if (self._validAccounts[node.fields.Account] === undefined) { + assert(UInt160.is_valid(node.fields.Account), + 'node has an invalid account'); + self._validAccounts[node.fields.Account] = true; + self._validAccountsCount++; + } self.deleteOffer(node, isOfferCancel); // We don't want to count an OfferCancel as a trade @@ -889,6 +991,12 @@ OrderBook.prototype.notify = function(transaction) { break; case 'ModifiedNode': + if (self._validAccounts[node.fields.Account] === undefined) { + assert(UInt160.is_valid(node.fields.Account), + 'node has an invalid account'); + self._validAccounts[node.fields.Account] = true; + self._validAccountsCount++; + } self.modifyOffer(node); takerGetsTotal = takerGetsTotal @@ -901,6 +1009,12 @@ OrderBook.prototype.notify = function(transaction) { break; case 'CreatedNode': + if (self._validAccounts[node.fields.Account] === undefined) { + assert(UInt160.is_valid(node.fields.Account), + 'node has an invalid account'); + self._validAccounts[node.fields.Account] = true; + self._validAccountsCount++; + } // rippled does not set owner_funds if the order maker is the issuer // because the value would be infinite const fundedAmount = transactionOwnerFunds !== undefined ? @@ -914,7 +1028,9 @@ OrderBook.prototype.notify = function(transaction) { _.each(affectedNodes, handleNode); this.emit('transaction', transaction); + this.notifyDirectOffersChanged(); + if (!takerGetsTotal.is_zero()) { this.emit('trade', takerPaysTotal, takerGetsTotal); } @@ -946,17 +1062,27 @@ OrderBook.prototype.insertOffer = function(node) { const originalLength = this._offers.length; - for (let i = 0; i < originalLength; i++) { - const quality = OrderBookUtils.getOfferQuality(offer, this._currencyGets); - const existingOfferQuality = OrderBookUtils.getOfferQuality( - this._offers[i], - this._currencyGets - ); + if (!this._currencyGets.has_interest()) { + // use fast path + for (let i = 0; i < originalLength; i++) { + if (offer.qualityHex <= this._offers[i].qualityHex) { + this._offers.splice(i, 0, offer); + break; + } + } + } else { + for (let i = 0; i < originalLength; i++) { + const quality = OrderBookUtils.getOfferQuality(offer, this._currencyGets); + const existingOfferQuality = OrderBookUtils.getOfferQuality( + this._offers[i], + this._currencyGets + ); - if (quality.compareTo(existingOfferQuality) <= 0) { - this._offers.splice(i, 0, offer); + if (quality.compareTo(existingOfferQuality) <= 0) { + this._offers.splice(i, 0, offer); - break; + break; + } } } @@ -1062,28 +1188,33 @@ OrderBook.prototype.deleteOffer = function(node, isOfferCancel) { OrderBook.prototype.setOffers = function(offers) { assert(Array.isArray(offers), 'Offers is not an array'); - const self = this; - this.resetCache(); - const newOffers = _.map(offers, function(rawOffer) { - const offer = OrderBook.offerRewrite(rawOffer); + let i = -1, offer; + const l = offers.length; - if (offer.hasOwnProperty('owner_funds')) { + while (++i < l) { + offer = OrderBook.offerRewrite(offers[i]); + + if (this._validAccounts[offer.Account] === undefined) { + assert(UInt160.is_valid(offer.Account), 'Account is invalid'); + this._validAccounts[offer.Account] = true; + this._validAccountsCount++; + } + if (offer.owner_funds !== undefined) { // The first offer of each owner from book_offers contains owner balance // of offer's output - self.setOwnerFunds(offer.Account, offer.owner_funds); + this.setOwnerFunds(offer.Account, offer.owner_funds); } - self.incrementOwnerOfferCount(offer.Account); + this.incrementOwnerOfferCount(offer.Account); - self.setOfferFundedAmount(offer); - self.addOwnerOfferTotal(offer.Account, offer.TakerGets); + this.setOfferFundedAmount(offer); + this.addOwnerOfferTotal(offer.Account, offer.TakerGets); + offers[i] = offer; + } - return offer; - }); - - this._offers = newOffers; + this._offers = offers; }; /** @@ -1185,6 +1316,14 @@ OrderBook.prototype.computeAutobridgedOffers = function() { assert(!this._currencyGets.is_native() && !this._currencyPays.is_native(), 'Autobridging is only for IOU:IOU orderbooks'); + if (this._destroyed) { + return; + } + + if (!this._gotOffersFromLegOne || !this._gotOffersFromLegTwo) { + return; + } + const autobridgeCalculator = new AutobridgeCalculator( this._currencyGets, this._currencyPays, @@ -1197,6 +1336,44 @@ OrderBook.prototype.computeAutobridgedOffers = function() { this._offersAutobridged = autobridgeCalculator.calculate(); }; +OrderBook.prototype.computeAutobridgedOffersWrapper = function() { + var startTime = Date.now(); + this.computeAutobridgedOffers(); + this.mergeDirectAndAutobridgedBooks(); + var lasted = (Date.now() - startTime); + + const newMult = + ((lasted * 2 / OrderBook.AUTOBRIDGE_CALCULATE_THROTTLE_TIME) << 0) + 1; + if (newMult !== this._autobridgeThrottleTimeMultiplier) { + this._autobridgeThrottleTimeMultiplier = newMult; + this.createDebouncedOffersWrapper(); + } +} + +OrderBook.prototype.createDebouncedOffersWrapper = function() { + const m = this._autobridgeThrottleTimeMultiplier; + this.computeAutobridgedOffersThrottled = + _.debounce( + _.throttle( + this.computeAutobridgedOffersWrapper, + OrderBook.AUTOBRIDGE_CALCULATE_THROTTLE_TIME * m, + {leading: true, trailing: true}), + OrderBook.AUTOBRIDGE_CALCULATE_DEBOUNCE_TIME, + {maxWait: OrderBook.AUTOBRIDGE_CALCULATE_DEBOUNCE_MAXWAIT}); +} + + +function _sortOffers(a, b) { + const aQuality = OrderBookUtils.getOfferQuality(a, this._currencyGets); + const bQuality = OrderBookUtils.getOfferQuality(b, this._currencyGets); + + return aQuality._value.comparedTo(bQuality._value); +} + +function _sortOffersQuick(a, b) { + return a.qualityHex.localeCompare(b.qualityHex); +} + /** * Merge direct and autobridged offers into a combined orderbook * @@ -1204,20 +1381,24 @@ OrderBook.prototype.computeAutobridgedOffers = function() { */ OrderBook.prototype.mergeDirectAndAutobridgedBooks = function() { - const self = this; + + if (this._destroyed) { + return; + } if (_.isEmpty(this._offers) && _.isEmpty(this._offersAutobridged)) { + if (this._synchronized && this._gotOffersFromLegOne && + this._gotOffersFromLegTwo) { + // emit empty model to indicate to listeners that we've got offers, + // just there was no one + this.emit('model', []); + } return; } this._mergedOffers = this._offers .concat(this._offersAutobridged) - .sort(function(a, b) { - const aQuality = OrderBookUtils.getOfferQuality(a, self._currencyGets); - const bQuality = OrderBookUtils.getOfferQuality(b, self._currencyGets); - - return aQuality.compareTo(bQuality); - }); + .sort(this.sortOffers); this.emit('model', this._mergedOffers); }; diff --git a/src/orderbookutils.js b/src/orderbookutils.js index 8ab54fae..89b5b5df 100644 --- a/src/orderbookutils.js +++ b/src/orderbookutils.js @@ -1,18 +1,31 @@ 'use strict'; -var _ = require('lodash'); -var assert = require('assert'); -var SerializedObject = require('./serializedobject').SerializedObject; -var Types = require('./serializedtypes'); -var Amount = require('./amount').Amount; +const _ = require('lodash'); +const assert = require('assert'); +const SerializedObject = require('./serializedobject').SerializedObject; +const Types = require('./serializedtypes'); +const Amount = require('./amount').Amount; +const Currency = require('./currency').Currency; +const UInt160 = require('./uint160').UInt160; -var IOU_SUFFIX = '/000/rrrrrrrrrrrrrrrrrrrrrhoLvTp'; -var OrderBookUtils = {}; +// const IOU_SUFFIX = '/000/rrrrrrrrrrrrrrrrrrrrrhoLvTp'; +const IOU_SUFFIX_CURRENCY = Currency.from_json('000'); +const IOU_SUFFIX_ISSUER = UInt160.from_json('rrrrrrrrrrrrrrrrrrrrrhoLvTp'); +const OrderBookUtils = {}; function assertValidNumber(number, message) { assert(!_.isNull(number) && !isNaN(number), message); } +function createAmount(number) { + const amount = new Amount(); + amount.set_issuer(IOU_SUFFIX_ISSUER); + amount._currency = IOU_SUFFIX_CURRENCY; + amount.parse_value(number); + + return amount; +} + /** * Casts and returns offer's taker gets funded amount as a default IOU amount * @@ -23,7 +36,7 @@ function assertValidNumber(number, message) { OrderBookUtils.getOfferTakerGetsFunded = function(offer) { assertValidNumber(offer.taker_gets_funded, 'Taker gets funded is invalid'); - return Amount.from_json(offer.taker_gets_funded + IOU_SUFFIX); + return createAmount(offer.taker_gets_funded); }; /** @@ -36,7 +49,7 @@ OrderBookUtils.getOfferTakerGetsFunded = function(offer) { OrderBookUtils.getOfferTakerPaysFunded = function(offer) { assertValidNumber(offer.taker_pays_funded, 'Taker gets funded is invalid'); - return Amount.from_json(offer.taker_pays_funded + IOU_SUFFIX); + return createAmount(offer.taker_pays_funded); }; /** @@ -50,7 +63,7 @@ OrderBookUtils.getOfferTakerPaysFunded = function(offer) { OrderBookUtils.getOfferTakerGets = function(offer) { assert(typeof offer, 'object', 'Offer is invalid'); - return Amount.from_json(offer.TakerGets + IOU_SUFFIX); + return createAmount(offer.TakerGets); }; /** @@ -61,7 +74,7 @@ OrderBookUtils.getOfferTakerGets = function(offer) { */ OrderBookUtils.getOfferQuality = function(offer, currencyGets) { - var amount; + let amount; if (currencyGets.has_interest()) { // XXX Should use Amount#from_quality @@ -71,7 +84,7 @@ OrderBookUtils.getOfferQuality = function(offer, currencyGets) { reference_date: new Date() }); } else { - amount = Amount.from_json(offer.quality + IOU_SUFFIX); + amount = createAmount(offer.quality); } return amount; @@ -89,8 +102,25 @@ OrderBookUtils.getOfferQuality = function(offer, currencyGets) { OrderBookUtils.convertOfferQualityToHex = function(quality) { assert(quality instanceof Amount, 'Quality is not an amount'); - var so = new SerializedObject(); - Types.Quality.serialize(so, quality.to_text() + IOU_SUFFIX); + const so = new SerializedObject(); + Types.Quality.serialize(so, createAmount(quality.to_text())); + + return so.to_hex(); +}; + +/** + * Formats an offer quality amount to a hex that can be parsed by + * Amount.parse_quality + * + * @param {String} quality + * + * @return {String} + */ + +OrderBookUtils.convertOfferQualityToHexFromText = function(quality) { + + const so = new SerializedObject(); + Types.Quality.serialize(so, createAmount(quality)); return so.to_hex(); }; @@ -100,7 +130,7 @@ OrderBookUtils.convertOfferQualityToHex = function(quality) { */ OrderBookUtils.normalizeAmount = function(value) { - return Amount.from_json(value + IOU_SUFFIX); + return createAmount(value); }; module.exports = OrderBookUtils; diff --git a/test/fixtures/orderbook.js b/test/fixtures/orderbook.js index 826103a7..77cd7952 100644 --- a/test/fixtures/orderbook.js +++ b/test/fixtures/orderbook.js @@ -2,9 +2,12 @@ 'use strict'; -var _ = require('lodash'); -var addresses = require('./addresses'); -var Meta = require('ripple-lib').Meta; +const _ = require('lodash'); +const addresses = require('./addresses'); +const Meta = require('ripple-lib').Meta; +const Amount = require('ripple-lib').Amount; +const SerializedObject = require('ripple-lib').SerializedObject; +const Types = require('ripple-lib').types; module.exports.FIAT_BALANCE = '10'; module.exports.NATIVE_BALANCE = '55'; @@ -809,6 +812,8 @@ module.exports.transactionWithInvalidAccountRoot = function(options) { }; }; +const IOU_SUFFIX = '/000/rrrrrrrrrrrrrrrrrrrrrhoLvTp'; + module.exports.transactionWithCreatedOffer = function(options) { options = options || {}; _.defaults(options, { @@ -816,6 +821,15 @@ module.exports.transactionWithCreatedOffer = function(options) { amount: '1.9951' }); + const takerGets = Amount.from_json(options.amount + IOU_SUFFIX); + const takerPays = Amount.from_json(module.exports.TAKER_PAYS + IOU_SUFFIX); + const quality = takerPays.divide(takerGets); + + const so = new SerializedObject(); + Types.Quality.serialize(so, quality); + + const BookDirectory = so.to_hex(); + var meta = new Meta({ AffectedNodes: [ { @@ -824,7 +838,7 @@ module.exports.transactionWithCreatedOffer = function(options) { LedgerIndex: 'AF3C702057C9C47DB9E809FD8C76CD22521012C5CC7AE95D914EC9E226F1D7E5', NewFields: { Account: options.account, - BookDirectory: '7B73A610A009249B0CC0D4311E8BA7927B5A34D86634581C5F211CEE1E0697A0', + BookDirectory: BookDirectory, Flags: 131072, Sequence: 1404, TakerGets: { diff --git a/test/orderbook-autobridge-test.js b/test/orderbook-autobridge-test.js index 8d07d037..c30ea7e3 100644 --- a/test/orderbook-autobridge-test.js +++ b/test/orderbook-autobridge-test.js @@ -1,19 +1,30 @@ -/*eslint-disable max-len */ +/* eslint-disable max-len */ 'use strict'; -var _ = require('lodash'); -var assert = require('assert-diff'); -var Remote = require('ripple-lib').Remote; -var Currency = require('ripple-lib').Currency; -var addresses = require('./fixtures/addresses'); -var fixtures = require('./fixtures/orderbook'); +const _ = require('lodash'); +const assert = require('assert-diff'); +const Remote = require('ripple-lib').Remote; +const Currency = require('ripple-lib').Currency; +const Amount = require('ripple-lib').Amount; +const addresses = require('./fixtures/addresses'); +const fixtures = require('./fixtures/orderbook'); describe('OrderBook Autobridging', function() { this.timeout(0); + function createRemote() { + const remote = new Remote(); + + remote.isConnected = function() { + return true; + }; + + return remote; + } + it('Initialize IOU/IOU', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', @@ -27,23 +38,24 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 1); @@ -58,25 +70,26 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - leg one partially funded', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); legOneOffers[0].owner_funds = '2105863129'; book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 1); @@ -88,25 +101,26 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - leg two partially funded', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); legTwoOffers[0].owner_funds = '10'; book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 1); @@ -118,25 +132,26 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - leg two transfer rate', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1002000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); legTwoOffers[0].owner_funds = '10'; book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '9.980039920159681'); @@ -146,19 +161,19 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - taker funds < leg two in', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); legOneOffers[0].owner_funds = '33461561812'; @@ -169,6 +184,7 @@ describe('OrderBook Autobridging', function() { book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 1); @@ -180,19 +196,19 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - leg one partially funded - owners equal', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); legOneOffers[0].owner_funds = '2105863129'; @@ -201,6 +217,7 @@ describe('OrderBook Autobridging', function() { book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 1); @@ -212,19 +229,19 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - leg one partially funded - owners equal - leg two in > leg one out', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); legOneOffers[0].owner_funds = '2105863129'; @@ -236,6 +253,7 @@ describe('OrderBook Autobridging', function() { book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 1); @@ -247,23 +265,24 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - leg one consumes leg two fully', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 2)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 2)); book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 2); @@ -280,19 +299,19 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - leg two consumes first leg one offer fully', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 2)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 2)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 1)); legTwoOffers[0].TakerGets.value = '170.7639524223001'; legTwoOffers[0].TakerPays = '49439476610'; @@ -301,6 +320,7 @@ describe('OrderBook Autobridging', function() { book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 2); @@ -317,19 +337,19 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - owners equal', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1002000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 2)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 2)); legOneOffers[0].owner_funds = '2105863129'; legTwoOffers[1].owner_funds = '19.32660005780981'; @@ -339,6 +359,7 @@ describe('OrderBook Autobridging', function() { book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 2); @@ -355,19 +376,19 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - owners equal - leg one overfunded', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1002000000); - var legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); - var legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 2)); + const legOneOffers = _.cloneDeep(fixtures.LEG_ONE_OFFERS.slice(0, 1)); + const legTwoOffers = _.cloneDeep(fixtures.LEG_TWO_OFFERS.slice(0, 2)); legOneOffers[0].owner_funds = '41461561812'; @@ -378,6 +399,7 @@ describe('OrderBook Autobridging', function() { book._legOneBook.setOffers(legOneOffers); book._legTwoBook.setOffers(legTwoOffers); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 2); @@ -394,20 +416,21 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - TakerPays < Quality * TakerGets', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); book._legOneBook.setOffers([ { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: '75', TakerPays: { value: '50', @@ -422,6 +445,7 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers([ { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: { value: '90', issuer: addresses.ISSUER, @@ -433,6 +457,7 @@ describe('OrderBook Autobridging', function() { } ]); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 1); @@ -444,20 +469,21 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - update funded amount', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); book._legOneBook.setOffers([ { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: '100', TakerPays: { value: '100', @@ -469,6 +495,7 @@ describe('OrderBook Autobridging', function() { }, { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: '50', TakerPays: { value: '100', @@ -482,6 +509,7 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers([ { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: { value: '90', issuer: addresses.ISSUER, @@ -493,6 +521,7 @@ describe('OrderBook Autobridging', function() { }, { Account: addresses.OTHER_ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: { value: '30', issuer: addresses.ISSUER, @@ -504,6 +533,7 @@ describe('OrderBook Autobridging', function() { } ]); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 3); @@ -525,20 +555,21 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - update funded amount - owners equal', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); book._legOneBook.setOffers([ { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: '100', TakerPays: { value: '100', @@ -550,6 +581,7 @@ describe('OrderBook Autobridging', function() { }, { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: '20', TakerPays: { value: '100', @@ -563,6 +595,7 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers([ { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: { value: '90', issuer: addresses.ISSUER, @@ -574,6 +607,7 @@ describe('OrderBook Autobridging', function() { }, { Account: addresses.OTHER_ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: { value: '30', issuer: addresses.ISSUER, @@ -585,6 +619,7 @@ describe('OrderBook Autobridging', function() { } ]); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 3); @@ -606,20 +641,21 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - update funded amount - first two owners equal', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); book._legOneBook.setOffers([ { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: '100', TakerPays: { value: '100', @@ -631,6 +667,7 @@ describe('OrderBook Autobridging', function() { }, { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: '100', TakerPays: { value: '200', @@ -644,6 +681,7 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers([ { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: { value: '90', issuer: addresses.ISSUER, @@ -655,6 +693,7 @@ describe('OrderBook Autobridging', function() { }, { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: { value: '30', issuer: addresses.ISSUER, @@ -665,6 +704,7 @@ describe('OrderBook Autobridging', function() { }, { Account: addresses.OTHER_ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: { value: '20', issuer: addresses.ISSUER, @@ -676,6 +716,7 @@ describe('OrderBook Autobridging', function() { } ]); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 4); @@ -702,20 +743,21 @@ describe('OrderBook Autobridging', function() { }); it('Compute autobridged offers - unfunded offer - owners equal', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, currency_pays: 'USD', issuer_pays: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; - book._legOneBook._issuerTransferRate = 1000000000; - book._legTwoBook._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); + book._legOneBook._issuerTransferRate = Amount.from_json(1000000000); + book._legTwoBook._issuerTransferRate = Amount.from_json(1000000000); book._legOneBook.setOffers([ { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: '75', TakerPays: { value: '75', @@ -730,6 +772,7 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers([ { Account: addresses.ACCOUNT, + BookDirectory: '3B95C29205977C2136BBC70F21895F8C8F471C8522BF446E570463F9CDB31517', TakerGets: { value: '90', issuer: addresses.ISSUER, @@ -741,6 +784,7 @@ describe('OrderBook Autobridging', function() { } ]); + book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; book.computeAutobridgedOffers(); assert.strictEqual(book._offersAutobridged.length, 1); diff --git a/test/orderbook-test.js b/test/orderbook-test.js index f37f68ad..14fc50fb 100644 --- a/test/orderbook-test.js +++ b/test/orderbook-test.js @@ -1,20 +1,30 @@ -/*eslint-disable max-len */ +/* eslint-disable max-len */ 'use strict'; -var assert = require('assert-diff'); -var Remote = require('ripple-lib').Remote; -var Currency = require('ripple-lib').Currency; -var Amount = require('ripple-lib').Amount; -var Meta = require('ripple-lib').Meta; -var addresses = require('./fixtures/addresses'); -var fixtures = require('./fixtures/orderbook'); +const assert = require('assert-diff'); +const Remote = require('ripple-lib').Remote; +const Currency = require('ripple-lib').Currency; +const Amount = require('ripple-lib').Amount; +const Meta = require('ripple-lib').Meta; +const addresses = require('./fixtures/addresses'); +const fixtures = require('./fixtures/orderbook'); describe('OrderBook', function() { this.timeout(0); + function createRemote() { + const remote = new Remote(); + + remote.isConnected = function() { + return true; + }; + + return remote; + } + it('toJSON', function() { - var book = new Remote().createOrderBook({ + let book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -30,7 +40,7 @@ describe('OrderBook', function() { } }); - book = new Remote().createOrderBook({ + book = createRemote().createOrderBook({ issuer_gets: addresses.ISSUER, currency_gets: 'BTC', currency_pays: 'XRP' @@ -48,7 +58,7 @@ describe('OrderBook', function() { }); it('Check orderbook validity', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -58,7 +68,7 @@ describe('OrderBook', function() { }); it('Automatic subscription (based on listeners)', function(done) { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -72,13 +82,13 @@ describe('OrderBook', function() { }); it('Subscribe', function(done) { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' }); - var requestedOffers = false; + let requestedOffers = false; book.subscribeTransactions = function() { assert(requestedOffers); @@ -94,7 +104,7 @@ describe('OrderBook', function() { }); it('Unsubscribe', function(done) { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -114,7 +124,7 @@ describe('OrderBook', function() { }); it('Automatic unsubscription - remove all listeners', function(done) { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -129,7 +139,7 @@ describe('OrderBook', function() { }); it('Automatic unsubscription - once listener', function(done) { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -144,33 +154,33 @@ describe('OrderBook', function() { }); it('Set owner funds', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' }); - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOwnerFunds(addresses.ACCOUNT, '1'); assert.strictEqual(book.getOwnerFunds(addresses.ACCOUNT).to_text(), '1'); }); it('Set owner funds - unadjusted funds', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); book.setOwnerFunds(addresses.ACCOUNT, '1'); assert.strictEqual(book._ownerFundsUnadjusted[addresses.ACCOUNT], '1'); }); it('Set owner funds - invalid account', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -182,7 +192,7 @@ describe('OrderBook', function() { }); it('Set owner funds - invalid amount', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -194,7 +204,7 @@ describe('OrderBook', function() { }); it('Has owner funds', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -205,7 +215,7 @@ describe('OrderBook', function() { }); it('Delete owner funds', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -218,23 +228,8 @@ describe('OrderBook', function() { assert(!book.hasOwnerFunds(addresses.ACCOUNT)); }); - it('Delete owner funds', function() { - var book = new Remote().createOrderBook({ - currency_gets: 'BTC', - issuer_gets: addresses.ISSUER, - currency_pays: 'XRP' - }); - - book._ownerFunds[addresses.ACCOUNT] = '1'; - assert(book.hasOwnerFunds(addresses.ACCOUNT)); - - assert.throws(function() { - book.deleteOwnerFunds('0rrrrrrrrrrrrrrrrrrrrBZbvji'); - }); - }); - it('Increment owner offer count', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -244,20 +239,8 @@ describe('OrderBook', function() { assert.strictEqual(book.getOwnerOfferCount(addresses.ACCOUNT), 1); }); - it('Increment owner offer count - invalid address', function() { - var book = new Remote().createOrderBook({ - currency_gets: 'BTC', - issuer_gets: addresses.ISSUER, - currency_pays: 'XRP' - }); - - assert.throws(function() { - book.incrementOwnerOfferCount('zrrrrrrrrrrrrrrrrrrrBZbvji'); - }); - }); - it('Decrement owner offer count', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -270,7 +253,7 @@ describe('OrderBook', function() { }); it('Decrement owner offer count - no more offers', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -283,20 +266,8 @@ describe('OrderBook', function() { assert.strictEqual(book.getOwnerFunds(addresses.ACCOUNT), undefined); }); - it('Decrement owner offer count - invalid address', function() { - var book = new Remote().createOrderBook({ - currency_gets: 'BTC', - issuer_gets: addresses.ISSUER, - currency_pays: 'XRP' - }); - - assert.throws(function() { - book.decrementOwnerOfferCount('zrrrrrrrrrrrrrrrrrrrBZbvji'); - }); - }); - it('Subtract owner offer total', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -308,13 +279,13 @@ describe('OrderBook', function() { issuer: addresses.ISSUER }); - var newAmount = book.subtractOwnerOfferTotal(addresses.ACCOUNT, { + const newAmount = book.subtractOwnerOfferTotal(addresses.ACCOUNT, { value: 2, currency: 'BTC', issuer: addresses.ISSUER }); - var offerTotal = Amount.from_json({ + const offerTotal = Amount.from_json({ value: 1, currency: 'BTC', issuer: addresses.ISSUER @@ -324,7 +295,7 @@ describe('OrderBook', function() { }); it('Subtract owner offer total - negative total', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -340,7 +311,7 @@ describe('OrderBook', function() { }); it('Get owner offer total', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -355,7 +326,7 @@ describe('OrderBook', function() { }); it('Get owner offer total - native', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'XRP' @@ -367,7 +338,7 @@ describe('OrderBook', function() { }); it('Get owner offer total - no total', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -377,7 +348,7 @@ describe('OrderBook', function() { }); it('Get owner offer total - native - no total', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -387,31 +358,31 @@ describe('OrderBook', function() { }); it('Apply transfer rate - cached transfer rate', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); assert.strictEqual(book.applyTransferRate('1'), '0.9980039920159681'); }); it('Apply transfer rate - native currency', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' }); - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); assert.strictEqual(book.applyTransferRate('0.9980039920159681'), '0.9980039920159681'); }); it('Apply transfer rate - invalid balance', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -423,7 +394,7 @@ describe('OrderBook', function() { }); it('Apply transfer rate - invalid transfer rate', function() { - var book = new Remote().createOrderBook({ + const book = createRemote().createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -435,8 +406,8 @@ describe('OrderBook', function() { }); it('Request transfer rate', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -451,20 +422,20 @@ describe('OrderBook', function() { request.emit('success', { account_data: { - TransferRate: 1002000000 + TransferRate: Amount.from_json(1002000000) } }); }; book.requestTransferRate(function(err, rate) { assert.ifError(err); - assert.strictEqual(rate, 1002000000); + assert(rate.equals(1002000000)); }); }); it('Request transfer rate - not set', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -485,19 +456,19 @@ describe('OrderBook', function() { book.requestTransferRate(function(err, rate) { assert.ifError(err); - assert.strictEqual(rate, 1000000000); + assert(rate.equals(1000000000)); }); }); it('Request transfer rate - cached transfer rate', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); remote.request = function() { assert(false); @@ -505,13 +476,13 @@ describe('OrderBook', function() { book.requestTransferRate(function(err, rate) { assert.ifError(err); - assert.strictEqual(rate, 1002000000); + assert(rate.equals(1002000000)); }); }); it('Request transfer rate - native currency', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' @@ -523,22 +494,22 @@ describe('OrderBook', function() { book.requestTransferRate(function(err, rate) { assert.ifError(err); - assert.strictEqual(rate, 1000000000); - assert.strictEqual(book._issuerTransferRate, 1000000000); + assert(rate.equals(1000000000)); + assert(book._issuerTransferRate.equals(1000000000)); }); }); it('Set offer funded amount - iou/xrp - fully funded', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'BTC', currency_pays: 'XRP', issuer_gets: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); - var offer = { + const offer = { Account: addresses.ACCOUNT, TakerGets: { value: '100', @@ -551,7 +522,7 @@ describe('OrderBook', function() { book.setOwnerFunds(addresses.ACCOUNT, '100.1234'); book.setOfferFundedAmount(offer); - var expected = { + const expected = { Account: addresses.ACCOUNT, TakerGets: offer.TakerGets, TakerPays: offer.TakerPays, @@ -565,16 +536,16 @@ describe('OrderBook', function() { }); it('Set offer funded amount - iou/xrp - unfunded', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'BTC', currency_pays: 'XRP', issuer_gets: addresses.ISSUER }); - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); - var offer = { + const offer = { Account: addresses.ACCOUNT, TakerGets: { value: '100', @@ -588,7 +559,7 @@ describe('OrderBook', function() { book.setOwnerFunds(addresses.ACCOUNT, '99'); book.setOfferFundedAmount(offer); - var expected = { + const expected = { Account: addresses.ACCOUNT, TakerGets: offer.TakerGets, TakerPays: offer.TakerPays, @@ -603,16 +574,16 @@ describe('OrderBook', function() { }); it('Set offer funded amount - xrp/iou - funded', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' }); - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); - var offer = { + const offer = { Account: addresses.ACCOUNT, TakerGets: '100', TakerPays: { @@ -625,7 +596,7 @@ describe('OrderBook', function() { book.setOwnerFunds(addresses.ACCOUNT, '100100000'); book.setOfferFundedAmount(offer); - var expected = { + const expected = { Account: addresses.ACCOUNT, TakerGets: offer.TakerGets, TakerPays: offer.TakerPays, @@ -639,16 +610,16 @@ describe('OrderBook', function() { }); it('Set offer funded amount - xrp/iou - unfunded', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' }); - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); - var offer = { + const offer = { Account: addresses.ACCOUNT, TakerGets: '100', TakerPays: { @@ -662,7 +633,7 @@ describe('OrderBook', function() { book.setOwnerFunds(addresses.ACCOUNT, '99'); book.setOfferFundedAmount(offer); - var expected = { + const expected = { Account: addresses.ACCOUNT, TakerGets: offer.TakerGets, TakerPays: offer.TakerPays, @@ -677,16 +648,16 @@ describe('OrderBook', function() { }); it('Set offer funded amount - zero funds', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' }); - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); - var offer = { + const offer = { Account: addresses.ACCOUNT, TakerGets: { value: '100', @@ -711,15 +682,15 @@ describe('OrderBook', function() { }); it('Check is balance change node', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - var meta = new Meta({ + const meta = new Meta({ AffectedNodes: [{ ModifiedNode: { FinalFields: { @@ -761,15 +732,15 @@ describe('OrderBook', function() { }); it('Check is balance change node - not balance change', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' }); - var meta = new Meta({ + const meta = new Meta({ AffectedNodes: [{ ModifiedNode: { FinalFields: { @@ -804,15 +775,15 @@ describe('OrderBook', function() { }); it('Check is balance change node - different currency', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'BTC', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - var meta = new Meta({ + const meta = new Meta({ AffectedNodes: [{ ModifiedNode: { FinalFields: { @@ -854,15 +825,15 @@ describe('OrderBook', function() { }); it('Check is balance change node - different issuer', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - var meta = new Meta({ + const meta = new Meta({ AffectedNodes: [{ ModifiedNode: { FinalFields: { @@ -904,15 +875,15 @@ describe('OrderBook', function() { }); it('Check is balance change node - native currency', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' }); - var meta = new Meta({ + const meta = new Meta({ AffectedNodes: [{ ModifiedNode: { FinalFields: { @@ -939,15 +910,15 @@ describe('OrderBook', function() { }); it('Check is balance change node - native currency - not balance change', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'BTC' }); - var meta = new Meta({ + const meta = new Meta({ AffectedNodes: [{ ModifiedNode: { FinalFields: { @@ -969,15 +940,15 @@ describe('OrderBook', function() { }); it('Parse account balance from node', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - var meta = new Meta({ + const meta = new Meta({ AffectedNodes: [ { ModifiedNode: { @@ -1064,15 +1035,15 @@ describe('OrderBook', function() { }); it('Parse account balance from node - native currency', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - var meta = new Meta({ + const meta = new Meta({ AffectedNodes: [{ ModifiedNode: { FinalFields: { @@ -1102,20 +1073,20 @@ describe('OrderBook', function() { }); it('Update funded amounts', function(done) { - var receivedChangedEvents = 0; - var receivedFundsChangedEvents = 0; + let receivedChangedEvents = 0; + let receivedFundsChangedEvents = 0; - var remote = new Remote(); + const remote = createRemote(); - var message = fixtures.transactionWithRippleState(); + const message = fixtures.transactionWithRippleState(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book._synchronized = true; book._offers = fixtures.fiatOffers(); @@ -1154,21 +1125,21 @@ describe('OrderBook', function() { }); it('Update funded amounts - increase funds', function() { - var receivedFundsChangedEvents = 0; + let receivedFundsChangedEvents = 0; - var remote = new Remote(); + const remote = createRemote(); - var message = fixtures.transactionWithRippleState({ + const message = fixtures.transactionWithRippleState({ balance: '50' }); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book._synchronized = true; book.setOffers(fixtures.fiatOffers({ @@ -1198,17 +1169,17 @@ describe('OrderBook', function() { }); it('Update funded amounts - owner_funds', function(done) { - var remote = new Remote(); + const remote = createRemote(); - var message = fixtures.transactionWithRippleState(); + const message = fixtures.transactionWithRippleState(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); book._synchronized = true; book._offers = fixtures.fiatOffers(); @@ -1225,17 +1196,17 @@ describe('OrderBook', function() { }); it('Update funded amounts - issuer transfer rate set', function(done) { - var remote = new Remote(); + const remote = createRemote(); - var message = fixtures.transactionWithRippleState(); + const message = fixtures.transactionWithRippleState(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); book._synchronized = true; book._ownerFunds[addresses.ACCOUNT] = '100'; @@ -1251,14 +1222,14 @@ describe('OrderBook', function() { }); it('Update funded amounts - native currency', function(done) { - var receivedChangedEvents = 0; - var receivedFundsChangedEvents = 0; + let receivedChangedEvents = 0; + let receivedFundsChangedEvents = 0; - var remote = new Remote(); + const remote = createRemote(); - var message = fixtures.transactionWithAccountRoot(); + const message = fixtures.transactionWithAccountRoot(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'USD' @@ -1297,13 +1268,13 @@ describe('OrderBook', function() { }); it('Update funded amounts - no affected account', function(done) { - var remote = new Remote(); + const remote = createRemote(); - var message = fixtures.transactionWithAccountRoot({ + const message = fixtures.transactionWithAccountRoot({ account: addresses.ACCOUNT }); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'USD' @@ -1331,15 +1302,15 @@ describe('OrderBook', function() { }); it('Update funded amounts - no balance change', function(done) { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'XRP', issuer_pays: addresses.ISSUER, currency_pays: 'USD' }); - var message = fixtures.transactionWithInvalidAccountRoot(); + const message = fixtures.transactionWithInvalidAccountRoot(); book._synchronized = true; @@ -1366,15 +1337,15 @@ describe('OrderBook', function() { }); it('Update funded amounts - deferred TransferRate', function(done) { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - var message = fixtures.transactionWithRippleState(); + const message = fixtures.transactionWithRippleState(); remote.request = function(request) { assert.deepEqual(request.message, { @@ -1385,7 +1356,7 @@ describe('OrderBook', function() { request.emit('success', fixtures.accountInfoResponse()); - assert.strictEqual(book._issuerTransferRate, fixtures.TRANSFER_RATE); + assert(book._issuerTransferRate.equals(fixtures.TRANSFER_RATE)); done(); }; @@ -1394,17 +1365,17 @@ describe('OrderBook', function() { }); it('Set offers - issuer transfer rate set - iou/xrp', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); - var offers = fixtures.bookOffersResponse().offers; + const offers = fixtures.bookOffersResponse().offers; book.setOffers(offers); @@ -1427,29 +1398,29 @@ describe('OrderBook', function() { }); it('Set offers - issuer transfer rate set - iou/xrp - funded amounts', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); - var offers = fixtures.bookOffersResponse({ + const offers = fixtures.bookOffersResponse({ account_funds: '233.13532' }).offers; book.setOffers(offers); - var offerOneTakerGetsFunded = Amount.from_json({ + const offerOneTakerGetsFunded = Amount.from_json({ value: book._offers[0].taker_gets_funded, currency: 'USD', issuer: addresses.ISSUER }); - var offerOneTakerGetsFundedExpected = Amount.from_json({ + const offerOneTakerGetsFundedExpected = Amount.from_json({ value: '79.39192374', currency: 'USD', issuer: addresses.ISSUER @@ -1458,41 +1429,41 @@ describe('OrderBook', function() { assert.strictEqual(offerOneTakerGetsFunded.equals(offerOneTakerGetsFundedExpected), true); assert.strictEqual(book._offers[0].is_fully_funded, true); - var offerTwoTakerGetsFunded = Amount.from_json({ + const offerTwoTakerGetsFunded = Amount.from_json({ value: book._offers[1].taker_gets_funded, currency: 'USD', issuer: addresses.ISSUER }); - var offerTwoTakerGetsFundedExpected = Amount.from_json({ + const offerTwoTakerGetsFundedExpected = Amount.from_json({ value: '24.01284027983332', currency: 'USD', issuer: addresses.ISSUER }); - var offerTwoTakerPaysFunded = Amount.from_json(book._offers[1].taker_pays_funded); + const offerTwoTakerPaysFunded = Amount.from_json(book._offers[1].taker_pays_funded); - var offerTwoTakerPaysFundedExpected = Amount.from_json('1661400177'); + const offerTwoTakerPaysFundedExpected = Amount.from_json('1661400177'); assert.strictEqual(offerTwoTakerGetsFunded.equals(offerTwoTakerGetsFundedExpected), true); assert.strictEqual(offerTwoTakerPaysFunded.equals(offerTwoTakerPaysFundedExpected), true); assert.strictEqual(book._offers[1].is_fully_funded, false); - var offerFiveTakerGetsFunded = Amount.from_json({ + const offerFiveTakerGetsFunded = Amount.from_json({ value: book._offers[4].taker_gets_funded, currency: 'USD', issuer: addresses.ISSUER }); - var offerFiveTakerGetsFundedExpected = Amount.from_json({ + const offerFiveTakerGetsFundedExpected = Amount.from_json({ value: '153.2780562999202', currency: 'USD', issuer: addresses.ISSUER }); - var offerFiveTakerPaysFunded = Amount.from_json(book._offers[4].taker_pays_funded); + const offerFiveTakerPaysFunded = Amount.from_json(book._offers[4].taker_pays_funded); - var offerFiveTakerPaysFundedExpected = Amount.from_json('10684615137'); + const offerFiveTakerPaysFundedExpected = Amount.from_json('10684615137'); assert.strictEqual(offerFiveTakerGetsFunded.equals(offerFiveTakerGetsFundedExpected), true); assert.strictEqual(offerFiveTakerPaysFunded.equals(offerFiveTakerPaysFundedExpected), true); @@ -1500,17 +1471,17 @@ describe('OrderBook', function() { }); it('Set offers - multiple calls', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); - var offers = fixtures.bookOffersResponse().offers; + const offers = fixtures.bookOffersResponse().offers; book.setOffers(offers); book.setOffers(offers); @@ -1534,17 +1505,17 @@ describe('OrderBook', function() { }); it('Set offers - incorrect taker pays funded', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); - var offers = fixtures.DECIMAL_TAKER_PAYS_FUNDED_OFFERS; + const offers = fixtures.DECIMAL_TAKER_PAYS_FUNDED_OFFERS; book.setOffers(offers); @@ -1555,18 +1526,18 @@ describe('OrderBook', function() { }); it('Notify - created node', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); book._subscribed = true; - var message = fixtures.transactionWithCreatedOffer(); + const message = fixtures.transactionWithCreatedOffer(); book.notify(message); @@ -1577,25 +1548,25 @@ describe('OrderBook', function() { }); it('Notify - created nodes - correct sorting', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); book._subscribed = true; - var offer = fixtures.transactionWithCreatedOffer(); + const offer = fixtures.transactionWithCreatedOffer(); - var lowQualityOffer = fixtures.transactionWithCreatedOffer({ + const lowQualityOffer = fixtures.transactionWithCreatedOffer({ account: addresses.OTHER_ACCOUNT, amount: '1.5' }); - var highQualityOffer = fixtures.transactionWithCreatedOffer({ + const highQualityOffer = fixtures.transactionWithCreatedOffer({ account: addresses.THIRD_ACCOUNT, amount: '3.83' }); @@ -1610,14 +1581,14 @@ describe('OrderBook', function() { assert.strictEqual(book._offers[2].Account, addresses.OTHER_ACCOUNT); }); - it('Notify - created nodes - events', function() { - var numTransactionEvents = 0; - var numModelEvents = 0; - var numOfferAddedEvents = 0; + it('Notify - created nodes - events', function(done) { + let numTransactionEvents = 0; + let numModelEvents = 0; + let numOfferAddedEvents = 0; - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -1635,37 +1606,40 @@ describe('OrderBook', function() { numOfferAddedEvents += 1; }); - book._issuerTransferRate = 1002000000; + book._issuerTransferRate = Amount.from_json(1002000000); book._subscribed = true; - var offer = fixtures.transactionWithCreatedOffer(); - var offer2 = fixtures.transactionWithCreatedOffer(); - var offer3 = fixtures.transactionWithCreatedOffer(); + const offer = fixtures.transactionWithCreatedOffer(); + const offer2 = fixtures.transactionWithCreatedOffer(); + const offer3 = fixtures.transactionWithCreatedOffer(); book.notify(offer); book.notify(offer2); book.notify(offer3); assert.strictEqual(numTransactionEvents, 3); - assert.strictEqual(numModelEvents, 3); assert.strictEqual(numOfferAddedEvents, 3); + setTimeout(function() { + assert.strictEqual(numModelEvents, 1); + done(); + }, 300); }); it('Notify - deleted node', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers()); - var message = fixtures.transactionWithDeletedOffer(); + const message = fixtures.transactionWithDeletedOffer(); book.notify(message); @@ -1675,20 +1649,20 @@ describe('OrderBook', function() { }); it('Notify - deleted node - last offer', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers().slice(0, 1)); - var message = fixtures.transactionWithDeletedOffer(); + const message = fixtures.transactionWithDeletedOffer(); book.notify(message); @@ -1696,14 +1670,14 @@ describe('OrderBook', function() { assert.strictEqual(book.getOwnerFunds(addresses.ACCOUNT), undefined); }); - it('Notify - deleted node - events', function() { - var numTransactionEvents = 0; - var numModelEvents = 0; - var numTradeEvents = 0; - var numOfferRemovedEvents = 0; + it('Notify - deleted node - events', function(done) { + let numTransactionEvents = 0; + let numModelEvents = 0; + let numTradeEvents = 0; + let numOfferRemovedEvents = 0; - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -1726,31 +1700,34 @@ describe('OrderBook', function() { }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers()); - var message = fixtures.transactionWithDeletedOffer(); + const message = fixtures.transactionWithDeletedOffer(); book.notify(message); assert.strictEqual(numTransactionEvents, 1); - assert.strictEqual(numModelEvents, 1); assert.strictEqual(numTradeEvents, 1); assert.strictEqual(numOfferRemovedEvents, 1); + setTimeout(function() { + assert.strictEqual(numModelEvents, 1); + done(); + }, 300) }); it('Notify - deleted node - trade', function(done) { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book.on('trade', function(tradePays, tradeGets) { - var expectedTradePays = Amount.from_json(fixtures.TAKER_PAYS); - var expectedTradeGets = Amount.from_json({ + const expectedTradePays = Amount.from_json(fixtures.TAKER_PAYS); + const expectedTradeGets = Amount.from_json({ value: fixtures.TAKER_GETS, currency: 'USD', issuer: addresses.ISSUER @@ -1763,30 +1740,30 @@ describe('OrderBook', function() { }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers()); - var message = fixtures.transactionWithDeletedOffer(); + const message = fixtures.transactionWithDeletedOffer(); book.notify(message); }); it('Notify - deleted node - offer cancel', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers()); - var message = fixtures.transactionWithDeletedOffer({ + const message = fixtures.transactionWithDeletedOffer({ transaction_type: 'OfferCancel' }); @@ -1798,20 +1775,20 @@ describe('OrderBook', function() { }); it('Notify - deleted node - offer cancel - last offer', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers().slice(0, 1)); - var message = fixtures.transactionWithDeletedOffer({ + const message = fixtures.transactionWithDeletedOffer({ transaction_type: 'OfferCancel' }); @@ -1822,20 +1799,20 @@ describe('OrderBook', function() { }); it('Notify - modified node', function() { - var remote = new Remote(); + const remote = createRemote(); - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers()); - var message = fixtures.transactionWithModifiedOffer(); + const message = fixtures.transactionWithModifiedOffer(); book.notify(message); @@ -1852,14 +1829,14 @@ describe('OrderBook', function() { assert.strictEqual(book._offers[1].taker_pays_funded, '972251352'); }); - it('Notify - modified node - events', function() { - var numTransactionEvents = 0; - var numModelEvents = 0; - var numTradeEvents = 0; - var numOfferChangedEvents = 0; + it('Notify - modified node - events', function(done) { + let numTransactionEvents = 0; + let numModelEvents = 0; + let numTradeEvents = 0; + let numOfferChangedEvents = 0; - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -1882,31 +1859,34 @@ describe('OrderBook', function() { }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers()); - var message = fixtures.transactionWithModifiedOffer(); + const message = fixtures.transactionWithModifiedOffer(); book.notify(message); assert.strictEqual(numTransactionEvents, 1); - assert.strictEqual(numModelEvents, 1); assert.strictEqual(numTradeEvents, 1); assert.strictEqual(numOfferChangedEvents, 1); + setTimeout(function() { + assert.strictEqual(numModelEvents, 1); + done(); + }, 300); }); it('Notify - modified node - trade', function(done) { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book.on('trade', function(tradePays, tradeGets) { - var expectedTradePays = Amount.from_json('800000000'); - var expectedTradeGets = Amount.from_json({ + const expectedTradePays = Amount.from_json('800000000'); + const expectedTradeGets = Amount.from_json({ value: 1, currency: 'USD', issuer: addresses.ISSUER @@ -1919,26 +1899,26 @@ describe('OrderBook', function() { }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers()); - var message = fixtures.transactionWithModifiedOffer(); + const message = fixtures.transactionWithModifiedOffer(); book.notify(message); }); it('Notify - modified nodes - trade', function(done) { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book.on('trade', function(tradePays, tradeGets) { - var expectedTradePays = Amount.from_json('870000000'); - var expectedTradeGets = Amount.from_json({ + const expectedTradePays = Amount.from_json('870000000'); + const expectedTradeGets = Amount.from_json({ value: 2, currency: 'USD', issuer: addresses.ISSUER @@ -1951,23 +1931,23 @@ describe('OrderBook', function() { }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers()); - var message = fixtures.transactionWithModifiedOffers(); + const message = fixtures.transactionWithModifiedOffers(); book.notify(message); }); it('Notify - no nodes', function() { - var numTransactionEvents = 0; - var numModelEvents = 0; - var numTradeEvents = 0; - var numOfferChangedEvents = 0; + let numTransactionEvents = 0; + let numModelEvents = 0; + let numTradeEvents = 0; + let numOfferChangedEvents = 0; - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' @@ -1990,11 +1970,11 @@ describe('OrderBook', function() { }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers()); - var message = fixtures.transactionWithNoNodes(); + const message = fixtures.transactionWithNoNodes(); book.notify(message); @@ -2005,15 +1985,15 @@ describe('OrderBook', function() { }); it('Delete offer - offer cancel - funded after delete', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers({ account_funds: '20' @@ -2032,15 +2012,15 @@ describe('OrderBook', function() { }); it('Delete offer - offer cancel - not fully funded after delete', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers({ account_funds: '4.5' @@ -2061,15 +2041,15 @@ describe('OrderBook', function() { }); it('Insert offer - best quality', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.QUALITY_OFFERS); @@ -2085,15 +2065,15 @@ describe('OrderBook', function() { }); it('Insert offer - best quality - insufficient funds for all offers', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers()); @@ -2120,15 +2100,15 @@ describe('OrderBook', function() { }); it('Insert offer - worst quality - insufficient funds for all orders', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers({ account_funds: '25' @@ -2157,15 +2137,15 @@ describe('OrderBook', function() { }); it('Insert offer - middle quality - insufficient funds for all offers', function() { - var remote = new Remote(); - var book = remote.createOrderBook({ + const remote = createRemote(); + const book = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: addresses.ISSUER, currency_pays: 'XRP' }); book._subscribed = true; - book._issuerTransferRate = 1000000000; + book._issuerTransferRate = Amount.from_json(1000000000); book.setOffers(fixtures.fiatOffers({ account_funds: '30' @@ -2194,13 +2174,13 @@ describe('OrderBook', function() { }); it('Request offers - native currency', function(done) { - var remote = new Remote(); + const remote = createRemote(); - var offers = { + const offers = { offers: fixtures.REQUEST_OFFERS_NATIVE }; - var expected = [ + const expected = [ { Account: addresses.ACCOUNT, BookDirectory: '6EAB7C172DEFA430DBFAD120FDC373B5F5AF8B191649EC985711A3A4254F5000', @@ -2220,6 +2200,7 @@ describe('OrderBook', function() { is_fully_funded: false, taker_gets_funded: '600', taker_pays_funded: '33.6398379637041', + qualityHex: '5711A3A4254F5000', quality: '.0560663966061735' }, { @@ -2242,6 +2223,7 @@ describe('OrderBook', function() { is_fully_funded: true, taker_gets_funded: '2000', taker_pays_funded: '99.72233516476456', + qualityHex: '5711B6D8C62EF414', quality: '0.049861167582382' }, { @@ -2264,6 +2246,7 @@ describe('OrderBook', function() { is_fully_funded: true, taker_gets_funded: '2000', taker_pays_funded: '99.72233516476456', + qualityHex: '5711B6D8C62EF414', quality: '0.049861167582382' }, { @@ -2286,6 +2269,7 @@ describe('OrderBook', function() { taker_gets_funded: '1900', taker_pays_funded: '94.7362184065258', owner_funds: '3900', + qualityHex: '5711B6D8C62EF414', quality: '0.049861167582382' } ]; @@ -2313,7 +2297,7 @@ describe('OrderBook', function() { } }; - var book = remote.createOrderBook({ + const book = remote.createOrderBook({ currency_gets: 'XRP', currency_pays: 'USD', issuer_pays: addresses.ISSUER