From 512817a2db3a03efacbff8da85027b24fb63a0b5 Mon Sep 17 00:00:00 2001 From: Chris Clark Date: Thu, 15 Oct 2015 11:49:48 -0700 Subject: [PATCH] Remove demurrage --- src/core/amount.js | 78 +------- src/core/autobridgecalculator.js | 8 +- src/core/currency.js | 299 +++---------------------------- src/core/ieee754.js | 107 ----------- src/core/orderbook.js | 41 +---- src/core/orderbookutils.js | 25 +-- test/amount-test.js | 89 +-------- test/currency-test.js | 174 ------------------ test/remote-test.js | 8 +- 9 files changed, 60 insertions(+), 769 deletions(-) delete mode 100644 src/core/ieee754.js diff --git a/src/core/amount.js b/src/core/amount.js index d207df51..25bb5bc6 100644 --- a/src/core/amount.js +++ b/src/core/amount.js @@ -190,12 +190,9 @@ Amount.prototype.divide = function(divisor) { * @return {Amount} The resulting ratio. Unit will be the same as numerator. */ -Amount.prototype.ratio_human = function(denom, opts) { - const options = extend({ }, opts); - +Amount.prototype.ratio_human = function(denom) { const numerator = this.clone(); - - let denominator = Amount.from_json(denom); + const denominator = Amount.from_json(denom); // If either operand is NaN, the result is NaN. if (!numerator.is_valid() || !denominator.is_valid()) { @@ -206,14 +203,6 @@ Amount.prototype.ratio_human = function(denom, opts) { return new Amount(NaN); } - // Apply interest/demurrage - // - // We only need to apply it to the second factor, because the currency unit of - // the first factor will carry over into the result. - if (options.reference_date) { - denominator = denominator.applyInterest(options.reference_date); - } - // Special case: The denominator is a native (XRP) amount. // // In that case, it's going to be expressed as base units (1 XRP = @@ -252,23 +241,14 @@ Amount.prototype.ratio_human = function(denom, opts) { * for Ripple epoch. * @return {Amount} The product. Unit will be the same as the first factor. */ -Amount.prototype.product_human = function(factor, options = {}) { - - let fac = Amount.from_json(factor); +Amount.prototype.product_human = function(factor) { + const fac = Amount.from_json(factor); // If either operand is NaN, the result is NaN. if (!this.is_valid() || !fac.is_valid()) { return new Amount(); } - // Apply interest/demurrage - // - // We only need to apply it to the second factor, because the currency unit of - // the first factor will carry over into the result. - if (options.reference_date) { - fac = fac.applyInterest(options.reference_date); - } - const product = this.multiply(fac); // Special case: The second factor is a native (XRP) amount expressed as base @@ -464,9 +444,7 @@ Amount.prototype.negate = function() { * $ */ -Amount.prototype.parse_human = function(j, options) { - const opts = options || {}; - +Amount.prototype.parse_human = function(j) { const hex_RE = /^[a-fA-F0-9]{40}$/; const currency_RE = /^([a-zA-Z]{3}|[0-9]{3})$/; @@ -516,14 +494,6 @@ Amount.prototype.parse_human = function(j, options) { (this._is_native ? new XRPValue(value) : new IOUValue(value)); this._set_value(newValue); - - // Apply interest/demurrage - if (opts.reference_date && this._currency.has_interest()) { - const interest = this._currency.get_interest_at(opts.reference_date); - this._set_value( - this._value.divide(new IOUValue(interest.toString()))); - } - return this; }; @@ -627,12 +597,6 @@ function(quality, counterCurrency, counterIssuer, opts) { this._set_value(nativeAdjusted); } - if (options.reference_date && baseCurrency.is_valid() - && baseCurrency.has_interest()) { - const interest = baseCurrency.get_interest_at(options.reference_date); - this._set_value( - this._value.divide(new IOUValue(interest.toString()))); - } return this; }; @@ -782,27 +746,6 @@ Amount.prototype.to_text = function() { + (s_post ? '.' + post.substring(0, 1 + post.length - s_post[0].length) : ''); }; -/** - * Calculate present value based on currency and a reference date. - * - * This only affects demurraging and interest-bearing currencies. - * - * User should not store amount objects after the interest is applied. This is - * intended by display functions such as toHuman(). - * - * @param {Date|Number} referenceDate Date based on which demurrage/interest - * should be applied. Can be given as JavaScript Date or int for Ripple epoch. - * @return {Amount} The amount with interest applied. - */ -Amount.prototype.applyInterest = function(referenceDate) { - if (!this._currency.has_interest()) { - return this; - } - const interest = this._currency.get_interest_at(referenceDate); - return this._copy( - this._value.multiply(new IOUValue(interest.toString()))); -}; - /** * Format only value in a human-readable format. * @@ -836,13 +779,9 @@ Amount.prototype.to_human = function(options) { /* eslint-disable consistent-this */ // Apply demurrage/interest - let ref = this; + const ref = this; /* eslint-enable consistent-this */ - if (opts.reference_date) { - ref = this.applyInterest(opts.reference_date); - } - const isNegative = ref._value.isNegative(); const valueString = ref._value.abs().toFixed(); const parts = valueString.split('.'); @@ -930,7 +869,7 @@ Amount.prototype.to_human = function(options) { Amount.prototype.to_human_full = function(options) { const opts = options || {}; const value = this.to_human(opts); - const currency = this._currency.to_human(); + const currency = this._currency.to_json(); const issuer = this._issuer; const base = value + '/' + currency; return this.is_native() ? base : (base + '/' + issuer); @@ -943,8 +882,7 @@ Amount.prototype.to_json = function() { const amount_json = { value: this.to_text(), - currency: this._currency.has_interest() ? - this._currency.to_hex() : this._currency.to_json() + currency: this._currency.to_json() }; if (isValidAddress(this._issuer)) { diff --git a/src/core/autobridgecalculator.js b/src/core/autobridgecalculator.js index b708e7ca..375ea9ee 100644 --- a/src/core/autobridgecalculator.js +++ b/src/core/autobridgecalculator.js @@ -157,7 +157,7 @@ function(legOneOffer, legTwoOffer) { this._currencyPays, this._issuerPays); const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer, this._currencyGets, this._issuerGets); - const legOneQuality = Utils.getOfferQuality(legOneOffer, this._currencyGets, + const legOneQuality = Utils.getOfferQuality(legOneOffer, this._currencyPays, this._issuerPays); const autobridgedTakerGets = Utils.getOfferTakerGetsFunded(legTwoOffer, @@ -202,7 +202,7 @@ function(legOneOffer, legTwoOffer) { this._currencyPays, this._issuerPays); const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer, this._currencyGets, this._issuerGets); - const legTwoQuality = Utils.getOfferQuality(legTwoOffer, this._currencyGets, + const legTwoQuality = Utils.getOfferQuality(legTwoOffer, this._currencyGets, this._issuerGets); const autobridgedTakerGets = legOneTakerGetsFunded.divide(legTwoQuality); @@ -463,7 +463,7 @@ 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._currencyPays, this._issuerPays)) .to_text(); @@ -485,7 +485,7 @@ 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._currencyPays, this._issuerPays); legOneOffer.TakerGets = takerGets.to_text(); diff --git a/src/core/currency.js b/src/core/currency.js index 8e97445f..ab0d976d 100644 --- a/src/core/currency.js +++ b/src/core/currency.js @@ -1,13 +1,9 @@ 'use strict'; +const _ = require('lodash'); const assert = require('assert'); const utils = require('./utils'); -const Float = require('./ieee754').Float; const BN = require('bn.js'); -// -// Currency support -// - function Currency() { // Internal form: 0 = XRP. 3 letter-code. // XXX Internal should be 0 or hex with three letter annotation when valid. @@ -26,44 +22,6 @@ Currency.HEX_CURRENCY_BAD = '0000000000000000000000005852500000000000'; Currency.HEX_ZERO = '0000000000000000000000000000000000000000'; Currency.HEX_ONE = '0000000000000000000000000000000000000001'; -/** - * Tries to correctly interpret a Currency as entered by a user. - * - * Examples: - * - * USD => currency - * USD - Dollar => currency with optional full currency - * name - * XAU (-0.5%pa) => XAU with 0.5% effective demurrage rate - * per year - * XAU - Gold (-0.5%pa) => Optionally allowed full currency name - * USD (1%pa) => US dollars with 1% effective interest - * per year - * INR - Indian Rupees => Optional full currency name with spaces - * TYX - 30-Year Treasuries => Optional full currency with numbers - * and a dash - * TYX - 30-Year Treasuries (1.5%pa) => Optional full currency with numbers, - * dash and interest rate - * - * The regular expression below matches above cases, broken down for better - * understanding: - * - * ^\s* // start with any amount of whitespace - * ([a-zA-Z]{3}|[0-9]{3}) // either 3 letter alphabetic currency-code or 3 - * digit numeric currency-code. See ISO 4217 - * (\s*-\s*[- \w]+) // optional full currency name following the dash - * after currency code, full currency code can - * contain letters, numbers and dashes - * (\s*\(-?\d+\.?\d*%pa\))? // optional demurrage rate, has optional - and - * . notation (-0.5%pa) - * \s*$ // end with any amount of whitespace - * - */ - -/* 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*/ - Currency.from_json = function(j, shouldInterpretXrpAsIou) { return (new Currency()).parse_json(j, shouldInterpretXrpAsIou); }; @@ -92,10 +50,6 @@ Currency.prototype.to_hex = function() { return utils.arrayToHex(this.to_bytes()); }; -Currency.from_human = function(j, opts) { - return (new Currency().parse_human(j, opts)); -}; - Currency.json_rewrite = function(j, opts) { return this.from_json(j).to_json(opts); }; @@ -133,7 +87,7 @@ Currency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) { } break; case 'string': - if (!j || j === '0') { + if (!j || j === '0' || j === 'XRP') { // Empty string or XRP this.parse_hex(shouldInterpretXrpAsIou ? Currency.HEX_CURRENCY_BAD @@ -153,93 +107,22 @@ Currency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) { break; } - // match the given string to see if it's in an allowed format - const matches = j.match(this.human_RE); - - if (matches) { - let currencyCode = matches[1]; - - // for the currency 'XRP' case - // we drop everything else that could have been provided - // e.g. 'XRP - Ripple' - if (!currencyCode || /^(0|XRP)$/.test(currencyCode)) { - this.parse_hex(shouldInterpretXrpAsIou - ? Currency.HEX_CURRENCY_BAD - : Currency.HEX_ZERO); - - // early break, we can't have interest on XRP - break; - } - - // the full currency is matched as it is part of the valid currency - // format, but not stored - // var full_currency = matches[2] || ''; - const interest = matches[3] || ''; - - // interest is defined as interest per year, per annum (pa) - let percentage = interest.match(/(-?\d+\.?\d+)/); - - currencyCode = currencyCode.toUpperCase(); - - const currencyData = utils.arraySet(20, 0); - - if (percentage) { - /* - * 20 byte layout of a interest bearing currency - * - * 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ - * CURCODE- DATE------- RATE------------------- RESERVED--- - */ - - // byte 1 for type, use '1' to denote demurrage currency - currencyData[0] = 1; - - // byte 2-4 for currency code - currencyData[1] = currencyCode.charCodeAt(0) & 0xff; - currencyData[2] = currencyCode.charCodeAt(1) & 0xff; - currencyData[3] = currencyCode.charCodeAt(2) & 0xff; - - // byte 5-8 are for reference date, but should always be 0 so we - // won't fill it - - // byte 9-16 are for the interest - percentage = parseFloat(percentage[0]); - - // the interest or demurrage is expressed as a yearly (per annum) - // value - 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 - const interestEfold = secondsPerYear / Math.log(1 + percentage / 100); - const bytes = Float.toIEEE754Double(interestEfold); - - for (let i = 0; i <= bytes.length; i++) { - currencyData[8 + i] = bytes[i] & 0xff; - } - - // the last 4 bytes are reserved for future use, so we won't fill - // those - - } else { - currencyData[12] = currencyCode.charCodeAt(0) & 0xff; - currencyData[13] = currencyCode.charCodeAt(1) & 0xff; - currencyData[14] = currencyCode.charCodeAt(2) & 0xff; - } - - this.parse_bytes(currencyData); - } + const currencyCode = j.toUpperCase(); + const currencyData = utils.arraySet(20, 0); + currencyData[12] = currencyCode.charCodeAt(0) & 0xff; + currencyData[13] = currencyCode.charCodeAt(1) & 0xff; + currencyData[14] = currencyCode.charCodeAt(2) & 0xff; + this.parse_bytes(currencyData); + break; + case 'undefined': + this.parse_hex(Currency.HEX_ZERO); break; } + this._update(); return this; }; -Currency.prototype.parse_human = function(j) { - return this.parse_json(j); -}; - Currency.prototype.is_valid = function() { return this._value instanceof BN; }; @@ -274,6 +157,12 @@ Currency.prototype.to_bytes = function() { return this._value.toArray('be', this.constructor.width); }; +Currency.prototype._isISOCode = function() { + return _.every(this.to_bytes(), (octet, i) => + octet === 0 || (i >= 12 && i <= 14)) + && /^[A-Z0-9]{3}$/.test(this._iso_code); +}; + /** * Recalculate internal representation. * @@ -287,13 +176,11 @@ Currency.prototype._update = function() { let isZeroExceptInStandardPositions = true; if (!bytes) { - return; + return; // before being initialized } this._native = false; this._type = -1; - this._interest_start = NaN; - this._interest_period = NaN; this._iso_code = ''; for (let i = 0; i < 20; i++) { @@ -318,11 +205,6 @@ Currency.prototype._update = function() { + String.fromCharCode(bytes[3]); this._type = 1; - this._interest_start = (bytes[4] << 24) + - (bytes[5] << 16) + - (bytes[6] << 8) + - (bytes[7]); - this._interest_period = Float.fromIEEE754Double(bytes.slice(8, 16)); } }; @@ -346,8 +228,6 @@ Currency.prototype.copyTo = function(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; @@ -364,149 +244,26 @@ Currency.prototype.parse_bytes = function(j) { return this; }; -// XXX Probably not needed anymore? -/* -Currency.prototype.parse_bytes = function(byte_array) { - if (Array.isArray(byte_array) && byte_array.length === 20) { - var result; - // is it 0 everywhere except 12, 13, 14? - var isZeroExceptInStandardPositions = true; - - for (var i=0; i<20; i++) { - isZeroExceptInStandardPositions = isZeroExceptInStandardPositions - && (i===12 || i===13 || i===14 || byte_array[0]===0) - } - - if (isZeroExceptInStandardPositions) { - var currencyCode = String.fromCharCode(byte_array[12]) - + String.fromCharCode(byte_array[13]) - + String.fromCharCode(byte_array[14]); - if (/^[A-Z0-9]{3}$/.test(currencyCode) && currencyCode !== 'XRP' ) { - this._value = currencyCode; - } else if (currencyCode === '\0\0\0') { - this._value = 0; - } else { - this._value = NaN; - } - } else { - // XXX Should support non-standard currency codes - this._value = NaN; - } - } else { - this._value = NaN; - } - return this; -}; -*/ - Currency.prototype.is_native = function() { return this._native; }; -/** - * @return {Boolean} whether this currency is an interest-bearing currency - */ - -Currency.prototype.has_interest = function() { - return this._type === 1 - && !isNaN(this._interest_start) - && !isNaN(this._interest_period); -}; - -/** - * - * @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_) { - 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; - } - - if (referenceDate instanceof Date) { - referenceDate = utils.fromTimestamp(referenceDate.getTime()); - } - - // calculate interest by e-fold number - return Math.exp((referenceDate - this._interest_start) - / this._interest_period); -}; - -Currency.prototype.get_interest_percentage_at = function(referenceDate, - decimals -) { - let interest = this.get_interest_at(referenceDate, decimals); - - // convert to percentage - interest = (interest * 100) - 100; - const decimalMultiplier = decimals ? Math.pow(10, decimals) : 100; - - // round to two decimals behind the dot - return Math.round(interest * decimalMultiplier) / decimalMultiplier; -}; - -// XXX Currently we inherit UInt.prototype.is_valid, which is mostly fine. -// -// We could be doing further checks into the internal format of the -// currency data, since there are some values that are invalid. -// -// Currency.prototype.is_valid = function() { -// return UInt.prototype.is_valid() && ...; -// }; - Currency.prototype.to_json = function(opts = {}) { if (!this.is_valid()) { - // XXX This is backwards compatible behavior, but probably not very good. - return 'XRP'; + throw new Error('Invalid currency object'); } - let currency; - const fullName = opts && opts.full_name ? ' - ' + opts.full_name : ''; - opts.show_interest = opts.show_interest !== undefined - ? opts.show_interest - : this.has_interest(); - - if (!opts.force_hex && /^[A-Z0-9]{3}$/.test(this._iso_code)) { - currency = this._iso_code + fullName; - if (opts.show_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 - ) - : 0; - currency += ' (' + interestPercentage + '%pa)'; - } - - } else { - // Fallback to returning the raw currency hex - currency = this.to_hex(); - - // XXX This is to maintain backwards compatibility, but it is very, very - // odd behavior, so we should deprecate it and get rid of it as soon as - // possible. - if (currency === Currency.HEX_ONE) { - currency = 1; - } + if (this._isISOCode() && !opts.force_hex) { + const fullName = opts && opts.full_name ? ' - ' + opts.full_name : ''; + return this._iso_code + fullName; } - return currency; -}; + const hex = this.to_hex(); -Currency.prototype.to_human = function(opts) { - // to_human() will always print the human-readable currency code if available. - return this.to_json(opts); + // XXX This is to maintain backwards compatibility, but it is very, very + // odd behavior, so we should deprecate it and get rid of it as soon as + // possible. + return hex === Currency.HEX_ONE ? 1 : hex; }; Currency.prototype.get_iso = function() { diff --git a/src/core/ieee754.js b/src/core/ieee754.js deleted file mode 100644 index d5d61878..00000000 --- a/src/core/ieee754.js +++ /dev/null @@ -1,107 +0,0 @@ -// Convert a JavaScript number to IEEE-754 Double Precision -// value represented as an array of 8 bytes (octets) -// -// Based on: -// http://cautionsingularityahead.blogspot.com/2010/04/javascript-and-ieee754-redux.html -// -// Found and modified from: -// https://gist.github.com/bartaz/1119041 - -var Float = exports.Float = {}; - -Float.toIEEE754 = function(v, ebits, fbits) { - - var bias = (1 << (ebits - 1)) - 1; - - // Compute sign, exponent, fraction - var s, e, f; - if (isNaN(v)) { - e = (1 << bias) - 1; f = 1; s = 0; - } - else if (v === Infinity || v === -Infinity) { - e = (1 << bias) - 1; f = 0; s = (v < 0) ? 1 : 0; - } - else if (v === 0) { - e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0; - } - else { - s = v < 0; - v = Math.abs(v); - - if (v >= Math.pow(2, 1 - bias)) { - var ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias); - e = ln + bias; - f = v * Math.pow(2, fbits - ln) - Math.pow(2, fbits); - } - else { - e = 0; - f = v / Math.pow(2, 1 - bias - fbits); - } - } - - // Pack sign, exponent, fraction - var i, bits = []; - for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = Math.floor(f / 2); } - for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = Math.floor(e / 2); } - bits.push(s ? 1 : 0); - bits.reverse(); - var str = bits.join(''); - - // Bits to bytes - var bytes = []; - while (str.length) { - bytes.push(parseInt(str.substring(0, 8), 2)); - str = str.substring(8); - } - return bytes; -} - -Float.fromIEEE754 = function(bytes, ebits, fbits) { - - // Bytes to bits - var bits = []; - for (var i = bytes.length; i; i -= 1) { - var byte = bytes[i - 1]; - for (var j = 8; j; j -= 1) { - bits.push(byte % 2 ? 1 : 0); byte = byte >> 1; - } - } - bits.reverse(); - var str = bits.join(''); - - // Unpack sign, exponent, fraction - var bias = (1 << (ebits - 1)) - 1; - var s = parseInt(str.substring(0, 1), 2) ? -1 : 1; - var e = parseInt(str.substring(1, 1 + ebits), 2); - var f = parseInt(str.substring(1 + ebits), 2); - - // Produce number - if (e === (1 << ebits) - 1) { - return f !== 0 ? NaN : s * Infinity; - } - else if (e > 0) { - return s * Math.pow(2, e - bias) * (1 + f / Math.pow(2, fbits)); - } - else if (f !== 0) { - return s * Math.pow(2, -(bias-1)) * (f / Math.pow(2, fbits)); - } - else { - return s * 0; - } -} - -Float.fromIEEE754Double = function(b) { return Float.fromIEEE754(b, 11, 52); } -Float.toIEEE754Double = function(v) { return Float.toIEEE754(v, 11, 52); } -Float.fromIEEE754Single = function(b) { return Float.fromIEEE754(b, 8, 23); } -Float.toIEEE754Single = function(v) { return Float.toIEEE754(v, 8, 23); } - - -// Convert array of octets to string binary representation -// by bartaz - -Float.toIEEE754DoubleString = function(v) { - return exports.toIEEE754Double(v) - .map(function(n){ for(n = n.toString(2);n.length < 8;n="0"+n); return n }) - .join('') - .replace(/(.)(.{11})(.{52})/, "$1 $2 $3") -} \ No newline at end of file diff --git a/src/core/orderbook.js b/src/core/orderbook.js index b9c554b4..a9bca763 100644 --- a/src/core/orderbook.js +++ b/src/core/orderbook.js @@ -25,13 +25,6 @@ const log = require('./log').internal.sub('orderbook'); const {IOUValue} = require('ripple-lib-value'); const RippleError = require('./rippleerror').RippleError; -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); } @@ -94,8 +87,7 @@ function OrderBook(remote, this._calculatorRunning = false; - this.sortOffers = this._currencyGets.has_interest() ? - _sortOffers.bind(this) : _sortOffersQuick; + this.sortOffers = _sortOffersQuick; this._isAutobridgeable = !this._currencyGets.is_native() && !this._currencyPays.is_native(); @@ -749,7 +741,7 @@ OrderBook.prototype.setOfferFundedAmount = function(offer) { } else if (previousOfferSum.compareTo(fundedAmount) < 0) { offer.taker_gets_funded = fundedAmount.subtract(previousOfferSum).to_text(); - const quality = OrderBookUtils.getOfferQuality(offer, this._currencyGets); + const quality = OrderBookUtils.getOfferQuality(offer); const takerPaysFunded = quality.multiply( OrderBookUtils.getOfferTakerGetsFunded(offer) ); @@ -1014,13 +1006,13 @@ OrderBook.prototype.notify = function(transaction) { let takerGetsTotal = Amount.from_json( '0' + ((Currency.from_json(this._currencyGets).is_native()) ? '' - : ('/' + this._currencyGets.to_human() + '/' + this._issuerGets)) + : ('/' + this._currencyGets.to_json() + '/' + this._issuerGets)) ); let takerPaysTotal = Amount.from_json( '0' + ((Currency.from_json(this._currencyPays).is_native()) ? '' - : ('/' + this._currencyPays.to_human() + '/' + this._issuerPays)) + : ('/' + this._currencyPays.to_json() + '/' + this._issuerPays)) ); const isOfferCancel = @@ -1117,27 +1109,10 @@ OrderBook.prototype.insertOffer = function(node) { const originalLength = this._offers.length; - 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); - - break; - } + for (let i = 0; i < originalLength; i++) { + if (offer.qualityHex <= this._offers[i].qualityHex) { + this._offers.splice(i, 0, offer); + break; } } diff --git a/src/core/orderbookutils.js b/src/core/orderbookutils.js index 164188af..22b96a96 100644 --- a/src/core/orderbookutils.js +++ b/src/core/orderbookutils.js @@ -108,27 +108,10 @@ OrderBookUtils.getOfferTakerGets = function(offer, currency_, issuer_) { * @param {Currency} currencyGets */ -OrderBookUtils.getOfferQuality = function(offer, currencyGets, currency_, - issuer_ -) { - let amount; - - if (currencyGets.has_interest()) { - // XXX Should use Amount#from_quality - amount = Amount.from_json( - offer.TakerPays - ).ratio_human(offer.TakerGets, { - reference_date: new Date() - }); - } else { - - const currency = currency_ || getCurrencyFromOffer(offer); - const issuer = issuer_ || getIssuerFromOffer(offer); - - amount = createAmount(offer.quality, currency, issuer); - } - - return amount; +OrderBookUtils.getOfferQuality = function(offer, currency_, issuer_) { + const currency = currency_ || getCurrencyFromOffer(offer); + const issuer = issuer_ || getIssuerFromOffer(offer); + return createAmount(offer.quality, currency, issuer); }; /** diff --git a/test/amount-test.js b/test/amount-test.js index 265988c0..6815d0f6 100644 --- a/test/amount-test.js +++ b/test/amount-test.js @@ -168,10 +168,10 @@ describe('Amount', function() { assert.strictEqual(Amount.from_human('12345.6789 XAU').to_human_full(), '12,345.6789/XAU/NaN'); }); it('12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000', function() { - assert.strictEqual(Amount.from_human('12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000').to_text_full(), '12345.6789/XAU (-0.5%pa)/NaN'); + assert.strictEqual(Amount.from_human('12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000').to_text_full(), '12345.6789/015841551A748AD2C1F76FF6ECB0CCCD00000000/NaN'); }); it('12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000 human', function() { - assert.strictEqual(Amount.from_human('12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000').to_human_full(), '12,345.6789/XAU (-0.5%pa)/NaN'); + assert.strictEqual(Amount.from_human('12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000').to_human_full(), '12,345.6789/015841551A748AD2C1F76FF6ECB0CCCD00000000/NaN'); }); it('12345.6789 0000000000000000000000005553440000000000', function() { assert.strictEqual(Amount.from_human('12345.6789 0000000000000000000000005553440000000000').to_text_full(), '12345.6789/USD/NaN'); @@ -320,16 +320,10 @@ describe('Amount', function() { assert(isNaN(Amount.from_json('x').to_text())); }); it('parse dem', function() { - assert.strictEqual(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_text_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); + assert.strictEqual(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_text_full(), '10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); }); it('parse dem human', function() { - assert.strictEqual(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - }); - it('parse dem', function() { - assert.strictEqual(Amount.from_json('10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_text_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - }); - it('parse dem human', function() { - assert.strictEqual(Amount.from_json('10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); + assert.strictEqual(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full(), '10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); }); it('Parse native 0', function() { assert.strictEqual('0/XRP', Amount.from_json('0').to_text_full()); @@ -948,9 +942,6 @@ describe('Amount', function() { it('Multiply XRP with XRP', function() { assert.strictEqual(Amount.from_json('10000000').product_human(Amount.from_json('10')).to_text_full(), '0.0001/XRP'); }); - it('Multiply USD with XAU (dem)', function() { - assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_text_full(), '19900.00316303883/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - }); it('Multiply 0 XRP with 0 XRP human', function() { assert.strictEqual('0/XRP', Amount.from_json('0').product_human(Amount.from_json('0')).to_human_full()); }); @@ -1020,9 +1011,6 @@ describe('Amount', function() { it('Multiply XRP with XRP human', function() { assert.strictEqual(Amount.from_json('10000000').product_human(Amount.from_json('10')).to_human_full(), '0.0001/XRP'); }); - it('Multiply USD with XAU (dem) human', function() { - assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_human_full(), '19,900.00316303883/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - }); }); describe('ratio_human', function() { @@ -1037,12 +1025,6 @@ describe('Amount', function() { assert.deepEqual(c.to_json(), {value: '0.005441114728882572', currency: 'USD', issuer: 'rLFPPebckMYZf3urdomLsaqRGmQ6zHVrrK'}); }); - it('Divide USD by XAU (dem)', function() { - assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').ratio_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_text_full(), '201.0049931765529/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - }); - it('Divide USD by XAU (dem) human', function() { - assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').ratio_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_human_full(), '201.0049931765529/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - }); }); describe('_invert', function() { @@ -1090,18 +1072,6 @@ describe('Amount', function() { it('BTC/USD inverse', function() { assert.strictEqual(Amount.from_quality('20294C923E80A51B487EB9547B3835FD483748B170D2D0A455071AFD498D0000', 'USD', 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', {inverse: true, base_currency: 'BTC'}).to_text_full(), '0.5/USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'); }); - it('XAU(dem)/XRP', function() { - assert.strictEqual(Amount.from_quality('587322CCBDE0ABD01704769A73A077C32FB39057D813D4165F1FF973CAF997EF', 'XRP', NaN, {base_currency: '015841551A748AD2C1F76FF6ECB0CCCD00000000', reference_date: 443845330 + 31535000}).to_text_full(), '90,452.246928/XRP'); - }); - it('XAU(dem)/XRP inverse', function() { - assert.strictEqual(Amount.from_quality('F72C7A9EAE4A45ED1FB547AD037D07B9B965C6E662BEBAFA4A03F2A976804235', 'XRP', NaN, {inverse: true, base_currency: '015841551A748AD2C1F76FF6ECB0CCCD00000000', reference_date: 443845330 + 31535000}).to_text_full(), '90,442.196677/XRP'); - }); - it('USD/XAU(dem)', function() { - assert.strictEqual(Amount.from_quality('4743E58E44974B325D42FD2BB683A6E36950F350EE46DD3A521B644B99782F5F', '015841551A748AD2C1F76FF6ECB0CCCD00000000', 'rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN', {base_currency: 'USD', reference_date: 443845330 + 31535000}).to_text_full(), '0.007710100231303007/XAU (-0.5%pa)/rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN'); - }); - it('USD/XAU(dem) inverse', function() { - assert.strictEqual(Amount.from_quality('CDFD3AFB2F8C5DBEF75B081F7C957FF5509563266F28F36C5704A0FB0BAD8800', '015841551A748AD2C1F76FF6ECB0CCCD00000000', 'rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN', {inverse: true, base_currency: 'USD', reference_date: 443845330 + 31535000}).to_text_full(), '0.007675186123263489/XAU (-0.5%pa)/rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN'); - }); it('BTC/XRP human', function() { assert.strictEqual(Amount.from_quality('7B73A610A009249B0CC0D4311E8BA7927B5A34D86634581C5F0FF9FF678E1000', 'XRP', NaN, {base_currency: 'BTC'}).to_human_full(), '44,970/XRP'); }); @@ -1120,57 +1090,6 @@ describe('Amount', function() { it('BTC/USD inverse human', function() { assert.strictEqual(Amount.from_quality('20294C923E80A51B487EB9547B3835FD483748B170D2D0A455071AFD498D0000', 'USD', 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', {inverse: true, base_currency: 'BTC'}).to_human_full(), '0.5/USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'); }); - it('XAU(dem)/XRP human', function() { - assert.strictEqual(Amount.from_quality('587322CCBDE0ABD01704769A73A077C32FB39057D813D4165F1FF973CAF997EF', 'XRP', NaN, {base_currency: '015841551A748AD2C1F76FF6ECB0CCCD00000000', reference_date: 443845330 + 31535000}).to_human_full(), '90,452.246928/XRP'); - }); - it('XAU(dem)/XRP inverse human', function() { - assert.strictEqual(Amount.from_quality('F72C7A9EAE4A45ED1FB547AD037D07B9B965C6E662BEBAFA4A03F2A976804235', 'XRP', NaN, {inverse: true, base_currency: '015841551A748AD2C1F76FF6ECB0CCCD00000000', reference_date: 443845330 + 31535000}).to_human_full(), '90,442.196677/XRP'); - }); - it('USD/XAU(dem) human', function() { - assert.strictEqual(Amount.from_quality('4743E58E44974B325D42FD2BB683A6E36950F350EE46DD3A521B644B99782F5F', '015841551A748AD2C1F76FF6ECB0CCCD00000000', 'rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN', {base_currency: 'USD', reference_date: 443845330 + 31535000}).to_human_full(), '0.007710100231303007/XAU (-0.5%pa)/rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN'); - }); - it('USD/XAU(dem) inverse human', function() { - assert.strictEqual(Amount.from_quality('CDFD3AFB2F8C5DBEF75B081F7C957FF5509563266F28F36C5704A0FB0BAD8800', '015841551A748AD2C1F76FF6ECB0CCCD00000000', 'rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN', {inverse: true, base_currency: 'USD', reference_date: 443845330 + 31535000}).to_human_full(), '0.007675186123263489/XAU (-0.5%pa)/rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN'); - }); - }); - - describe('apply interest', function() { - it('from_json apply interest 10 XAU', function() { - let demAmount = Amount.from_json('10/0158415500000000C1F76FF6ECB0BAC600000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - assert.strictEqual(demAmount.to_text_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - demAmount = demAmount.applyInterest(459990264); - assert.strictEqual(demAmount.to_text_full(), '9.294949401870436/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - - }); - it('from_json apply interest XAU', function() { - let demAmount = Amount.from_json('1235.5/0158415500000000C1F76FF6ECB0BAC600000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - assert.strictEqual(demAmount.to_text_full(), '1235.5/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - demAmount = demAmount.applyInterest(459990264); - assert.strictEqual(demAmount.to_text_full(), '1148.390998601092/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - }); - it('from_human with reference date', function() { - const demAmount = Amount.from_human('10 0158415500000000C1F76FF6ECB0BAC600000000', {reference_date: 459990264}); - demAmount.set_issuer('rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - assert.strictEqual(demAmount.to_text_full(), '10.75853086191915/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - }); - it('from_json apply interest 10 XAU human', function() { - let demAmount = Amount.from_json('10/0158415500000000C1F76FF6ECB0BAC600000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - assert.strictEqual(demAmount.to_human_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - demAmount = demAmount.applyInterest(459990264); - assert.strictEqual(demAmount.to_human_full(), '9.294949401870436/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - - }); - it('from_json apply interest XAU human', function() { - let demAmount = Amount.from_json('1235.5/0158415500000000C1F76FF6ECB0BAC600000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - assert.strictEqual(demAmount.to_human_full(), '1,235.5/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - demAmount = demAmount.applyInterest(459990264); - assert.strictEqual(demAmount.to_human_full(), '1,148.390998601092/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - }); - it('from_human with reference date human', function() { - const demAmount = Amount.from_human('10 0158415500000000C1F76FF6ECB0BAC600000000', {reference_date: 459990264}); - demAmount.set_issuer('rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - assert.strictEqual(demAmount.to_human_full(), '10.75853086191915/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); - }); }); describe('amount limits', function() { diff --git a/test/currency-test.js b/test/currency-test.js index f41ba207..54525a04 100644 --- a/test/currency-test.js +++ b/test/currency-test.js @@ -9,23 +9,10 @@ describe('Currency', function() { it('json_rewrite("USD") == "USD"', function() { assert.strictEqual('USD', currency.json_rewrite('USD')); }); - it('json_rewrite("NaN") == "XRP"', function() { - assert.strictEqual('XRP', currency.json_rewrite(NaN)); - }); - it('json_rewrite("015841551A748AD2C1F76FF6ECB0CCCD00000000") == "XAU (-0.5%pa)"', function() { - assert.strictEqual(currency.json_rewrite("015841551A748AD2C1F76FF6ECB0CCCD00000000"), - "XAU (-0.5%pa)"); - }); }); describe('from_json', function() { it('from_json().to_json() == "XRP"', function() { var r = currency.from_json(); - assert(!r.is_valid()); - assert.strictEqual('XRP', r.to_json()); - }); - it('from_json(NaN).to_json() == "XRP"', function() { - var r = currency.from_json(NaN); - assert(!r.is_valid()); assert.strictEqual('XRP', r.to_json()); }); it('from_json().to_json("") == "XRP"', function() { @@ -70,135 +57,21 @@ describe('Currency', function() { var r = currency.from_json("XAU"); assert.strictEqual('0000000000000000000000005841550000000000', r.to_json({force_hex: true})); }); - it('from_json("XAU (0.5%pa").to_json() hex', function() { - var r = currency.from_json("XAU (0.5%pa)"); - assert.strictEqual('015841550000000041F78E0A28CBF19200000000', r.to_json({force_hex: true})); - }); - it('json_rewrite("015841550000000041F78E0A28CBF19200000000").to_json() hex', function() { - var r = currency.json_rewrite('015841550000000041F78E0A28CBF19200000000'); - assert.strictEqual('XAU (0.5%pa)', r); - }); it('json_rewrite("015841550000000041F78E0A28CBF19200000000") hex', function() { var r = currency.json_rewrite('015841550000000041F78E0A28CBF19200000000', {force_hex: true}); assert.strictEqual('015841550000000041F78E0A28CBF19200000000', r); }); }); - describe('from_human', function() { - it('From human "USD - Gold (-25%pa)"', function() { - var cur = currency.from_human('USD - Gold (-25%pa)'); - assert.strictEqual(cur.to_json(), 'USD (-25%pa)'); - assert.strictEqual(cur.to_hex(), '0155534400000000C19A22BC51297F0B00000000'); - assert.strictEqual(cur.to_json(), cur.to_human()); - }); - it('From human "EUR (-0.5%pa)', function() { - var cur = currency.from_human('EUR (-0.5%pa)'); - assert.strictEqual(cur.to_json(), 'EUR (-0.5%pa)'); - }); - it('From human "EUR (0.5361%pa)", test decimals', function() { - var cur = currency.from_human('EUR (0.5361%pa)'); - assert.strictEqual(cur.to_json(), 'EUR (0.54%pa)'); - assert.strictEqual(cur.to_json({decimals:4}), 'EUR (0.5361%pa)'); - assert.strictEqual(cur.get_interest_percentage_at(undefined, 4), 0.5361); - }); - it('From human "EUR - Euro (0.5361%pa)", test decimals and full_name', function() { - var cur = currency.from_human('EUR (0.5361%pa)'); - assert.strictEqual(cur.to_json(), 'EUR (0.54%pa)'); - assert.strictEqual(cur.to_json({decimals:4, full_name:'Euro'}), 'EUR - Euro (0.5361%pa)'); - assert.strictEqual(cur.to_json({decimals:void(0), full_name:'Euro'}), 'EUR - Euro (0.54%pa)'); - assert.strictEqual(cur.to_json({decimals:undefined, full_name:'Euro'}), 'EUR - Euro (0.54%pa)'); - assert.strictEqual(cur.to_json({decimals:'henk', full_name:'Euro'}), 'EUR - Euro (0.54%pa)'); - assert.strictEqual(cur.get_interest_percentage_at(undefined, 4), 0.5361); - }); - it('From human "TYX - 30-Year Treasuries (1.5%pa)"', function() { - var cur = currency.from_human('TYX - 30-Year Treasuries (1.5%pa)'); - assert.strictEqual(cur.to_json(), 'TYX (1.5%pa)'); - }); - it('From human "TYX - 30-Year Treasuries"', function() { - var cur = currency.from_human('TYX - 30-Year Treasuries'); - assert.strictEqual(cur.to_json(), 'TYX'); - }); - it('From human "INR - Indian Rupees (-0.5%)"', function() { - var cur = currency.from_human('INR - Indian Rupees (-0.5%pa)'); - assert.strictEqual(cur.to_json(), 'INR (-0.5%pa)'); - }); - it('From human "INR - 30 Indian Rupees"', function() { - var cur = currency.from_human('INR - 30 Indian Rupees'); - assert.strictEqual(cur.to_json(), 'INR'); - }); - it('From human "XRP"', function() { - var cur = currency.from_human('XRP'); - assert.strictEqual(cur.to_json(), 'XRP'); - assert(cur.is_native(), true); - }); - it('From human "XRP - Ripples"', function() { - var cur = currency.from_human('XRP - Ripples'); - assert.strictEqual(cur.to_json(), 'XRP'); - assert(cur.is_native(), true); - }); - - }); - - describe('to_human', function() { - it('"USD".to_human() == "USD"', function() { - assert.strictEqual('USD', currency.from_json('USD').to_human()); - }); - it('"NaN".to_human() == "XRP"', function() { - assert.strictEqual('XRP', currency.from_json(NaN).to_human()); - }); - it('"015841551A748AD2C1F76FF6ECB0CCCD00000000") == "015841551A748AD2C1F76FF6ECB0CCCD00000000"', function() { - assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human(), 'XAU (-0.5%pa)'); - }); - it('"015841551A748AD2C1F76FF6ECB0CCCD00000000") == "015841551A748AD2C1F76FF6ECB0CCCD00000000"', function() { - assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human({full_name:'Gold'}), 'XAU - Gold (-0.5%pa)'); - }); - it('to_human interest XAU with full name, do not show interest', function() { - assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human({full_name:'Gold', show_interest:false}), 'XAU - Gold'); - }); - it('to_human interest XAU with full name, show interest', function() { - assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human({full_name:'Gold', show_interest:true}), 'XAU - Gold (-0.5%pa)'); - }); - it('to_human interest XAU, do show interest', function() { - assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human({show_interest:true}), 'XAU (-0.5%pa)'); - }); - it('to_human interest XAU, do not show interest', function() { - assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human({show_interest:false}), 'XAU'); - }); - it('to_human with full_name "USD - US Dollar show interest"', function() { - assert.strictEqual(currency.from_json('USD').to_human({full_name:'US Dollar', show_interest:true}), 'USD - US Dollar (0%pa)'); - }); - it('to_human with full_name "USD - US Dollar do not show interest"', function() { - assert.strictEqual(currency.from_json('USD').to_human({full_name:'US Dollar', show_interest:false}), 'USD - US Dollar'); - }); - it('to_human with full_name "USD - US Dollar"', function() { - assert.strictEqual('USD - US Dollar', currency.from_json('USD').to_human({full_name:'US Dollar'})); - }); - it('to_human with full_name "XRP - Ripples"', function() { - assert.strictEqual('XRP - Ripples', currency.from_json('XRP').to_human({full_name:'Ripples'})); - }); - it('to_human human "TIM" without full_name', function() { - var cur = currency.from_json("TIM"); - assert.strictEqual(cur.to_human(), "TIM"); - }); - it('to_human "TIM" with null full_name', function() { - var cur = currency.from_json("TIM"); - assert.strictEqual(cur.to_human({full_name: null}), "TIM"); - }); - - }); - describe('from_hex', function() { it('"015841551A748AD2C1F76FF6ECB0CCCD00000000" === "XAU (-0.5%pa)"', function() { var cur = currency.from_hex('015841551A748AD2C1F76FF6ECB0CCCD00000000'); - assert.strictEqual(cur.to_json(), 'XAU (-0.5%pa)'); assert.strictEqual(cur.to_hex(), '015841551A748AD2C1F76FF6ECB0CCCD00000000'); - assert.strictEqual(cur.to_json(), cur.to_human()); }); }); describe('parse_json', function() { it('should parse a currency object', function() { assert.strictEqual('USD', new currency().parse_json(currency.from_json('USD')).to_json()); - assert.strictEqual('USD (0.5%pa)', new currency().parse_json(currency.from_json('USD (0.5%pa)')).to_json()); }); it('should clone for parse_json on itself', function() { var cur = currency.from_json('USD'); @@ -241,53 +114,6 @@ describe('Currency', function() { assert.strictEqual('XRP', c.clone().to_json()); }); }); - describe('to_human', function() { - it('should generate human string', function() { - assert.strictEqual('XRP', currency.from_json('XRP').to_human()); - }); - }); - describe('has_interest', function() { - it('should be true for type 1 currency codes', function() { - assert(currency.from_hex('015841551A748AD2C1F76FF6ECB0CCCD00000000').has_interest()); - assert(currency.from_json('015841551A748AD2C1F76FF6ECB0CCCD00000000').has_interest()); - }); - it('should be false for type 0 currency codes', function() { - assert(!currency.from_hex('0000000000000000000000005553440000000000').has_interest()); - assert(!currency.from_json('USD').has_interest()); - }); - }); - function precision(num, precision) { - return +(Math.round(num + "e+"+precision) + "e-"+precision); - } - describe('get_interest_at', function() { - it('should return demurred value for demurrage currency', function() { - var cur = currency.from_json('015841551A748AD2C1F76FF6ECB0CCCD00000000'); - - // At start, no demurrage should occur - assert.equal(1, cur.get_interest_at(443845330)); - assert.equal(1, precision(cur.get_interest_at(new Date(timeUtil.fromRipple(443845330))), 14)); - - // After one year, 0.5% should have occurred - assert.equal(0.995, precision(cur.get_interest_at(443845330 + 31536000), 14)); - assert.equal(0.995, precision(cur.get_interest_at(new Date(timeUtil.fromRipple(443845330 + 31536000))), 14)); - - // After one demurrage period, 1/e should have occurred - var epsilon = 1e-14; - assert(Math.abs( - 1/Math.E - cur.get_interest_at(443845330 + 6291418827.05)) < epsilon); - - // One year before start, it should be (roughly) 0.5% higher. - assert.equal(1.005, precision(cur.get_interest_at(443845330 - 31536000), 4)); - - // One demurrage period before start, rate should be e - assert.equal(Math.E, cur.get_interest_at(443845330 - 6291418827.05)); - }); - it('should return 0 for currency without interest', function() { - var cur = currency.from_json('USD - US Dollar'); - assert.equal(0, cur.get_interest_at(443845330)); - assert.equal(0, cur.get_interest_at(443845330 + 31536000)); - }); - }); describe('get_iso', function() { it('should get "XRP" iso_code', function() { assert.strictEqual('XRP', currency.from_json('XRP').get_iso()); diff --git a/test/remote-test.js b/test/remote-test.js index 228661ac..311c0f16 100644 --- a/test/remote-test.js +++ b/test/remote-test.js @@ -1612,11 +1612,11 @@ describe('Remote', function() { command: 'book_offers', id: undefined, taker_gets: { - currency: Currency.from_human('USD').to_hex(), + currency: Currency.from_json('USD').to_hex(), issuer: ADDRESS }, taker_pays: { - currency: Currency.from_human('XRP').to_hex() + currency: Currency.from_json('XRP').to_hex() }, taker: ACCOUNT_ONE }); @@ -1639,11 +1639,11 @@ describe('Remote', function() { command: 'book_offers', id: undefined, taker_gets: { - currency: Currency.from_human('USD').to_hex(), + currency: Currency.from_json('USD').to_hex(), issuer: ADDRESS }, taker_pays: { - currency: Currency.from_human('XRP').to_hex() + currency: Currency.from_json('XRP').to_hex() }, taker: ACCOUNT_ONE, ledger_hash: LEDGER_HASH,