mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-12-06 17:27:59 +00:00
Remove BigNumber completely from Amount and small changes
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
@@ -29,10 +31,12 @@ function getAccountLines(remote, address, ledgerVersion, options, marker, limit,
|
||||
});
|
||||
}
|
||||
|
||||
/*:: type Options = {currency: string, counterparty: string,
|
||||
limit: number, ledgerVersion: number} */
|
||||
function getTrustlines(account: string, options: Options,
|
||||
callback: () => void): void {
|
||||
function getTrustlines(
|
||||
account: string,
|
||||
options: {currency: string, counterparty: string,
|
||||
limit: number, ledgerVersion: number},
|
||||
callback: () => void
|
||||
): void {
|
||||
validate.address(account);
|
||||
validate.options(options);
|
||||
|
||||
|
||||
43
src/core/IOUValue.js
Normal file
43
src/core/IOUValue.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/* @flow */
|
||||
|
||||
'use strict';
|
||||
|
||||
const Value = require('./value').Value;
|
||||
const GlobalBigNumber = require('bignumber.js');
|
||||
const BigNumber = GlobalBigNumber.another({
|
||||
ROUNDING_MODE: GlobalBigNumber.ROUND_HALF_UP,
|
||||
DECIMAL_PLACES: 40
|
||||
});
|
||||
|
||||
class IOUValue extends Value {
|
||||
|
||||
constructor(value: string | BigNumber) {
|
||||
super(value);
|
||||
}
|
||||
|
||||
multiplyByXRP(multiplicand: {_value: BigNumber, _bi_xns_unit: number}) {
|
||||
const constant = new BigNumber((multiplicand._bi_xns_unit).toString());
|
||||
const value = new BigNumber(multiplicand._value);
|
||||
multiplicand._value = (value).times(constant);
|
||||
return super.multiply(multiplicand);
|
||||
}
|
||||
|
||||
divideByXRP(divisor: {_value: BigNumber, _bi_xns_unit: number}) {
|
||||
const constant = new BigNumber((divisor._bi_xns_unit).toString());
|
||||
const value = new BigNumber(divisor._value);
|
||||
divisor._value = (value).times(constant);
|
||||
return super.divide(divisor);
|
||||
}
|
||||
|
||||
_canonicalize(value) {
|
||||
return new IOUValue(value.toPrecision(16));
|
||||
}
|
||||
|
||||
equals(comparator) {
|
||||
return (comparator instanceof IOUValue)
|
||||
&& this._value.equals(comparator.value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.IOUValue = IOUValue;
|
||||
29
src/core/XRPValue.js
Normal file
29
src/core/XRPValue.js
Normal file
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const GlobalBigNumber = require('bignumber.js');
|
||||
const BigNumber = GlobalBigNumber.another({
|
||||
ROUNDING_MODE: GlobalBigNumber.ROUND_HALF_UP,
|
||||
DECIMAL_PLACES: 40
|
||||
});
|
||||
|
||||
const Value = require('./value').Value;
|
||||
|
||||
class XRPValue extends Value {
|
||||
|
||||
constructor(value, bi_xns_unit) {
|
||||
super(value);
|
||||
this._bi_xns_unit = bi_xns_unit;
|
||||
}
|
||||
|
||||
_canonicalize(value) {
|
||||
return new XRPValue(value.round(6, BigNumber.ROUND_DOWN));
|
||||
}
|
||||
|
||||
equals(comparator) {
|
||||
return (comparator instanceof XRPValue)
|
||||
&& this._value.equals(comparator.value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.XRPValue = XRPValue;
|
||||
@@ -9,18 +9,13 @@ const utils = require('./utils');
|
||||
const UInt160 = require('./uint160').UInt160;
|
||||
const Seed = require('./seed').Seed;
|
||||
const Currency = require('./currency').Currency;
|
||||
const GlobalBigNumber = require('bignumber.js');
|
||||
const Value_IOU = require('./value_IOU').Value_IOU;
|
||||
const Value_XRP = require('./value_XRP').Value_XRP;
|
||||
|
||||
const BigNumber = GlobalBigNumber.another({
|
||||
ROUNDING_MODE: GlobalBigNumber.ROUND_HALF_UP,
|
||||
DECIMAL_PLACES: 40
|
||||
});
|
||||
const Value = require('./value').Value;
|
||||
const IOUValue = require('./IOUValue').IOUValue;
|
||||
const XRPValue = require('./XRPValue').XRPValue;
|
||||
|
||||
|
||||
function inverse(number) {
|
||||
return (new BigNumber(number)).toPower(-1);
|
||||
return new IOUValue(number).invert()._value;
|
||||
}
|
||||
|
||||
function Amount() {
|
||||
@@ -28,7 +23,7 @@ function Amount() {
|
||||
// integer : XRP
|
||||
// { 'value' : ..., 'currency' : ..., 'issuer' : ...}
|
||||
|
||||
this._value = new BigNumber(NaN);
|
||||
this._value = new Value(NaN)._value;
|
||||
this._is_native = true; // Default to XRP. Only valid if value is not NaN.
|
||||
this._currency = new Currency();
|
||||
this._issuer = new UInt160();
|
||||
@@ -47,18 +42,18 @@ const consts = {
|
||||
|
||||
// bi_ prefix refers to "big integer"
|
||||
// TODO: we shouldn't expose our BigNumber library publicly
|
||||
bi_5: new BigNumber(5),
|
||||
bi_7: new BigNumber(7),
|
||||
bi_10: new BigNumber(10),
|
||||
bi_1e14: new BigNumber(1e14),
|
||||
bi_1e16: new BigNumber(1e16),
|
||||
bi_1e17: new BigNumber(1e17),
|
||||
bi_1e32: new BigNumber(1e32),
|
||||
bi_man_max_value: new BigNumber('9999999999999999'),
|
||||
bi_man_min_value: new BigNumber(1e15),
|
||||
bi_xns_max: new BigNumber(1e17),
|
||||
bi_xns_min: new BigNumber(-1e17),
|
||||
bi_xns_unit: new BigNumber(1e6),
|
||||
bi_5: new Value(5)._value,
|
||||
bi_7: new Value(7)._value,
|
||||
bi_10: new Value(10)._value,
|
||||
bi_1e14: new Value(1e14)._value,
|
||||
bi_1e16: new Value(1e16)._value,
|
||||
bi_1e17: new Value(1e17)._value,
|
||||
bi_1e32: new Value(1e32)._value,
|
||||
bi_man_max_value: new Value('9999999999999999')._value,
|
||||
bi_man_min_value: new Value(1e15)._value,
|
||||
bi_xns_max: new Value(1e17)._value,
|
||||
bi_xns_min: new Value(-1e17)._value,
|
||||
bi_xns_unit: new Value(1e6)._value,
|
||||
|
||||
cMinOffset: -96,
|
||||
cMaxOffset: 80,
|
||||
@@ -70,9 +65,9 @@ const consts = {
|
||||
min_value: '-1000000000000000e-96'
|
||||
};
|
||||
|
||||
const MAX_XRP_VALUE = new BigNumber(1e11);
|
||||
const MAX_IOU_VALUE = new BigNumber(consts.max_value);
|
||||
const MIN_IOU_VALUE = (new BigNumber(consts.min_value)).abs();
|
||||
const MAX_XRP_VALUE = new Value(1e11)._value;
|
||||
const MAX_IOU_VALUE = new Value(consts.max_value)._value;
|
||||
const MIN_IOU_VALUE = new Value(consts.min_value)._value.abs();
|
||||
|
||||
// Add constants to Amount class
|
||||
extend(Amount, consts);
|
||||
@@ -116,23 +111,30 @@ Amount.is_valid_full = function(j) {
|
||||
|
||||
Amount.NaN = function() {
|
||||
const result = new Amount();
|
||||
result._value = new BigNumber(NaN); // should have no effect
|
||||
result._value = new Value(NaN)._value; // should have no effect
|
||||
return result; // but let's be careful
|
||||
};
|
||||
|
||||
// be sure that _is_native is set properly BEFORE calling _set_value
|
||||
Amount.prototype._set_value = function(value, roundingMode) {
|
||||
assert(value instanceof BigNumber);
|
||||
this._value = value.isZero() && value.isNegative() ? value.negated() : value;
|
||||
assert(value instanceof Object);
|
||||
|
||||
this._value = this._value = value.isZero() && value.isNegative() ?
|
||||
value.negated()._value : value._value;
|
||||
if (!this._value) {
|
||||
this._value = value.isZero() && value.isNegative() ?
|
||||
value.negated() : value;
|
||||
}
|
||||
this.canonicalize(roundingMode);
|
||||
this._check_limits();
|
||||
|
||||
};
|
||||
|
||||
// Returns a new value which is the absolute value of this.
|
||||
Amount.prototype.abs = function() {
|
||||
|
||||
const val = (new Value_IOU(this._value)).abs();
|
||||
return this._copy(new BigNumber(val._value));
|
||||
const val = (new IOUValue(this._value)).abs();
|
||||
return this._copy(val);
|
||||
|
||||
};
|
||||
|
||||
@@ -143,9 +145,9 @@ Amount.prototype.add = function(addend) {
|
||||
return new Amount(NaN);
|
||||
}
|
||||
|
||||
const thisValue = new Value_IOU(this._value);
|
||||
const addendValue = new Value_IOU(addendAmount._value);
|
||||
return this._copy(new BigNumber(thisValue.add(addendValue)._value));
|
||||
const thisValue = new IOUValue(this._value);
|
||||
const addendValue = new IOUValue(addendAmount._value);
|
||||
return this._copy(thisValue.add(addendValue));
|
||||
|
||||
};
|
||||
|
||||
@@ -158,11 +160,17 @@ Amount.prototype.subtract = function(subtrahend) {
|
||||
Amount.prototype.multiply = function(multiplicand) {
|
||||
|
||||
const multiplicandAmount = Amount.from_json(multiplicand);
|
||||
const multiplyBy = multiplicandAmount.is_native() ?
|
||||
new Value_XRP(multiplicandAmount._value, Amount.bi_xns_unit)
|
||||
: new Value_IOU(multiplicandAmount._value);
|
||||
const thisValue = new Value_IOU(this._value);
|
||||
return this._copy(new BigNumber(thisValue.multiply(multiplyBy)._value));
|
||||
const thisValue = new IOUValue(this._value);
|
||||
|
||||
let multiplyBy;
|
||||
|
||||
if (multiplicandAmount.is_native()) {
|
||||
multiplyBy = new XRPValue(multiplicandAmount._value, Amount.bi_xns_unit);
|
||||
return this._copy(thisValue.multiplyByXRP(multiplyBy)._value);
|
||||
}
|
||||
|
||||
multiplyBy = new IOUValue(multiplicandAmount._value);
|
||||
return this._copy(thisValue.multiply(multiplyBy));
|
||||
|
||||
};
|
||||
|
||||
@@ -172,20 +180,17 @@ Amount.prototype.scale = function(scaleFactor) {
|
||||
|
||||
Amount.prototype.divide = function(divisor) {
|
||||
const divisorAmount = Amount.from_json(divisor);
|
||||
if (!this.is_valid()) {
|
||||
throw new Error('Invalid dividend');
|
||||
const thisValue = new IOUValue(this._value);
|
||||
|
||||
let divideBy;
|
||||
|
||||
if (divisorAmount.is_native()) {
|
||||
divideBy = new XRPValue(divisorAmount._value, Amount.bi_xns_unit);
|
||||
return this._copy(thisValue.divideByXRP(divideBy)._value);
|
||||
}
|
||||
if (!divisorAmount.is_valid()) {
|
||||
throw new Error('Invalid divisor');
|
||||
}
|
||||
if (divisorAmount.is_zero()) {
|
||||
throw new Error('divide by zero');
|
||||
}
|
||||
const divideBy = divisorAmount.is_native() ?
|
||||
new Value_XRP(divisorAmount._value, Amount.bi_xns_unit)
|
||||
: new Value_IOU(divisorAmount._value);
|
||||
const thisValue = new Value_IOU(this._value);
|
||||
return this._copy(new BigNumber(thisValue.divide(divideBy)._value));
|
||||
|
||||
divideBy = new IOUValue(divisorAmount._value);
|
||||
return this._copy(thisValue.divide(divideBy));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -243,7 +248,7 @@ Amount.prototype.ratio_human = function(denom, opts) {
|
||||
//
|
||||
// To compensate, we multiply the numerator by 10^xns_precision.
|
||||
if (denominator._is_native) {
|
||||
numerator._set_value(numerator._value.times(Amount.bi_xns_unit));
|
||||
numerator._set_value(numerator.multiply(Amount.bi_xns_unit));
|
||||
}
|
||||
|
||||
return numerator.divide(denominator);
|
||||
@@ -270,8 +275,7 @@ 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(fac, opts) {
|
||||
const options = opts || {};
|
||||
Amount.prototype.product_human = function(fac, options = {}) {
|
||||
|
||||
let factor = Amount.from_json(fac);
|
||||
|
||||
@@ -295,7 +299,8 @@ Amount.prototype.product_human = function(fac, opts) {
|
||||
//
|
||||
// See also Amount#ratio_human.
|
||||
if (factor._is_native) {
|
||||
product._set_value(product._value.dividedBy(Amount.bi_xns_unit));
|
||||
const quotient = product.divide(Amount.bi_xns_unit.toString());
|
||||
product._set_value(quotient._value);
|
||||
}
|
||||
|
||||
return product;
|
||||
@@ -353,12 +358,15 @@ Amount.prototype.invert = function() {
|
||||
*/
|
||||
|
||||
Amount.prototype.canonicalize = function(roundingMode) {
|
||||
if (typeof this._value === 'undefined') {
|
||||
throw new Error('undefined value');
|
||||
}
|
||||
if (this._is_native) {
|
||||
this._value = this._value.round(6, BigNumber.ROUND_DOWN);
|
||||
this._value = this._value.round(6, Value.getBNRoundDown());
|
||||
} else if (roundingMode) {
|
||||
this._value = new BigNumber(this._value.toPrecision(16, roundingMode));
|
||||
this._value = new Value(this._value.toPrecision(16, roundingMode))._value;
|
||||
} else {
|
||||
this._value = new BigNumber(this._value.toPrecision(16));
|
||||
this._value = new Value(this._value.toPrecision(16))._value;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -540,12 +548,13 @@ Amount.prototype.parse_human = function(j, options) {
|
||||
currency = currency.toUpperCase();
|
||||
this.set_currency(currency);
|
||||
this._is_native = (currency === 'XRP');
|
||||
this._set_value(new BigNumber(value));
|
||||
this._set_value(new Value(value)._value);
|
||||
|
||||
// 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.dividedBy(interest.toString()));
|
||||
this._set_value(
|
||||
new IOUValue(this._value).divide(new Value(interest.toString())));
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -599,11 +608,11 @@ function(quality, counterCurrency, counterIssuer, opts) {
|
||||
const mantissa_hex = quality.substring(quality.length - 14);
|
||||
const offset_hex = quality.substring(
|
||||
quality.length - 16, quality.length - 14);
|
||||
const mantissa = new BigNumber(mantissa_hex, 16);
|
||||
const mantissa = new Value(mantissa_hex, 16)._value;
|
||||
const offset = parseInt(offset_hex, 16) - 100;
|
||||
|
||||
const value = new BigNumber(mantissa.toString() + 'e' + offset.toString());
|
||||
|
||||
const valueStr = mantissa.toString() + 'e' + offset.toString();
|
||||
const value = new Value(valueStr)._value;
|
||||
this._currency = Currency.from_json(counterCurrency);
|
||||
this._issuer = UInt160.from_json(counterIssuer);
|
||||
this._is_native = this._currency.is_native();
|
||||
@@ -626,7 +635,8 @@ function(quality, counterCurrency, counterIssuer, opts) {
|
||||
inverted : 3000000 drops / 5 USD
|
||||
*/
|
||||
const adjusted = options.inverse ? inverse(value) : value;
|
||||
let nativeAdjusted = adjusted;
|
||||
let nativeAdjusted = this._is_native ?
|
||||
new XRPValue(adjusted, Amount.bi_xns_unit) : new IOUValue(adjusted);
|
||||
|
||||
if (!options.xrp_as_drops) {
|
||||
// `In a currency exchange, the exchange rate is quoted as the units of the
|
||||
@@ -637,20 +647,20 @@ function(quality, counterCurrency, counterIssuer, opts) {
|
||||
if (this._is_native) {
|
||||
// pay:$price drops get:1 X
|
||||
// pay:($price / 1,000,000) XRP get:1 X
|
||||
nativeAdjusted = adjusted.div(Amount.bi_xns_unit);
|
||||
nativeAdjusted = nativeAdjusted.divide(new Value(Amount.bi_xns_unit));
|
||||
} else if (baseCurrency.is_valid() && baseCurrency.is_native()) {
|
||||
// pay:$price X get:1 drop
|
||||
// pay:($price * 1,000,000) X get:1 XRP
|
||||
nativeAdjusted = adjusted.times(Amount.bi_xns_unit);
|
||||
nativeAdjusted = nativeAdjusted.multiply(new Value(Amount.bi_xns_unit));
|
||||
}
|
||||
}
|
||||
|
||||
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.dividedBy(interest.toString()));
|
||||
this._set_value(
|
||||
new IOUValue(this._value).divide(new Value(interest.toString())));
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -660,7 +670,7 @@ Amount.prototype.parse_number = function(n) {
|
||||
this._is_native = false;
|
||||
this._currency = Currency.from_json(1);
|
||||
this._issuer = UInt160.from_json(1);
|
||||
this._set_value(new BigNumber(n));
|
||||
this._set_value(new Value(n)._value);
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -711,7 +721,7 @@ Amount.prototype.parse_json = function(j) {
|
||||
break;
|
||||
|
||||
default:
|
||||
this._set_value(new BigNumber(NaN));
|
||||
this._set_value(new Value(NaN)._value);
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -726,11 +736,11 @@ Amount.prototype.parse_native = function(j) {
|
||||
if (j.indexOf('.') >= 0) {
|
||||
throw new Error('Native amounts must be specified in integer drops');
|
||||
}
|
||||
const value = new BigNumber(j);
|
||||
const value = new XRPValue(j, Amount.bi_xns_unit);
|
||||
this._is_native = true;
|
||||
this._set_value(value.dividedBy(Amount.bi_xns_unit));
|
||||
this._set_value(value.divide(new Value(Amount.bi_xns_unit)));
|
||||
} else {
|
||||
this._set_value(new BigNumber(NaN));
|
||||
this._set_value(new Value(NaN)._value);
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -740,7 +750,7 @@ Amount.prototype.parse_native = function(j) {
|
||||
// Requires _currency to be set!
|
||||
Amount.prototype.parse_value = function(j) {
|
||||
this._is_native = false;
|
||||
this._set_value(new BigNumber(j), BigNumber.ROUND_DOWN);
|
||||
this._set_value(new Value(j)._value, Value.getBNRoundDown());
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -771,7 +781,8 @@ Amount.prototype.to_text = function() {
|
||||
}
|
||||
|
||||
if (this._is_native) {
|
||||
return this._value.times(Amount.bi_xns_unit).toString();
|
||||
return new XRPValue(this._value).multiply(
|
||||
new Value(Amount.bi_xns_unit))._value.toString();
|
||||
}
|
||||
|
||||
// not native
|
||||
@@ -813,7 +824,8 @@ Amount.prototype.applyInterest = function(referenceDate) {
|
||||
return this;
|
||||
}
|
||||
const interest = this._currency.get_interest_at(referenceDate);
|
||||
return this._copy(this._value.times(interest.toString()));
|
||||
return this._copy(
|
||||
new IOUValue(this._value).multiply(new Value(interest.toString())));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -992,7 +1004,7 @@ Amount.prototype.not_equals_why = function(d, ignore_issuer) {
|
||||
return 'Native mismatch.';
|
||||
}
|
||||
|
||||
let type = this._is_native ? 'XRP' : 'Non-XRP';
|
||||
const type = this._is_native ? 'XRP' : 'Non-XRP';
|
||||
if (!this._value.isZero() && this._value.negated().equals(d._value)) {
|
||||
return type + ' sign differs.';
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ const Currency = require('./currency').Currency;
|
||||
const AutobridgeCalculator = require('./autobridgecalculator');
|
||||
const OrderBookUtils = require('./orderbookutils');
|
||||
const log = require('./log').internal.sub('orderbook');
|
||||
const Value_IOU = require('./value_IOU').Value_IOU;
|
||||
const IOUValue = require('./IOUValue').IOUValue;
|
||||
|
||||
function assertValidNumber(number, message) {
|
||||
assert(!_.isNull(number) && !isNaN(number), message);
|
||||
@@ -449,9 +449,9 @@ OrderBook.prototype.applyTransferRate = function(balance) {
|
||||
assert(!isNaN(balance), 'Balance is invalid');
|
||||
assertValidNumber(this._issuerTransferRate, 'Transfer rate is invalid');
|
||||
|
||||
const adjustedBalance = (new Value_IOU(balance))
|
||||
.divide(new Value_IOU(this._issuerTransferRate))
|
||||
.multiply(new Value_IOU(OrderBook.DEFAULT_TRANSFER_RATE))
|
||||
const adjustedBalance = (new IOUValue(balance))
|
||||
.divide(new IOUValue(this._issuerTransferRate))
|
||||
.multiply(new IOUValue(OrderBook.DEFAULT_TRANSFER_RATE))
|
||||
._value.toString();
|
||||
|
||||
return adjustedBalance;
|
||||
|
||||
@@ -12,23 +12,48 @@ function assertValidNumber(number, message) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON amount object using
|
||||
* Creates a new Amount from a JSON amount object using
|
||||
* passed parameters for value, currency and counterparty
|
||||
* if currency or counterparty is undefined, defaults to IOU
|
||||
*
|
||||
* @param amount of value, currency, counterparty
|
||||
* @return JSON amount object
|
||||
*/
|
||||
|
||||
function createAmount(value, currency, counterparty) {
|
||||
if (currency === undefined || counterparty === undefined) {
|
||||
return {'value': value,
|
||||
'currency': '000',
|
||||
'issuer': 'rrrrrrrrrrrrrrrrrrrrrhoLvTp'};
|
||||
}
|
||||
return {'value': value, 'currency': currency, 'issuer': counterparty};
|
||||
const newJSON =
|
||||
{'value': value, 'currency': currency, 'issuer': counterparty};
|
||||
return Amount.from_json(newJSON);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets currency for getOfferTaker(Gets/Pays)Funded
|
||||
* @param offer
|
||||
* @return currency
|
||||
*/
|
||||
|
||||
function getCurrencyFromOffer(offer) {
|
||||
let currency = offer.TakerPays.currency;
|
||||
|
||||
if (!currency) {
|
||||
currency = offer.TakerGets.currency;
|
||||
}
|
||||
return currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets issuer for getOfferTaker(Gets/Pays)Funded
|
||||
* @param offer
|
||||
* @return issuer
|
||||
*/
|
||||
|
||||
function getIssuerFromOffer(offer) {
|
||||
let issuer = offer.TakerPays.issuer;
|
||||
|
||||
if (!issuer) {
|
||||
issuer = offer.TakerGets.issuer;
|
||||
}
|
||||
return issuer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts and returns offer's taker gets funded amount as a default IOU amount
|
||||
@@ -40,16 +65,10 @@ function createAmount(value, currency, counterparty) {
|
||||
OrderBookUtils.getOfferTakerGetsFunded = function(offer) {
|
||||
assertValidNumber(offer.taker_gets_funded, 'Taker gets funded is invalid');
|
||||
|
||||
let currency = offer.TakerPays.currency;
|
||||
let issuer = offer.TakerPays.issuer;
|
||||
const currency = getCurrencyFromOffer(offer);
|
||||
const issuer = getIssuerFromOffer(offer);
|
||||
|
||||
if (currency === undefined || issuer === undefined) {
|
||||
currency = offer.TakerGets.currency;
|
||||
issuer = offer.TakerGets.issuer;
|
||||
}
|
||||
|
||||
return Amount.from_json(
|
||||
createAmount(offer.taker_gets_funded, currency, issuer));
|
||||
return createAmount(offer.taker_gets_funded, currency, issuer);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -62,16 +81,10 @@ OrderBookUtils.getOfferTakerGetsFunded = function(offer) {
|
||||
OrderBookUtils.getOfferTakerPaysFunded = function(offer) {
|
||||
assertValidNumber(offer.taker_pays_funded, 'Taker gets funded is invalid');
|
||||
|
||||
let currency = offer.TakerGets.currency;
|
||||
let issuer = offer.TakerGets.issuer;
|
||||
const currency = getCurrencyFromOffer(offer);
|
||||
const issuer = getIssuerFromOffer(offer);
|
||||
|
||||
if (currency === undefined || issuer === undefined) {
|
||||
currency = offer.TakerPays.currency;
|
||||
issuer = offer.TakerPays.issuer;
|
||||
}
|
||||
|
||||
return Amount.from_json(
|
||||
createAmount(offer.taker_pays_funded, currency, issuer));
|
||||
return createAmount(offer.taker_pays_funded, currency, issuer);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -85,10 +98,10 @@ OrderBookUtils.getOfferTakerPaysFunded = function(offer) {
|
||||
OrderBookUtils.getOfferTakerGets = function(offer) {
|
||||
assert(typeof offer, 'object', 'Offer is invalid');
|
||||
|
||||
let currency = offer.TakerPays.currency;
|
||||
let issuer = offer.TakerPays.issuer;
|
||||
const currency = offer.TakerPays.currency;
|
||||
const issuer = offer.TakerPays.issuer;
|
||||
|
||||
return Amount.from_json(createAmount(offer.TakerGets, currency, issuer));
|
||||
return createAmount(offer.TakerGets, currency, issuer);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -110,15 +123,10 @@ OrderBookUtils.getOfferQuality = function(offer, currencyGets) {
|
||||
});
|
||||
} else {
|
||||
|
||||
let currency = offer.TakerGets.currency;
|
||||
let issuer = offer.TakerGets.issuer;
|
||||
const currency = getCurrencyFromOffer(offer);
|
||||
const issuer = getIssuerFromOffer(offer);
|
||||
|
||||
if (currency === undefined || issuer === undefined) {
|
||||
currency = offer.TakerPays.currency;
|
||||
issuer = offer.TakerPays.issuer;
|
||||
}
|
||||
|
||||
amount = Amount.from_json(createAmount(offer.quality, currency, issuer));
|
||||
amount = createAmount(offer.quality, currency, issuer);
|
||||
}
|
||||
|
||||
return amount;
|
||||
@@ -136,7 +144,7 @@ OrderBookUtils.getOfferQuality = function(offer, currencyGets) {
|
||||
OrderBookUtils.convertOfferQualityToHex = function(quality) {
|
||||
assert(quality instanceof Amount, 'Quality is not an amount');
|
||||
|
||||
let so = new SerializedObject();
|
||||
const so = new SerializedObject();
|
||||
Types.Quality.serialize(so, quality.to_text());
|
||||
|
||||
return so.to_hex();
|
||||
@@ -148,7 +156,7 @@ OrderBookUtils.convertOfferQualityToHex = function(quality) {
|
||||
|
||||
OrderBookUtils.normalizeAmount = function(value) {
|
||||
|
||||
return Amount.from_json(createAmount(value));
|
||||
return Amount.from_number(value);
|
||||
};
|
||||
|
||||
module.exports = OrderBookUtils;
|
||||
|
||||
@@ -45,7 +45,7 @@ function isHexInt64String(val) {
|
||||
}
|
||||
|
||||
function serializeBits(so, bits, noLength) {
|
||||
let byteData = sjcl.codec.bytes.fromBits(bits);
|
||||
const byteData = sjcl.codec.bytes.fromBits(bits);
|
||||
if (!noLength) {
|
||||
SerializedType.serialize_varint(so, byteData.length);
|
||||
}
|
||||
@@ -68,18 +68,18 @@ function convertByteArrayToHex(byte_array) {
|
||||
}
|
||||
|
||||
function convertHexToString(hexString) {
|
||||
let bits = sjcl.codec.hex.toBits(hexString);
|
||||
const bits = sjcl.codec.hex.toBits(hexString);
|
||||
return sjcl.codec.utf8String.fromBits(bits);
|
||||
}
|
||||
|
||||
function sort_fields(keys) {
|
||||
function sort_field_compare(a, b) {
|
||||
let a_field_coordinates = binformat.fieldsInverseMap[a];
|
||||
let a_type_bits = a_field_coordinates[0];
|
||||
let a_field_bits = a_field_coordinates[1];
|
||||
let b_field_coordinates = binformat.fieldsInverseMap[b];
|
||||
let b_type_bits = b_field_coordinates[0];
|
||||
let b_field_bits = b_field_coordinates[1];
|
||||
const a_field_coordinates = binformat.fieldsInverseMap[a];
|
||||
const a_type_bits = a_field_coordinates[0];
|
||||
const a_field_bits = a_field_coordinates[1];
|
||||
const b_field_coordinates = binformat.fieldsInverseMap[b];
|
||||
const b_type_bits = b_field_coordinates[0];
|
||||
const b_field_bits = b_field_coordinates[1];
|
||||
|
||||
// Sort by type id first, then by field id
|
||||
return a_type_bits !== b_type_bits
|
||||
@@ -110,7 +110,8 @@ SerializedType.serialize_varint = function(so, val) {
|
||||
};
|
||||
|
||||
SerializedType.prototype.parse_varint = function(so) {
|
||||
let b1 = so.read(1)[0], b2, b3;
|
||||
const b1 = so.read(1)[0];
|
||||
let b2, b3;
|
||||
let result;
|
||||
|
||||
if (b1 > 254) {
|
||||
@@ -153,7 +154,7 @@ function convertIntegerToByteArray(val, bytes) {
|
||||
throw new Error('Value out of bounds ');
|
||||
}
|
||||
|
||||
let newBytes = [ ];
|
||||
const newBytes = [ ];
|
||||
|
||||
for (let i = 0; i < bytes; i++) {
|
||||
newBytes.unshift(val >>> (i * 8) & 0xff);
|
||||
@@ -172,7 +173,7 @@ function readAndSum(so, bytes) {
|
||||
}
|
||||
|
||||
for (let i = 0; i < bytes; i++) {
|
||||
let byte = so.read(1)[0];
|
||||
const byte = so.read(1)[0];
|
||||
sum += (byte << (8 * (bytes - i - 1)));
|
||||
}
|
||||
|
||||
@@ -195,10 +196,10 @@ function serialize(so, field_name, value) {
|
||||
// so: a byte-stream to serialize into.
|
||||
// field_name: a string for the field name ('LedgerEntryType' etc.)
|
||||
// value: the value of that field.
|
||||
let field_coordinates = binformat.fieldsInverseMap[field_name];
|
||||
let type_bits = field_coordinates[0];
|
||||
let field_bits = field_coordinates[1];
|
||||
let tag_byte = (type_bits < 16
|
||||
const field_coordinates = binformat.fieldsInverseMap[field_name];
|
||||
const type_bits = field_coordinates[0];
|
||||
const field_bits = field_coordinates[1];
|
||||
const tag_byte = (type_bits < 16
|
||||
? type_bits << 4
|
||||
: 0) | (field_bits < 16
|
||||
? field_bits
|
||||
@@ -248,14 +249,14 @@ exports.serialize = exports.serialize_whatever = serialize;
|
||||
// parsing of that.
|
||||
|
||||
function parse(so) {
|
||||
let tag_byte = so.read(1)[0];
|
||||
const tag_byte = so.read(1)[0];
|
||||
let type_bits = tag_byte >> 4;
|
||||
|
||||
if (type_bits === 0) {
|
||||
type_bits = so.read(1)[0];
|
||||
}
|
||||
|
||||
let field_bits = tag_byte & 0x0f;
|
||||
const field_bits = tag_byte & 0x0f;
|
||||
let field_name = (field_bits === 0)
|
||||
? field_name = binformat.fields[type_bits][so.read(1)[0]]
|
||||
: field_name = binformat.fields[type_bits][field_bits];
|
||||
@@ -264,7 +265,7 @@ function parse(so) {
|
||||
+ tag_byte.toString(16));
|
||||
|
||||
// Get the parser class (ST...) for a field based on the type bits.
|
||||
let type = (field_name === 'Memo')
|
||||
const type = (field_name === 'Memo')
|
||||
? exports.STMemo
|
||||
: exports[binformat.types[type_bits]];
|
||||
|
||||
@@ -324,7 +325,7 @@ const STInt64 = exports.Int64 = new SerializedType({
|
||||
serializeBits(so, bigNumObject.toBits(64), true); // noLength = true
|
||||
},
|
||||
parse: function(so) {
|
||||
let bytes = so.read(8);
|
||||
const bytes = so.read(8);
|
||||
return SJCL_BN.fromBits(sjcl.codec.bytes.toBits(bytes));
|
||||
}
|
||||
});
|
||||
@@ -333,7 +334,7 @@ STInt64.id = 3;
|
||||
|
||||
const STHash128 = exports.Hash128 = new SerializedType({
|
||||
serialize: function(so, val) {
|
||||
let hash = UInt128.from_json(val);
|
||||
const hash = UInt128.from_json(val);
|
||||
if (!hash.is_valid()) {
|
||||
throw new Error('Invalid Hash128');
|
||||
}
|
||||
@@ -348,7 +349,7 @@ STHash128.id = 4;
|
||||
|
||||
const STHash256 = exports.Hash256 = new SerializedType({
|
||||
serialize: function(so, val) {
|
||||
let hash = UInt256.from_json(val);
|
||||
const hash = UInt256.from_json(val);
|
||||
if (!hash.is_valid()) {
|
||||
throw new Error('Invalid Hash256');
|
||||
}
|
||||
@@ -363,7 +364,7 @@ STHash256.id = 5;
|
||||
|
||||
const STHash160 = exports.Hash160 = new SerializedType({
|
||||
serialize: function(so, val) {
|
||||
let hash = UInt160.from_json(val);
|
||||
const hash = UInt160.from_json(val);
|
||||
if (!hash.is_valid()) {
|
||||
throw new Error('Invalid Hash160');
|
||||
}
|
||||
@@ -379,7 +380,7 @@ STHash160.id = 17;
|
||||
// Internal
|
||||
const STCurrency = new SerializedType({
|
||||
serialize: function(so, val) {
|
||||
let currencyData = val.to_bytes();
|
||||
const currencyData = val.to_bytes();
|
||||
|
||||
if (!currencyData) {
|
||||
throw new Error(
|
||||
@@ -389,8 +390,8 @@ const STCurrency = new SerializedType({
|
||||
so.append(currencyData);
|
||||
},
|
||||
parse: function(so) {
|
||||
let bytes = so.read(20);
|
||||
let currency = Currency.from_bytes(bytes);
|
||||
const bytes = so.read(20);
|
||||
const currency = Currency.from_bytes(bytes);
|
||||
// XXX Disabled check. Theoretically, the Currency class should support any
|
||||
// UInt160 value and consider it valid. But it doesn't, so for the
|
||||
// deserialization to be usable, we need to allow invalid results for
|
||||
@@ -414,7 +415,7 @@ exports.Quality = new SerializedType({
|
||||
let value;
|
||||
// if in format: amount/currency/issuer
|
||||
if (val.includes('/')) {
|
||||
let amount = Amount.from_json(val);
|
||||
const amount = Amount.from_json(val);
|
||||
|
||||
if (!amount.is_valid()) {
|
||||
throw new Error('Not a valid Amount object.');
|
||||
@@ -426,14 +427,14 @@ exports.Quality = new SerializedType({
|
||||
|
||||
let hi = 0, lo = 0;
|
||||
|
||||
let offset = value.e - 15;
|
||||
const offset = value.e - 15;
|
||||
if (val !== 0) {
|
||||
// First eight bits: offset/exponent
|
||||
hi |= ((100 + offset) & 0xff) << 24;
|
||||
|
||||
// Remaining 56 bits: mantissa
|
||||
let mantissaDecimal = utils.getMantissaDecimalString(value.abs());
|
||||
let mantissaHex = (new BigNumber(mantissaDecimal)).toString(16);
|
||||
const mantissaDecimal = utils.getMantissaDecimalString(value.abs());
|
||||
const mantissaHex = (new BigNumber(mantissaDecimal)).toString(16);
|
||||
assert(mantissaHex.length <= 16,
|
||||
'Mantissa hex representation ' + mantissaHex +
|
||||
' exceeds the maximum length of 16');
|
||||
@@ -453,14 +454,14 @@ exports.Quality = new SerializedType({
|
||||
*/
|
||||
const STAmount = exports.Amount = new SerializedType({
|
||||
serialize: function(so, val) {
|
||||
let amount = Amount.from_json(val);
|
||||
const amount = Amount.from_json(val);
|
||||
|
||||
if (!amount.is_valid()) {
|
||||
throw new Error('Not a valid Amount object.');
|
||||
}
|
||||
|
||||
let value = new BigNumber(amount.to_text());
|
||||
let offset = value.e - 15;
|
||||
const value = new BigNumber(amount.to_text());
|
||||
const offset = value.e - 15;
|
||||
|
||||
// Amount (64-bit integer)
|
||||
let valueBytes = utils.arraySet(8, 0);
|
||||
@@ -506,8 +507,8 @@ const STAmount = exports.Amount = new SerializedType({
|
||||
hi |= ((97 + offset) & 0xff) << 22;
|
||||
|
||||
// Remaining 54 bits: mantissa
|
||||
let mantissaDecimal = utils.getMantissaDecimalString(value.abs());
|
||||
let mantissaHex = (new BigNumber(mantissaDecimal)).toString(16);
|
||||
const mantissaDecimal = utils.getMantissaDecimalString(value.abs());
|
||||
const mantissaHex = (new BigNumber(mantissaDecimal)).toString(16);
|
||||
assert(mantissaHex.length <= 16,
|
||||
'Mantissa hex representation ' + mantissaHex +
|
||||
' exceeds the maximum length of 16');
|
||||
@@ -522,7 +523,7 @@ const STAmount = exports.Amount = new SerializedType({
|
||||
|
||||
if (!amount.is_native()) {
|
||||
// Currency (160-bit hash)
|
||||
let currency = amount.currency();
|
||||
const currency = amount.currency();
|
||||
STCurrency.serialize(so, currency, true);
|
||||
|
||||
// Issuer (160-bit hash)
|
||||
@@ -530,27 +531,28 @@ const STAmount = exports.Amount = new SerializedType({
|
||||
}
|
||||
},
|
||||
parse: function(so) {
|
||||
let value_bytes = so.read(8);
|
||||
const value_bytes = so.read(8);
|
||||
let is_zero = !(value_bytes[0] & 0x7f);
|
||||
|
||||
for (let i = 1; i < 8; i++) {
|
||||
is_zero = is_zero && !value_bytes[i];
|
||||
}
|
||||
|
||||
let is_negative = !is_zero && !(value_bytes[0] & 0x40);
|
||||
const is_negative = !is_zero && !(value_bytes[0] & 0x40);
|
||||
|
||||
if (value_bytes[0] & 0x80) {
|
||||
// non-native
|
||||
let currency = STCurrency.parse(so);
|
||||
let issuer_bytes = so.read(20);
|
||||
let issuer = UInt160.from_bytes(issuer_bytes);
|
||||
const currency = STCurrency.parse(so);
|
||||
const issuer_bytes = so.read(20);
|
||||
const issuer = UInt160.from_bytes(issuer_bytes);
|
||||
issuer.set_version(Base.VER_ACCOUNT_ID);
|
||||
let offset = ((value_bytes[0] & 0x3f) << 2) + (value_bytes[1] >>> 6) - 97;
|
||||
let mantissa_bytes = value_bytes.slice(1);
|
||||
const offset =
|
||||
((value_bytes[0] & 0x3f) << 2) + (value_bytes[1] >>> 6) - 97;
|
||||
const mantissa_bytes = value_bytes.slice(1);
|
||||
mantissa_bytes[0] &= 0x3f;
|
||||
let mantissa = new BigNumber(utils.arrayToHex(mantissa_bytes), 16);
|
||||
let sign = is_negative ? '-' : '';
|
||||
let valueString = sign + mantissa.toString() + 'e' + offset.toString();
|
||||
const mantissa = new BigNumber(utils.arrayToHex(mantissa_bytes), 16);
|
||||
const sign = is_negative ? '-' : '';
|
||||
const valueString = sign + mantissa.toString() + 'e' + offset.toString();
|
||||
|
||||
return Amount.from_json({
|
||||
currency: currency,
|
||||
@@ -560,10 +562,10 @@ const STAmount = exports.Amount = new SerializedType({
|
||||
}
|
||||
|
||||
// native
|
||||
let integer_bytes = value_bytes.slice();
|
||||
const integer_bytes = value_bytes.slice();
|
||||
integer_bytes[0] &= 0x3f;
|
||||
let integer_hex = utils.arrayToHex(integer_bytes);
|
||||
let value = new BigNumber(integer_hex, 16);
|
||||
const integer_hex = utils.arrayToHex(integer_bytes);
|
||||
const value = new BigNumber(integer_hex, 16);
|
||||
return Amount.from_json((is_negative ? '-' : '') + value.toString());
|
||||
}
|
||||
});
|
||||
@@ -579,7 +581,7 @@ const STVL = exports.VariableLength = exports.VL = new SerializedType({
|
||||
}
|
||||
},
|
||||
parse: function(so) {
|
||||
let len = this.parse_varint(so);
|
||||
const len = this.parse_varint(so);
|
||||
return convertByteArrayToHex(so.read(len));
|
||||
}
|
||||
});
|
||||
@@ -588,20 +590,20 @@ STVL.id = 7;
|
||||
|
||||
const STAccount = exports.Account = new SerializedType({
|
||||
serialize: function(so, val) {
|
||||
let account = UInt160.from_json(val);
|
||||
const account = UInt160.from_json(val);
|
||||
if (!account.is_valid()) {
|
||||
throw new Error('Invalid account!');
|
||||
}
|
||||
serializeBits(so, account.to_bits());
|
||||
},
|
||||
parse: function(so) {
|
||||
let len = this.parse_varint(so);
|
||||
const len = this.parse_varint(so);
|
||||
|
||||
if (len !== 20) {
|
||||
throw new Error('Non-standard-length account ID');
|
||||
}
|
||||
|
||||
let result = UInt160.from_bytes(so.read(len));
|
||||
const result = UInt160.from_bytes(so.read(len));
|
||||
result.set_version(Base.VER_ACCOUNT_ID);
|
||||
|
||||
if (false && !result.is_valid()) {
|
||||
@@ -628,7 +630,7 @@ const STPathSet = exports.PathSet = new SerializedType({
|
||||
}
|
||||
|
||||
for (let j = 0, l2 = val[i].length; j < l2; j++) {
|
||||
let entry = val[i][j];
|
||||
const entry = val[i][j];
|
||||
// if (entry.hasOwnProperty('_value')) {entry = entry._value;}
|
||||
let type = 0;
|
||||
|
||||
@@ -649,7 +651,7 @@ const STPathSet = exports.PathSet = new SerializedType({
|
||||
}
|
||||
|
||||
if (entry.currency) {
|
||||
let currency = Currency.from_json(entry.currency, entry.non_native);
|
||||
const currency = Currency.from_json(entry.currency, entry.non_native);
|
||||
STCurrency.serialize(so, currency);
|
||||
}
|
||||
|
||||
@@ -675,7 +677,7 @@ const STPathSet = exports.PathSet = new SerializedType({
|
||||
amount, currency, issuer.
|
||||
*/
|
||||
|
||||
let path_list = [];
|
||||
const path_list = [];
|
||||
let current_path = [];
|
||||
let tag_byte;
|
||||
|
||||
@@ -695,7 +697,7 @@ const STPathSet = exports.PathSet = new SerializedType({
|
||||
}
|
||||
|
||||
// It's an entry-begin tag.
|
||||
let entry = {};
|
||||
const entry = {};
|
||||
let type = 0;
|
||||
|
||||
if (tag_byte & this.typeAccount) {
|
||||
@@ -747,8 +749,8 @@ const STVector256 = exports.Vector256 = new SerializedType({
|
||||
}
|
||||
},
|
||||
parse: function(so) {
|
||||
let length = this.parse_varint(so);
|
||||
let output = [];
|
||||
const length = this.parse_varint(so);
|
||||
const output = [];
|
||||
// length is number of bytes not number of Hash256
|
||||
for (let i = 0; i < length / 32; i++) {
|
||||
output.push(STHash256.parse(so));
|
||||
@@ -791,16 +793,16 @@ exports.STMemo = new SerializedType({
|
||||
}
|
||||
},
|
||||
parse: function(so) {
|
||||
let output = {};
|
||||
const output = {};
|
||||
|
||||
while (so.peek(1)[0] !== 0xe1) {
|
||||
let keyval = parse(so);
|
||||
const keyval = parse(so);
|
||||
output[keyval[0]] = keyval[1];
|
||||
}
|
||||
|
||||
if (output.MemoType !== undefined) {
|
||||
try {
|
||||
let parsedType = convertHexToString(output.MemoType);
|
||||
const parsedType = convertHexToString(output.MemoType);
|
||||
|
||||
if (parsedType !== 'unformatted_memo') {
|
||||
output.parsed_memo_type = parsedType;
|
||||
@@ -889,9 +891,9 @@ const STObject = exports.Object = new SerializedType({
|
||||
},
|
||||
|
||||
parse: function(so) {
|
||||
let output = {};
|
||||
const output = {};
|
||||
while (so.peek(1)[0] !== 0xe1) {
|
||||
let keyval = parse(so);
|
||||
const keyval = parse(so);
|
||||
output[keyval[0]] = keyval[1];
|
||||
}
|
||||
so.read(1);
|
||||
@@ -904,15 +906,15 @@ STObject.id = 14;
|
||||
const STArray = exports.Array = new SerializedType({
|
||||
serialize: function(so, val) {
|
||||
for (let i = 0, l = val.length; i < l; i++) {
|
||||
let keys = Object.keys(val[i]);
|
||||
const keys = Object.keys(val[i]);
|
||||
|
||||
if (keys.length !== 1) {
|
||||
throw new Error(
|
||||
'Cannot serialize an array containing non-single-key objects');
|
||||
}
|
||||
|
||||
let field_name = keys[0];
|
||||
let value = val[i][field_name];
|
||||
const field_name = keys[0];
|
||||
const value = val[i][field_name];
|
||||
serialize(so, field_name, value);
|
||||
}
|
||||
|
||||
@@ -921,11 +923,11 @@ const STArray = exports.Array = new SerializedType({
|
||||
},
|
||||
|
||||
parse: function(so) {
|
||||
let output = [ ];
|
||||
const output = [ ];
|
||||
|
||||
while (so.peek(1)[0] !== 0xf1) {
|
||||
let keyval = parse(so);
|
||||
let obj = { };
|
||||
const keyval = parse(so);
|
||||
const obj = { };
|
||||
obj[keyval[0]] = keyval[1];
|
||||
output.push(obj);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
'use strict';
|
||||
|
||||
const GlobalBigNumber = require('bignumber.js');
|
||||
@@ -7,49 +9,79 @@ const BigNumber = GlobalBigNumber.another({
|
||||
DECIMAL_PLACES: 40
|
||||
});
|
||||
|
||||
function Value(value) {
|
||||
this._value = new BigNumber(value);
|
||||
class Value {
|
||||
|
||||
constructor(value: string | BigNumber, base: number) {
|
||||
this._value = new BigNumber(value, base);
|
||||
}
|
||||
|
||||
static getBNRoundDown() {
|
||||
return BigNumber.ROUND_DOWN;
|
||||
}
|
||||
|
||||
abs() {
|
||||
const result = this._value.abs();
|
||||
return this._canonicalize(result);
|
||||
}
|
||||
|
||||
add(addend: Value) {
|
||||
const result = this._value.plus(addend._value);
|
||||
return this._canonicalize(result);
|
||||
}
|
||||
|
||||
subtract(subtrahend: Value) {
|
||||
const result = this._value.minus(subtrahend._value);
|
||||
return this._canonicalize(result);
|
||||
}
|
||||
|
||||
multiply(multiplicand: Value) {
|
||||
const val = this._value;
|
||||
const mult = multiplicand._value;
|
||||
const result = (val).times(mult);
|
||||
return this._canonicalize(result);
|
||||
}
|
||||
|
||||
scale(scaleFactor: Value) {
|
||||
const result = this._value.times(scaleFactor._value);
|
||||
return this._canonicalize(result);
|
||||
|
||||
}
|
||||
|
||||
divide(divisor: Value) {
|
||||
if (this._value.isNaN()) {
|
||||
throw new Error('Invalid dividend');
|
||||
}
|
||||
if (divisor.isNaN()) {
|
||||
throw new Error('Invalid divisor');
|
||||
}
|
||||
if (divisor.isZero()) {
|
||||
throw new Error('divide by zero');
|
||||
}
|
||||
const result = this._value.dividedBy(divisor._value);
|
||||
return this._canonicalize(result);
|
||||
}
|
||||
|
||||
invert() {
|
||||
const result = (new BigNumber(this._value)).toPower(-1);
|
||||
return this._canonicalize(result);
|
||||
}
|
||||
|
||||
isNaN() {
|
||||
return this._value.isNaN();
|
||||
}
|
||||
|
||||
isZero() {
|
||||
return this._value.isZero();
|
||||
}
|
||||
|
||||
isNegative() {
|
||||
return this._value.isNegative();
|
||||
}
|
||||
|
||||
negated() {
|
||||
return this._value.neg();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Value.prototype.abs = function() {
|
||||
let result = this._value.abs();
|
||||
return this._canonicalize(result);
|
||||
};
|
||||
|
||||
Value.prototype.add = function(addend) {
|
||||
let result = this._value.plus(addend._value);
|
||||
return this._canonicalize(result);
|
||||
};
|
||||
|
||||
Value.prototype.subtract = function(subtrahend) {
|
||||
let result = this._value.minus(subtrahend._value);
|
||||
return this._canonicalize(result);
|
||||
};
|
||||
|
||||
Value.prototype.multiply = function(multiplicand) {
|
||||
let val = this._value;
|
||||
let mult = multiplicand._value;
|
||||
let result = (val).times(mult);
|
||||
return this._canonicalize(result);
|
||||
};
|
||||
|
||||
Value.prototype.scale = function(scaleFactor) {
|
||||
let result = this._value.times(scaleFactor._value);
|
||||
return this._canonicalize(result);
|
||||
|
||||
};
|
||||
|
||||
Value.prototype.divide = function(divisor) {
|
||||
if (divisor === 0) {
|
||||
throw new Error('Divide by zero');
|
||||
}
|
||||
let result = this._value.dividedBy(divisor._value);
|
||||
return this._canonicalize(result);
|
||||
};
|
||||
|
||||
Value.prototype.invert = function() {
|
||||
let result = (new BigNumber(this._value)).toPower(-1);
|
||||
return this._canonicalize(result);
|
||||
};
|
||||
|
||||
exports.Value = Value;
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const Value = require('./value').Value;
|
||||
const GlobalBigNumber = require('bignumber.js');
|
||||
const BigNumber = GlobalBigNumber.another({
|
||||
ROUNDING_MODE: GlobalBigNumber.ROUND_HALF_UP,
|
||||
DECIMAL_PLACES: 40
|
||||
});
|
||||
|
||||
function Value_IOU(value) {
|
||||
Value.call(this, value);
|
||||
}
|
||||
|
||||
Value_IOU.prototype = Object.create(Value.prototype);
|
||||
|
||||
Value_IOU.prototype.constructor = Value_IOU;
|
||||
|
||||
Value_IOU.fromXRPValue = function(XRPvalue, bi_xns_unit) {
|
||||
const newV = new Value_IOU(XRPvalue);
|
||||
newV._XRP = true;
|
||||
newV._bi_xns_unit = bi_xns_unit;
|
||||
return newV;
|
||||
};
|
||||
|
||||
Value_IOU.prototype.multiply = function(multiplicand) {
|
||||
let mult = multiplicand;
|
||||
if (mult._XRP) {
|
||||
let constant = new BigNumber((mult._bi_xns_unit).toString());
|
||||
let value = new BigNumber(mult._value);
|
||||
mult._value = (value).times(constant);
|
||||
}
|
||||
return Value.prototype.multiply.call(this, mult);
|
||||
};
|
||||
|
||||
Value_IOU.prototype.divide = function(divisor) {
|
||||
let div = divisor;
|
||||
if (div._XRP) {
|
||||
let constant = new BigNumber((div._bi_xns_unit).toString());
|
||||
let value = new BigNumber(div._value);
|
||||
div._value = (value).times(constant);
|
||||
}
|
||||
return Value.prototype.divide.call(this, div);
|
||||
};
|
||||
|
||||
Value_IOU.prototype._canonicalize = function(value) {
|
||||
return new Value_IOU(value.toPrecision(16));
|
||||
};
|
||||
|
||||
Value_IOU.prototype.equals = function(comparator) {
|
||||
return (comparator instanceof Value_IOU)
|
||||
&& this._value.equals(comparator.value);
|
||||
};
|
||||
|
||||
exports.Value_IOU = Value_IOU;
|
||||
@@ -1,30 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const GlobalBigNumber = require('bignumber.js');
|
||||
const BigNumber = GlobalBigNumber.another({
|
||||
ROUNDING_MODE: GlobalBigNumber.ROUND_HALF_UP,
|
||||
DECIMAL_PLACES: 40
|
||||
});
|
||||
|
||||
const Value = require('./value').Value;
|
||||
|
||||
function Value_XRP(value, bi_xns_unit) {
|
||||
Value.call(this, value);
|
||||
this._bi_xns_unit = bi_xns_unit;
|
||||
this._XRP = true;
|
||||
}
|
||||
|
||||
Value_XRP.prototype = Object.create(Value.prototype);
|
||||
|
||||
Value_XRP.prototype.constructor = Value_XRP;
|
||||
|
||||
Value_XRP.prototype._canonicalize = function(value) {
|
||||
return new Value_XRP(value.round(6, BigNumber.ROUND_DOWN));
|
||||
};
|
||||
|
||||
Value_XRP.prototype.equals = function(comparator) {
|
||||
return (comparator instanceof Value_XRP)
|
||||
&& this._value.equals(comparator.value);
|
||||
};
|
||||
|
||||
exports.Value_XRP = Value_XRP;
|
||||
Reference in New Issue
Block a user