mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-27 15:45:48 +00:00
Remove demurrage
This commit is contained in:
@@ -190,12 +190,9 @@ Amount.prototype.divide = function(divisor) {
|
|||||||
* @return {Amount} The resulting ratio. Unit will be the same as numerator.
|
* @return {Amount} The resulting ratio. Unit will be the same as numerator.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Amount.prototype.ratio_human = function(denom, opts) {
|
Amount.prototype.ratio_human = function(denom) {
|
||||||
const options = extend({ }, opts);
|
|
||||||
|
|
||||||
const numerator = this.clone();
|
const numerator = this.clone();
|
||||||
|
const denominator = Amount.from_json(denom);
|
||||||
let denominator = Amount.from_json(denom);
|
|
||||||
|
|
||||||
// If either operand is NaN, the result is NaN.
|
// If either operand is NaN, the result is NaN.
|
||||||
if (!numerator.is_valid() || !denominator.is_valid()) {
|
if (!numerator.is_valid() || !denominator.is_valid()) {
|
||||||
@@ -206,14 +203,6 @@ Amount.prototype.ratio_human = function(denom, opts) {
|
|||||||
return new Amount(NaN);
|
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.
|
// Special case: The denominator is a native (XRP) amount.
|
||||||
//
|
//
|
||||||
// In that case, it's going to be expressed as base units (1 XRP =
|
// 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.
|
* for Ripple epoch.
|
||||||
* @return {Amount} The product. Unit will be the same as the first factor.
|
* @return {Amount} The product. Unit will be the same as the first factor.
|
||||||
*/
|
*/
|
||||||
Amount.prototype.product_human = function(factor, options = {}) {
|
Amount.prototype.product_human = function(factor) {
|
||||||
|
const fac = Amount.from_json(factor);
|
||||||
let fac = Amount.from_json(factor);
|
|
||||||
|
|
||||||
// If either operand is NaN, the result is NaN.
|
// If either operand is NaN, the result is NaN.
|
||||||
if (!this.is_valid() || !fac.is_valid()) {
|
if (!this.is_valid() || !fac.is_valid()) {
|
||||||
return new Amount();
|
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);
|
const product = this.multiply(fac);
|
||||||
|
|
||||||
// Special case: The second factor is a native (XRP) amount expressed as base
|
// 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) {
|
Amount.prototype.parse_human = function(j) {
|
||||||
const opts = options || {};
|
|
||||||
|
|
||||||
const hex_RE = /^[a-fA-F0-9]{40}$/;
|
const hex_RE = /^[a-fA-F0-9]{40}$/;
|
||||||
const currency_RE = /^([a-zA-Z]{3}|[0-9]{3})$/;
|
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) :
|
(this._is_native ? new XRPValue(value) :
|
||||||
new IOUValue(value));
|
new IOUValue(value));
|
||||||
this._set_value(newValue);
|
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;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -627,12 +597,6 @@ function(quality, counterCurrency, counterIssuer, opts) {
|
|||||||
this._set_value(nativeAdjusted);
|
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;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -782,27 +746,6 @@ Amount.prototype.to_text = function() {
|
|||||||
+ (s_post ? '.' + post.substring(0, 1 + post.length - s_post[0].length) : '');
|
+ (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.
|
* Format only value in a human-readable format.
|
||||||
*
|
*
|
||||||
@@ -836,13 +779,9 @@ Amount.prototype.to_human = function(options) {
|
|||||||
|
|
||||||
/* eslint-disable consistent-this */
|
/* eslint-disable consistent-this */
|
||||||
// Apply demurrage/interest
|
// Apply demurrage/interest
|
||||||
let ref = this;
|
const ref = this;
|
||||||
/* eslint-enable consistent-this */
|
/* eslint-enable consistent-this */
|
||||||
|
|
||||||
if (opts.reference_date) {
|
|
||||||
ref = this.applyInterest(opts.reference_date);
|
|
||||||
}
|
|
||||||
|
|
||||||
const isNegative = ref._value.isNegative();
|
const isNegative = ref._value.isNegative();
|
||||||
const valueString = ref._value.abs().toFixed();
|
const valueString = ref._value.abs().toFixed();
|
||||||
const parts = valueString.split('.');
|
const parts = valueString.split('.');
|
||||||
@@ -930,7 +869,7 @@ Amount.prototype.to_human = function(options) {
|
|||||||
Amount.prototype.to_human_full = function(options) {
|
Amount.prototype.to_human_full = function(options) {
|
||||||
const opts = options || {};
|
const opts = options || {};
|
||||||
const value = this.to_human(opts);
|
const value = this.to_human(opts);
|
||||||
const currency = this._currency.to_human();
|
const currency = this._currency.to_json();
|
||||||
const issuer = this._issuer;
|
const issuer = this._issuer;
|
||||||
const base = value + '/' + currency;
|
const base = value + '/' + currency;
|
||||||
return this.is_native() ? base : (base + '/' + issuer);
|
return this.is_native() ? base : (base + '/' + issuer);
|
||||||
@@ -943,8 +882,7 @@ Amount.prototype.to_json = function() {
|
|||||||
|
|
||||||
const amount_json = {
|
const amount_json = {
|
||||||
value: this.to_text(),
|
value: this.to_text(),
|
||||||
currency: this._currency.has_interest() ?
|
currency: this._currency.to_json()
|
||||||
this._currency.to_hex() : this._currency.to_json()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isValidAddress(this._issuer)) {
|
if (isValidAddress(this._issuer)) {
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ function(legOneOffer, legTwoOffer) {
|
|||||||
this._currencyPays, this._issuerPays);
|
this._currencyPays, this._issuerPays);
|
||||||
const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer,
|
const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer,
|
||||||
this._currencyGets, this._issuerGets);
|
this._currencyGets, this._issuerGets);
|
||||||
const legOneQuality = Utils.getOfferQuality(legOneOffer, this._currencyGets,
|
const legOneQuality = Utils.getOfferQuality(legOneOffer,
|
||||||
this._currencyPays, this._issuerPays);
|
this._currencyPays, this._issuerPays);
|
||||||
|
|
||||||
const autobridgedTakerGets = Utils.getOfferTakerGetsFunded(legTwoOffer,
|
const autobridgedTakerGets = Utils.getOfferTakerGetsFunded(legTwoOffer,
|
||||||
@@ -202,7 +202,7 @@ function(legOneOffer, legTwoOffer) {
|
|||||||
this._currencyPays, this._issuerPays);
|
this._currencyPays, this._issuerPays);
|
||||||
const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer,
|
const legTwoTakerPaysFunded = Utils.getOfferTakerPaysFunded(legTwoOffer,
|
||||||
this._currencyGets, this._issuerGets);
|
this._currencyGets, this._issuerGets);
|
||||||
const legTwoQuality = Utils.getOfferQuality(legTwoOffer, this._currencyGets,
|
const legTwoQuality = Utils.getOfferQuality(legTwoOffer,
|
||||||
this._currencyGets, this._issuerGets);
|
this._currencyGets, this._issuerGets);
|
||||||
|
|
||||||
const autobridgedTakerGets = legOneTakerGetsFunded.divide(legTwoQuality);
|
const autobridgedTakerGets = legOneTakerGetsFunded.divide(legTwoQuality);
|
||||||
@@ -463,7 +463,7 @@ function setLegOneTakerGetsFunded(legOneOffer, takerGetsFunded) {
|
|||||||
|
|
||||||
legOneOffer.taker_gets_funded = takerGetsFunded.to_text();
|
legOneOffer.taker_gets_funded = takerGetsFunded.to_text();
|
||||||
legOneOffer.taker_pays_funded = takerGetsFunded
|
legOneOffer.taker_pays_funded = takerGetsFunded
|
||||||
.multiply(Utils.getOfferQuality(legOneOffer, this._currencyGets,
|
.multiply(Utils.getOfferQuality(legOneOffer,
|
||||||
this._currencyPays, this._issuerPays))
|
this._currencyPays, this._issuerPays))
|
||||||
.to_text();
|
.to_text();
|
||||||
|
|
||||||
@@ -485,7 +485,7 @@ function(legOneOffer, takerGets) {
|
|||||||
assertValidLegOneOffer(legOneOffer, 'Leg one offer is invalid');
|
assertValidLegOneOffer(legOneOffer, 'Leg one offer is invalid');
|
||||||
assert(takerGets instanceof Amount, 'Taker gets funded 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);
|
this._currencyPays, this._issuerPays);
|
||||||
|
|
||||||
legOneOffer.TakerGets = takerGets.to_text();
|
legOneOffer.TakerGets = takerGets.to_text();
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
const _ = require('lodash');
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const Float = require('./ieee754').Float;
|
|
||||||
const BN = require('bn.js');
|
const BN = require('bn.js');
|
||||||
|
|
||||||
//
|
|
||||||
// Currency support
|
|
||||||
//
|
|
||||||
|
|
||||||
function Currency() {
|
function Currency() {
|
||||||
// Internal form: 0 = XRP. 3 letter-code.
|
// Internal form: 0 = XRP. 3 letter-code.
|
||||||
// XXX Internal should be 0 or hex with three letter annotation when valid.
|
// 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_ZERO = '0000000000000000000000000000000000000000';
|
||||||
Currency.HEX_ONE = '0000000000000000000000000000000000000001';
|
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) {
|
Currency.from_json = function(j, shouldInterpretXrpAsIou) {
|
||||||
return (new Currency()).parse_json(j, shouldInterpretXrpAsIou);
|
return (new Currency()).parse_json(j, shouldInterpretXrpAsIou);
|
||||||
};
|
};
|
||||||
@@ -92,10 +50,6 @@ Currency.prototype.to_hex = function() {
|
|||||||
return utils.arrayToHex(this.to_bytes());
|
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) {
|
Currency.json_rewrite = function(j, opts) {
|
||||||
return this.from_json(j).to_json(opts);
|
return this.from_json(j).to_json(opts);
|
||||||
};
|
};
|
||||||
@@ -133,7 +87,7 @@ Currency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'string':
|
case 'string':
|
||||||
if (!j || j === '0') {
|
if (!j || j === '0' || j === 'XRP') {
|
||||||
// Empty string or XRP
|
// Empty string or XRP
|
||||||
this.parse_hex(shouldInterpretXrpAsIou
|
this.parse_hex(shouldInterpretXrpAsIou
|
||||||
? Currency.HEX_CURRENCY_BAD
|
? Currency.HEX_CURRENCY_BAD
|
||||||
@@ -153,93 +107,22 @@ Currency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// match the given string to see if it's in an allowed format
|
const currencyCode = j.toUpperCase();
|
||||||
const matches = j.match(this.human_RE);
|
const currencyData = utils.arraySet(20, 0);
|
||||||
|
currencyData[12] = currencyCode.charCodeAt(0) & 0xff;
|
||||||
if (matches) {
|
currencyData[13] = currencyCode.charCodeAt(1) & 0xff;
|
||||||
let currencyCode = matches[1];
|
currencyData[14] = currencyCode.charCodeAt(2) & 0xff;
|
||||||
|
this.parse_bytes(currencyData);
|
||||||
// for the currency 'XRP' case
|
break;
|
||||||
// we drop everything else that could have been provided
|
case 'undefined':
|
||||||
// e.g. 'XRP - Ripple'
|
this.parse_hex(Currency.HEX_ZERO);
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._update();
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Currency.prototype.parse_human = function(j) {
|
|
||||||
return this.parse_json(j);
|
|
||||||
};
|
|
||||||
|
|
||||||
Currency.prototype.is_valid = function() {
|
Currency.prototype.is_valid = function() {
|
||||||
return this._value instanceof BN;
|
return this._value instanceof BN;
|
||||||
};
|
};
|
||||||
@@ -274,6 +157,12 @@ Currency.prototype.to_bytes = function() {
|
|||||||
return this._value.toArray('be', this.constructor.width);
|
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.
|
* Recalculate internal representation.
|
||||||
*
|
*
|
||||||
@@ -287,13 +176,11 @@ Currency.prototype._update = function() {
|
|||||||
let isZeroExceptInStandardPositions = true;
|
let isZeroExceptInStandardPositions = true;
|
||||||
|
|
||||||
if (!bytes) {
|
if (!bytes) {
|
||||||
return;
|
return; // before being initialized
|
||||||
}
|
}
|
||||||
|
|
||||||
this._native = false;
|
this._native = false;
|
||||||
this._type = -1;
|
this._type = -1;
|
||||||
this._interest_start = NaN;
|
|
||||||
this._interest_period = NaN;
|
|
||||||
this._iso_code = '';
|
this._iso_code = '';
|
||||||
|
|
||||||
for (let i = 0; i < 20; i++) {
|
for (let i = 0; i < 20; i++) {
|
||||||
@@ -318,11 +205,6 @@ Currency.prototype._update = function() {
|
|||||||
+ String.fromCharCode(bytes[3]);
|
+ String.fromCharCode(bytes[3]);
|
||||||
|
|
||||||
this._type = 1;
|
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._native = this._native;
|
||||||
d._type = this._type;
|
d._type = this._type;
|
||||||
d._interest_start = this._interest_start;
|
|
||||||
d._interest_period = this._interest_period;
|
|
||||||
d._iso_code = this._iso_code;
|
d._iso_code = this._iso_code;
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
@@ -364,149 +244,26 @@ Currency.prototype.parse_bytes = function(j) {
|
|||||||
return this;
|
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() {
|
Currency.prototype.is_native = function() {
|
||||||
return this._native;
|
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 = {}) {
|
Currency.prototype.to_json = function(opts = {}) {
|
||||||
if (!this.is_valid()) {
|
if (!this.is_valid()) {
|
||||||
// XXX This is backwards compatible behavior, but probably not very good.
|
throw new Error('Invalid currency object');
|
||||||
return 'XRP';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let currency;
|
if (this._isISOCode() && !opts.force_hex) {
|
||||||
const fullName = opts && opts.full_name ? ' - ' + opts.full_name : '';
|
const fullName = opts && opts.full_name ? ' - ' + opts.full_name : '';
|
||||||
opts.show_interest = opts.show_interest !== undefined
|
return this._iso_code + fullName;
|
||||||
? 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return currency;
|
const hex = this.to_hex();
|
||||||
};
|
|
||||||
|
|
||||||
Currency.prototype.to_human = function(opts) {
|
// XXX This is to maintain backwards compatibility, but it is very, very
|
||||||
// to_human() will always print the human-readable currency code if available.
|
// odd behavior, so we should deprecate it and get rid of it as soon as
|
||||||
return this.to_json(opts);
|
// possible.
|
||||||
|
return hex === Currency.HEX_ONE ? 1 : hex;
|
||||||
};
|
};
|
||||||
|
|
||||||
Currency.prototype.get_iso = function() {
|
Currency.prototype.get_iso = function() {
|
||||||
|
|||||||
@@ -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")
|
|
||||||
}
|
|
||||||
@@ -25,13 +25,6 @@ const log = require('./log').internal.sub('orderbook');
|
|||||||
const {IOUValue} = require('ripple-lib-value');
|
const {IOUValue} = require('ripple-lib-value');
|
||||||
const RippleError = require('./rippleerror').RippleError;
|
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) {
|
function _sortOffersQuick(a, b) {
|
||||||
return a.qualityHex.localeCompare(b.qualityHex);
|
return a.qualityHex.localeCompare(b.qualityHex);
|
||||||
}
|
}
|
||||||
@@ -94,8 +87,7 @@ function OrderBook(remote,
|
|||||||
this._calculatorRunning = false;
|
this._calculatorRunning = false;
|
||||||
|
|
||||||
|
|
||||||
this.sortOffers = this._currencyGets.has_interest() ?
|
this.sortOffers = _sortOffersQuick;
|
||||||
_sortOffers.bind(this) : _sortOffersQuick;
|
|
||||||
|
|
||||||
this._isAutobridgeable = !this._currencyGets.is_native()
|
this._isAutobridgeable = !this._currencyGets.is_native()
|
||||||
&& !this._currencyPays.is_native();
|
&& !this._currencyPays.is_native();
|
||||||
@@ -749,7 +741,7 @@ OrderBook.prototype.setOfferFundedAmount = function(offer) {
|
|||||||
} else if (previousOfferSum.compareTo(fundedAmount) < 0) {
|
} else if (previousOfferSum.compareTo(fundedAmount) < 0) {
|
||||||
offer.taker_gets_funded = fundedAmount.subtract(previousOfferSum).to_text();
|
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(
|
const takerPaysFunded = quality.multiply(
|
||||||
OrderBookUtils.getOfferTakerGetsFunded(offer)
|
OrderBookUtils.getOfferTakerGetsFunded(offer)
|
||||||
);
|
);
|
||||||
@@ -1014,13 +1006,13 @@ OrderBook.prototype.notify = function(transaction) {
|
|||||||
let takerGetsTotal = Amount.from_json(
|
let takerGetsTotal = Amount.from_json(
|
||||||
'0' + ((Currency.from_json(this._currencyGets).is_native())
|
'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(
|
let takerPaysTotal = Amount.from_json(
|
||||||
'0' + ((Currency.from_json(this._currencyPays).is_native())
|
'0' + ((Currency.from_json(this._currencyPays).is_native())
|
||||||
? ''
|
? ''
|
||||||
: ('/' + this._currencyPays.to_human() + '/' + this._issuerPays))
|
: ('/' + this._currencyPays.to_json() + '/' + this._issuerPays))
|
||||||
);
|
);
|
||||||
|
|
||||||
const isOfferCancel =
|
const isOfferCancel =
|
||||||
@@ -1117,27 +1109,10 @@ OrderBook.prototype.insertOffer = function(node) {
|
|||||||
|
|
||||||
const originalLength = this._offers.length;
|
const originalLength = this._offers.length;
|
||||||
|
|
||||||
if (!this._currencyGets.has_interest()) {
|
for (let i = 0; i < originalLength; i++) {
|
||||||
// use fast path
|
if (offer.qualityHex <= this._offers[i].qualityHex) {
|
||||||
for (let i = 0; i < originalLength; i++) {
|
this._offers.splice(i, 0, offer);
|
||||||
if (offer.qualityHex <= this._offers[i].qualityHex) {
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,27 +108,10 @@ OrderBookUtils.getOfferTakerGets = function(offer, currency_, issuer_) {
|
|||||||
* @param {Currency} currencyGets
|
* @param {Currency} currencyGets
|
||||||
*/
|
*/
|
||||||
|
|
||||||
OrderBookUtils.getOfferQuality = function(offer, currencyGets, currency_,
|
OrderBookUtils.getOfferQuality = function(offer, currency_, issuer_) {
|
||||||
issuer_
|
const currency = currency_ || getCurrencyFromOffer(offer);
|
||||||
) {
|
const issuer = issuer_ || getIssuerFromOffer(offer);
|
||||||
let amount;
|
return createAmount(offer.quality, currency, issuer);
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -168,10 +168,10 @@ describe('Amount', function() {
|
|||||||
assert.strictEqual(Amount.from_human('12345.6789 XAU').to_human_full(), '12,345.6789/XAU/NaN');
|
assert.strictEqual(Amount.from_human('12345.6789 XAU').to_human_full(), '12,345.6789/XAU/NaN');
|
||||||
});
|
});
|
||||||
it('12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000', function() {
|
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() {
|
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() {
|
it('12345.6789 0000000000000000000000005553440000000000', function() {
|
||||||
assert.strictEqual(Amount.from_human('12345.6789 0000000000000000000000005553440000000000').to_text_full(), '12345.6789/USD/NaN');
|
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()));
|
assert(isNaN(Amount.from_json('x').to_text()));
|
||||||
});
|
});
|
||||||
it('parse dem', function() {
|
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() {
|
it('parse dem human', function() {
|
||||||
assert.strictEqual(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/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 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');
|
|
||||||
});
|
});
|
||||||
it('Parse native 0', function() {
|
it('Parse native 0', function() {
|
||||||
assert.strictEqual('0/XRP', Amount.from_json('0').to_text_full());
|
assert.strictEqual('0/XRP', Amount.from_json('0').to_text_full());
|
||||||
@@ -948,9 +942,6 @@ describe('Amount', function() {
|
|||||||
it('Multiply XRP with XRP', 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');
|
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() {
|
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());
|
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() {
|
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');
|
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() {
|
describe('ratio_human', function() {
|
||||||
@@ -1037,12 +1025,6 @@ describe('Amount', function() {
|
|||||||
assert.deepEqual(c.to_json(), {value: '0.005441114728882572',
|
assert.deepEqual(c.to_json(), {value: '0.005441114728882572',
|
||||||
currency: 'USD', issuer: 'rLFPPebckMYZf3urdomLsaqRGmQ6zHVrrK'});
|
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() {
|
describe('_invert', function() {
|
||||||
@@ -1090,18 +1072,6 @@ describe('Amount', function() {
|
|||||||
it('BTC/USD inverse', 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');
|
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() {
|
it('BTC/XRP human', function() {
|
||||||
assert.strictEqual(Amount.from_quality('7B73A610A009249B0CC0D4311E8BA7927B5A34D86634581C5F0FF9FF678E1000', 'XRP', NaN, {base_currency: 'BTC'}).to_human_full(), '44,970/XRP');
|
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() {
|
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');
|
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() {
|
describe('amount limits', function() {
|
||||||
|
|||||||
@@ -9,23 +9,10 @@ describe('Currency', function() {
|
|||||||
it('json_rewrite("USD") == "USD"', function() {
|
it('json_rewrite("USD") == "USD"', function() {
|
||||||
assert.strictEqual('USD', currency.json_rewrite('USD'));
|
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() {
|
describe('from_json', function() {
|
||||||
it('from_json().to_json() == "XRP"', function() {
|
it('from_json().to_json() == "XRP"', function() {
|
||||||
var r = currency.from_json();
|
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());
|
assert.strictEqual('XRP', r.to_json());
|
||||||
});
|
});
|
||||||
it('from_json().to_json("") == "XRP"', function() {
|
it('from_json().to_json("") == "XRP"', function() {
|
||||||
@@ -70,135 +57,21 @@ describe('Currency', function() {
|
|||||||
var r = currency.from_json("XAU");
|
var r = currency.from_json("XAU");
|
||||||
assert.strictEqual('0000000000000000000000005841550000000000', r.to_json({force_hex: true}));
|
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() {
|
it('json_rewrite("015841550000000041F78E0A28CBF19200000000") hex', function() {
|
||||||
var r = currency.json_rewrite('015841550000000041F78E0A28CBF19200000000', {force_hex: true});
|
var r = currency.json_rewrite('015841550000000041F78E0A28CBF19200000000', {force_hex: true});
|
||||||
assert.strictEqual('015841550000000041F78E0A28CBF19200000000', r);
|
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() {
|
describe('from_hex', function() {
|
||||||
it('"015841551A748AD2C1F76FF6ECB0CCCD00000000" === "XAU (-0.5%pa)"', function() {
|
it('"015841551A748AD2C1F76FF6ECB0CCCD00000000" === "XAU (-0.5%pa)"', function() {
|
||||||
var cur = currency.from_hex('015841551A748AD2C1F76FF6ECB0CCCD00000000');
|
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_hex(), '015841551A748AD2C1F76FF6ECB0CCCD00000000');
|
||||||
assert.strictEqual(cur.to_json(), cur.to_human());
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('parse_json', function() {
|
describe('parse_json', function() {
|
||||||
it('should parse a currency object', function() {
|
it('should parse a currency object', function() {
|
||||||
assert.strictEqual('USD', new currency().parse_json(currency.from_json('USD')).to_json());
|
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() {
|
it('should clone for parse_json on itself', function() {
|
||||||
var cur = currency.from_json('USD');
|
var cur = currency.from_json('USD');
|
||||||
@@ -241,53 +114,6 @@ describe('Currency', function() {
|
|||||||
assert.strictEqual('XRP', c.clone().to_json());
|
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() {
|
describe('get_iso', function() {
|
||||||
it('should get "XRP" iso_code', function() {
|
it('should get "XRP" iso_code', function() {
|
||||||
assert.strictEqual('XRP', currency.from_json('XRP').get_iso());
|
assert.strictEqual('XRP', currency.from_json('XRP').get_iso());
|
||||||
|
|||||||
@@ -1612,11 +1612,11 @@ describe('Remote', function() {
|
|||||||
command: 'book_offers',
|
command: 'book_offers',
|
||||||
id: undefined,
|
id: undefined,
|
||||||
taker_gets: {
|
taker_gets: {
|
||||||
currency: Currency.from_human('USD').to_hex(),
|
currency: Currency.from_json('USD').to_hex(),
|
||||||
issuer: ADDRESS
|
issuer: ADDRESS
|
||||||
},
|
},
|
||||||
taker_pays: {
|
taker_pays: {
|
||||||
currency: Currency.from_human('XRP').to_hex()
|
currency: Currency.from_json('XRP').to_hex()
|
||||||
},
|
},
|
||||||
taker: ACCOUNT_ONE
|
taker: ACCOUNT_ONE
|
||||||
});
|
});
|
||||||
@@ -1639,11 +1639,11 @@ describe('Remote', function() {
|
|||||||
command: 'book_offers',
|
command: 'book_offers',
|
||||||
id: undefined,
|
id: undefined,
|
||||||
taker_gets: {
|
taker_gets: {
|
||||||
currency: Currency.from_human('USD').to_hex(),
|
currency: Currency.from_json('USD').to_hex(),
|
||||||
issuer: ADDRESS
|
issuer: ADDRESS
|
||||||
},
|
},
|
||||||
taker_pays: {
|
taker_pays: {
|
||||||
currency: Currency.from_human('XRP').to_hex()
|
currency: Currency.from_json('XRP').to_hex()
|
||||||
},
|
},
|
||||||
taker: ACCOUNT_ONE,
|
taker: ACCOUNT_ONE,
|
||||||
ledger_hash: LEDGER_HASH,
|
ledger_hash: LEDGER_HASH,
|
||||||
|
|||||||
Reference in New Issue
Block a user