optimize AutobridgeCalculator and Amount for speed

This commit is contained in:
Ivan Tivonenko
2015-09-17 18:51:29 +03:00
parent c7df5df163
commit 20fa8bc953
9 changed files with 214 additions and 123 deletions

View File

@@ -1,10 +1,7 @@
machine:
node:
version: 0.12.0
<<<<<<< HEAD
test:
override:
- bin/ci.sh "$CIRCLE_NODE_INDEX" "$CIRCLE_NODE_TOTAL":
parallel: true
=======
>>>>>>> upstream/master

View File

@@ -105,6 +105,19 @@ Amount.NaN = function() {
return result; // but let's be careful
};
Amount.createFast = function(value: Value, currency: Currency, issuer: UInt160,
isNative: boolean
) {
const res = new Amount(value);
res._is_native = isNative;
res._currency = currency;
res._issuer = issuer;
res._value = value.isZero() && value.isNegative() ?
value.negate() : value;
return res;
};
// be sure that _is_native is set properly BEFORE calling _set_value
Amount.prototype._set_value = function(value: Value) {
@@ -122,27 +135,30 @@ Amount.prototype.abs = function() {
};
Amount.prototype.add = function(addend) {
const addendAmount = Amount.from_json(addend);
const addendAmount = addend instanceof Amount ?
addend : Amount.from_json(addend);
if (!this.is_comparable(addendAmount)) {
return new Amount();
}
return this._copy(this._value.add(addendAmount._value));
};
Amount.prototype.subtract = function(subtrahend) {
// Correctness over speed, less code has less bugs, reuse add code.
return this.add(Amount.from_json(subtrahend).negate());
const subsAmount = subtrahend instanceof Amount ?
subtrahend : Amount.from_json(subtrahend);
return this.add(subsAmount.negate());
};
// XXX Diverges from cpp.
Amount.prototype.multiply = function(multiplicand) {
const multiplicandValue = multiplicand instanceof Amount ?
multiplicand._value :
Amount.from_json(multiplicand)._value;
const multiplicandAmount = Amount.from_json(multiplicand);
return this._copy(this._value.multiply(multiplicandAmount._value));
return this._copy(this._value.multiply(multiplicandValue));
};
@@ -151,9 +167,11 @@ Amount.prototype.scale = function(scaleFactor) {
};
Amount.prototype.divide = function(divisor) {
const divisorAmount = Amount.from_json(divisor);
const divisorValue = divisor instanceof Amount ?
divisor._value :
Amount.from_json(divisor)._value;
return this._copy(this._value.divide(divisorAmount._value));
return this._copy(this._value.divide(divisorValue));
};
/**
@@ -344,7 +362,7 @@ Amount.prototype._check_limits = function() {
};
Amount.prototype.clone = function(negate) {
return this.copyTo(new Amount(), negate);
return this.copyTo(new Amount(this._value), negate);
};
Amount.prototype._copy = function(value) {
@@ -354,9 +372,10 @@ Amount.prototype._copy = function(value) {
};
Amount.prototype.compareTo = function(to) {
const toAmount = Amount.from_json(to);
const toAmount = to instanceof Amount ? to : Amount.from_json(to);
if (!this.is_comparable(toAmount)) {
return 0;
throw new Error('Not comparable');
}
return this._value.comparedTo(toAmount._value);
};
@@ -743,8 +762,9 @@ Amount.prototype.to_text = function() {
// not native
const offset = this._value.getExponent() - 15;
const sign = this._value.isNegative() ? '-' : '';
const mantissa = utils.getMantissa16FromString(
this._value.abs().toString());
const mantissa = this._value.isNegative() ?
utils.getMantissa16FromString(this._value.abs().toString()) :
utils.getMantissa16FromString(this._value.toString());
if (offset !== 0 && (offset < -25 || offset > -4)) {
// Use e notation.
// XXX Clamp output.

View File

@@ -18,19 +18,23 @@ function assertValidLegOneOffer(legOneOffer, message) {
}
function AutobridgeCalculator(currencyGets, currencyPays,
legOneOffers, legTwoOffers, issuerGets, issuerPays) {
legOneOffers, legTwoOffers, issuerGets, issuerPays
) {
this._currencyGets = currencyGets;
this._currencyPays = currencyPays;
this._currencyGetsHex = currencyGets.to_hex();
this._currencyPaysHex = currencyPays.to_hex();
this._issuerGets = issuerGets;
this._issuerGetsObj = UInt160.from_json(issuerGets);
this._issuerPays = issuerPays;
this._issuerPaysObj = UInt160.from_json(issuerPays);
this.legOneOffers = _.cloneDeep(legOneOffers);
this.legTwoOffers = _.cloneDeep(legTwoOffers);
this._ownerFundsLeftover = {};
}
AutobridgeCalculator.NULL_AMOUNT = Utils.normalizeAmount('0');
const NULL_AMOUNT = Utils.normalizeAmount('0');
/**
* Calculates an ordered array of autobridged offers by quality
@@ -39,6 +43,9 @@ AutobridgeCalculator.NULL_AMOUNT = Utils.normalizeAmount('0');
*/
AutobridgeCalculator.prototype.calculate = function() {
const oldMode = Amount.strict_mode;
Amount.strict_mode = false;
let legOnePointer = 0;
let legTwoPointer = 0;
@@ -58,8 +65,10 @@ AutobridgeCalculator.prototype.calculate = function() {
this.adjustLegOneFundedAmount(legOneOffer);
}
const legOneTakerGetsFunded = Utils.getOfferTakerGetsFunded(legOneOffer);
const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer);
const legOneTakerGetsFunded = Utils.getOfferTakerGetsFunded(legOneOffer,
this._currencyPays, this._issuerPaysObj);
const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer,
this._currencyGets, this._issuerGetsObj);
if (legOneTakerGetsFunded.is_zero()) {
legOnePointer++;
@@ -103,6 +112,7 @@ AutobridgeCalculator.prototype.calculate = function() {
offersAutobridged.push(autobridgedOffer);
}
Amount.strict_mode = oldMode;
return offersAutobridged;
};
@@ -118,15 +128,20 @@ AutobridgeCalculator.prototype.calculate = function() {
AutobridgeCalculator.prototype.getAutobridgedOfferWithClampedLegOne =
function(legOneOffer, legTwoOffer) {
const legOneTakerGetsFunded = Utils.getOfferTakerGetsFunded(legOneOffer);
const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer);
const legOneQuality = Utils.getOfferQuality(legOneOffer, this._currencyGets);
const legOneTakerGetsFunded = Utils.getOfferTakerGetsFunded(legOneOffer,
this._currencyPays, this._issuerPaysObj);
const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer,
this._currencyGets, this._issuerGetsObj);
const legOneQuality = Utils.getOfferQuality(legOneOffer, this._currencyGets,
this._currencyPays, this._issuerPaysObj);
const autobridgedTakerGets = Utils.getOfferTakerGetsFunded(legTwoOffer);
const autobridgedTakerGets = Utils.getOfferTakerGetsFunded(legTwoOffer,
this._currencyGets, this._issuerGetsObj);
const autobridgedTakerPays = legTwoTakerPaysFunded.multiply(legOneQuality);
if (legOneOffer.Account === legTwoOffer.Account) {
const legOneTakerGets = Utils.getOfferTakerGets(legOneOffer);
const legOneTakerGets = Utils.getOfferTakerGets(legOneOffer,
this._currencyPays, this._issuerPaysObj);
const updatedTakerGets = legOneTakerGets.subtract(legTwoTakerPaysFunded);
this.setLegOneTakerGets(legOneOffer, updatedTakerGets);
@@ -158,15 +173,20 @@ function(legOneOffer, legTwoOffer) {
AutobridgeCalculator.prototype.getAutobridgedOfferWithClampedLegTwo =
function(legOneOffer, legTwoOffer) {
const legOneTakerGetsFunded = Utils.getOfferTakerGetsFunded(legOneOffer);
const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer);
const legTwoQuality = Utils.getOfferQuality(legTwoOffer, this._currencyGets);
const legOneTakerGetsFunded = Utils.getOfferTakerGetsFunded(legOneOffer,
this._currencyPays, this._issuerPaysObj);
const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer,
this._currencyGets, this._issuerGetsObj);
const legTwoQuality = Utils.getOfferQuality(legTwoOffer, this._currencyGets,
this._currencyGets, this._issuerGetsObj);
const autobridgedTakerGets = legOneTakerGetsFunded.divide(legTwoQuality);
const autobridgedTakerPays = Utils.getOfferTakerPaysFunded(legOneOffer);
const autobridgedTakerPays = Utils.getOfferTakerPaysFunded(legOneOffer,
this._currencyPays, this._issuerPaysObj);
// Update funded amount since leg two offer was not completely consumed
legTwoOffer.taker_gets_funded = Utils.getOfferTakerGetsFunded(legTwoOffer)
legTwoOffer.taker_gets_funded = Utils.getOfferTakerGetsFunded(legTwoOffer,
this._currencyGets, this._issuerGetsObj)
.subtract(autobridgedTakerGets)
.to_text();
legTwoOffer.taker_pays_funded = legTwoTakerPaysFunded
@@ -190,8 +210,10 @@ function(legOneOffer, legTwoOffer) {
AutobridgeCalculator.prototype.getAutobridgedOfferWithoutClamps =
function(legOneOffer, legTwoOffer) {
const autobridgedTakerGets = Utils.getOfferTakerGetsFunded(legTwoOffer);
const autobridgedTakerPays = Utils.getOfferTakerPaysFunded(legOneOffer);
const autobridgedTakerGets = Utils.getOfferTakerGetsFunded(legTwoOffer,
this._currencyGets, this._issuerGetsObj);
const autobridgedTakerPays = Utils.getOfferTakerPaysFunded(legOneOffer,
this._currencyPays, this._issuerPaysObj);
return this.formatAutobridgedOffer(
autobridgedTakerGets,
@@ -216,7 +238,7 @@ AutobridgeCalculator.prototype.clearOwnerFundsLeftover = function() {
*/
AutobridgeCalculator.prototype.resetOwnerFundsLeftover = function(account) {
this._ownerFundsLeftover[account] = Utils.normalizeAmount('0');
this._ownerFundsLeftover[account] = NULL_AMOUNT.clone();
return this._ownerFundsLeftover[account];
};
@@ -233,7 +255,7 @@ AutobridgeCalculator.prototype.getLeftoverOwnerFunds = function(account) {
let amount = this._ownerFundsLeftover[account];
if (!amount) {
amount = AutobridgeCalculator.NULL_AMOUNT.clone();
amount = NULL_AMOUNT.clone();
}
return amount;
@@ -308,7 +330,8 @@ function(takerGets, takerPays) {
autobridgedOffer.autobridged = true;
autobridgedOffer.BookDirectory = Utils.convertOfferQualityToHexFromText(autobridgedOffer.quality);
autobridgedOffer.BookDirectory =
Utils.convertOfferQualityToHexFromText(autobridgedOffer.quality);
autobridgedOffer.qualityHex = autobridgedOffer.BookDirectory;
return autobridgedOffer;
@@ -326,11 +349,13 @@ function(takerGets, takerPays) {
AutobridgeCalculator.prototype.unclampLegOneOwnerFunds = function(legOneOffer) {
assertValidLegOneOffer(legOneOffer, 'Leg one offer is invalid');
legOneOffer.initTakerGetsFunded = Utils.getOfferTakerGetsFunded(legOneOffer);
legOneOffer.initTakerGetsFunded = Utils.getOfferTakerGetsFunded(legOneOffer,
this._currencyPays, this._issuerPaysObj);
this.setLegOneTakerGetsFunded(
legOneOffer,
Utils.getOfferTakerGets(legOneOffer)
Utils.getOfferTakerGets(legOneOffer, this._currencyPays,
this._issuerPaysObj)
);
};
@@ -351,7 +376,8 @@ AutobridgeCalculator.prototype.unclampLegOneOwnerFunds = function(legOneOffer) {
AutobridgeCalculator.prototype.clampLegOneOwnerFunds = function(legOneOffer) {
assertValidLegOneOffer(legOneOffer, 'Leg one offer is invalid');
const takerGets = Utils.getOfferTakerGets(legOneOffer);
const takerGets = Utils.getOfferTakerGets(legOneOffer, this._currencyPays,
this._issuerPaysObj);
if (takerGets.compareTo(legOneOffer.initTakerGetsFunded) > 0) {
// After clamping, TakerGets is still greater than initial funded amount
@@ -376,12 +402,16 @@ function(legOneOffer) {
assertValidLegOneOffer(legOneOffer, 'Leg one offer is invalid');
assert(!legOneOffer.is_fully_funded, 'Leg one offer cannot be fully funded');
const fundedSum = Utils.getOfferTakerGetsFunded(legOneOffer)
const fundedSum = Utils.getOfferTakerGetsFunded(legOneOffer,
this._currencyPays, this._issuerPaysObj)
.add(this.getLeftoverOwnerFunds(legOneOffer.Account));
if (fundedSum.compareTo(Utils.getOfferTakerGets(legOneOffer)) >= 0) {
if (fundedSum.compareTo(Utils.getOfferTakerGets(legOneOffer,
this._currencyPays, this._issuerPaysObj)) >= 0
) {
// There are enough extra funds to fully fund the offer
const legOneTakerGets = Utils.getOfferTakerGets(legOneOffer);
const legOneTakerGets = Utils.getOfferTakerGets(legOneOffer,
this._currencyPays, this._issuerPaysObj);
const updatedLeftover = fundedSum.subtract(legOneTakerGets);
this.setLegOneTakerGetsFunded(legOneOffer, legOneTakerGets);
@@ -408,7 +438,8 @@ function setLegOneTakerGetsFunded(legOneOffer, takerGetsFunded) {
legOneOffer.taker_gets_funded = takerGetsFunded.to_text();
legOneOffer.taker_pays_funded = takerGetsFunded
.multiply(Utils.getOfferQuality(legOneOffer, this._currencyGets))
.multiply(Utils.getOfferQuality(legOneOffer, this._currencyGets,
this._currencyPays, this._issuerPaysObj))
.to_text();
if (legOneOffer.taker_gets_funded === legOneOffer.TakerGets.value) {
@@ -429,10 +460,11 @@ function(legOneOffer, takerGets) {
assertValidLegOneOffer(legOneOffer, 'Leg one offer is invalid');
assert(takerGets instanceof Amount, 'Taker gets funded is invalid');
const legOneQuality = Utils.getOfferQuality(legOneOffer, this._currencyGets);
const legOneQuality = Utils.getOfferQuality(legOneOffer, this._currencyGets,
this._currencyPays, this._issuerPaysObj);
legOneOffer.TakerGets = takerGets.to_text();
legOneOffer.TakerPays = takerGets.multiply(legOneQuality);
legOneOffer.TakerPays = takerGets.multiply(legOneQuality).to_json();
};
module.exports = AutobridgeCalculator;

View File

@@ -1,15 +1,15 @@
'use strict';
var extend = require('extend');
var UInt160 = require('./uint160').UInt160;
var utils = require('./utils');
var Float = require('./ieee754').Float;
const extend = require('extend');
const UInt160 = require('./uint160').UInt160;
const utils = require('./utils');
const Float = require('./ieee754').Float;
//
// Currency support
//
var Currency = extend(function() {
const Currency = extend(function() {
// Internal form: 0 = XRP. 3 letter-code.
// XXX Internal should be 0 or hex with three letter annotation when valid.
@@ -61,9 +61,9 @@ Currency.HEX_CURRENCY_BAD = '0000000000000000000000005852500000000000';
*
*/
/*eslint-disable max-len*/
/* eslint-disable max-len*/
Currency.prototype.human_RE = /^\s*([a-zA-Z0-9\<\>\(\)\{\}\[\]\|\?\!\@\#\$\%\^\&]{3})(\s*-\s*[- \w]+)?(\s*\(-?\d+\.?\d*%pa\))?\s*$/;
/*eslint-enable max-len*/
/* eslint-enable max-len*/
Currency.from_json = function(j, shouldInterpretXrpAsIou) {
return (new Currency()).parse_json(j, shouldInterpretXrpAsIou);
@@ -78,7 +78,7 @@ Currency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) {
this._value = NaN;
if (j instanceof Currency) {
this._value = j.copyTo({})._value;
this._value = j._value;
this._update();
return this;
}
@@ -111,10 +111,10 @@ Currency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) {
}
// match the given string to see if it's in an allowed format
var matches = j.match(this.human_RE);
const matches = j.match(this.human_RE);
if (matches) {
var currencyCode = matches[1];
let currencyCode = matches[1];
// for the currency 'XRP' case
// we drop everything else that could have been provided
@@ -131,14 +131,14 @@ Currency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) {
// the full currency is matched as it is part of the valid currency
// format, but not stored
// var full_currency = matches[2] || '';
var interest = matches[3] || '';
const interest = matches[3] || '';
// interest is defined as interest per year, per annum (pa)
var percentage = interest.match(/(-?\d+\.?\d+)/);
let percentage = interest.match(/(-?\d+\.?\d+)/);
currencyCode = currencyCode.toUpperCase();
var currencyData = utils.arraySet(20, 0);
const currencyData = utils.arraySet(20, 0);
if (percentage) {
/*
@@ -164,15 +164,15 @@ Currency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) {
// the interest or demurrage is expressed as a yearly (per annum)
// value
var secondsPerYear = 31536000; // 60 * 60 * 24 * 365
const secondsPerYear = 31536000; // 60 * 60 * 24 * 365
// Calculating the interest e-fold
// 0.5% demurrage is expressed 0.995, 0.005 less than 1
// 0.5% interest is expressed as 1.005, 0.005 more than 1
var interestEfold = secondsPerYear / Math.log(1 + percentage / 100);
var bytes = Float.toIEEE754Double(interestEfold);
const interestEfold = secondsPerYear / Math.log(1 + percentage / 100);
const bytes = Float.toIEEE754Double(interestEfold);
for (var i = 0; i <= bytes.length; i++) {
for (let i = 0; i <= bytes.length; i++) {
currencyData[8 + i] = bytes[i] & 0xff;
}
@@ -204,10 +204,10 @@ Currency.prototype.parse_human = function(j) {
*/
Currency.prototype._update = function() {
var bytes = this.to_bytes();
const bytes = this.to_bytes();
// is it 0 everywhere except 12, 13, 14?
var isZeroExceptInStandardPositions = true;
let isZeroExceptInStandardPositions = true;
if (!bytes) {
return;
@@ -219,7 +219,7 @@ Currency.prototype._update = function() {
this._interest_period = NaN;
this._iso_code = '';
for (var i = 0; i < 20; i++) {
for (let i = 0; i < 20; i++) {
isZeroExceptInStandardPositions = isZeroExceptInStandardPositions
&& (i === 12 || i === 13 || i === 14 || bytes[i] === 0);
}
@@ -249,6 +249,34 @@ Currency.prototype._update = function() {
}
};
/**
* Returns copy.
*
* This copies code from UInt.copyTo so we do not call _update,
* bvecause to_bytes is very expensive.
*/
Currency.prototype.copyTo = function(d) {
d._value = this._value;
if (this._version_byte !== undefined) {
d._version_byte = this._version_byte;
}
if (!d.is_valid()) {
return d;
}
d._native = this._native;
d._type = this._type;
d._interest_start = this._interest_start;
d._interest_period = this._interest_period;
d._iso_code = this._iso_code;
return d;
};
// XXX Probably not needed anymore?
/*
Currency.prototype.parse_bytes = function(byte_array) {
@@ -300,18 +328,20 @@ Currency.prototype.has_interest = function() {
/**
*
* @param {number} referenceDate number of seconds since the Ripple Epoch
* @param {number} referenceDate_ number of seconds since the Ripple Epoch
* (0:00 on January 1, 2000 UTC) used to calculate the
* interest over provided interval pass in one years
* worth of seconds to ge the yearly interest
* @returns {number} interest for provided interval, can be negative for
* demurred currencies
*/
Currency.prototype.get_interest_at = function(referenceDate) {
Currency.prototype.get_interest_at = function(referenceDate_) {
if (!this.has_interest()) {
return 0;
}
let referenceDate = referenceDate_;
// use one year as a default period
if (!referenceDate) {
referenceDate = this._interest_start + 3600 * 24 * 365;
@@ -326,13 +356,14 @@ Currency.prototype.get_interest_at = function(referenceDate) {
/ this._interest_period);
};
Currency.prototype.get_interest_percentage_at
= function(referenceDate, decimals) {
var interest = this.get_interest_at(referenceDate, decimals);
Currency.prototype.get_interest_percentage_at = function(referenceDate,
decimals
) {
let interest = this.get_interest_at(referenceDate, decimals);
// convert to percentage
interest = (interest * 100) - 100;
var decimalMultiplier = decimals ? Math.pow(10, decimals) : 100;
const decimalMultiplier = decimals ? Math.pow(10, decimals) : 100;
// round to two decimals behind the dot
return Math.round(interest * decimalMultiplier) / decimalMultiplier;
@@ -347,18 +378,14 @@ Currency.prototype.get_interest_percentage_at
// return UInt.prototype.is_valid() && ...;
// };
Currency.prototype.to_json = function(opts) {
Currency.prototype.to_json = function(opts = {}) {
if (!this.is_valid()) {
// XXX This is backwards compatible behavior, but probably not very good.
return 'XRP';
}
if (!opts) {
opts = {};
}
var currency;
var fullName = opts && opts.full_name ? ' - ' + opts.full_name : '';
let currency;
const fullName = opts && opts.full_name ? ' - ' + opts.full_name : '';
opts.show_interest = opts.show_interest !== undefined
? opts.show_interest
: this.has_interest();
@@ -366,8 +393,8 @@ Currency.prototype.to_json = function(opts) {
if (!opts.force_hex && /^[A-Z0-9]{3}$/.test(this._iso_code)) {
currency = this._iso_code + fullName;
if (opts.show_interest) {
var decimals = !isNaN(opts.decimals) ? opts.decimals : undefined;
var interestPercentage = this.has_interest()
const decimals = !isNaN(opts.decimals) ? opts.decimals : undefined;
const interestPercentage = this.has_interest()
? this.get_interest_percentage_at(
this._interest_start + 3600 * 24 * 365, decimals
)

View File

@@ -24,6 +24,17 @@ const OrderBookUtils = require('./orderbookutils');
const log = require('./log').internal.sub('orderbook');
const IOUValue = require('./iouvalue').IOUValue;
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);
}
/**
* @constructor OrderBook
* @param {Remote} remote
@@ -37,7 +48,8 @@ const IOUValue = require('./iouvalue').IOUValue;
*/
function OrderBook(remote,
currencyGets, issuerGets, currencyPays, issuerPays, key) {
currencyGets, issuerGets, currencyPays, issuerPays, key
) {
EventEmitter.call(this);
const self = this;
@@ -1343,18 +1355,18 @@ OrderBook.prototype.computeAutobridgedOffers = function() {
};
OrderBook.prototype.computeAutobridgedOffersWrapper = function() {
var startTime = Date.now();
const startTime = Date.now();
this.computeAutobridgedOffers();
this.mergeDirectAndAutobridgedBooks();
var lasted = (Date.now() - startTime);
const lasted = (Date.now() - startTime);
const newMult =
((lasted * 2 / OrderBook.AUTOBRIDGE_CALCULATE_THROTTLE_TIME) << 0) + 1;
Math.floor(lasted * 2 / OrderBook.AUTOBRIDGE_CALCULATE_THROTTLE_TIME) + 1;
if (newMult !== this._autobridgeThrottleTimeMultiplier) {
this._autobridgeThrottleTimeMultiplier = newMult;
this.createDebouncedOffersWrapper();
}
}
};
OrderBook.prototype.createDebouncedOffersWrapper = function() {
const m = this._autobridgeThrottleTimeMultiplier;
@@ -1366,20 +1378,9 @@ OrderBook.prototype.createDebouncedOffersWrapper = function() {
{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
*

View File

@@ -5,6 +5,9 @@ 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;
const IOUValue = require('./iouvalue').IOUValue;
const OrderBookUtils = {};
function assertValidNumber(number, message) {
@@ -19,10 +22,17 @@ function assertValidNumber(number, message) {
* @return JSON amount object
*/
function createAmount(value, currency, counterparty) {
const newJSON =
{'value': value, 'currency': currency, 'issuer': counterparty};
return Amount.from_json(newJSON);
function createAmount(value, currency_, counterparty_) {
const currency = currency_ instanceof Currency ?
currency_ :
Currency.from_json(currency_);
const counterparty = counterparty_ instanceof UInt160 ?
counterparty_ :
UInt160.from_json(counterparty_);
return Amount.createFast(new IOUValue(value), currency, counterparty, false);
}
/**
@@ -52,11 +62,11 @@ function getIssuerFromOffer(offer) {
* @return {Amount}
*/
OrderBookUtils.getOfferTakerGetsFunded = function(offer) {
OrderBookUtils.getOfferTakerGetsFunded = function(offer, currency_, issuer_) {
assertValidNumber(offer.taker_gets_funded, 'Taker gets funded is invalid');
const currency = getCurrencyFromOffer(offer);
const issuer = getIssuerFromOffer(offer);
const currency = currency_ || getCurrencyFromOffer(offer);
const issuer = issuer_ || getIssuerFromOffer(offer);
return createAmount(offer.taker_gets_funded, currency, issuer);
};
@@ -68,11 +78,11 @@ OrderBookUtils.getOfferTakerGetsFunded = function(offer) {
* @return {Amount}
*/
OrderBookUtils.getOfferTakerPaysFunded = function(offer) {
OrderBookUtils.getOfferTakerPaysFunded = function(offer, currency_, issuer_) {
assertValidNumber(offer.taker_pays_funded, 'Taker gets funded is invalid');
const currency = getCurrencyFromOffer(offer);
const issuer = getIssuerFromOffer(offer);
const currency = currency_ || getCurrencyFromOffer(offer);
const issuer = issuer_ || getIssuerFromOffer(offer);
return createAmount(offer.taker_pays_funded, currency, issuer);
};
@@ -85,11 +95,11 @@ OrderBookUtils.getOfferTakerPaysFunded = function(offer) {
* @return {Amount}
*/
OrderBookUtils.getOfferTakerGets = function(offer) {
OrderBookUtils.getOfferTakerGets = function(offer, currency_, issuer_) {
assert(typeof offer, 'object', 'Offer is invalid');
const currency = offer.TakerPays.currency;
const issuer = offer.TakerPays.issuer;
const currency = currency_ || offer.TakerPays.currency;
const issuer = issuer_ || offer.TakerPays.issuer;
return createAmount(offer.TakerGets, currency, issuer);
};
@@ -101,7 +111,9 @@ OrderBookUtils.getOfferTakerGets = function(offer) {
* @param {Currency} currencyGets
*/
OrderBookUtils.getOfferQuality = function(offer, currencyGets) {
OrderBookUtils.getOfferQuality = function(offer, currencyGets, currency_,
issuer_
) {
let amount;
if (currencyGets.has_interest()) {
@@ -113,8 +125,8 @@ OrderBookUtils.getOfferQuality = function(offer, currencyGets) {
});
} else {
const currency = getCurrencyFromOffer(offer);
const issuer = getIssuerFromOffer(offer);
const currency = currency_ || getCurrencyFromOffer(offer);
const issuer = issuer_ || getIssuerFromOffer(offer);
amount = createAmount(offer.quality, currency, issuer);
}
@@ -158,13 +170,17 @@ OrderBookUtils.convertOfferQualityToHexFromText = function(quality) {
};
OrderBookUtils.CURRENCY_ONE = Currency.from_json(1);
OrderBookUtils.ISSUER_ONE = UInt160.from_json(1);
/**
*
*/
OrderBookUtils.normalizeAmount = function(value) {
return Amount.from_number(value);
return Amount.createFast(new IOUValue(value), OrderBookUtils.CURRENCY_ONE,
OrderBookUtils.ISSUER_ONE, false);
};
module.exports = OrderBookUtils;

View File

@@ -1,11 +1,10 @@
/*eslint-disable max-len, no-param-reassign*/
/* eslint-disable max-len, no-param-reassign */
'use strict';
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;
const IOUValue = require('ripple-lib')._test.IOUValue;
@@ -830,7 +829,7 @@ module.exports.transactionWithCreatedOffer = function(options) {
const BookDirectory = so.to_hex();
var meta = new Meta({
const meta = new Meta({
AffectedNodes: [
{
CreatedNode: {

View File

@@ -6,7 +6,6 @@ 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');
const IOUValue = require('ripple-lib')._test.IOUValue;

View File

@@ -1706,7 +1706,7 @@ describe('OrderBook', function() {
setTimeout(function() {
assert.strictEqual(numModelEvents, 1);
done();
}, 300)
}, 300);
});
it('Notify - deleted node - trade', function(done) {