Remove demurrage

This commit is contained in:
Chris Clark
2015-10-15 11:49:48 -07:00
parent 462e440d5b
commit 512817a2db
9 changed files with 60 additions and 769 deletions

View File

@@ -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)) {

View File

@@ -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();

View File

@@ -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() {

View File

@@ -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")
}

View File

@@ -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;
}
}

View File

@@ -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);
};
/**

View File

@@ -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() {

View File

@@ -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());

View File

@@ -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,