mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 04:05:52 +00:00
[TASK] Refactor to use bignumber.js
This commit is contained in:
5
npm-shrinkwrap.json
generated
5
npm-shrinkwrap.json
generated
@@ -7,6 +7,11 @@
|
||||
"from": "async@>=0.8.0 <0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.8.0.tgz"
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "2.0.0",
|
||||
"from": "bignumber.js@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.0.0.tgz"
|
||||
},
|
||||
"extend": {
|
||||
"version": "1.2.1",
|
||||
"from": "extend@>=1.2.1 <1.3.0",
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "~0.8.0",
|
||||
"bignumber.js": "^2.0.0",
|
||||
"extend": "~1.2.1",
|
||||
"lodash": "^2.4.1",
|
||||
"lru-cache": "~2.5.0",
|
||||
|
||||
1210
src/js/jsbn/jsbn.js
1210
src/js/jsbn/jsbn.js
File diff suppressed because it is too large
Load Diff
@@ -1,53 +1,45 @@
|
||||
// Represent Ripple amounts and currencies.
|
||||
// - Numbers in hex are big-endian.
|
||||
|
||||
var assert = require('assert');
|
||||
var extend = require('extend');
|
||||
var utils = require('./utils');
|
||||
var sjcl = utils.sjcl;
|
||||
var bn = sjcl.bn;
|
||||
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
var Seed = require('./seed').Seed;
|
||||
var Currency = require('./currency').Currency;
|
||||
|
||||
//
|
||||
// Amount class in the style of Java's BigInteger class
|
||||
// http://docs.oracle.com/javase/1.3/docs/api/java/math/BigInteger.html
|
||||
//
|
||||
var BigNumber = require('./bignumber');
|
||||
|
||||
function Amount() {
|
||||
// Json format:
|
||||
// integer : XRP
|
||||
// { 'value' : ..., 'currency' : ..., 'issuer' : ...}
|
||||
|
||||
this._value = new BigInteger(); // NaN for bad value. Always positive.
|
||||
this._offset = 0; // Always 0 for XRP.
|
||||
this._value = new BigNumber(NaN);
|
||||
this._is_native = true; // Default to XRP. Only valid if value is not NaN.
|
||||
this._is_negative = false;
|
||||
this._currency = new Currency();
|
||||
this._issuer = new UInt160();
|
||||
};
|
||||
}
|
||||
|
||||
var consts = {
|
||||
currency_xns: 0,
|
||||
currency_one: 1,
|
||||
xns_precision: 6,
|
||||
|
||||
// BigInteger values prefixed with bi_.
|
||||
bi_5: new BigInteger('5'),
|
||||
bi_7: new BigInteger('7'),
|
||||
bi_10: new BigInteger('10'),
|
||||
bi_1e14: new BigInteger(String(1e14)),
|
||||
bi_1e16: new BigInteger(String(1e16)),
|
||||
bi_1e17: new BigInteger(String(1e17)),
|
||||
bi_1e32: new BigInteger('100000000000000000000000000000000'),
|
||||
bi_man_max_value: new BigInteger('9999999999999999'),
|
||||
bi_man_min_value: new BigInteger('1000000000000000'),
|
||||
bi_xns_max: new BigInteger('9000000000000000000'), // Json wire limit.
|
||||
bi_xns_min: new BigInteger('-9000000000000000000'),// Json wire limit.
|
||||
bi_xns_unit: new BigInteger('1000000'),
|
||||
// bi_ prefix refers to "big integer"
|
||||
bi_5: new BigNumber('5'),
|
||||
bi_7: new BigNumber('7'),
|
||||
bi_10: new BigNumber('10'),
|
||||
bi_1e14: new BigNumber(String(1e14)),
|
||||
bi_1e16: new BigNumber(String(1e16)),
|
||||
bi_1e17: new BigNumber(String(1e17)),
|
||||
bi_1e32: new BigNumber('100000000000000000000000000000000'),
|
||||
bi_man_max_value: new BigNumber('9999999999999999'),
|
||||
bi_man_min_value: new BigNumber('1000000000000000'),
|
||||
bi_xns_max: new BigNumber('9000000000000000000'), // Json wire limit.
|
||||
bi_xns_min: new BigNumber('-9000000000000000000'),// Json wire limit.
|
||||
bi_xrp_max: new BigNumber('9000000000000'),
|
||||
bi_xrp_min: new BigNumber('-9000000000000'),
|
||||
bi_xns_unit: new BigNumber('1000000'),
|
||||
|
||||
cMinOffset: -96,
|
||||
cMaxOffset: 80,
|
||||
@@ -101,8 +93,16 @@ Amount.is_valid_full = function(j) {
|
||||
|
||||
Amount.NaN = function() {
|
||||
var result = new Amount();
|
||||
result._value = NaN;
|
||||
return result;
|
||||
result._value = new BigNumber(NaN); // 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;
|
||||
this.canonicalize(roundingMode);
|
||||
this._check_limits();
|
||||
};
|
||||
|
||||
// Returns a new value which is the absolute value of this.
|
||||
@@ -110,170 +110,47 @@ Amount.prototype.abs = function() {
|
||||
return this.clone(this.is_negative());
|
||||
};
|
||||
|
||||
// Result in terms of this' currency and issuer.
|
||||
Amount.prototype.add = function(v) {
|
||||
var result;
|
||||
Amount.prototype.add = function(addend) {
|
||||
var addendAmount = Amount.from_json(addend);
|
||||
|
||||
v = Amount.from_json(v);
|
||||
|
||||
if (!this.is_comparable(v)) {
|
||||
result = Amount.NaN();
|
||||
} else if (v.is_zero()) {
|
||||
result = this;
|
||||
} else if (this.is_zero()) {
|
||||
result = v.clone();
|
||||
result._is_native = this._is_native;
|
||||
result._currency = this._currency;
|
||||
result._issuer = this._issuer;
|
||||
} else if (this._is_native) {
|
||||
result = new Amount();
|
||||
|
||||
var v1 = this._is_negative ? this._value.negate() : this._value;
|
||||
var v2 = v._is_negative ? v._value.negate() : v._value;
|
||||
var s = v1.add(v2);
|
||||
|
||||
result._is_negative = s.compareTo(BigInteger.ZERO) < 0;
|
||||
result._value = result._is_negative ? s.negate() : s;
|
||||
result._currency = this._currency;
|
||||
result._issuer = this._issuer;
|
||||
} else {
|
||||
var v1 = this._is_negative ? this._value.negate() : this._value;
|
||||
var o1 = this._offset;
|
||||
var v2 = v._is_negative ? v._value.negate() : v._value;
|
||||
var o2 = v._offset;
|
||||
|
||||
while (o1 < o2) {
|
||||
v1 = v1.divide(Amount.bi_10);
|
||||
o1 += 1;
|
||||
if (!this.is_comparable(addendAmount)) {
|
||||
return Amount.NaN();
|
||||
}
|
||||
|
||||
while (o2 < o1) {
|
||||
v2 = v2.divide(Amount.bi_10);
|
||||
o2 += 1;
|
||||
}
|
||||
|
||||
result = new Amount();
|
||||
result._is_native = false;
|
||||
result._offset = o1;
|
||||
result._value = v1.add(v2);
|
||||
result._is_negative = result._value.compareTo(BigInteger.ZERO) < 0;
|
||||
|
||||
if (result._is_negative) {
|
||||
result._value = result._value.negate();
|
||||
}
|
||||
|
||||
result._currency = this._currency;
|
||||
result._issuer = this._issuer;
|
||||
|
||||
result.canonicalize();
|
||||
}
|
||||
|
||||
return result;
|
||||
return this._copy(this._value.plus(addendAmount._value));
|
||||
};
|
||||
|
||||
// Result in terms of this currency and issuer.
|
||||
Amount.prototype.subtract = function(v) {
|
||||
Amount.prototype.subtract = function(subtrahend) {
|
||||
// Correctness over speed, less code has less bugs, reuse add code.
|
||||
return this.add(Amount.from_json(v).negate());
|
||||
return this.add(Amount.from_json(subtrahend).negate());
|
||||
};
|
||||
|
||||
// Result in terms of this' currency and issuer.
|
||||
// XXX Diverges from cpp.
|
||||
Amount.prototype.multiply = function(v) {
|
||||
var result;
|
||||
|
||||
v = Amount.from_json(v);
|
||||
|
||||
if (this.is_zero()) {
|
||||
result = this;
|
||||
} else if (v.is_zero()) {
|
||||
result = this.clone();
|
||||
result._value = BigInteger.ZERO;
|
||||
} else {
|
||||
var v1 = this._value;
|
||||
var o1 = this._offset;
|
||||
var v2 = v._value;
|
||||
var o2 = v._offset;
|
||||
|
||||
if (this.is_native()) {
|
||||
while (v1.compareTo(Amount.bi_man_min_value) < 0) {
|
||||
v1 = v1.multiply(Amount.bi_10);
|
||||
o1 -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (v.is_native()) {
|
||||
while (v2.compareTo(Amount.bi_man_min_value) < 0) {
|
||||
v2 = v2.multiply(Amount.bi_10);
|
||||
o2 -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
result = new Amount();
|
||||
result._offset = o1 + o2 + 14;
|
||||
result._value = v1.multiply(v2).divide(Amount.bi_1e14).add(Amount.bi_7);
|
||||
result._is_native = this._is_native;
|
||||
result._is_negative = this._is_negative !== v._is_negative;
|
||||
result._currency = this._currency;
|
||||
result._issuer = this._issuer;
|
||||
|
||||
result.canonicalize();
|
||||
}
|
||||
|
||||
return result;
|
||||
Amount.prototype.multiply = function(multiplicand) {
|
||||
var multiplicandAmount = Amount.from_json(multiplicand);
|
||||
// TODO: probably should just multiply by multiplicandAmount._value
|
||||
var multiplyBy = multiplicandAmount.is_native() ?
|
||||
multiplicandAmount._value.times(Amount.bi_xns_unit)
|
||||
: multiplicandAmount._value;
|
||||
return this._copy(this._value.times(multiplyBy));
|
||||
};
|
||||
|
||||
// Result in terms of this' currency and issuer.
|
||||
Amount.prototype.divide = function(d) {
|
||||
var result;
|
||||
|
||||
d = Amount.from_json(d);
|
||||
|
||||
if (d.is_zero()) {
|
||||
Amount.prototype.divide = function(divisor) {
|
||||
var divisorAmount = Amount.from_json(divisor);
|
||||
if (!this.is_valid()) {
|
||||
throw new Error('Invalid dividend');
|
||||
}
|
||||
if (!divisorAmount.is_valid()) {
|
||||
throw new Error('Invalid divisor');
|
||||
}
|
||||
if (divisorAmount.is_zero()) {
|
||||
throw new Error('divide by zero');
|
||||
}
|
||||
|
||||
if (this.is_zero()) {
|
||||
result = this;
|
||||
} else if (!this.is_valid()) {
|
||||
throw new Error('Invalid dividend');
|
||||
} else if (!d.is_valid()) {
|
||||
throw new Error('Invalid divisor');
|
||||
} else {
|
||||
var _n = this;
|
||||
|
||||
if (_n.is_native()) {
|
||||
_n = _n.clone();
|
||||
|
||||
while (_n._value.compareTo(Amount.bi_man_min_value) < 0) {
|
||||
_n._value = _n._value.multiply(Amount.bi_10);
|
||||
_n._offset -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
var _d = d;
|
||||
|
||||
if (_d.is_native()) {
|
||||
_d = _d.clone();
|
||||
|
||||
while (_d._value.compareTo(Amount.bi_man_min_value) < 0) {
|
||||
_d._value = _d._value.multiply(Amount.bi_10);
|
||||
_d._offset -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
result = new Amount();
|
||||
result._offset = _n._offset - _d._offset - 17;
|
||||
result._value = _n._value.multiply(Amount.bi_1e17).divide(_d._value).add(Amount.bi_5);
|
||||
result._is_native = _n._is_native;
|
||||
result._is_negative = _n._is_negative !== _d._is_negative;
|
||||
result._currency = _n._currency;
|
||||
result._issuer = _n._issuer;
|
||||
|
||||
result.canonicalize();
|
||||
}
|
||||
|
||||
return result;
|
||||
// TODO: probably should just divide by divisorAmount._value
|
||||
var divideBy = divisorAmount.is_native() ?
|
||||
divisorAmount._value.times(Amount.bi_xns_unit)
|
||||
: divisorAmount._value;
|
||||
return this._copy(this._value.dividedBy(divideBy));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -307,8 +184,6 @@ Amount.prototype.ratio_human = function(denominator, opts) {
|
||||
denominator = Amount.from_json(denominator);
|
||||
}
|
||||
|
||||
denominator = Amount.from_json(denominator);
|
||||
|
||||
// If either operand is NaN, the result is NaN.
|
||||
if (!numerator.is_valid() || !denominator.is_valid()) {
|
||||
return Amount.NaN();
|
||||
@@ -337,9 +212,7 @@ Amount.prototype.ratio_human = function(denominator, opts) {
|
||||
//
|
||||
// To compensate, we multiply the numerator by 10^xns_precision.
|
||||
if (denominator._is_native) {
|
||||
numerator = numerator.clone();
|
||||
numerator._value = numerator._value.multiply(Amount.bi_xns_unit);
|
||||
numerator.canonicalize();
|
||||
numerator._set_value(numerator._value.times(Amount.bi_xns_unit));
|
||||
}
|
||||
|
||||
return numerator.divide(denominator);
|
||||
@@ -396,8 +269,7 @@ Amount.prototype.product_human = function(factor, opts) {
|
||||
//
|
||||
// See also Amount#ratio_human.
|
||||
if (factor._is_native) {
|
||||
product._value = product._value.divide(Amount.bi_xns_unit);
|
||||
product.canonicalize();
|
||||
product._set_value(product._value.dividedBy(Amount.bi_xns_unit));
|
||||
}
|
||||
|
||||
return product;
|
||||
@@ -409,10 +281,7 @@ Amount.prototype.product_human = function(factor, opts) {
|
||||
* @private
|
||||
*/
|
||||
Amount.prototype._invert = function() {
|
||||
this._value = Amount.bi_1e32.divide(this._value);
|
||||
this._offset = -32 - this._offset;
|
||||
this.canonicalize();
|
||||
|
||||
this._set_value((new BigNumber(1)).dividedBy(this._value));
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -423,7 +292,7 @@ Amount.prototype._invert = function() {
|
||||
* inverse of the value.
|
||||
*/
|
||||
Amount.prototype.invert = function() {
|
||||
return this.copy()._invert();
|
||||
return this.clone()._invert();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -453,56 +322,35 @@ Amount.prototype.invert = function() {
|
||||
* @returns {Amount}
|
||||
* @throws {Error} if offset exceeds legal ranges, meaning the amount value is bigger than supported
|
||||
*/
|
||||
Amount.prototype.canonicalize = function() {
|
||||
if (!(this._value instanceof BigInteger)) {
|
||||
// NaN.
|
||||
// nothing
|
||||
} else if (this._is_native) {
|
||||
// Native.
|
||||
if (this._value.equals(BigInteger.ZERO)) {
|
||||
this._offset = 0;
|
||||
this._is_negative = false;
|
||||
|
||||
Amount.prototype.canonicalize = function(roundingMode) {
|
||||
if (this._is_native) {
|
||||
this._value = this._value.round(6, BigNumber.ROUND_DOWN);
|
||||
} else {
|
||||
// Normalize _offset to 0.
|
||||
|
||||
while (this._offset < 0) {
|
||||
this._value = this._value.divide(Amount.bi_10);
|
||||
this._offset += 1;
|
||||
}
|
||||
|
||||
while (this._offset > 0) {
|
||||
this._value = this._value.multiply(Amount.bi_10);
|
||||
this._offset -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (this.is_zero()) {
|
||||
this._offset = Amount.cMinOffset;
|
||||
this._is_negative = false;
|
||||
if (roundingMode) {
|
||||
var value = this._value;
|
||||
this._value = BigNumber.withRoundingMode(roundingMode, function() {
|
||||
return new BigNumber(value.toPrecision(16));
|
||||
});
|
||||
} else {
|
||||
// Normalize mantissa to valid range.
|
||||
|
||||
while (this._value.compareTo(Amount.bi_man_min_value) < 0) {
|
||||
this._value = this._value.multiply(Amount.bi_10);
|
||||
this._offset -= 1;
|
||||
}
|
||||
|
||||
while (this._value.compareTo(Amount.bi_man_max_value) > 0) {
|
||||
this._value = this._value.divide(Amount.bi_10);
|
||||
this._offset += 1;
|
||||
this._value = new BigNumber(this._value.toPrecision(16));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure not bigger than supported. Throw if so.
|
||||
if (this.is_negative() && this._offset < Amount.cMinOffset) {
|
||||
Amount.prototype._check_limits = function() {
|
||||
if (this._value.isNaN() || this._value.isZero()) {
|
||||
return this;
|
||||
}
|
||||
if (!this._is_native) {
|
||||
var absval = this._value.absoluteValue();
|
||||
if (absval.lessThan((new BigNumber(Amount.min_value)).absoluteValue())) {
|
||||
throw new Error('Exceeding min value of ' + Amount.min_value);
|
||||
}
|
||||
|
||||
// Make sure not smaller than supported. Throw if so.
|
||||
if (!this.is_negative() && this._offset > Amount.cMaxOffset) {
|
||||
if (absval.greaterThan(new BigNumber(Amount.max_value))) {
|
||||
throw new Error('Exceeding max value of ' + Amount.max_value);
|
||||
}
|
||||
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -510,61 +358,27 @@ Amount.prototype.clone = function(negate) {
|
||||
return this.copyTo(new Amount(), negate);
|
||||
};
|
||||
|
||||
Amount.prototype.compareTo = function(v) {
|
||||
var result;
|
||||
Amount.prototype._copy = function(value) {
|
||||
var copy = this.clone();
|
||||
copy._set_value(value);
|
||||
return copy;
|
||||
};
|
||||
|
||||
v = Amount.from_json(v);
|
||||
|
||||
if (!this.is_comparable(v)) {
|
||||
result = Amount.NaN();
|
||||
} else if (this._is_negative !== v._is_negative) {
|
||||
// Different sign.
|
||||
result = this._is_negative ? -1 : 1;
|
||||
} else if (this._value.equals(BigInteger.ZERO)) {
|
||||
// Same sign: positive.
|
||||
result = v._value.equals(BigInteger.ZERO) ? 0 : -1;
|
||||
} else if (v._value.equals(BigInteger.ZERO)) {
|
||||
// Same sign: positive.
|
||||
result = 1;
|
||||
} else if (!this._is_native && this._offset > v._offset) {
|
||||
result = this._is_negative ? -1 : 1;
|
||||
} else if (!this._is_native && this._offset < v._offset) {
|
||||
result = this._is_negative ? 1 : -1;
|
||||
} else {
|
||||
result = this._value.compareTo(v._value);
|
||||
if (result > 0) {
|
||||
result = this._is_negative ? -1 : 1;
|
||||
} else if (result < 0) {
|
||||
result = this._is_negative ? 1 : -1;
|
||||
Amount.prototype.compareTo = function(to) {
|
||||
var toAmount = Amount.from_json(to);
|
||||
if (!this.is_comparable(toAmount)) {
|
||||
return Amount.NaN();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return this._value.comparedTo(toAmount._value);
|
||||
};
|
||||
|
||||
// Make d a copy of this. Returns d.
|
||||
// Modification of objects internally refered to is not allowed.
|
||||
Amount.prototype.copyTo = function(d, negate) {
|
||||
if (typeof this._value === 'object') {
|
||||
this._value.copyTo(d._value);
|
||||
} else {
|
||||
d._value = this._value;
|
||||
}
|
||||
|
||||
d._offset = this._offset;
|
||||
d._value = negate ? this._value.negated() : this._value;
|
||||
d._is_native = this._is_native;
|
||||
d._is_negative = negate
|
||||
? !this._is_negative // Negating.
|
||||
: this._is_negative; // Just copying.
|
||||
|
||||
d._currency = this._currency;
|
||||
d._issuer = this._issuer;
|
||||
|
||||
// Prevent negative zero
|
||||
if (d.is_zero()) {
|
||||
d._is_negative = false;
|
||||
}
|
||||
|
||||
return d;
|
||||
};
|
||||
|
||||
@@ -577,20 +391,16 @@ Amount.prototype.equals = function(d, ignore_issuer) {
|
||||
return this.equals(Amount.from_json(d));
|
||||
}
|
||||
|
||||
var result = !((!this.is_valid() || !d.is_valid())
|
||||
|| (this._is_native !== d._is_native)
|
||||
|| (!this._value.equals(d._value) || this._offset !== d._offset)
|
||||
|| (this._is_negative !== d._is_negative)
|
||||
|| (!this._is_native && (!this._currency.equals(d._currency) || !ignore_issuer && !this._issuer.equals(d._issuer))));
|
||||
|
||||
return result;
|
||||
return this.is_valid() && d.is_valid()
|
||||
&& this._is_native === d._is_native
|
||||
&& this._value.equals(d._value)
|
||||
&& (this._is_native || (this._currency.equals(d._currency)
|
||||
&& (ignore_issuer || this._issuer.equals(d._issuer))));
|
||||
};
|
||||
|
||||
// True if Amounts are valid and both native or non-native.
|
||||
Amount.prototype.is_comparable = function(v) {
|
||||
return this._value instanceof BigInteger
|
||||
&& v._value instanceof BigInteger
|
||||
&& this._is_native === v._is_native;
|
||||
return this.is_valid() && v.is_valid() && this._is_native === v._is_native;
|
||||
};
|
||||
|
||||
Amount.prototype.is_native = function() {
|
||||
@@ -598,9 +408,7 @@ Amount.prototype.is_native = function() {
|
||||
};
|
||||
|
||||
Amount.prototype.is_negative = function() {
|
||||
return this._value instanceof BigInteger
|
||||
? this._is_negative
|
||||
: false; // NaN is not negative
|
||||
return this._value.isNegative();
|
||||
};
|
||||
|
||||
Amount.prototype.is_positive = function() {
|
||||
@@ -609,7 +417,7 @@ Amount.prototype.is_positive = function() {
|
||||
|
||||
// Only checks the value. Not the currency and issuer.
|
||||
Amount.prototype.is_valid = function() {
|
||||
return this._value instanceof BigInteger;
|
||||
return !this._value.isNaN();
|
||||
};
|
||||
|
||||
Amount.prototype.is_valid_full = function() {
|
||||
@@ -617,7 +425,7 @@ Amount.prototype.is_valid_full = function() {
|
||||
};
|
||||
|
||||
Amount.prototype.is_zero = function() {
|
||||
return this._value instanceof BigInteger ? this._value.equals(BigInteger.ZERO) : false;
|
||||
return this._value.isZero();
|
||||
};
|
||||
|
||||
Amount.prototype.issuer = function() {
|
||||
@@ -629,23 +437,6 @@ Amount.prototype.negate = function() {
|
||||
return this.clone('NEGATE');
|
||||
};
|
||||
|
||||
/**
|
||||
* Invert this amount and return the new value.
|
||||
*
|
||||
* Creates a new Amount object as a copy of the current one (including the same
|
||||
* unit (currency & issuer), inverts it (1/x) and returns the result.
|
||||
*/
|
||||
Amount.prototype.invert = function() {
|
||||
var one = this.clone();
|
||||
one._value = BigInteger.ONE;
|
||||
one._offset = 0;
|
||||
one._is_negative = false;
|
||||
|
||||
one.canonicalize();
|
||||
|
||||
return one.ratio_human(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Tries to correctly interpret an amount as entered by a user.
|
||||
*
|
||||
@@ -659,74 +450,54 @@ Amount.prototype.invert = function() {
|
||||
*
|
||||
* The regular expression below matches above cases, broken down for better understanding:
|
||||
*
|
||||
* ^\s* // start with any amount of whitespace
|
||||
* ([A-z]{3}|[0-9]{3}) // either 3 letter alphabetic currency-code or 3 digit numeric currency-code. See ISO 4217
|
||||
* \s* // any amount of whitespace
|
||||
* (-)? // optional dash
|
||||
* (\d+) // 1 or more digits
|
||||
* (?:\.(\d*))? // optional . character with any amount of digits
|
||||
* \s* // any amount of whitespace
|
||||
* ([A-z]{3}|[0-9]{3})? // either 3 letter alphabetic currency-code or 3 digit numeric currency-code. See ISO 4217
|
||||
* \s* // any amount of whitespace
|
||||
* $ // end of string
|
||||
*
|
||||
*/
|
||||
Amount.human_RE_hex = /^\s*(-)?(\d+)(?:\.(\d*))?\s*([a-fA-F0-9]{40})\s*$/;
|
||||
Amount.human_RE = /^\s*([A-z]{3}|[0-9]{3})?\s*(-)?(\d+)(?:\.(\d*))?\s*([A-z]{3}|[0-9]{3})?\s*$/;
|
||||
|
||||
Amount.prototype.parse_human = function(j, opts) {
|
||||
opts = opts || {};
|
||||
|
||||
var integer;
|
||||
var fraction;
|
||||
var hex_RE = /^[a-fA-F0-9]{40}$/;
|
||||
var currency_RE = /^([a-zA-Z]{3}|[0-9]{3})$/;
|
||||
|
||||
var value;
|
||||
var currency;
|
||||
var precision = null;
|
||||
|
||||
// first check if it's a hex formatted currency
|
||||
var matches = String(j).match(Amount.human_RE_hex);
|
||||
if (matches && matches.length === 5 && matches[4]) {
|
||||
integer = matches[2];
|
||||
fraction = matches[3] || '';
|
||||
currency = matches[4];
|
||||
this._is_negative = Boolean(matches[1]);
|
||||
}
|
||||
var words = j.split(' ').filter(function(word) { return word !== ''; });
|
||||
|
||||
if (integer === void(0) && currency === void(0)) {
|
||||
var m = String(j).match(Amount.human_RE);
|
||||
if (m) {
|
||||
currency = m[5] || m[1] || 'XRP';
|
||||
integer = m[5] && m[1] ? m[1] + '' + m[3] : (m[3] || '0');
|
||||
fraction = m[4] || '';
|
||||
this._is_negative = Boolean(m[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (integer) {
|
||||
currency = currency.toUpperCase();
|
||||
|
||||
this._value = new BigInteger(integer);
|
||||
this.set_currency(currency);
|
||||
|
||||
// XRP have exactly six digits of precision
|
||||
if (currency === 'XRP') {
|
||||
fraction = fraction.slice(0, 6);
|
||||
while (fraction.length < 6) {
|
||||
fraction += '0';
|
||||
}
|
||||
this._is_native = true;
|
||||
this._value = this._value.multiply(Amount.bi_xns_unit).add(new BigInteger(fraction));
|
||||
if (words.length === 1) {
|
||||
if (isFinite(words[0])) {
|
||||
value = words[0];
|
||||
currency = 'XRP';
|
||||
} else {
|
||||
// Other currencies have arbitrary precision
|
||||
fraction = fraction.replace(/0+$/, '');
|
||||
precision = fraction.length;
|
||||
|
||||
this._is_native = false;
|
||||
var multiplier = Amount.bi_10.clone().pow(precision);
|
||||
this._value = this._value.multiply(multiplier).add(new BigInteger(fraction));
|
||||
this._offset = -precision;
|
||||
|
||||
this.canonicalize();
|
||||
value = words[0].slice(0, -3);
|
||||
currency = words[0].slice(-3);
|
||||
if (!(isFinite(value) && currency.match(currency_RE))) {
|
||||
return Amount.NaN();
|
||||
}
|
||||
}
|
||||
} else if (words.length === 2) {
|
||||
if (isFinite(words[0]) && words[1].match(hex_RE)) {
|
||||
value = words[0];
|
||||
currency = words[1];
|
||||
} else if (words[0].match(currency_RE) && isFinite(words[1])) {
|
||||
value = words[1];
|
||||
currency = words[0];
|
||||
} else if (isFinite(words[0]) && words[1].match(currency_RE)) {
|
||||
value = words[0];
|
||||
currency = words[1];
|
||||
} else {
|
||||
return Amount.NaN();
|
||||
}
|
||||
} else {
|
||||
return Amount.NaN();
|
||||
}
|
||||
|
||||
currency = currency.toUpperCase();
|
||||
this.set_currency(currency);
|
||||
this._is_native = (currency === 'XRP');
|
||||
this._set_value(new BigNumber(value));
|
||||
|
||||
// Apply interest/demurrage
|
||||
if (opts.reference_date && this._currency.has_interest()) {
|
||||
@@ -742,21 +513,15 @@ Amount.prototype.parse_human = function(j, opts) {
|
||||
var interestTempAmount = Amount.from_json(''+interest+'/1/1');
|
||||
|
||||
if (interestTempAmount.is_valid()) {
|
||||
var ref = this.divide(interestTempAmount);
|
||||
this._value = ref._value;
|
||||
this._offset = ref._offset;
|
||||
this._set_value(this.divide(interestTempAmount)._value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._value = NaN;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Amount.prototype.parse_issuer = function(issuer) {
|
||||
this._issuer = UInt160.from_json(issuer);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -798,29 +563,41 @@ Amount.prototype.parse_quality = function(quality, counterCurrency, counterIssue
|
||||
|
||||
var baseCurrency = Currency.from_json(opts.base_currency);
|
||||
|
||||
this._is_negative = false;
|
||||
this._value = new BigInteger(quality.substring(quality.length-14), 16);
|
||||
this._offset = parseInt(quality.substring(quality.length-16, quality.length-14), 16)-100;
|
||||
var mantissa_hex = quality.substring(quality.length-14);
|
||||
var offset_hex = quality.substring(quality.length-16, quality.length-14);
|
||||
var mantissa = new BigNumber(mantissa_hex, 16);
|
||||
var offset = parseInt(offset_hex, 16) - 100;
|
||||
|
||||
var value = new BigNumber(mantissa.toString() + 'e' + offset.toString());
|
||||
|
||||
this._currency = Currency.from_json(counterCurrency);
|
||||
this._issuer = UInt160.from_json(counterIssuer);
|
||||
this._is_native = this._currency.is_native();
|
||||
|
||||
var power = 0;
|
||||
if (this._is_native) {
|
||||
if (opts.inverse) {
|
||||
power += 1;
|
||||
} else {
|
||||
power -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Correct offset if xrp_as_drops option is not set and base currency is XRP
|
||||
if (!opts.xrp_as_drops &&
|
||||
baseCurrency.is_valid() &&
|
||||
baseCurrency.is_native()) {
|
||||
if (opts.inverse) {
|
||||
this._offset -= 6;
|
||||
power -= 1;
|
||||
} else {
|
||||
this._offset += 6;
|
||||
power += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.inverse) {
|
||||
this._invert();
|
||||
}
|
||||
|
||||
this.canonicalize();
|
||||
var one = new BigNumber(1);
|
||||
var adjusted = value.times(Amount.bi_xns_unit.toPower(power));
|
||||
var newValue = opts.inverse ? one.dividedBy(adjusted) : adjusted;
|
||||
this._set_value(newValue);
|
||||
|
||||
if (opts.reference_date && baseCurrency.is_valid() && baseCurrency.has_interest()) {
|
||||
var interest = baseCurrency.get_interest_at(opts.reference_date);
|
||||
@@ -829,9 +606,7 @@ Amount.prototype.parse_quality = function(quality, counterCurrency, counterIssue
|
||||
var interestTempAmount = Amount.from_json(''+interest+'/1/1');
|
||||
|
||||
if (interestTempAmount.is_valid()) {
|
||||
var v = this.divide(interestTempAmount);
|
||||
this._value = v._value;
|
||||
this._offset = v._offset;
|
||||
this._set_value(this.divide(interestTempAmount)._value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -842,12 +617,7 @@ Amount.prototype.parse_number = function(n) {
|
||||
this._is_native = false;
|
||||
this._currency = Currency.from_json(1);
|
||||
this._issuer = UInt160.from_json(1);
|
||||
this._is_negative = n < 0 ? true : false;
|
||||
this._value = new BigInteger(String(this._is_negative ? -n : n));
|
||||
this._offset = 0;
|
||||
|
||||
this.canonicalize();
|
||||
|
||||
this._set_value(new BigNumber(n));
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -897,7 +667,7 @@ Amount.prototype.parse_json = function(j) {
|
||||
break;
|
||||
|
||||
default:
|
||||
this._value = NaN;
|
||||
this._set_value(new BigNumber(NaN));
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -908,33 +678,20 @@ Amount.prototype.parse_json = function(j) {
|
||||
// - float = with precision 6
|
||||
// XXX Improvements: disallow leading zeros.
|
||||
Amount.prototype.parse_native = function(j) {
|
||||
var m;
|
||||
|
||||
if (typeof j === 'string') {
|
||||
m = j.match(/^(-?)(\d*)(\.\d{0,6})?$/);
|
||||
}
|
||||
|
||||
if (m) {
|
||||
if (m[3] === void(0)) {
|
||||
// Integer notation
|
||||
this._value = new BigInteger(m[2]);
|
||||
} else {
|
||||
// Float notation : values multiplied by 1,000,000.
|
||||
var int_part = (new BigInteger(m[2])).multiply(Amount.bi_xns_unit);
|
||||
var fraction_part = (new BigInteger(m[3])).multiply(new BigInteger(String(Math.pow(10, 1+Amount.xns_precision-m[3].length))));
|
||||
|
||||
this._value = int_part.add(fraction_part);
|
||||
}
|
||||
|
||||
if (typeof j === 'string' && j.match(/^-?\d*(\.\d{0,6})?$/)) {
|
||||
var value = new BigNumber(j);
|
||||
this._is_native = true;
|
||||
this._offset = 0;
|
||||
this._is_negative = !!m[1] && this._value.compareTo(BigInteger.ZERO) !== 0;
|
||||
|
||||
if (this._value.compareTo(Amount.bi_xns_max) > 0) {
|
||||
this._value = NaN;
|
||||
if (j.indexOf('.') >= 0) {
|
||||
this._set_value(value);
|
||||
} else {
|
||||
this._set_value(value.dividedBy(Amount.bi_xns_unit));
|
||||
}
|
||||
// TODO: move this overflow check to canonicalize
|
||||
if (this._value.abs().greaterThan(Amount.bi_xrp_max)) {
|
||||
this._set_value(new BigNumber(NaN));
|
||||
}
|
||||
} else {
|
||||
this._value = NaN;
|
||||
this._set_value(new BigNumber(NaN));
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -944,62 +701,13 @@ Amount.prototype.parse_native = function(j) {
|
||||
// Requires _currency to be set!
|
||||
Amount.prototype.parse_value = function(j) {
|
||||
this._is_native = false;
|
||||
|
||||
switch (typeof j) {
|
||||
case 'number':
|
||||
this._is_negative = j < 0;
|
||||
this._value = new BigInteger(Math.abs(j));
|
||||
this._offset = 0;
|
||||
|
||||
this.canonicalize();
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
var i = j.match(/^(-?)(\d+)$/);
|
||||
var d = !i && j.match(/^(-?)(\d*)\.(\d*)$/);
|
||||
var e = !e && j.match(/^(-?)(\d*)e(-?\d+)$/);
|
||||
|
||||
if (e) {
|
||||
// e notation
|
||||
this._value = new BigInteger(e[2]);
|
||||
this._offset = parseInt(e[3]);
|
||||
this._is_negative = !!e[1];
|
||||
|
||||
this.canonicalize();
|
||||
} else if (d) {
|
||||
// float notation
|
||||
var integer = new BigInteger(d[2]);
|
||||
var fraction = new BigInteger(d[3]);
|
||||
var precision = d[3].length;
|
||||
|
||||
this._value = integer.multiply(Amount.bi_10.clone().pow(precision)).add(fraction);
|
||||
this._offset = -precision;
|
||||
this._is_negative = !!d[1];
|
||||
|
||||
this.canonicalize();
|
||||
} else if (i) {
|
||||
// integer notation
|
||||
this._value = new BigInteger(i[2]);
|
||||
this._offset = 0;
|
||||
this._is_negative = !!i[1];
|
||||
|
||||
this.canonicalize();
|
||||
} else {
|
||||
this._value = NaN;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
this._value = j instanceof BigInteger ? j : NaN;
|
||||
}
|
||||
|
||||
this._set_value(new BigNumber(j), BigNumber.ROUND_DOWN);
|
||||
return this;
|
||||
};
|
||||
|
||||
Amount.prototype.set_currency = function(c) {
|
||||
this._currency = Currency.from_json(c);
|
||||
this._is_native = this._currency.is_native();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -1020,37 +728,43 @@ Amount.prototype.to_number = function(allow_nan) {
|
||||
|
||||
// Convert only value to JSON wire format.
|
||||
Amount.prototype.to_text = function(allow_nan) {
|
||||
var result = NaN;
|
||||
if (this._is_native && this._value.abs().greaterThan(Amount.bi_xrp_max)) {
|
||||
return '0';
|
||||
}
|
||||
if (this._value.isNaN() && !allow_nan) {
|
||||
return '0';
|
||||
} else if (this._value.isNaN()) {
|
||||
return NaN; // TODO: why does to_text return NaN? return 'NaN'?
|
||||
}
|
||||
|
||||
if (this._is_native) {
|
||||
if (this.is_valid() && this._value.compareTo(Amount.bi_xns_max) <= 0){
|
||||
result = this._value.toString();
|
||||
if (this.is_valid() && this._value.lessThanOrEqualTo(Amount.bi_xns_max)){
|
||||
return this._value.times(Amount.bi_xns_unit).toString();
|
||||
} else {
|
||||
return NaN; // TODO: why does to_text return NaN? return 'NaN'?
|
||||
}
|
||||
} else if (this.is_zero()) {
|
||||
result = '0';
|
||||
} else if (this._offset && (this._offset < -25 || this._offset > -4)) {
|
||||
}
|
||||
|
||||
// not native
|
||||
var offset = this._value.e - 15;
|
||||
var sign = this._value.isNegative() ? '-' : '';
|
||||
var mantissa = utils.getMantissaDecimalString(this._value.absoluteValue());
|
||||
if (offset !== 0 && (offset < -25 || offset > -4)) {
|
||||
// Use e notation.
|
||||
// XXX Clamp output.
|
||||
result = this._value.toString() + 'e' + this._offset;
|
||||
return sign + mantissa.toString() + 'e' + offset.toString();
|
||||
} else {
|
||||
var val = '000000000000000000000000000' + this._value.toString() + '00000000000000000000000';
|
||||
var pre = val.substring(0, this._offset + 43);
|
||||
var post = val.substring(this._offset + 43);
|
||||
var val = '000000000000000000000000000' + mantissa.toString()
|
||||
+ '00000000000000000000000';
|
||||
var pre = val.substring(0, offset + 43);
|
||||
var post = val.substring(offset + 43);
|
||||
var s_pre = pre.match(/[1-9].*$/); // Everything but leading zeros.
|
||||
var s_post = post.match(/[1-9]0*$/); // Last non-zero plus trailing zeros.
|
||||
|
||||
result = ''
|
||||
+ (s_pre ? s_pre[0] : '0')
|
||||
return sign + (s_pre ? s_pre[0] : '0')
|
||||
+ (s_post ? '.' + post.substring(0, 1 + post.length - s_post[0].length) : '');
|
||||
}
|
||||
|
||||
if (!allow_nan && typeof result === 'number' && isNaN(result)) {
|
||||
result = '0';
|
||||
} else if (this._is_negative) {
|
||||
result = '-' + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1131,15 +845,11 @@ Amount.prototype.to_human = function(opts) {
|
||||
ref = this.applyInterest(opts.reference_date);
|
||||
}
|
||||
|
||||
var order = ref._is_native ? Amount.xns_precision : -ref._offset;
|
||||
var denominator = Amount.bi_10.clone().pow(order);
|
||||
var int_part = ref._value.divide(denominator).toString();
|
||||
var fraction_part = ref._value.mod(denominator).toString();
|
||||
|
||||
// Add leading zeros to fraction
|
||||
while (fraction_part.length < order) {
|
||||
fraction_part = '0' + fraction_part;
|
||||
}
|
||||
var isNegative = ref._value.isNegative();
|
||||
var valueString = ref._value.abs().toString();
|
||||
var parts = valueString.split('.');
|
||||
var int_part = parts[0];
|
||||
var fraction_part = parts.length === 2 ? parts[1] : '';
|
||||
|
||||
int_part = int_part.replace(/^0*/, '');
|
||||
fraction_part = fraction_part.replace(/0*$/, '');
|
||||
@@ -1208,7 +918,7 @@ Amount.prototype.to_human = function(opts) {
|
||||
}
|
||||
|
||||
var formatted = '';
|
||||
if (opts.signed && this._is_negative) {
|
||||
if (opts.signed && isNegative) {
|
||||
if (typeof opts.signed !== 'string') {
|
||||
opts.signed = '-';
|
||||
}
|
||||
@@ -1250,11 +960,9 @@ Amount.prototype.to_json = function() {
|
||||
};
|
||||
|
||||
Amount.prototype.to_text_full = function(opts) {
|
||||
return this._value instanceof BigInteger
|
||||
? this._is_native
|
||||
return this._is_native
|
||||
? this.to_human() + '/XRP'
|
||||
: this.to_text() + '/' + this._currency.to_json() + '/' + this._issuer.to_json(opts)
|
||||
: NaN;
|
||||
: this.to_text() + '/' + this._currency.to_json() + '/' + this._issuer.to_json(opts);
|
||||
};
|
||||
|
||||
// For debugging.
|
||||
@@ -1276,10 +984,10 @@ Amount.prototype.not_equals_why = function(d, ignore_issuer) {
|
||||
} else {
|
||||
var type = this._is_native ? 'XRP' : 'Non-XRP';
|
||||
|
||||
if (!this._value.equals(d._value) || this._offset !== d._offset) {
|
||||
result = type + ' value differs.';
|
||||
} else if (this._is_negative !== d._is_negative) {
|
||||
if (!this._value.isZero() && this._value.negated().equals(d._value)) {
|
||||
result = type + ' sign differs.';
|
||||
} else if (!this._value.equals(d._value)) {
|
||||
result = type + ' value differs.';
|
||||
} else if (!this._is_native) {
|
||||
if (!this._currency.equals(d._currency)) {
|
||||
result = 'Non-XRP currency differs.';
|
||||
|
||||
@@ -2,8 +2,6 @@ var sjcl = require('./utils').sjcl;
|
||||
var utils = require('./utils');
|
||||
var extend = require('extend');
|
||||
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
var Base = {};
|
||||
|
||||
var alphabets = Base.alphabets = {
|
||||
@@ -25,33 +23,142 @@ extend(Base, {
|
||||
|
||||
function sha256(bytes) {
|
||||
return sjcl.codec.bytes.fromBits(sjcl.hash.sha256.hash(sjcl.codec.bytes.toBits(bytes)));
|
||||
};
|
||||
}
|
||||
|
||||
function sha256hash(bytes) {
|
||||
return sha256(sha256(bytes));
|
||||
};
|
||||
}
|
||||
|
||||
function divmod58(number, startAt) {
|
||||
var remainder = 0;
|
||||
for (var i = startAt; i < number.length; i++) {
|
||||
var digit256 = number[i] & 0xFF;
|
||||
var temp = remainder * 256 + digit256;
|
||||
number[i] = (temp / 58);
|
||||
remainder = temp % 58;
|
||||
}
|
||||
return remainder;
|
||||
}
|
||||
|
||||
function divmod256(number58, startAt) {
|
||||
var remainder = 0;
|
||||
for (var i = startAt; i < number58.length; i++) {
|
||||
var digit58 = number58[i] & 0xFF;
|
||||
var temp = remainder * 58 + digit58;
|
||||
number58[i] = (temp / 256);
|
||||
remainder = temp % 256;
|
||||
}
|
||||
return remainder;
|
||||
}
|
||||
|
||||
function encodeString (alphabet, input) {
|
||||
if (input.length == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// we need to copy the buffer for calc
|
||||
scratch = input.slice();
|
||||
|
||||
// Count leading zeroes.
|
||||
var zeroCount = 0;
|
||||
while (zeroCount < scratch.length &&
|
||||
scratch[zeroCount] == 0)
|
||||
++zeroCount;
|
||||
|
||||
// The actual encoding.
|
||||
var out = new Array(scratch.length * 2);
|
||||
var j = out.length;
|
||||
var startAt = zeroCount;
|
||||
|
||||
while (startAt < scratch.length) {
|
||||
var mod = divmod58(scratch, startAt);
|
||||
if (scratch[startAt] == 0) {
|
||||
++startAt;
|
||||
}
|
||||
out[--j] = alphabet[mod];
|
||||
}
|
||||
|
||||
// Strip extra 'r' if there are some after decoding.
|
||||
while (j < out.length && out[j] == alphabet[0]) ++j;
|
||||
// Add as many leading 'r' as there were leading zeros.
|
||||
while (--zeroCount >= 0) out[--j] = alphabet[0];
|
||||
while(j--) out.shift();
|
||||
|
||||
return out.join('');
|
||||
}
|
||||
|
||||
function decodeString(indexes, input) {
|
||||
var isString = typeof input === 'string';
|
||||
|
||||
if (input.length == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
input58 = new Array(input.length);
|
||||
|
||||
// Transform the String to a base58 byte sequence
|
||||
for (var i = 0; i < input.length; ++i) {
|
||||
if (isString) {
|
||||
var c = input.charCodeAt(i);
|
||||
}
|
||||
|
||||
var digit58 = -1;
|
||||
if (c >= 0 && c < 128) {
|
||||
digit58 = indexes[c];
|
||||
}
|
||||
if (digit58 < 0) {
|
||||
throw new Error("Illegal character " + c + " at " + i);
|
||||
}
|
||||
|
||||
input58[i] = digit58;
|
||||
}
|
||||
// Count leading zeroes
|
||||
var zeroCount = 0;
|
||||
while (zeroCount < input58.length && input58[zeroCount] == 0) {
|
||||
++zeroCount;
|
||||
}
|
||||
// The encoding
|
||||
out = utils.arraySet(input.length, 0);
|
||||
var j = out.length;
|
||||
|
||||
var startAt = zeroCount;
|
||||
while (startAt < input58.length) {
|
||||
var mod = divmod256(input58, startAt);
|
||||
if (input58[startAt] == 0) {
|
||||
++startAt;
|
||||
}
|
||||
out[--j] = mod;
|
||||
}
|
||||
|
||||
// Do no add extra leading zeroes, move j to first non null byte.
|
||||
while (j < out.length && (out[j] == 0)) ++j;
|
||||
|
||||
j -= zeroCount;
|
||||
while(j--) out.shift();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function Base58(alphabet) {
|
||||
var indexes = utils.arraySet(128, -1);
|
||||
for (var i = 0; i < alphabet.length; i++) {
|
||||
indexes[alphabet.charCodeAt(i)] = i;
|
||||
}
|
||||
return {
|
||||
decode: decodeString.bind(null, indexes),
|
||||
encode: encodeString.bind(null, alphabet)
|
||||
};
|
||||
}
|
||||
|
||||
Base.encoders = {};
|
||||
Object.keys(alphabets).forEach(function(alphabet){
|
||||
Base.encoders[alphabet] = Base58(alphabets[alphabet]);
|
||||
});
|
||||
|
||||
// --> input: big-endian array of bytes.
|
||||
// <-- string at least as long as input.
|
||||
Base.encode = function(input, alpha) {
|
||||
var alphabet = alphabets[alpha || 'ripple'];
|
||||
var bi_base = new BigInteger(String(alphabet.length));
|
||||
var bi_q = new BigInteger();
|
||||
var bi_r = new BigInteger();
|
||||
var bi_value = new BigInteger(input);
|
||||
var buffer = [];
|
||||
|
||||
while (bi_value.compareTo(BigInteger.ZERO) > 0) {
|
||||
bi_value.divRemTo(bi_base, bi_q, bi_r);
|
||||
bi_q.copyTo(bi_value);
|
||||
buffer.push(alphabet[bi_r.intValue()]);
|
||||
}
|
||||
|
||||
for (var i=0; i !== input.length && !input[i]; i += 1) {
|
||||
buffer.push(alphabet[0]);
|
||||
}
|
||||
|
||||
return buffer.reverse().join('');
|
||||
return this.encoders[alpha || 'ripple'].encode(input);
|
||||
};
|
||||
|
||||
// --> input: String
|
||||
@@ -60,48 +167,12 @@ Base.decode = function(input, alpha) {
|
||||
if (typeof input !== 'string') {
|
||||
return void(0);
|
||||
}
|
||||
|
||||
var alphabet = alphabets[alpha || 'ripple'];
|
||||
var bi_base = new BigInteger(String(alphabet.length));
|
||||
var bi_value = new BigInteger();
|
||||
var i;
|
||||
|
||||
for (i = 0; i !== input.length && input[i] === alphabet[0]; i += 1) {
|
||||
try {
|
||||
return this.encoders[alpha || 'ripple'].decode(input);
|
||||
}
|
||||
|
||||
for (; i !== input.length; i += 1) {
|
||||
var v = alphabet.indexOf(input[i]);
|
||||
|
||||
if (v < 0) {
|
||||
return void(0);
|
||||
catch(e) {
|
||||
return (void 0);
|
||||
}
|
||||
|
||||
var r = new BigInteger();
|
||||
r.fromInt(v);
|
||||
bi_value = bi_value.multiply(bi_base).add(r);
|
||||
}
|
||||
|
||||
// toByteArray:
|
||||
// - Returns leading zeros!
|
||||
// - Returns signed bytes!
|
||||
var bytes = bi_value.toByteArray().map(function(b) { return b ? b < 0 ? 256+b : b : 0; });
|
||||
var extra = 0;
|
||||
|
||||
while (extra !== bytes.length && !bytes[extra]) {
|
||||
extra += 1;
|
||||
}
|
||||
|
||||
if (extra) {
|
||||
bytes = bytes.slice(extra);
|
||||
}
|
||||
|
||||
var zeros = 0;
|
||||
|
||||
while (zeros !== input.length && input[zeros] === alphabet[0]) {
|
||||
zeros += 1;
|
||||
}
|
||||
|
||||
return [].concat(utils.arraySet(zeros, 0), bytes);
|
||||
};
|
||||
|
||||
Base.verify_checksum = function(bytes) {
|
||||
@@ -129,7 +200,7 @@ Base.encode_check = function(version, input, alphabet) {
|
||||
};
|
||||
|
||||
// --> input : String
|
||||
// <-- NaN || BigInteger
|
||||
// <-- NaN || sjcl.bn
|
||||
Base.decode_check = function(version, input, alphabet) {
|
||||
var buffer = Base.decode(input, alphabet);
|
||||
|
||||
@@ -163,7 +234,8 @@ Base.decode_check = function(version, input, alphabet) {
|
||||
// intrepret the value as a negative number
|
||||
buffer[0] = 0;
|
||||
|
||||
return new BigInteger(buffer.slice(0, -4), 256);
|
||||
return sjcl.bn.fromBits (
|
||||
sjcl.codec.bytes.toBits(buffer.slice(0, -4)));
|
||||
};
|
||||
|
||||
exports.Base = Base;
|
||||
|
||||
33
src/js/ripple/bignumber.js
Normal file
33
src/js/ripple/bignumber.js
Normal file
@@ -0,0 +1,33 @@
|
||||
var BigNumber = require('bignumber.js');
|
||||
var extend = require('extend');
|
||||
|
||||
function BigNumberWrapper(value, base) {
|
||||
// reset config every time a BigNumber is instantiated so that
|
||||
// these global settings won't be overridden if another file tries
|
||||
// to set them at require-time.
|
||||
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP,
|
||||
DECIMAL_PLACES: 40 });
|
||||
BigNumber.call(this, value, base);
|
||||
}
|
||||
|
||||
extend(BigNumberWrapper, BigNumber); // copy class static properties
|
||||
BigNumberWrapper.prototype = BigNumber.prototype;
|
||||
|
||||
BigNumberWrapper.config = function() {
|
||||
throw new Error('BigNumber.config may only be called from bignumber.js');
|
||||
};
|
||||
|
||||
BigNumberWrapper.withRoundingMode = function(roundingMode, func) {
|
||||
var config = BigNumber.config();
|
||||
var oldRoundingMode = config.ROUNDING_MODE;
|
||||
config.ROUNDING_MODE = roundingMode;
|
||||
BigNumber.config(config);
|
||||
try {
|
||||
return func();
|
||||
} finally {
|
||||
config.ROUNDING_MODE = oldRoundingMode;
|
||||
BigNumber.config(config);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = BigNumberWrapper;
|
||||
@@ -308,7 +308,7 @@ Currency.prototype.get_interest_percentage_at = function(referenceDate, decimals
|
||||
// currency data, since there are some values that are invalid.
|
||||
//
|
||||
//Currency.prototype.is_valid = function() {
|
||||
// return this._value instanceof BigInteger && ...;
|
||||
// return UInt.prototype.is_valid() && ...;
|
||||
//};
|
||||
|
||||
Currency.prototype.to_json = function(opts) {
|
||||
|
||||
@@ -29,7 +29,6 @@ exports.RangeSet = require('./rangeset').RangeSet;
|
||||
// the official client, it makes sense to expose the SJCL instance so we don't
|
||||
// have to include it twice.
|
||||
exports.sjcl = require('./utils').sjcl;
|
||||
exports.jsbn = require('./utils').jsbn;
|
||||
exports.types = require('./serializedtypes');
|
||||
|
||||
exports.config = require('./config');
|
||||
|
||||
@@ -6,8 +6,6 @@ var extend = require('extend');
|
||||
var utils = require('./utils');
|
||||
var sjcl = utils.sjcl;
|
||||
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
var Base = require('./base').Base;
|
||||
var UInt = require('./uint').UInt;
|
||||
var UInt256 = require('./uint256').UInt256;
|
||||
@@ -15,7 +13,6 @@ var UInt160 = require('./uint160').UInt160;
|
||||
var KeyPair = require('./keypair').KeyPair;
|
||||
|
||||
var Seed = extend(function () {
|
||||
// Internal form: NaN or BigInteger
|
||||
this._curve = sjcl.ecc.curves.k256;
|
||||
this._value = NaN;
|
||||
}, UInt);
|
||||
@@ -60,7 +57,7 @@ Seed.prototype.parse_passphrase = function (j) {
|
||||
};
|
||||
|
||||
Seed.prototype.to_json = function () {
|
||||
if (!(this._value instanceof BigInteger)) {
|
||||
if (!(this.is_valid())) {
|
||||
return NaN;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
var _ = require('lodash');
|
||||
var assert = require('assert');
|
||||
var extend = require('extend');
|
||||
var binformat = require('./binformat');
|
||||
var stypes = require('./serializedtypes');
|
||||
var UInt256 = require('./uint256').UInt256;
|
||||
var Crypt = require('./crypt').Crypt;
|
||||
var utils = require('./utils');
|
||||
|
||||
var sjcl = utils.sjcl;
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
var TRANSACTION_TYPES = { };
|
||||
|
||||
@@ -27,6 +26,13 @@ Object.keys(binformat.ter).forEach(function(key) {
|
||||
TRANSACTION_RESULTS[binformat.ter[key]] = key;
|
||||
});
|
||||
|
||||
function normalize_sjcl_bn_hex(string) {
|
||||
var hex = string.slice(2); // remove '0x' prefix
|
||||
// now strip leading zeros
|
||||
var i = _.findIndex(hex, function(c) { return c !== '0'; });
|
||||
return i >= 0 ? hex.slice(i) : '0';
|
||||
}
|
||||
|
||||
function SerializedObject(buf) {
|
||||
if (Array.isArray(buf) || (Buffer && Buffer.isBuffer(buf)) ) {
|
||||
this.buffer = buf;
|
||||
@@ -38,11 +44,11 @@ function SerializedObject(buf) {
|
||||
throw new Error('Invalid buffer passed.');
|
||||
}
|
||||
this.pointer = 0;
|
||||
};
|
||||
}
|
||||
|
||||
SerializedObject.from_json = function(obj) {
|
||||
// Create a copy of the object so we don't modify it
|
||||
var obj = extend(true, {}, obj);
|
||||
obj = extend(true, {}, obj);
|
||||
var so = new SerializedObject();
|
||||
var typedef;
|
||||
|
||||
@@ -103,8 +109,8 @@ SerializedObject.check_no_missing_fields = function(typedef, obj) {
|
||||
|
||||
if (binformat.REQUIRED === requirement && obj[field] === void(0)) {
|
||||
missing_fields.push(field);
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_fields.length > 0) {
|
||||
var object_name;
|
||||
@@ -114,12 +120,12 @@ SerializedObject.check_no_missing_fields = function(typedef, obj) {
|
||||
} else if (obj.LedgerEntryType != null){
|
||||
object_name = SerializedObject.lookup_type_le(obj.LedgerEntryType);
|
||||
} else {
|
||||
object_name = "TransactionMetaData";
|
||||
object_name = 'TransactionMetaData';
|
||||
}
|
||||
|
||||
throw new Error(object_name + " is missing fields: " +
|
||||
throw new Error(object_name + ' is missing fields: ' +
|
||||
JSON.stringify(missing_fields));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
SerializedObject.prototype.append = function(bytes) {
|
||||
@@ -152,7 +158,7 @@ function readOrPeek(advance) {
|
||||
|
||||
return result;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
SerializedObject.prototype.read = readOrPeek(true);
|
||||
|
||||
@@ -209,8 +215,8 @@ SerializedObject.jsonify_structure = function(structure, field_name) {
|
||||
|
||||
if (typeof structure.to_json === 'function') {
|
||||
output = structure.to_json();
|
||||
} else if (structure instanceof BigInteger) {
|
||||
output = ('0000000000000000' + structure.toString(16).toUpperCase()).slice(-16);
|
||||
} else if (structure instanceof sjcl.bn) {
|
||||
output = ('0000000000000000' + normalize_sjcl_bn_hex(structure.toString()).toUpperCase()).slice(-16);
|
||||
} else {
|
||||
//new Array or Object
|
||||
output = new structure.constructor();
|
||||
@@ -250,7 +256,7 @@ SerializedObject.prototype.hash = function(prefix) {
|
||||
var sign_buffer = new SerializedObject();
|
||||
|
||||
// Add hashing prefix
|
||||
if ("undefined" !== typeof prefix) {
|
||||
if ('undefined' !== typeof prefix) {
|
||||
stypes.Int32.serialize(sign_buffer, prefix);
|
||||
}
|
||||
|
||||
@@ -312,7 +318,7 @@ SerializedObject.sort_typedef = function(typedef) {
|
||||
function sort_field_compare(a, b) {
|
||||
// Sort by type id first, then by field id
|
||||
return a[3] !== b[3] ? stypes[a[3]].id - stypes[b[3]].id : a[2] - b[2];
|
||||
};
|
||||
}
|
||||
|
||||
return typedef.sort(sort_field_compare);
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ var extend = require('extend');
|
||||
var binformat = require('./binformat');
|
||||
var utils = require('./utils');
|
||||
var sjcl = utils.sjcl;
|
||||
var BigNumber = require('./bignumber');
|
||||
|
||||
var UInt128 = require('./uint128').UInt128;
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
@@ -21,59 +22,48 @@ var amount = require('./amount');
|
||||
var Amount = amount.Amount;
|
||||
var Currency = amount.Currency;
|
||||
|
||||
// Shortcuts
|
||||
var hex = sjcl.codec.hex;
|
||||
var bytes = sjcl.codec.bytes;
|
||||
var utf8 = sjcl.codec.utf8String;
|
||||
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
|
||||
var SerializedType = function (methods) {
|
||||
extend(this, methods);
|
||||
};
|
||||
|
||||
function isNumber(val) {
|
||||
return typeof val === 'number' && isFinite(val);
|
||||
};
|
||||
}
|
||||
|
||||
function isString(val) {
|
||||
return typeof val === 'string';
|
||||
};
|
||||
}
|
||||
|
||||
function isHexInt64String(val) {
|
||||
return isString(val) && /^[0-9A-F]{0,16}$/i.test(val);
|
||||
};
|
||||
}
|
||||
|
||||
function isCurrencyString(val) {
|
||||
return isString(val) && /^[A-Z0-9]{3}$/.test(val);
|
||||
};
|
||||
|
||||
function isBigInteger(val) {
|
||||
return val instanceof BigInteger;
|
||||
};
|
||||
|
||||
function serializeHex(so, hexData, noLength) {
|
||||
var byteData = bytes.fromBits(hex.toBits(hexData));
|
||||
function serializeBits(so, bits, noLength) {
|
||||
var byteData = sjcl.codec.bytes.fromBits(bits);
|
||||
if (!noLength) {
|
||||
SerializedType.serialize_varint(so, byteData.length);
|
||||
}
|
||||
so.append(byteData);
|
||||
};
|
||||
}
|
||||
|
||||
function serializeHex(so, hexData, noLength) {
|
||||
serializeBits(so, sjcl.codec.hex.toBits(hexData), noLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* parses bytes as hex
|
||||
*/
|
||||
function convertByteArrayToHex (byte_array) {
|
||||
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(byte_array)).toUpperCase();
|
||||
};
|
||||
}
|
||||
|
||||
function convertStringToHex(string) {
|
||||
return hex.fromBits(utf8.toBits(string)).toUpperCase();
|
||||
var utf8String = sjcl.codec.utf8String.toBits(string);
|
||||
return sjcl.codec.hex.fromBits(utf8String).toUpperCase();
|
||||
}
|
||||
|
||||
function convertHexToString(hexString) {
|
||||
return utf8.fromBits(hex.toBits(hexString));
|
||||
return sjcl.codec.utf8String.fromBits(sjcl.codec.hex.toBits(hexString));
|
||||
}
|
||||
|
||||
SerializedType.serialize_varint = function (so, val) {
|
||||
@@ -130,7 +120,7 @@ function convertIntegerToByteArray(val, bytes) {
|
||||
}
|
||||
|
||||
if (val < 0 || val >= Math.pow(256, bytes)) {
|
||||
throw new Error('Value out of bounds');
|
||||
throw new Error('Value out of bounds ');
|
||||
}
|
||||
|
||||
var newBytes = [ ];
|
||||
@@ -140,7 +130,7 @@ function convertIntegerToByteArray(val, bytes) {
|
||||
}
|
||||
|
||||
return newBytes;
|
||||
};
|
||||
}
|
||||
|
||||
// Convert a certain number of bytes from the serialized object ('so') into an integer.
|
||||
function readAndSum(so, bytes) {
|
||||
@@ -157,7 +147,7 @@ function readAndSum(so, bytes) {
|
||||
|
||||
// Convert to unsigned integer
|
||||
return sum >>> 0;
|
||||
};
|
||||
}
|
||||
|
||||
var STInt8 = exports.Int8 = new SerializedType({
|
||||
serialize: function (so, val) {
|
||||
@@ -201,41 +191,25 @@ var STInt64 = exports.Int64 = new SerializedType({
|
||||
if (val < 0) {
|
||||
throw new Error('Negative value for unsigned Int64 is invalid.');
|
||||
}
|
||||
bigNumObject = new BigInteger(String(val), 10);
|
||||
bigNumObject = new sjcl.bn(val, 10);
|
||||
} else if (isString(val)) {
|
||||
if (!isHexInt64String(val)) {
|
||||
throw new Error('Not a valid hex Int64.');
|
||||
}
|
||||
bigNumObject = new BigInteger(val, 16);
|
||||
} else if (isBigInteger(val)) {
|
||||
if (val.compareTo(BigInteger.ZERO) < 0) {
|
||||
bigNumObject = new sjcl.bn(val, 16);
|
||||
} else if (val instanceof sjcl.bn) {
|
||||
if (!val.greaterEquals(0)) {
|
||||
throw new Error('Negative value for unsigned Int64 is invalid.');
|
||||
}
|
||||
bigNumObject = val;
|
||||
} else {
|
||||
throw new Error('Invalid type for Int64');
|
||||
}
|
||||
|
||||
var hex = bigNumObject.toString(16);
|
||||
|
||||
if (hex.length > 16) {
|
||||
throw new Error('Int64 is too large');
|
||||
}
|
||||
|
||||
while (hex.length < 16) {
|
||||
hex = '0' + hex;
|
||||
}
|
||||
|
||||
serializeHex(so, hex, true); //noLength = true
|
||||
serializeBits(so, bigNumObject.toBits(64), true); //noLength = true
|
||||
},
|
||||
parse: function (so) {
|
||||
var bytes = so.read(8);
|
||||
// We need to add a 0, so if the high bit is set it won't think it's a
|
||||
// pessimistic numeric fraek. What doth lief?
|
||||
var result = new BigInteger([0].concat(bytes), 256);
|
||||
assert(result instanceof BigInteger);
|
||||
|
||||
return result;
|
||||
return sjcl.bn.fromBits(sjcl.codec.bytes.toBits(bytes));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -247,7 +221,7 @@ var STHash128 = exports.Hash128 = new SerializedType({
|
||||
if (!hash.is_valid()) {
|
||||
throw new Error('Invalid Hash128');
|
||||
}
|
||||
serializeHex(so, hash.to_hex(), true); //noLength = true
|
||||
serializeBits(so, hash.to_bits(), true); //noLength = true
|
||||
},
|
||||
parse: function (so) {
|
||||
return UInt128.from_bytes(so.read(16));
|
||||
@@ -262,7 +236,7 @@ var STHash256 = exports.Hash256 = new SerializedType({
|
||||
if (!hash.is_valid()) {
|
||||
throw new Error('Invalid Hash256');
|
||||
}
|
||||
serializeHex(so, hash.to_hex(), true); //noLength = true
|
||||
serializeBits(so, hash.to_bits(), true); //noLength = true
|
||||
},
|
||||
parse: function (so) {
|
||||
return UInt256.from_bytes(so.read(32));
|
||||
@@ -277,7 +251,7 @@ var STHash160 = exports.Hash160 = new SerializedType({
|
||||
if (!hash.is_valid()) {
|
||||
throw new Error('Invalid Hash160');
|
||||
}
|
||||
serializeHex(so, hash.to_hex(), true); //noLength = true
|
||||
serializeBits(so, hash.to_bits(), true); //noLength = true
|
||||
},
|
||||
parse: function (so) {
|
||||
return UInt160.from_bytes(so.read(20));
|
||||
@@ -288,7 +262,7 @@ STHash160.id = 17;
|
||||
|
||||
// Internal
|
||||
var STCurrency = new SerializedType({
|
||||
serialize: function (so, val, xrp_as_ascii) {
|
||||
serialize: function (so, val) {
|
||||
var currencyData = val.to_bytes();
|
||||
|
||||
if (!currencyData) {
|
||||
@@ -317,11 +291,14 @@ var STAmount = exports.Amount = new SerializedType({
|
||||
throw new Error('Not a valid Amount object.');
|
||||
}
|
||||
|
||||
var value = new BigNumber(amount.to_text());
|
||||
var offset = value.e - 15;
|
||||
|
||||
// Amount (64-bit integer)
|
||||
var valueBytes = utils.arraySet(8, 0);
|
||||
|
||||
if (amount.is_native()) {
|
||||
var valueHex = amount._value.toString(16);
|
||||
var valueHex = value.absoluteValue().toString(16);
|
||||
|
||||
// Enforce correct length (64 bits)
|
||||
if (valueHex.length > 16) {
|
||||
@@ -332,7 +309,7 @@ var STAmount = exports.Amount = new SerializedType({
|
||||
valueHex = '0' + valueHex;
|
||||
}
|
||||
|
||||
valueBytes = bytes.fromBits(hex.toBits(valueHex));
|
||||
valueBytes = sjcl.codec.bytes.fromBits(sjcl.codec.hex.toBits(valueHex));
|
||||
// Clear most significant two bits - these bits should already be 0 if
|
||||
// Amount enforces the range correctly, but we'll clear them anyway just
|
||||
// so this code can make certain guarantees about the encoded value.
|
||||
@@ -354,10 +331,16 @@ var STAmount = exports.Amount = new SerializedType({
|
||||
}
|
||||
|
||||
// Next eight bits: offset/exponent
|
||||
hi |= ((97 + amount._offset) & 0xff) << 22;
|
||||
hi |= ((97 + offset) & 0xff) << 22;
|
||||
|
||||
// Remaining 54 bits: mantissa
|
||||
hi |= amount._value.shiftRight(32).intValue() & 0x3fffff;
|
||||
lo = amount._value.intValue() & 0xffffffff;
|
||||
var mantissaDecimal = utils.getMantissaDecimalString(value.abs());
|
||||
var mantissaHex = (new BigNumber(mantissaDecimal)).toString(16);
|
||||
assert(mantissaHex.length <= 16,
|
||||
'Mantissa hex representation ' + mantissaHex +
|
||||
' exceeds the maximum length of 16');
|
||||
hi |= parseInt(mantissaHex.slice(0, -8), 16) & 0x3fffff;
|
||||
lo = parseInt(mantissaHex.slice(-8), 16);
|
||||
}
|
||||
|
||||
valueBytes = sjcl.codec.bytes.fromBits([hi, lo]);
|
||||
@@ -375,7 +358,6 @@ var STAmount = exports.Amount = new SerializedType({
|
||||
}
|
||||
},
|
||||
parse: function (so) {
|
||||
var amount = new Amount();
|
||||
var value_bytes = so.read(8);
|
||||
var is_zero = !(value_bytes[0] & 0x7f);
|
||||
|
||||
@@ -383,6 +365,8 @@ var STAmount = exports.Amount = new SerializedType({
|
||||
is_zero = is_zero && !value_bytes[i];
|
||||
}
|
||||
|
||||
var is_negative = !is_zero && !(value_bytes[0] & 0x40);
|
||||
|
||||
if (value_bytes[0] & 0x80) {
|
||||
//non-native
|
||||
var currency = STCurrency.parse(so);
|
||||
@@ -392,26 +376,23 @@ var STAmount = exports.Amount = new SerializedType({
|
||||
var offset = ((value_bytes[0] & 0x3f) << 2) + (value_bytes[1] >>> 6) - 97;
|
||||
var mantissa_bytes = value_bytes.slice(1);
|
||||
mantissa_bytes[0] &= 0x3f;
|
||||
var value = new BigInteger(mantissa_bytes, 256);
|
||||
var mantissa = new BigNumber(utils.arrayToHex(mantissa_bytes), 16);
|
||||
var sign = is_negative ? '-' : '';
|
||||
var valueString = sign + mantissa.toString() + 'e' + offset.toString();
|
||||
|
||||
if (value.equals(BigInteger.ZERO) && !is_zero ) {
|
||||
throw new Error('Invalid zero representation');
|
||||
}
|
||||
|
||||
amount._value = value;
|
||||
amount._offset = offset;
|
||||
amount._currency = currency;
|
||||
amount._issuer = issuer;
|
||||
amount._is_native = false;
|
||||
return Amount.from_json({
|
||||
currency: currency,
|
||||
issuer: issuer.to_json(),
|
||||
value: valueString
|
||||
});
|
||||
} else {
|
||||
//native
|
||||
var integer_bytes = value_bytes.slice();
|
||||
integer_bytes[0] &= 0x3f;
|
||||
amount._value = new BigInteger(integer_bytes, 256);
|
||||
amount._is_native = true;
|
||||
var integer_hex = utils.arrayToHex(integer_bytes);
|
||||
var value = new BigNumber(integer_hex, 16);
|
||||
return Amount.from_json((is_negative ? '-' : '') + value.toString());
|
||||
}
|
||||
amount._is_negative = !is_zero && !(value_bytes[0] & 0x40);
|
||||
return amount;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -440,7 +421,7 @@ var STAccount = exports.Account = new SerializedType({
|
||||
if (!account.is_valid()) {
|
||||
throw new Error('Invalid account!');
|
||||
}
|
||||
serializeHex(so, account.to_hex());
|
||||
serializeBits(so, account.to_bits());
|
||||
},
|
||||
parse: function (so) {
|
||||
var len = this.parse_varint(so);
|
||||
@@ -493,7 +474,7 @@ var STPathSet = exports.PathSet = new SerializedType({
|
||||
STInt8.serialize(so, type);
|
||||
|
||||
if (entry.account) {
|
||||
so.append(UInt160.from_json(entry.account).to_bytes());
|
||||
STHash160.serialize(so, entry.account);
|
||||
}
|
||||
|
||||
if (entry.currency) {
|
||||
@@ -502,7 +483,7 @@ var STPathSet = exports.PathSet = new SerializedType({
|
||||
}
|
||||
|
||||
if (entry.issuer) {
|
||||
so.append(UInt160.from_json(entry.issuer).to_bytes());
|
||||
STHash160.serialize(so, entry.issuer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -572,7 +553,7 @@ var STPathSet = exports.PathSet = new SerializedType({
|
||||
|
||||
if (entry.account || entry.currency || entry.issuer) {
|
||||
entry.type = type;
|
||||
entry.type_hex = ("000000000000000" + type.toString(16)).slice(-16);
|
||||
entry.type_hex = ('000000000000000' + type.toString(16)).slice(-16);
|
||||
|
||||
current_path.push(entry);
|
||||
} else {
|
||||
@@ -593,7 +574,7 @@ STPathSet.id = 18;
|
||||
|
||||
var STVector256 = exports.Vector256 = new SerializedType({
|
||||
serialize: function (so, val) { //Assume val is an array of STHash256 objects.
|
||||
var length_as_varint = SerializedType.serialize_varint(so, val.length * 32);
|
||||
SerializedType.serialize_varint(so, val.length * 32);
|
||||
for (var i=0, l=val.length; i<l; i++) {
|
||||
STHash256.serialize(so, val[i]);
|
||||
}
|
||||
@@ -612,7 +593,7 @@ var STVector256 = exports.Vector256 = new SerializedType({
|
||||
STVector256.id = 19;
|
||||
|
||||
// Internal
|
||||
var STMemo = exports.STMemo = new SerializedType({
|
||||
exports.STMemo = new SerializedType({
|
||||
serialize: function(so, val, no_marker) {
|
||||
|
||||
var keys = [];
|
||||
@@ -682,29 +663,29 @@ var STMemo = exports.STMemo = new SerializedType({
|
||||
output[keyval[0]] = keyval[1];
|
||||
}
|
||||
|
||||
if (output['MemoType'] !== void(0)) {
|
||||
var parsedType = convertHexToString(output['MemoType']);
|
||||
if (output.MemoType !== void(0)) {
|
||||
var parsedType = convertHexToString(output.MemoType);
|
||||
|
||||
if (parsedType !== 'unformatted_memo') {
|
||||
output['parsed_memo_type'] = convertHexToString(output['MemoType']);
|
||||
output.parsed_memo_type = convertHexToString(output.MemoType);
|
||||
}
|
||||
}
|
||||
|
||||
if (output['MemoFormat'] !== void(0)) {
|
||||
output['parsed_memo_format'] = convertHexToString(output['MemoFormat']);
|
||||
if (output.MemoFormat !== void(0)) {
|
||||
output.parsed_memo_format = convertHexToString(output.MemoFormat);
|
||||
}
|
||||
|
||||
if (output['MemoData'] !== void(0)) {
|
||||
if (output.MemoData !== void(0)) {
|
||||
|
||||
// see if we can parse JSON
|
||||
if (output['parsed_memo_format'] === 'json') {
|
||||
if (output.parsed_memo_format === 'json') {
|
||||
try {
|
||||
output['parsed_memo_data'] = JSON.parse(convertHexToString(output['MemoData']));
|
||||
output.parsed_memo_data = JSON.parse(convertHexToString(output.MemoData));
|
||||
} catch(e) {
|
||||
// fail, which is fine, we just won't add the memo_data field
|
||||
}
|
||||
} else if(output['parsed_memo_format'] === 'text') {
|
||||
output['parsed_memo_data'] = convertHexToString(output['MemoData']);
|
||||
} else if(output.parsed_memo_format === 'text') {
|
||||
output.parsed_memo_data = convertHexToString(output.MemoData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -788,7 +769,7 @@ function parse(so) {
|
||||
assert(type, 'Unknown type - header byte is 0x' + tag_byte.toString(16));
|
||||
|
||||
return [ field_name, type.parse(so) ]; //key, value
|
||||
};
|
||||
}
|
||||
|
||||
function sort_fields(keys) {
|
||||
function sort_field_compare(a, b) {
|
||||
@@ -801,7 +782,7 @@ function sort_fields(keys) {
|
||||
|
||||
// Sort by type id first, then by field id
|
||||
return a_type_bits !== b_type_bits ? a_type_bits - b_type_bits : a_field_bits - b_field_bits;
|
||||
};
|
||||
}
|
||||
|
||||
return keys.sort(sort_field_compare);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ var utils = require('./utils');
|
||||
var sjcl = utils.sjcl;
|
||||
var config = require('./config');
|
||||
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
//
|
||||
// Abstract UInt class
|
||||
//
|
||||
@@ -11,7 +9,7 @@ var BigInteger = utils.jsbn.BigInteger;
|
||||
//
|
||||
|
||||
var UInt = function() {
|
||||
// Internal form: NaN or BigInteger
|
||||
// Internal form: NaN or sjcl.bn
|
||||
this._value = NaN;
|
||||
this._update();
|
||||
};
|
||||
@@ -107,17 +105,15 @@ UInt.prototype.copyTo = function(d) {
|
||||
};
|
||||
|
||||
UInt.prototype.equals = function(d) {
|
||||
return this._value instanceof BigInteger
|
||||
&& d._value instanceof BigInteger
|
||||
&& this._value.equals(d._value);
|
||||
return this.is_valid() && d.is_valid() && this._value.equals(d._value);
|
||||
};
|
||||
|
||||
UInt.prototype.is_valid = function() {
|
||||
return this._value instanceof BigInteger;
|
||||
return this._value instanceof sjcl.bn;
|
||||
};
|
||||
|
||||
UInt.prototype.is_zero = function() {
|
||||
return this._value.equals(BigInteger.ZERO);
|
||||
return this.is_valid() && this._value.equals(new sjcl.bn(0));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -147,24 +143,25 @@ UInt.prototype.parse_generic = function(j) {
|
||||
case this.constructor.STR_ZERO:
|
||||
case this.constructor.ACCOUNT_ZERO:
|
||||
case this.constructor.HEX_ZERO:
|
||||
this._value = BigInteger.valueOf();
|
||||
this._value = new sjcl.bn(0);
|
||||
break;
|
||||
|
||||
case '1':
|
||||
case this.constructor.STR_ONE:
|
||||
case this.constructor.ACCOUNT_ONE:
|
||||
case this.constructor.HEX_ONE:
|
||||
this._value = new BigInteger([1]);
|
||||
this._value = new sjcl.bn(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (typeof j !== 'string') {
|
||||
this._value = NaN;
|
||||
} else if (this.constructor.width === j.length) {
|
||||
this._value = new BigInteger(utils.stringToArray(j), 256);
|
||||
var hex = utils.arrayToHex(utils.stringToArray(j));
|
||||
this._value = new sjcl.bn(hex, 16);
|
||||
} else if ((this.constructor.width * 2) === j.length) {
|
||||
// XXX Check char set!
|
||||
this._value = new BigInteger(j, 16);
|
||||
this._value = new sjcl.bn(j, 16);
|
||||
} else {
|
||||
this._value = NaN;
|
||||
}
|
||||
@@ -177,7 +174,7 @@ UInt.prototype.parse_generic = function(j) {
|
||||
|
||||
UInt.prototype.parse_hex = function(j) {
|
||||
if (typeof j === 'string' && j.length === (this.constructor.width * 2)) {
|
||||
this._value = new BigInteger(j, 16);
|
||||
this._value = new sjcl.bn(j, 16);
|
||||
} else {
|
||||
this._value = NaN;
|
||||
}
|
||||
@@ -191,8 +188,9 @@ UInt.prototype.parse_bits = function(j) {
|
||||
if (sjcl.bitArray.bitLength(j) !== this.constructor.width * 8) {
|
||||
this._value = NaN;
|
||||
} else {
|
||||
var bytes = sjcl.codec.bytes.fromBits(j);
|
||||
this.parse_bytes(bytes);
|
||||
this._value = sjcl.bn.fromBits(j);
|
||||
// var bytes = sjcl.codec.bytes.fromBits(j);
|
||||
// this.parse_bytes(bytes);
|
||||
}
|
||||
|
||||
this._update();
|
||||
@@ -205,7 +203,8 @@ UInt.prototype.parse_bytes = function(j) {
|
||||
if (!Array.isArray(j) || j.length !== this.constructor.width) {
|
||||
this._value = NaN;
|
||||
} else {
|
||||
this._value = new BigInteger([0].concat(j), 256);
|
||||
var bits = sjcl.codec.bytes.toBits(j);
|
||||
this._value = sjcl.bn.fromBits(bits);
|
||||
}
|
||||
|
||||
this._update();
|
||||
@@ -218,8 +217,9 @@ UInt.prototype.parse_json = UInt.prototype.parse_hex;
|
||||
|
||||
UInt.prototype.parse_bn = function(j) {
|
||||
if ((j instanceof sjcl.bn) && j.bitLength() <= this.constructor.width * 8) {
|
||||
var bytes = sjcl.codec.bytes.fromBits(j.toBits());
|
||||
this._value = new BigInteger(bytes, 256);
|
||||
// var bytes = sjcl.codec.bytes.fromBits(j.toBits());
|
||||
// this._value = new sjcl.bn(utils.arrayToHex(bytes), 16);
|
||||
this._value = new sjcl.bn(j);
|
||||
} else {
|
||||
this._value = NaN;
|
||||
}
|
||||
@@ -233,7 +233,7 @@ UInt.prototype.parse_number = function(j) {
|
||||
this._value = NaN;
|
||||
|
||||
if (typeof j === 'number' && isFinite(j) && j >= 0) {
|
||||
this._value = new BigInteger(String(j));
|
||||
this._value = new sjcl.bn(j);
|
||||
}
|
||||
|
||||
this._update();
|
||||
@@ -243,51 +243,31 @@ UInt.prototype.parse_number = function(j) {
|
||||
|
||||
// Convert from internal form.
|
||||
UInt.prototype.to_bytes = function() {
|
||||
if (!(this._value instanceof BigInteger)) {
|
||||
if (!this.is_valid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bytes = this._value.toByteArray();
|
||||
|
||||
bytes = bytes.map(function(b) {
|
||||
return (b + 256) % 256;
|
||||
});
|
||||
|
||||
var target = this.constructor.width;
|
||||
|
||||
// XXX Make sure only trim off leading zeros.
|
||||
bytes = bytes.slice(-target);
|
||||
|
||||
while (bytes.length < target) {
|
||||
bytes.unshift(0);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
return sjcl.codec.bytes.fromBits(this.to_bits());
|
||||
};
|
||||
|
||||
UInt.prototype.to_hex = function() {
|
||||
if (!(this._value instanceof BigInteger)) {
|
||||
if (!this.is_valid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bytes = this.to_bytes();
|
||||
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(bytes)).toUpperCase();
|
||||
return sjcl.codec.hex.fromBits(this.to_bits()).toUpperCase();
|
||||
};
|
||||
|
||||
UInt.prototype.to_json = UInt.prototype.to_hex;
|
||||
|
||||
UInt.prototype.to_bits = function() {
|
||||
if (!(this._value instanceof BigInteger)) {
|
||||
if (!this.is_valid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bytes = this.to_bytes();
|
||||
|
||||
return sjcl.codec.bytes.toBits(bytes);
|
||||
return this._value.toBits(this.constructor.width * 8);
|
||||
};
|
||||
|
||||
UInt.prototype.to_bn = function() {
|
||||
if (!(this._value instanceof BigInteger)) {
|
||||
if (!this.is_valid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ var UInt = require('./uint').UInt;
|
||||
//
|
||||
|
||||
var UInt128 = extend(function () {
|
||||
// Internal form: NaN or BigInteger
|
||||
this._value = NaN;
|
||||
}, UInt);
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ var utils = require('./utils');
|
||||
var config = require('./config');
|
||||
var extend = require('extend');
|
||||
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
var UInt = require('./uint').UInt;
|
||||
var Base = require('./base').Base;
|
||||
|
||||
@@ -12,7 +10,6 @@ var Base = require('./base').Base;
|
||||
//
|
||||
|
||||
var UInt160 = extend(function() {
|
||||
// Internal form: NaN or BigInteger
|
||||
this._value = NaN;
|
||||
this._version_byte = void(0);
|
||||
this._update();
|
||||
@@ -49,7 +46,7 @@ UInt160.prototype.parse_json = function(j) {
|
||||
// Allow raw numbers - DEPRECATED
|
||||
// This is used mostly by the test suite and is supported
|
||||
// as a legacy feature only. DO NOT RELY ON THIS BEHAVIOR.
|
||||
this._value = new BigInteger(String(j));
|
||||
this.parse_number(j);
|
||||
this._version_byte = Base.VER_ACCOUNT_ID;
|
||||
} else if (typeof j !== 'string') {
|
||||
this._value = NaN;
|
||||
@@ -83,7 +80,7 @@ UInt160.prototype.parse_generic = function(j) {
|
||||
UInt160.prototype.to_json = function(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
if (this._value instanceof BigInteger) {
|
||||
if (this.is_valid()) {
|
||||
// If this value has a type, return a Base58 encoded string.
|
||||
if (typeof this._version_byte === 'number') {
|
||||
var output = Base.encode_check(this._version_byte, this.to_bytes());
|
||||
|
||||
@@ -7,7 +7,6 @@ var UInt = require('./uint').UInt;
|
||||
//
|
||||
|
||||
var UInt256 = extend(function() {
|
||||
// Internal form: NaN or BigInteger
|
||||
this._value = NaN;
|
||||
}, UInt);
|
||||
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
|
||||
function getMantissaDecimalString(bignum) {
|
||||
var mantissa = bignum.toPrecision(16)
|
||||
.replace(/\./, '') // remove decimal point
|
||||
.replace(/e.*/, '') // remove scientific notation
|
||||
.replace(/^0*/, ''); // remove leading zeroes
|
||||
while (mantissa.length < 16) {
|
||||
mantissa += '0'; // add trailing zeroes until length is 16
|
||||
}
|
||||
return mantissa;
|
||||
}
|
||||
|
||||
function filterErr(code, done) {
|
||||
return function(e) {
|
||||
done(e.code !== code ? e : void(0));
|
||||
@@ -69,6 +81,13 @@ function hexToArray(h) {
|
||||
return stringToArray(hexToString(h));
|
||||
};
|
||||
|
||||
function arrayToHex(a) {
|
||||
return a.map(function(byteValue) {
|
||||
var hex = byteValue.toString(16);
|
||||
return hex.length > 1 ? hex : '0' + hex;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function chunkString(str, n, leftAlign) {
|
||||
var ret = [];
|
||||
var i=0, len=str.length;
|
||||
@@ -144,15 +163,16 @@ exports.hexToString = hexToString;
|
||||
exports.hexToArray = hexToArray;
|
||||
exports.stringToArray = stringToArray;
|
||||
exports.stringToHex = stringToHex;
|
||||
exports.arrayToHex = arrayToHex;
|
||||
exports.chunkString = chunkString;
|
||||
exports.assert = assert;
|
||||
exports.arrayUnique = arrayUnique;
|
||||
exports.toTimestamp = toTimestamp;
|
||||
exports.fromTimestamp = fromTimestamp;
|
||||
exports.getMantissaDecimalString = getMantissaDecimalString;
|
||||
|
||||
// Going up three levels is needed to escape the src-cov folder used for the
|
||||
// test coverage stuff.
|
||||
exports.sjcl = require('../../../build/sjcl');
|
||||
exports.jsbn = require('../../../src/js/jsbn/jsbn');
|
||||
|
||||
// vim:sw=2:sts=2:ts=8:et
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
var assert = require('assert');
|
||||
var BigInteger = require('ripple-lib').jsbn.BigInteger;
|
||||
var Amount = require('ripple-lib').Amount;
|
||||
var UInt160 = require('ripple-lib').UInt160;
|
||||
var load_config = require('ripple-lib').config.load;
|
||||
@@ -127,6 +126,9 @@ describe('Amount', function() {
|
||||
it('1 XRP human', function() {
|
||||
assert.strictEqual(Amount.from_human("1 XRP").to_human_full(), '1/XRP');
|
||||
});
|
||||
it('1XRP human', function() {
|
||||
assert.strictEqual(Amount.from_human('1XRP').to_human_full(), '1/XRP');
|
||||
});
|
||||
it('0.1 XRP', function() {
|
||||
assert.strictEqual(Amount.from_human("0.1 XRP").to_text_full(), '0.1/XRP');
|
||||
});
|
||||
@@ -281,14 +283,11 @@ describe('Amount', function() {
|
||||
});
|
||||
});
|
||||
describe('UInt160', function() {
|
||||
it('Parse 0', function () {
|
||||
assert.deepEqual(new BigInteger(), UInt160.from_generic('0')._value);
|
||||
});
|
||||
it('Parse 0 export', function () {
|
||||
assert.strictEqual(UInt160.ACCOUNT_ZERO, UInt160.from_generic('0').set_version(0).to_json());
|
||||
});
|
||||
it('Parse 1', function () {
|
||||
assert.deepEqual(new BigInteger([1]), UInt160.from_generic('1')._value);
|
||||
assert.deepEqual(UInt160.ACCOUNT_ONE, UInt160.from_generic('1').set_version(0).to_json());
|
||||
});
|
||||
it('Parse rrrrrrrrrrrrrrrrrrrrrhoLvTp export', function () {
|
||||
assert.strictEqual(UInt160.ACCOUNT_ZERO, UInt160.from_json('rrrrrrrrrrrrrrrrrrrrrhoLvTp').to_json());
|
||||
@@ -973,7 +972,7 @@ describe('Amount', function() {
|
||||
assert.strictEqual(Amount.from_json('10000000').product_human(Amount.from_json('10')).to_text_full(), '0.0001/XRP');
|
||||
});
|
||||
it('Multiply USD with XAU (dem)', function () {
|
||||
assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_text_full(), '19900.00316303882/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||
assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_text_full(), '19900.00316303883/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||
});
|
||||
it('Multiply 0 XRP with 0 XRP human', function () {
|
||||
assert.strictEqual('0/XRP', Amount.from_json('0').product_human(Amount.from_json('0')).to_human_full());
|
||||
@@ -1045,7 +1044,7 @@ describe('Amount', function() {
|
||||
assert.strictEqual(Amount.from_json('10000000').product_human(Amount.from_json('10')).to_human_full(), '0.0001/XRP');
|
||||
});
|
||||
it('Multiply USD with XAU (dem) human', function () {
|
||||
assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_human_full(), '19,900.00316303882/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1220,7 +1219,6 @@ describe('Amount', function() {
|
||||
|
||||
it ('from_json minimum IOU', function() {
|
||||
var amt = Amount.from_json('-1e-81/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||
assert.strictEqual(amt._value.toString(), Amount.bi_man_min_value.toString());
|
||||
assert.strictEqual(amt.to_text(), '-1000000000000000e-96');
|
||||
assert.strictEqual(amt.to_text(), Amount.min_value);
|
||||
});
|
||||
@@ -1233,7 +1231,6 @@ describe('Amount', function() {
|
||||
|
||||
it ('from_json maximum IOU', function() {
|
||||
var amt = Amount.from_json('9999999999999999e80/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||
assert.strictEqual(amt._value.toString(), Amount.bi_man_max_value.toString());
|
||||
assert.strictEqual(amt.to_text(), '9999999999999999e80');
|
||||
});
|
||||
|
||||
@@ -1245,13 +1242,11 @@ describe('Amount', function() {
|
||||
|
||||
it ('from_json normalize mantissa to valid max range, lost significant digits', function() {
|
||||
var amt = Amount.from_json('99999999999999999999999999999999/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||
assert.strictEqual(amt._value.toString(), Amount.bi_man_max_value.toString());
|
||||
assert.strictEqual(amt.to_text(), '9999999999999999e16');
|
||||
});
|
||||
|
||||
it ('from_json normalize mantissa to min valid range, lost significant digits', function() {
|
||||
var amt = Amount.from_json('-0.0000000000000000000000001/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||
assert.strictEqual(amt._value.toString(), Amount.bi_man_min_value.toString());
|
||||
assert.strictEqual(amt.to_text(), '-1000000000000000e-40');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1566,8 +1566,8 @@ describe('OrderBook', function() {
|
||||
},
|
||||
index: 'B6BC3B0F87976370EE11F5575593FE63AA5DC1D602830DC96F04B2D597F044BF',
|
||||
owner_funds: '0.1129267125000245',
|
||||
taker_gets_funded: '0.1127013098802639',
|
||||
taker_pays_funded: '55.95620035555102',
|
||||
taker_gets_funded: '0.112701309880264',
|
||||
taker_pays_funded: '55.95620035555106',
|
||||
is_fully_funded: false },
|
||||
|
||||
{ Account: 'raudnGKfTK23YKfnS7ixejHrqGERTYNFXk',
|
||||
|
||||
@@ -2,7 +2,7 @@ var assert = require('assert');
|
||||
var SerializedObject = require('ripple-lib').SerializedObject;
|
||||
var types = require('ripple-lib').types;
|
||||
var Amount = require('ripple-lib').Amount;
|
||||
var BigInteger = require('ripple-lib').jsbn.BigInteger;
|
||||
var sjcl = require('ripple-lib').sjcl;
|
||||
|
||||
describe('Serialized types', function() {
|
||||
describe('Int8', function() {
|
||||
@@ -287,7 +287,7 @@ describe('Serialized types', function() {
|
||||
var so = new SerializedObject("8B2386F26F8E232B");
|
||||
var num = types.Int64.parse(so);
|
||||
// We get a positive number
|
||||
assert.strictEqual(num.toString(16), '8b2386f26f8e232b');
|
||||
assert.strictEqual(num.toString(), '0x8b2386f26f8e232b');
|
||||
});
|
||||
it('Serialize "0123456789ABCDEF"', function () {
|
||||
var so = new SerializedObject();
|
||||
@@ -299,15 +299,15 @@ describe('Serialized types', function() {
|
||||
types.Int64.serialize(so, 'F0E1D2C3B4A59687');
|
||||
assert.strictEqual(so.to_hex(), 'F0E1D2C3B4A59687');
|
||||
});
|
||||
it('Serialize BigInteger("FFEEDDCCBBAA9988")', function () {
|
||||
it('Serialize bn("FFEEDDCCBBAA9988")', function () {
|
||||
var so = new SerializedObject();
|
||||
types.Int64.serialize(so, new BigInteger('FFEEDDCCBBAA9988', 16));
|
||||
types.Int64.serialize(so, new sjcl.bn('FFEEDDCCBBAA9988', 16));
|
||||
assert.strictEqual(so.to_hex(), 'FFEEDDCCBBAA9988');
|
||||
});
|
||||
it('Fail to serialize BigInteger("-1")', function () {
|
||||
it('Fail to serialize BigNumber("-1")', function () {
|
||||
var so = new SerializedObject();
|
||||
assert.throws(function () {
|
||||
types.Int64.serialize(so, new BigInteger('-1', 10));
|
||||
types.Int64.serialize(so, new BigNumber('-1', 10));
|
||||
});
|
||||
});
|
||||
it('Fail to serialize "10000000000000000"', function () {
|
||||
@@ -343,7 +343,7 @@ describe('Serialized types', function() {
|
||||
it('Parse "0123456789ABCDEF"', function () {
|
||||
var so = new SerializedObject("0123456789ABCDEF");
|
||||
var num = types.Int64.parse(so);
|
||||
assert.strictEqual(num.toString(10), '81985529216486895');
|
||||
assert.strictEqual(num.toString(), '0x123456789abcdef');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ describe('UInt', function() {
|
||||
assert.strictEqual(val.to_hex(), '00000000000000000000000000000000');
|
||||
});
|
||||
it('should create 00000000000000000000000000000001 when called with 1', function () {
|
||||
var val = UInt128.from_number(0);
|
||||
assert.strictEqual(val.to_hex(), '00000000000000000000000000000000');
|
||||
var val = UInt128.from_number(1);
|
||||
assert.strictEqual(val.to_hex(), '00000000000000000000000000000001');
|
||||
});
|
||||
it('should create 000000000000000000000000FFFFFFFF when called with 0xFFFFFFFF', function () {
|
||||
var val = UInt128.from_number(0xFFFFFFFF);
|
||||
|
||||
Reference in New Issue
Block a user