diff --git a/HISTORY.md b/HISTORY.md index b9557def..62b60027 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -9,6 +9,14 @@ + [Fix bug where the paths would be set with an empty array](https://github.com/ripple/ripple-lib/commit/83874ec0962da311b76f2385623e51c68bc39035) + [Fix reserve calculation](https://github.com/ripple/ripple-lib/commit/52879febb92d876f01f2e4d70871baa07af631fb) +##0.12.7 and 0.12.8 + ++ [Improve performance of orderbook](https://github.com/ripple/ripple-lib/commit/c745faaaf0956ca98448a754b4fe97fb50574fc7) + ++ [Remove Firefox warning about prototype overwrite](https://github.com/ripple/ripple-lib/commit/0c62fa21123b220b066871e1c41a3b4fe6f51885) + ++ [Fix compare bug in Amount class](https://github.com/ripple/ripple-lib/commit/806547dd154e1b0bf252e8a74ad3ac6aa8a97660) + ##0.12.6 + [Fix webpack require failure due to "./" notation](https://github.com/ripple/ripple-lib/commit/8d9746d7b10be203ee613df523c2522012ff1baf) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 46cd1a7d..adae97ae 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -170,20 +170,6 @@ "version": "0.7.2", "resolved": "https://registry.npmjs.org/ws/-/ws-0.7.2.tgz", "dependencies": { - "bufferutil": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-1.1.0.tgz", - "dependencies": { - "bindings": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" - }, - "nan": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz" - } - } - }, "options": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz" @@ -191,20 +177,6 @@ "ultron": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz" - }, - "utf-8-validate": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-1.1.0.tgz", - "dependencies": { - "bindings": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" - }, - "nan": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz" - } - } } } } diff --git a/src/core/autobridgecalculator.js b/src/core/autobridgecalculator.js index 9b2a6e60..d3848337 100644 --- a/src/core/autobridgecalculator.js +++ b/src/core/autobridgecalculator.js @@ -2,8 +2,8 @@ const _ = require('lodash'); const assert = require('assert'); -const UInt160 = require('./uint160').UInt160; const Amount = require('./amount').Amount; +const UInt160 = require('./uint160').UInt160; const Utils = require('./orderbookutils'); function assertValidNumber(number, message) { @@ -42,18 +42,46 @@ const NULL_AMOUNT = Utils.normalizeAmount('0'); * @return {Array} */ -AutobridgeCalculator.prototype.calculate = function() { - const oldMode = Amount.strict_mode; - Amount.strict_mode = false; +AutobridgeCalculator.prototype.calculate = function(callback) { - let legOnePointer = 0; - let legTwoPointer = 0; + const legOnePointer = 0; + const legTwoPointer = 0; const offersAutobridged = []; this.clearOwnerFundsLeftover(); + this._calculateInternal(legOnePointer, legTwoPointer, offersAutobridged, + callback); +}; + +AutobridgeCalculator.prototype._calculateInternal = function( + legOnePointer_, legTwoPointer_, offersAutobridged, callback +) { + + // Amount class is calling _check_limits after each operation in strict mode, + // and _check_limits is very computationally expensive, so we turning it off + // whle doing calculations + this._oldMode = Amount.strict_mode; + Amount.strict_mode = false; + + let legOnePointer = legOnePointer_; + let legTwoPointer = legTwoPointer_; + + const startTime = Date.now(); + while (this.legOneOffers[legOnePointer] && this.legTwoOffers[legTwoPointer]) { + // manually implement cooperative multitasking that yields after 30ms + // of execution so user's browser stays responsive + const lasted = (Date.now() - startTime); + if (lasted > 30) { + setTimeout(this._calculateInternal.bind(this, legOnePointer, + legTwoPointer, offersAutobridged, callback), 0); + + Amount.strict_mode = this._oldMode; + return; + } + const legOneOffer = this.legOneOffers[legOnePointer]; const legTwoOffer = this.legTwoOffers[legTwoPointer]; const leftoverFunds = this.getLeftoverOwnerFunds(legOneOffer.Account); @@ -112,8 +140,8 @@ AutobridgeCalculator.prototype.calculate = function() { offersAutobridged.push(autobridgedOffer); } - Amount.strict_mode = oldMode; - return offersAutobridged; + Amount.strict_mode = this._oldMode; + callback(offersAutobridged); }; /** diff --git a/src/core/orderbook.js b/src/core/orderbook.js index 676f2104..ed080f78 100644 --- a/src/core/orderbook.js +++ b/src/core/orderbook.js @@ -87,29 +87,30 @@ function OrderBook(remote, this._gotOffersFromLegOne = false; this._gotOffersFromLegTwo = false; + this._waitingForOffers = false; + this._lastUpdateLedgerSequence = 0; + this._transactionsLeft = 0; + this._calculatorRunning = 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(); - this._autobridgeThrottleTimeMultiplier = 1; - this.createDebouncedOffersWrapper(); - function computeAutobridgedOffersWrapperOne() { - self._gotOffersFromLegOne = true; - self.computeAutobridgedOffersThrottled(); + if (!self._gotOffersFromLegOne) { + self._gotOffersFromLegOne = true; + self.computeAutobridgedOffersWrapper(); + } } function computeAutobridgedOffersWrapperTwo() { - self._gotOffersFromLegTwo = true; - self.computeAutobridgedOffersThrottled(); + if (!self._gotOffersFromLegTwo) { + self._gotOffersFromLegTwo = true; + self.computeAutobridgedOffersWrapper(); + } } function onDisconnect() { @@ -138,8 +139,12 @@ function OrderBook(remote, }); } - function updateFundedAmountsWrapper(transaction) { - self.updateFundedAmounts(transaction); + function onTransactionWrapper(transaction) { + self.onTransaction(transaction); + } + + function onLedgerClosedWrapper(message) { + self.onLedgerClosed(message); } function listenersModified(action, event) { @@ -152,7 +157,8 @@ function OrderBook(remote, self._shouldSubscribe = true; self.subscribe(); - self._remote.on('transaction', updateFundedAmountsWrapper); + self._remote.on('transaction', onTransactionWrapper); + self._remote.on('ledger_closed', onLedgerClosedWrapper); self._remote.once('disconnect', onDisconnect); if (self._isAutobridgeable) { @@ -181,7 +187,8 @@ function OrderBook(remote, this.on('unsubscribe', function() { self.resetCache(); - self._remote.removeListener('transaction', updateFundedAmountsWrapper); + self._remote.removeListener('transaction', onTransactionWrapper); + self._remote.removeListener('ledger_closed', onLedgerClosedWrapper); self._remote.removeListener('disconnect', onDisconnect); self._gotOffersFromLegOne = false; @@ -212,16 +219,6 @@ OrderBook.EVENTS = [ OrderBook.DEFAULT_TRANSFER_RATE = new IOUValue(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'); @@ -358,6 +355,8 @@ OrderBook.prototype.requestOffers = function(callback = function() {}, log.info('requesting offers', this._key); } + this._synchronized = false; + if (this._isAutobridgeable && !internal) { this._gotOffersFromLegOne = false; this._gotOffersFromLegTwo = false; @@ -372,9 +371,12 @@ OrderBook.prototype.requestOffers = function(callback = function() {}, return; } + self._waitingForOffers = false; + if (!Array.isArray(res.offers)) { // XXX What now? callback(new Error('Invalid response')); + self.emit('model', []); return; } @@ -382,7 +384,12 @@ OrderBook.prototype.requestOffers = function(callback = function() {}, log.info('requested offers', self._key, 'offers: ' + res.offers.length); } self.setOffers(res.offers); - self.notifyDirectOffersChanged(); + + if (self._isAutobridgeable) { + self.computeAutobridgedOffersWrapper(); + } else { + self.emit('model', self._offers); + } callback(null, self._offers); } @@ -393,9 +400,12 @@ OrderBook.prototype.requestOffers = function(callback = function() {}, log.info('failed to request offers', self._key, err); } + self._waitingForOffers = false; callback(err); } + this._waitingForOffers = true; + const requestOptions = _.merge({}, this.toJSON(), {ledger: 'validated'}); const request = this._remote.requestBookOffers(requestOptions); request.once('success', handleOffers); @@ -493,18 +503,6 @@ OrderBook.prototype.subscribeTransactions = function(callback) { return request; }; -/** - * Handles notifying listeners that direct offers have changed. For autobridged - * books, an additional merge step is also performed - */ - -OrderBook.prototype.notifyDirectOffersChangedInternal = function() { - if (this._isAutobridgeable) { - this.mergeDirectAndAutobridgedBooks(); - } else { - this.emit('model', this._offers); - } -}; /** * Reset cached owner's funds, offer counts, and offer sums @@ -839,6 +837,32 @@ OrderBook.prototype.isBalanceChangeNode = function(node) { return true; }; +OrderBook.prototype._canRunAutobridgeCalc = function(): boolean { + return !this._calculatorRunning; +}; + +OrderBook.prototype.onTransaction = function(transaction) { + this.updateFundedAmounts(transaction); + + + if (--this._transactionsLeft === 0 && !this._waitingForOffers) { + const lastClosedLedger = this._remote.getLedgerSequence(); + if (this._isAutobridgeable) { + if (this._canRunAutobridgeCalc()) { + if (this._legOneBook._lastUpdateLedgerSequence === lastClosedLedger || + this._legTwoBook._lastUpdateLedgerSequence === lastClosedLedger + ) { + this.computeAutobridgedOffersWrapper(); + } else if (this._lastUpdateLedgerSequence === lastClosedLedger) { + this.mergeDirectAndAutobridgedBooks(); + } + } + } else if (this._lastUpdateLedgerSequence === lastClosedLedger) { + this.emit('model', this._offers); + } + } +}; + /** * Updates funded amounts/balances using modified balance nodes * @@ -946,6 +970,16 @@ OrderBook.prototype.updateOwnerOffersFundedAmount = function(account) { }); }; + +OrderBook.prototype.onLedgerClosed = function(message) { + if (!message || (message && !_.isNumber(message.txn_count)) || + !this._subscribed || this._destroyed || this._waitingForOffers + ) { + return; + } + this._transactionsLeft = message.txn_count; +}; + /** * Notify orderbook of a relevant transaction * @@ -1046,7 +1080,7 @@ OrderBook.prototype.notify = function(transaction) { this.emit('transaction', transaction); - this.notifyDirectOffersChanged(); + this._lastUpdateLedgerSequence = this._remote.getLedgerSequence(); if (!takerGetsTotal.is_zero()) { this.emit('trade', takerPaysTotal, takerGetsTotal); @@ -1331,15 +1365,13 @@ OrderBook.prototype.is_valid = function() { * IOU:XRP and XRP:IOU books */ -OrderBook.prototype.computeAutobridgedOffers = function() { +OrderBook.prototype.computeAutobridgedOffers = function(callback = 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) { + if (this._destroyed) { return; } @@ -1352,36 +1384,26 @@ OrderBook.prototype.computeAutobridgedOffers = function() { this._issuerPays ); - this._offersAutobridged = autobridgeCalculator.calculate(); + autobridgeCalculator.calculate((autobridgedOffers) => { + this._offersAutobridged = autobridgedOffers; + callback(); + }); }; OrderBook.prototype.computeAutobridgedOffersWrapper = function() { - const startTime = Date.now(); - this.computeAutobridgedOffers(); - this.mergeDirectAndAutobridgedBooks(); - const lasted = (Date.now() - startTime); - - const newMult = - Math.floor(lasted * 2 / OrderBook.AUTOBRIDGE_CALCULATE_THROTTLE_TIME) + 1; - if (newMult !== this._autobridgeThrottleTimeMultiplier) { - this._autobridgeThrottleTimeMultiplier = newMult; - this.createDebouncedOffersWrapper(); + if (!this._gotOffersFromLegOne || !this._gotOffersFromLegTwo || + !this._synchronized || this._destroyed || this._calculatorRunning + ) { + return; } -}; -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}); + this._calculatorRunning = true; + this.computeAutobridgedOffers(() => { + this.mergeDirectAndAutobridgedBooks(); + this._calculatorRunning = false; + }); }; - /** * Merge direct and autobridged offers into a combined orderbook * diff --git a/test/orderbook-autobridge-test.js b/test/orderbook-autobridge-test.js index 6d61b907..bb4bb51a 100644 --- a/test/orderbook-autobridge-test.js +++ b/test/orderbook-autobridge-test.js @@ -16,6 +16,7 @@ describe('OrderBook Autobridging', function() { function createRemote() { const remote = new Remote(); + remote._ledger_current_index = 32570; remote.isConnected = function() { return true; }; @@ -37,7 +38,7 @@ describe('OrderBook Autobridging', function() { assert.deepEqual(book._legTwoBook._currencyPays.to_hex(), Currency.from_json('XRP').to_hex()); }); - it('Compute autobridged offers', function() { + it('Compute autobridged offers', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -56,20 +57,23 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 1); - assert.strictEqual(book._offersAutobridged.length, 1); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '17.07639524223001'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '58.61727326122974'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '17.07639524223001'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '58.61727326122974'); + assert.strictEqual(book._offersAutobridged[0].taker_gets_funded, '17.07639524223001'); + assert.strictEqual(book._offersAutobridged[0].taker_pays_funded, '58.61727326122974'); - assert.strictEqual(book._offersAutobridged[0].taker_gets_funded, '17.07639524223001'); - assert.strictEqual(book._offersAutobridged[0].taker_pays_funded, '58.61727326122974'); + assert(book._offersAutobridged[0].autobridged); + + done(); + }); - assert(book._offersAutobridged[0].autobridged); }); - it('Compute autobridged offers - leg one partially funded', function() { + it('Compute autobridged offers - leg one partially funded', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -90,17 +94,20 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 1); - assert.strictEqual(book._offersAutobridged.length, 1); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '7.273651248813431'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '24.96789265329184'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '7.273651248813431'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '24.96789265329184'); + assert(book._offersAutobridged[0].autobridged); + + done(); + }); - assert(book._offersAutobridged[0].autobridged); }); - it('Compute autobridged offers - leg two partially funded', function() { + it('Compute autobridged offers - leg two partially funded', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -121,17 +128,20 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 1); - assert.strictEqual(book._offersAutobridged.length, 1); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '10'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '34.32649132449533'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '10'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '34.32649132449533'); + assert(book._offersAutobridged[0].autobridged); + + done(); + }); - assert(book._offersAutobridged[0].autobridged); }); - it('Compute autobridged offers - leg two transfer rate', function() { + it('Compute autobridged offers - leg two transfer rate', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -152,15 +162,18 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '9.980039920159681'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '34.25797537722665'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '9.980039920159681'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '34.25797537722665'); + assert(book._offersAutobridged[0].autobridged); + + done(); + }); - assert(book._offersAutobridged[0].autobridged); }); - it('Compute autobridged offers - taker funds < leg two in', function() { + it('Compute autobridged offers - taker funds < leg two in', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -185,17 +198,20 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 1); - assert.strictEqual(book._offersAutobridged.length, 1); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '108.6682345172846'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '373.019921005'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '108.6682345172846'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '373.019921005'); + assert(book._offersAutobridged[0].autobridged); + + done(); + }); - assert(book._offersAutobridged[0].autobridged); }); - it('Compute autobridged offers - leg one partially funded - owners equal', function() { + it('Compute autobridged offers - leg one partially funded - owners equal', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -218,17 +234,20 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 1); - assert.strictEqual(book._offersAutobridged.length, 1); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '17.07639524223001'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '58.61727326122974'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '17.07639524223001'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '58.61727326122974'); + assert(book._offersAutobridged[0].autobridged); + + done(); + }); - assert(book._offersAutobridged[0].autobridged); }); - it('Compute autobridged offers - leg one partially funded - owners equal - leg two in > leg one out', function() { + it('Compute autobridged offers - leg one partially funded - owners equal - leg two in > leg one out', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -254,17 +273,20 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 1); - assert.strictEqual(book._offersAutobridged.length, 1); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '108.6682345172846'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '373.0199210049999'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '108.6682345172846'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '373.0199210049999'); + assert(book._offersAutobridged[0].autobridged); + + done(); + }); - assert(book._offersAutobridged[0].autobridged); }); - it('Compute autobridged offers - leg one consumes leg two fully', function() { + it('Compute autobridged offers - leg one consumes leg two fully', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -283,22 +305,25 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 2); - assert.strictEqual(book._offersAutobridged.length, 2); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '17.07639524223001'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '58.61727326122974'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '17.07639524223001'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '58.61727326122974'); + assert(book._offersAutobridged[0].autobridged); - assert(book._offersAutobridged[0].autobridged); + assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '5.038346688725268'); + assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '314.4026477437702'); - assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '5.038346688725268'); - assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '314.4026477437702'); + assert(book._offersAutobridged[1].autobridged); + + done(); + }); - assert(book._offersAutobridged[1].autobridged); }); - it('Compute autobridged offers - leg two consumes first leg one offer fully', function() { + it('Compute autobridged offers - leg two consumes first leg one offer fully', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -321,22 +346,25 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 2); - assert.strictEqual(book._offersAutobridged.length, 2); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '108.6682345172846'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '373.019921005'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '108.6682345172846'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '373.019921005'); + assert(book._offersAutobridged[0].autobridged); - assert(book._offersAutobridged[0].autobridged); + assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '62.0957179050155'); + assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '213.1791399943838'); - assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '62.0957179050155'); - assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '213.1791399943838'); + assert(book._offersAutobridged[1].autobridged); + + done(); + }); - assert(book._offersAutobridged[1].autobridged); }); - it('Compute autobridged offers - owners equal', function() { + it('Compute autobridged offers - owners equal', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -360,22 +388,25 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 2); - assert.strictEqual(book._offersAutobridged.length, 2); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '17.07639524223001'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '58.61727326122974'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '17.07639524223001'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '58.61727326122974'); + assert(book._offersAutobridged[0].autobridged); - assert(book._offersAutobridged[0].autobridged); + assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '0.4001139945128008'); + assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '24.96789265329184'); - assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '0.4001139945128008'); - assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '24.96789265329184'); + assert(book._offersAutobridged[1].autobridged); + + done(); + }); - assert(book._offersAutobridged[1].autobridged); }); - it('Compute autobridged offers - owners equal - leg one overfunded', function() { + it('Compute autobridged offers - owners equal - leg one overfunded', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -400,22 +431,25 @@ describe('OrderBook Autobridging', function() { book._legTwoBook.setOffers(legTwoOffers); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 2); - assert.strictEqual(book._offersAutobridged.length, 2); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '17.07639524223001'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '58.61727326122974'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '17.07639524223001'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '58.61727326122974'); + assert(book._offersAutobridged[0].autobridged); - assert(book._offersAutobridged[0].autobridged); + assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '5.038346688725268'); + assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '314.4026477437702'); - assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '5.038346688725268'); - assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '314.4026477437702'); + assert(book._offersAutobridged[1].autobridged); + + done(); + }); - assert(book._offersAutobridged[1].autobridged); }); - it('Compute autobridged offers - TakerPays < Quality * TakerGets', function() { + it('Compute autobridged offers - TakerPays < Quality * TakerGets', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -458,17 +492,20 @@ describe('OrderBook Autobridging', function() { ]); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 1); - assert.strictEqual(book._offersAutobridged.length, 1); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '75'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '75'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '75'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '75'); + assert(book._offersAutobridged[0].autobridged); + + done(); + }); - assert(book._offersAutobridged[0].autobridged); }); - it('Compute autobridged offers - update funded amount', function() { + it('Compute autobridged offers - update funded amount', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -534,27 +571,30 @@ describe('OrderBook Autobridging', function() { ]); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 3); - assert.strictEqual(book._offersAutobridged.length, 3); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '90'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '90'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '90'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '90'); + assert(book._offersAutobridged[0].autobridged); - assert(book._offersAutobridged[0].autobridged); + assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '5'); + assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '10'); - assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '5'); - assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '10'); + assert(book._offersAutobridged[1].autobridged); - assert(book._offersAutobridged[1].autobridged); + assert.strictEqual(book._offersAutobridged[2].TakerGets.value, '20'); + assert.strictEqual(book._offersAutobridged[2].TakerPays.value, '80'); - assert.strictEqual(book._offersAutobridged[2].TakerGets.value, '20'); - assert.strictEqual(book._offersAutobridged[2].TakerPays.value, '80'); + assert(book._offersAutobridged[2].autobridged); + + done(); + }); - assert(book._offersAutobridged[2].autobridged); }); - it('Compute autobridged offers - update funded amount - owners equal', function() { + it('Compute autobridged offers - update funded amount - owners equal', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -620,27 +660,30 @@ describe('OrderBook Autobridging', function() { ]); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 3); - assert.strictEqual(book._offersAutobridged.length, 3); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '90'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '90'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '90'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '90'); + assert(book._offersAutobridged[0].autobridged); - assert(book._offersAutobridged[0].autobridged); + assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '5'); + assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '10'); - assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '5'); - assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '10'); + assert(book._offersAutobridged[1].autobridged); - assert(book._offersAutobridged[1].autobridged); + assert.strictEqual(book._offersAutobridged[2].TakerGets.value, '10'); + assert.strictEqual(book._offersAutobridged[2].TakerPays.value, '100'); - assert.strictEqual(book._offersAutobridged[2].TakerGets.value, '10'); - assert.strictEqual(book._offersAutobridged[2].TakerPays.value, '100'); + assert(book._offersAutobridged[2].autobridged); + + done(); + }); - assert(book._offersAutobridged[2].autobridged); }); - it('Compute autobridged offers - update funded amount - first two owners equal', function() { + it('Compute autobridged offers - update funded amount - first two owners equal', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -717,32 +760,35 @@ describe('OrderBook Autobridging', function() { ]); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 4); - assert.strictEqual(book._offersAutobridged.length, 4); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '90'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '90'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '90'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '90'); + assert(book._offersAutobridged[0].autobridged); - assert(book._offersAutobridged[0].autobridged); + assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '5'); + assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '10'); - assert.strictEqual(book._offersAutobridged[1].TakerGets.value, '5'); - assert.strictEqual(book._offersAutobridged[1].TakerPays.value, '10'); + assert(book._offersAutobridged[1].autobridged); - assert(book._offersAutobridged[1].autobridged); + assert.strictEqual(book._offersAutobridged[2].TakerGets.value, '25'); + assert.strictEqual(book._offersAutobridged[2].TakerPays.value, '100'); - assert.strictEqual(book._offersAutobridged[2].TakerGets.value, '25'); - assert.strictEqual(book._offersAutobridged[2].TakerPays.value, '100'); + assert(book._offersAutobridged[2].autobridged); - assert(book._offersAutobridged[2].autobridged); + assert.strictEqual(book._offersAutobridged[3].TakerGets.value, '20'); + assert.strictEqual(book._offersAutobridged[3].TakerPays.value, '80'); - assert.strictEqual(book._offersAutobridged[3].TakerGets.value, '20'); - assert.strictEqual(book._offersAutobridged[3].TakerPays.value, '80'); + assert(book._offersAutobridged[3].autobridged); + + done(); + }); - assert(book._offersAutobridged[3].autobridged); }); - it('Compute autobridged offers - unfunded offer - owners equal', function() { + it('Compute autobridged offers - unfunded offer - owners equal', function(done) { const book = createRemote().createOrderBook({ currency_gets: 'EUR', issuer_gets: addresses.ISSUER, @@ -785,13 +831,16 @@ describe('OrderBook Autobridging', function() { ]); book._gotOffersFromLegOne = book._gotOffersFromLegTwo = true; - book.computeAutobridgedOffers(); + book.computeAutobridgedOffers(() => { + assert.strictEqual(book._offersAutobridged.length, 1); - assert.strictEqual(book._offersAutobridged.length, 1); + assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '75'); + assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '75'); - assert.strictEqual(book._offersAutobridged[0].TakerGets.value, '75'); - assert.strictEqual(book._offersAutobridged[0].TakerPays.value, '75'); + assert(book._offersAutobridged[0].autobridged); + + done(); + }); - assert(book._offersAutobridged[0].autobridged); }); }); diff --git a/test/orderbook-test.js b/test/orderbook-test.js index 7c6e77a6..fcca2bdc 100644 --- a/test/orderbook-test.js +++ b/test/orderbook-test.js @@ -16,7 +16,7 @@ describe('OrderBook', function() { function createRemote() { const remote = new Remote(); - + remote._ledger_current_index = 32570; remote.isConnected = function() { return true; }; @@ -1605,9 +1605,15 @@ describe('OrderBook', function() { const offer2 = fixtures.transactionWithCreatedOffer(); const offer3 = fixtures.transactionWithCreatedOffer(); + remote.emit('ledger_closed', {txn_count: 3}); + book.notify(offer); + remote.emit('transaction', offer); book.notify(offer2); + remote.emit('transaction', offer2); book.notify(offer3); + remote.emit('transaction', offer3); + assert.strictEqual(numTransactionEvents, 3); assert.strictEqual(numOfferAddedEvents, 3); @@ -1698,7 +1704,10 @@ describe('OrderBook', function() { const message = fixtures.transactionWithDeletedOffer(); + remote.emit('ledger_closed', {txn_count: 1}); + book.notify(message); + remote.emit('transaction', message); assert.strictEqual(numTransactionEvents, 1); assert.strictEqual(numTradeEvents, 1); @@ -1857,7 +1866,10 @@ describe('OrderBook', function() { const message = fixtures.transactionWithModifiedOffer(); + remote.emit('ledger_closed', {txn_count: 1}); + book.notify(message); + remote.emit('transaction', message); assert.strictEqual(numTransactionEvents, 1); assert.strictEqual(numTradeEvents, 1); diff --git a/test/remote-test.js b/test/remote-test.js index fe659392..f44c91e2 100644 --- a/test/remote-test.js +++ b/test/remote-test.js @@ -716,6 +716,7 @@ describe('Remote', function() { function() { const message = require('./fixtures/transaction-offercreate'); let i = 0; + remote._ledger_current_index = 32570; const orderbook = remote.createOrderBook({ currency_gets: 'USD', issuer_gets: 'rJy64aCJLP3vf8o3WPKn4iQKtfpjh6voAR',