[TASK] Refactor to use bignumber.js

This commit is contained in:
Chris Clark
2015-01-08 17:33:37 -08:00
parent 2cab50f920
commit d025b4a0c3
20 changed files with 571 additions and 1989 deletions

5
npm-shrinkwrap.json generated
View File

@@ -7,6 +7,11 @@
"from": "async@>=0.8.0 <0.9.0", "from": "async@>=0.8.0 <0.9.0",
"resolved": "https://registry.npmjs.org/async/-/async-0.8.0.tgz" "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": { "extend": {
"version": "1.2.1", "version": "1.2.1",
"from": "extend@>=1.2.1 <1.3.0", "from": "extend@>=1.2.1 <1.3.0",

View File

@@ -16,6 +16,7 @@
}, },
"dependencies": { "dependencies": {
"async": "~0.8.0", "async": "~0.8.0",
"bignumber.js": "^2.0.0",
"extend": "~1.2.1", "extend": "~1.2.1",
"lodash": "^2.4.1", "lodash": "^2.4.1",
"lru-cache": "~2.5.0", "lru-cache": "~2.5.0",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,6 @@ var sjcl = require('./utils').sjcl;
var utils = require('./utils'); var utils = require('./utils');
var extend = require('extend'); var extend = require('extend');
var BigInteger = utils.jsbn.BigInteger;
var Base = {}; var Base = {};
var alphabets = Base.alphabets = { var alphabets = Base.alphabets = {
@@ -25,33 +23,142 @@ extend(Base, {
function sha256(bytes) { function sha256(bytes) {
return sjcl.codec.bytes.fromBits(sjcl.hash.sha256.hash(sjcl.codec.bytes.toBits(bytes))); return sjcl.codec.bytes.fromBits(sjcl.hash.sha256.hash(sjcl.codec.bytes.toBits(bytes)));
}; }
function sha256hash(bytes) { function sha256hash(bytes) {
return sha256(sha256(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. // --> input: big-endian array of bytes.
// <-- string at least as long as input. // <-- string at least as long as input.
Base.encode = function(input, alpha) { Base.encode = function(input, alpha) {
var alphabet = alphabets[alpha || 'ripple']; return this.encoders[alpha || 'ripple'].encode(input);
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('');
}; };
// --> input: String // --> input: String
@@ -60,48 +167,12 @@ Base.decode = function(input, alpha) {
if (typeof input !== 'string') { if (typeof input !== 'string') {
return void(0); return void(0);
} }
try {
var alphabet = alphabets[alpha || 'ripple']; return this.encoders[alpha || 'ripple'].decode(input);
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) {
} }
catch(e) {
for (; i !== input.length; i += 1) { return (void 0);
var v = alphabet.indexOf(input[i]);
if (v < 0) {
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) { Base.verify_checksum = function(bytes) {
@@ -129,7 +200,7 @@ Base.encode_check = function(version, input, alphabet) {
}; };
// --> input : String // --> input : String
// <-- NaN || BigInteger // <-- NaN || sjcl.bn
Base.decode_check = function(version, input, alphabet) { Base.decode_check = function(version, input, alphabet) {
var buffer = Base.decode(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 // intrepret the value as a negative number
buffer[0] = 0; 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; exports.Base = Base;

View 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;

View File

@@ -308,7 +308,7 @@ Currency.prototype.get_interest_percentage_at = function(referenceDate, decimals
// currency data, since there are some values that are invalid. // currency data, since there are some values that are invalid.
// //
//Currency.prototype.is_valid = function() { //Currency.prototype.is_valid = function() {
// return this._value instanceof BigInteger && ...; // return UInt.prototype.is_valid() && ...;
//}; //};
Currency.prototype.to_json = function(opts) { Currency.prototype.to_json = function(opts) {

View File

@@ -29,7 +29,6 @@ exports.RangeSet = require('./rangeset').RangeSet;
// the official client, it makes sense to expose the SJCL instance so we don't // the official client, it makes sense to expose the SJCL instance so we don't
// have to include it twice. // have to include it twice.
exports.sjcl = require('./utils').sjcl; exports.sjcl = require('./utils').sjcl;
exports.jsbn = require('./utils').jsbn;
exports.types = require('./serializedtypes'); exports.types = require('./serializedtypes');
exports.config = require('./config'); exports.config = require('./config');

View File

@@ -6,8 +6,6 @@ var extend = require('extend');
var utils = require('./utils'); var utils = require('./utils');
var sjcl = utils.sjcl; var sjcl = utils.sjcl;
var BigInteger = utils.jsbn.BigInteger;
var Base = require('./base').Base; var Base = require('./base').Base;
var UInt = require('./uint').UInt; var UInt = require('./uint').UInt;
var UInt256 = require('./uint256').UInt256; var UInt256 = require('./uint256').UInt256;
@@ -15,7 +13,6 @@ var UInt160 = require('./uint160').UInt160;
var KeyPair = require('./keypair').KeyPair; var KeyPair = require('./keypair').KeyPair;
var Seed = extend(function () { var Seed = extend(function () {
// Internal form: NaN or BigInteger
this._curve = sjcl.ecc.curves.k256; this._curve = sjcl.ecc.curves.k256;
this._value = NaN; this._value = NaN;
}, UInt); }, UInt);
@@ -60,7 +57,7 @@ Seed.prototype.parse_passphrase = function (j) {
}; };
Seed.prototype.to_json = function () { Seed.prototype.to_json = function () {
if (!(this._value instanceof BigInteger)) { if (!(this.is_valid())) {
return NaN; return NaN;
} }

View File

@@ -1,13 +1,12 @@
var _ = require('lodash');
var assert = require('assert'); var assert = require('assert');
var extend = require('extend'); var extend = require('extend');
var binformat = require('./binformat'); var binformat = require('./binformat');
var stypes = require('./serializedtypes'); var stypes = require('./serializedtypes');
var UInt256 = require('./uint256').UInt256;
var Crypt = require('./crypt').Crypt; var Crypt = require('./crypt').Crypt;
var utils = require('./utils'); var utils = require('./utils');
var sjcl = utils.sjcl; var sjcl = utils.sjcl;
var BigInteger = utils.jsbn.BigInteger;
var TRANSACTION_TYPES = { }; var TRANSACTION_TYPES = { };
@@ -27,6 +26,13 @@ Object.keys(binformat.ter).forEach(function(key) {
TRANSACTION_RESULTS[binformat.ter[key]] = 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) { function SerializedObject(buf) {
if (Array.isArray(buf) || (Buffer && Buffer.isBuffer(buf)) ) { if (Array.isArray(buf) || (Buffer && Buffer.isBuffer(buf)) ) {
this.buffer = buf; this.buffer = buf;
@@ -38,11 +44,11 @@ function SerializedObject(buf) {
throw new Error('Invalid buffer passed.'); throw new Error('Invalid buffer passed.');
} }
this.pointer = 0; this.pointer = 0;
}; }
SerializedObject.from_json = function(obj) { SerializedObject.from_json = function(obj) {
// Create a copy of the object so we don't modify it // 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 so = new SerializedObject();
var typedef; var typedef;
@@ -103,8 +109,8 @@ SerializedObject.check_no_missing_fields = function(typedef, obj) {
if (binformat.REQUIRED === requirement && obj[field] === void(0)) { if (binformat.REQUIRED === requirement && obj[field] === void(0)) {
missing_fields.push(field); missing_fields.push(field);
}; }
}; }
if (missing_fields.length > 0) { if (missing_fields.length > 0) {
var object_name; var object_name;
@@ -114,12 +120,12 @@ SerializedObject.check_no_missing_fields = function(typedef, obj) {
} else if (obj.LedgerEntryType != null){ } else if (obj.LedgerEntryType != null){
object_name = SerializedObject.lookup_type_le(obj.LedgerEntryType); object_name = SerializedObject.lookup_type_le(obj.LedgerEntryType);
} else { } 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)); JSON.stringify(missing_fields));
}; }
}; };
SerializedObject.prototype.append = function(bytes) { SerializedObject.prototype.append = function(bytes) {
@@ -152,7 +158,7 @@ function readOrPeek(advance) {
return result; return result;
}; };
}; }
SerializedObject.prototype.read = readOrPeek(true); SerializedObject.prototype.read = readOrPeek(true);
@@ -209,8 +215,8 @@ SerializedObject.jsonify_structure = function(structure, field_name) {
if (typeof structure.to_json === 'function') { if (typeof structure.to_json === 'function') {
output = structure.to_json(); output = structure.to_json();
} else if (structure instanceof BigInteger) { } else if (structure instanceof sjcl.bn) {
output = ('0000000000000000' + structure.toString(16).toUpperCase()).slice(-16); output = ('0000000000000000' + normalize_sjcl_bn_hex(structure.toString()).toUpperCase()).slice(-16);
} else { } else {
//new Array or Object //new Array or Object
output = new structure.constructor(); output = new structure.constructor();
@@ -250,7 +256,7 @@ SerializedObject.prototype.hash = function(prefix) {
var sign_buffer = new SerializedObject(); var sign_buffer = new SerializedObject();
// Add hashing prefix // Add hashing prefix
if ("undefined" !== typeof prefix) { if ('undefined' !== typeof prefix) {
stypes.Int32.serialize(sign_buffer, prefix); stypes.Int32.serialize(sign_buffer, prefix);
} }
@@ -312,7 +318,7 @@ SerializedObject.sort_typedef = function(typedef) {
function sort_field_compare(a, b) { function sort_field_compare(a, b) {
// Sort by type id first, then by field id // 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 a[3] !== b[3] ? stypes[a[3]].id - stypes[b[3]].id : a[2] - b[2];
}; }
return typedef.sort(sort_field_compare); return typedef.sort(sort_field_compare);
}; };

View File

@@ -11,6 +11,7 @@ var extend = require('extend');
var binformat = require('./binformat'); var binformat = require('./binformat');
var utils = require('./utils'); var utils = require('./utils');
var sjcl = utils.sjcl; var sjcl = utils.sjcl;
var BigNumber = require('./bignumber');
var UInt128 = require('./uint128').UInt128; var UInt128 = require('./uint128').UInt128;
var UInt160 = require('./uint160').UInt160; var UInt160 = require('./uint160').UInt160;
@@ -21,59 +22,48 @@ var amount = require('./amount');
var Amount = amount.Amount; var Amount = amount.Amount;
var Currency = amount.Currency; 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) { var SerializedType = function (methods) {
extend(this, methods); extend(this, methods);
}; };
function isNumber(val) { function isNumber(val) {
return typeof val === 'number' && isFinite(val); return typeof val === 'number' && isFinite(val);
}; }
function isString(val) { function isString(val) {
return typeof val === 'string'; return typeof val === 'string';
}; }
function isHexInt64String(val) { function isHexInt64String(val) {
return isString(val) && /^[0-9A-F]{0,16}$/i.test(val); return isString(val) && /^[0-9A-F]{0,16}$/i.test(val);
}; }
function isCurrencyString(val) { function serializeBits(so, bits, noLength) {
return isString(val) && /^[A-Z0-9]{3}$/.test(val); var byteData = sjcl.codec.bytes.fromBits(bits);
};
function isBigInteger(val) {
return val instanceof BigInteger;
};
function serializeHex(so, hexData, noLength) {
var byteData = bytes.fromBits(hex.toBits(hexData));
if (!noLength) { if (!noLength) {
SerializedType.serialize_varint(so, byteData.length); SerializedType.serialize_varint(so, byteData.length);
} }
so.append(byteData); so.append(byteData);
}; }
function serializeHex(so, hexData, noLength) {
serializeBits(so, sjcl.codec.hex.toBits(hexData), noLength);
}
/** /**
* parses bytes as hex * parses bytes as hex
*/ */
function convertByteArrayToHex (byte_array) { function convertByteArrayToHex (byte_array) {
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(byte_array)).toUpperCase(); return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(byte_array)).toUpperCase();
}; }
function convertStringToHex(string) { 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) { 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) { SerializedType.serialize_varint = function (so, val) {
@@ -130,7 +120,7 @@ function convertIntegerToByteArray(val, bytes) {
} }
if (val < 0 || val >= Math.pow(256, 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 = [ ]; var newBytes = [ ];
@@ -140,7 +130,7 @@ function convertIntegerToByteArray(val, bytes) {
} }
return newBytes; return newBytes;
}; }
// Convert a certain number of bytes from the serialized object ('so') into an integer. // Convert a certain number of bytes from the serialized object ('so') into an integer.
function readAndSum(so, bytes) { function readAndSum(so, bytes) {
@@ -157,7 +147,7 @@ function readAndSum(so, bytes) {
// Convert to unsigned integer // Convert to unsigned integer
return sum >>> 0; return sum >>> 0;
}; }
var STInt8 = exports.Int8 = new SerializedType({ var STInt8 = exports.Int8 = new SerializedType({
serialize: function (so, val) { serialize: function (so, val) {
@@ -201,41 +191,25 @@ var STInt64 = exports.Int64 = new SerializedType({
if (val < 0) { if (val < 0) {
throw new Error('Negative value for unsigned Int64 is invalid.'); 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)) { } else if (isString(val)) {
if (!isHexInt64String(val)) { if (!isHexInt64String(val)) {
throw new Error('Not a valid hex Int64.'); throw new Error('Not a valid hex Int64.');
} }
bigNumObject = new BigInteger(val, 16); bigNumObject = new sjcl.bn(val, 16);
} else if (isBigInteger(val)) { } else if (val instanceof sjcl.bn) {
if (val.compareTo(BigInteger.ZERO) < 0) { if (!val.greaterEquals(0)) {
throw new Error('Negative value for unsigned Int64 is invalid.'); throw new Error('Negative value for unsigned Int64 is invalid.');
} }
bigNumObject = val; bigNumObject = val;
} else { } else {
throw new Error('Invalid type for Int64'); throw new Error('Invalid type for Int64');
} }
serializeBits(so, bigNumObject.toBits(64), true); //noLength = true
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
}, },
parse: function (so) { parse: function (so) {
var bytes = so.read(8); 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 return sjcl.bn.fromBits(sjcl.codec.bytes.toBits(bytes));
// pessimistic numeric fraek. What doth lief?
var result = new BigInteger([0].concat(bytes), 256);
assert(result instanceof BigInteger);
return result;
} }
}); });
@@ -247,7 +221,7 @@ var STHash128 = exports.Hash128 = new SerializedType({
if (!hash.is_valid()) { if (!hash.is_valid()) {
throw new Error('Invalid Hash128'); throw new Error('Invalid Hash128');
} }
serializeHex(so, hash.to_hex(), true); //noLength = true serializeBits(so, hash.to_bits(), true); //noLength = true
}, },
parse: function (so) { parse: function (so) {
return UInt128.from_bytes(so.read(16)); return UInt128.from_bytes(so.read(16));
@@ -262,7 +236,7 @@ var STHash256 = exports.Hash256 = new SerializedType({
if (!hash.is_valid()) { if (!hash.is_valid()) {
throw new Error('Invalid Hash256'); throw new Error('Invalid Hash256');
} }
serializeHex(so, hash.to_hex(), true); //noLength = true serializeBits(so, hash.to_bits(), true); //noLength = true
}, },
parse: function (so) { parse: function (so) {
return UInt256.from_bytes(so.read(32)); return UInt256.from_bytes(so.read(32));
@@ -277,7 +251,7 @@ var STHash160 = exports.Hash160 = new SerializedType({
if (!hash.is_valid()) { if (!hash.is_valid()) {
throw new Error('Invalid Hash160'); throw new Error('Invalid Hash160');
} }
serializeHex(so, hash.to_hex(), true); //noLength = true serializeBits(so, hash.to_bits(), true); //noLength = true
}, },
parse: function (so) { parse: function (so) {
return UInt160.from_bytes(so.read(20)); return UInt160.from_bytes(so.read(20));
@@ -288,7 +262,7 @@ STHash160.id = 17;
// Internal // Internal
var STCurrency = new SerializedType({ var STCurrency = new SerializedType({
serialize: function (so, val, xrp_as_ascii) { serialize: function (so, val) {
var currencyData = val.to_bytes(); var currencyData = val.to_bytes();
if (!currencyData) { if (!currencyData) {
@@ -317,11 +291,14 @@ var STAmount = exports.Amount = new SerializedType({
throw new Error('Not a valid Amount object.'); throw new Error('Not a valid Amount object.');
} }
var value = new BigNumber(amount.to_text());
var offset = value.e - 15;
// Amount (64-bit integer) // Amount (64-bit integer)
var valueBytes = utils.arraySet(8, 0); var valueBytes = utils.arraySet(8, 0);
if (amount.is_native()) { if (amount.is_native()) {
var valueHex = amount._value.toString(16); var valueHex = value.absoluteValue().toString(16);
// Enforce correct length (64 bits) // Enforce correct length (64 bits)
if (valueHex.length > 16) { if (valueHex.length > 16) {
@@ -332,7 +309,7 @@ var STAmount = exports.Amount = new SerializedType({
valueHex = '0' + valueHex; 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 // Clear most significant two bits - these bits should already be 0 if
// Amount enforces the range correctly, but we'll clear them anyway just // Amount enforces the range correctly, but we'll clear them anyway just
// so this code can make certain guarantees about the encoded value. // 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 // Next eight bits: offset/exponent
hi |= ((97 + amount._offset) & 0xff) << 22; hi |= ((97 + offset) & 0xff) << 22;
// Remaining 54 bits: mantissa // Remaining 54 bits: mantissa
hi |= amount._value.shiftRight(32).intValue() & 0x3fffff; var mantissaDecimal = utils.getMantissaDecimalString(value.abs());
lo = amount._value.intValue() & 0xffffffff; 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]); valueBytes = sjcl.codec.bytes.fromBits([hi, lo]);
@@ -375,7 +358,6 @@ var STAmount = exports.Amount = new SerializedType({
} }
}, },
parse: function (so) { parse: function (so) {
var amount = new Amount();
var value_bytes = so.read(8); var value_bytes = so.read(8);
var is_zero = !(value_bytes[0] & 0x7f); var is_zero = !(value_bytes[0] & 0x7f);
@@ -383,6 +365,8 @@ var STAmount = exports.Amount = new SerializedType({
is_zero = is_zero && !value_bytes[i]; is_zero = is_zero && !value_bytes[i];
} }
var is_negative = !is_zero && !(value_bytes[0] & 0x40);
if (value_bytes[0] & 0x80) { if (value_bytes[0] & 0x80) {
//non-native //non-native
var currency = STCurrency.parse(so); 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 offset = ((value_bytes[0] & 0x3f) << 2) + (value_bytes[1] >>> 6) - 97;
var mantissa_bytes = value_bytes.slice(1); var mantissa_bytes = value_bytes.slice(1);
mantissa_bytes[0] &= 0x3f; 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 ) { return Amount.from_json({
throw new Error('Invalid zero representation'); currency: currency,
} issuer: issuer.to_json(),
value: valueString
amount._value = value; });
amount._offset = offset;
amount._currency = currency;
amount._issuer = issuer;
amount._is_native = false;
} else { } else {
//native //native
var integer_bytes = value_bytes.slice(); var integer_bytes = value_bytes.slice();
integer_bytes[0] &= 0x3f; integer_bytes[0] &= 0x3f;
amount._value = new BigInteger(integer_bytes, 256); var integer_hex = utils.arrayToHex(integer_bytes);
amount._is_native = true; 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()) { if (!account.is_valid()) {
throw new Error('Invalid account!'); throw new Error('Invalid account!');
} }
serializeHex(so, account.to_hex()); serializeBits(so, account.to_bits());
}, },
parse: function (so) { parse: function (so) {
var len = this.parse_varint(so); var len = this.parse_varint(so);
@@ -493,7 +474,7 @@ var STPathSet = exports.PathSet = new SerializedType({
STInt8.serialize(so, type); STInt8.serialize(so, type);
if (entry.account) { if (entry.account) {
so.append(UInt160.from_json(entry.account).to_bytes()); STHash160.serialize(so, entry.account);
} }
if (entry.currency) { if (entry.currency) {
@@ -502,7 +483,7 @@ var STPathSet = exports.PathSet = new SerializedType({
} }
if (entry.issuer) { 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) { if (entry.account || entry.currency || entry.issuer) {
entry.type = type; 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); current_path.push(entry);
} else { } else {
@@ -593,7 +574,7 @@ STPathSet.id = 18;
var STVector256 = exports.Vector256 = new SerializedType({ var STVector256 = exports.Vector256 = new SerializedType({
serialize: function (so, val) { //Assume val is an array of STHash256 objects. 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++) { for (var i=0, l=val.length; i<l; i++) {
STHash256.serialize(so, val[i]); STHash256.serialize(so, val[i]);
} }
@@ -612,7 +593,7 @@ var STVector256 = exports.Vector256 = new SerializedType({
STVector256.id = 19; STVector256.id = 19;
// Internal // Internal
var STMemo = exports.STMemo = new SerializedType({ exports.STMemo = new SerializedType({
serialize: function(so, val, no_marker) { serialize: function(so, val, no_marker) {
var keys = []; var keys = [];
@@ -682,29 +663,29 @@ var STMemo = exports.STMemo = new SerializedType({
output[keyval[0]] = keyval[1]; output[keyval[0]] = keyval[1];
} }
if (output['MemoType'] !== void(0)) { if (output.MemoType !== void(0)) {
var parsedType = convertHexToString(output['MemoType']); var parsedType = convertHexToString(output.MemoType);
if (parsedType !== 'unformatted_memo') { if (parsedType !== 'unformatted_memo') {
output['parsed_memo_type'] = convertHexToString(output['MemoType']); output.parsed_memo_type = convertHexToString(output.MemoType);
} }
} }
if (output['MemoFormat'] !== void(0)) { if (output.MemoFormat !== void(0)) {
output['parsed_memo_format'] = convertHexToString(output['MemoFormat']); output.parsed_memo_format = convertHexToString(output.MemoFormat);
} }
if (output['MemoData'] !== void(0)) { if (output.MemoData !== void(0)) {
// see if we can parse JSON // see if we can parse JSON
if (output['parsed_memo_format'] === 'json') { if (output.parsed_memo_format === 'json') {
try { try {
output['parsed_memo_data'] = JSON.parse(convertHexToString(output['MemoData'])); output.parsed_memo_data = JSON.parse(convertHexToString(output.MemoData));
} catch(e) { } catch(e) {
// fail, which is fine, we just won't add the memo_data field // fail, which is fine, we just won't add the memo_data field
} }
} else if(output['parsed_memo_format'] === 'text') { } else if(output.parsed_memo_format === 'text') {
output['parsed_memo_data'] = convertHexToString(output['MemoData']); 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)); assert(type, 'Unknown type - header byte is 0x' + tag_byte.toString(16));
return [ field_name, type.parse(so) ]; //key, value return [ field_name, type.parse(so) ]; //key, value
}; }
function sort_fields(keys) { function sort_fields(keys) {
function sort_field_compare(a, b) { function sort_field_compare(a, b) {
@@ -801,7 +782,7 @@ function sort_fields(keys) {
// Sort by type id first, then by field id // 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 a_type_bits !== b_type_bits ? a_type_bits - b_type_bits : a_field_bits - b_field_bits;
}; }
return keys.sort(sort_field_compare); return keys.sort(sort_field_compare);
} }

View File

@@ -2,8 +2,6 @@ var utils = require('./utils');
var sjcl = utils.sjcl; var sjcl = utils.sjcl;
var config = require('./config'); var config = require('./config');
var BigInteger = utils.jsbn.BigInteger;
// //
// Abstract UInt class // Abstract UInt class
// //
@@ -11,7 +9,7 @@ var BigInteger = utils.jsbn.BigInteger;
// //
var UInt = function() { var UInt = function() {
// Internal form: NaN or BigInteger // Internal form: NaN or sjcl.bn
this._value = NaN; this._value = NaN;
this._update(); this._update();
}; };
@@ -107,17 +105,15 @@ UInt.prototype.copyTo = function(d) {
}; };
UInt.prototype.equals = function(d) { UInt.prototype.equals = function(d) {
return this._value instanceof BigInteger return this.is_valid() && d.is_valid() && this._value.equals(d._value);
&& d._value instanceof BigInteger
&& this._value.equals(d._value);
}; };
UInt.prototype.is_valid = function() { UInt.prototype.is_valid = function() {
return this._value instanceof BigInteger; return this._value instanceof sjcl.bn;
}; };
UInt.prototype.is_zero = function() { 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.STR_ZERO:
case this.constructor.ACCOUNT_ZERO: case this.constructor.ACCOUNT_ZERO:
case this.constructor.HEX_ZERO: case this.constructor.HEX_ZERO:
this._value = BigInteger.valueOf(); this._value = new sjcl.bn(0);
break; break;
case '1': case '1':
case this.constructor.STR_ONE: case this.constructor.STR_ONE:
case this.constructor.ACCOUNT_ONE: case this.constructor.ACCOUNT_ONE:
case this.constructor.HEX_ONE: case this.constructor.HEX_ONE:
this._value = new BigInteger([1]); this._value = new sjcl.bn(1);
break; break;
default: default:
if (typeof j !== 'string') { if (typeof j !== 'string') {
this._value = NaN; this._value = NaN;
} else if (this.constructor.width === j.length) { } 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) { } else if ((this.constructor.width * 2) === j.length) {
// XXX Check char set! // XXX Check char set!
this._value = new BigInteger(j, 16); this._value = new sjcl.bn(j, 16);
} else { } else {
this._value = NaN; this._value = NaN;
} }
@@ -177,7 +174,7 @@ UInt.prototype.parse_generic = function(j) {
UInt.prototype.parse_hex = function(j) { UInt.prototype.parse_hex = function(j) {
if (typeof j === 'string' && j.length === (this.constructor.width * 2)) { if (typeof j === 'string' && j.length === (this.constructor.width * 2)) {
this._value = new BigInteger(j, 16); this._value = new sjcl.bn(j, 16);
} else { } else {
this._value = NaN; this._value = NaN;
} }
@@ -191,8 +188,9 @@ UInt.prototype.parse_bits = function(j) {
if (sjcl.bitArray.bitLength(j) !== this.constructor.width * 8) { if (sjcl.bitArray.bitLength(j) !== this.constructor.width * 8) {
this._value = NaN; this._value = NaN;
} else { } else {
var bytes = sjcl.codec.bytes.fromBits(j); this._value = sjcl.bn.fromBits(j);
this.parse_bytes(bytes); // var bytes = sjcl.codec.bytes.fromBits(j);
// this.parse_bytes(bytes);
} }
this._update(); this._update();
@@ -205,7 +203,8 @@ UInt.prototype.parse_bytes = function(j) {
if (!Array.isArray(j) || j.length !== this.constructor.width) { if (!Array.isArray(j) || j.length !== this.constructor.width) {
this._value = NaN; this._value = NaN;
} else { } else {
this._value = new BigInteger([0].concat(j), 256); var bits = sjcl.codec.bytes.toBits(j);
this._value = sjcl.bn.fromBits(bits);
} }
this._update(); this._update();
@@ -218,8 +217,9 @@ UInt.prototype.parse_json = UInt.prototype.parse_hex;
UInt.prototype.parse_bn = function(j) { UInt.prototype.parse_bn = function(j) {
if ((j instanceof sjcl.bn) && j.bitLength() <= this.constructor.width * 8) { if ((j instanceof sjcl.bn) && j.bitLength() <= this.constructor.width * 8) {
var bytes = sjcl.codec.bytes.fromBits(j.toBits()); // var bytes = sjcl.codec.bytes.fromBits(j.toBits());
this._value = new BigInteger(bytes, 256); // this._value = new sjcl.bn(utils.arrayToHex(bytes), 16);
this._value = new sjcl.bn(j);
} else { } else {
this._value = NaN; this._value = NaN;
} }
@@ -233,7 +233,7 @@ UInt.prototype.parse_number = function(j) {
this._value = NaN; this._value = NaN;
if (typeof j === 'number' && isFinite(j) && j >= 0) { if (typeof j === 'number' && isFinite(j) && j >= 0) {
this._value = new BigInteger(String(j)); this._value = new sjcl.bn(j);
} }
this._update(); this._update();
@@ -243,51 +243,31 @@ UInt.prototype.parse_number = function(j) {
// Convert from internal form. // Convert from internal form.
UInt.prototype.to_bytes = function() { UInt.prototype.to_bytes = function() {
if (!(this._value instanceof BigInteger)) { if (!this.is_valid()) {
return null; return null;
} }
return sjcl.codec.bytes.fromBits(this.to_bits());
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;
}; };
UInt.prototype.to_hex = function() { UInt.prototype.to_hex = function() {
if (!(this._value instanceof BigInteger)) { if (!this.is_valid()) {
return null; return null;
} }
return sjcl.codec.hex.fromBits(this.to_bits()).toUpperCase();
var bytes = this.to_bytes();
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(bytes)).toUpperCase();
}; };
UInt.prototype.to_json = UInt.prototype.to_hex; UInt.prototype.to_json = UInt.prototype.to_hex;
UInt.prototype.to_bits = function() { UInt.prototype.to_bits = function() {
if (!(this._value instanceof BigInteger)) { if (!this.is_valid()) {
return null; return null;
} }
var bytes = this.to_bytes(); return this._value.toBits(this.constructor.width * 8);
return sjcl.codec.bytes.toBits(bytes);
}; };
UInt.prototype.to_bn = function() { UInt.prototype.to_bn = function() {
if (!(this._value instanceof BigInteger)) { if (!this.is_valid()) {
return null; return null;
} }

View File

@@ -7,7 +7,6 @@ var UInt = require('./uint').UInt;
// //
var UInt128 = extend(function () { var UInt128 = extend(function () {
// Internal form: NaN or BigInteger
this._value = NaN; this._value = NaN;
}, UInt); }, UInt);

View File

@@ -2,8 +2,6 @@ var utils = require('./utils');
var config = require('./config'); var config = require('./config');
var extend = require('extend'); var extend = require('extend');
var BigInteger = utils.jsbn.BigInteger;
var UInt = require('./uint').UInt; var UInt = require('./uint').UInt;
var Base = require('./base').Base; var Base = require('./base').Base;
@@ -12,7 +10,6 @@ var Base = require('./base').Base;
// //
var UInt160 = extend(function() { var UInt160 = extend(function() {
// Internal form: NaN or BigInteger
this._value = NaN; this._value = NaN;
this._version_byte = void(0); this._version_byte = void(0);
this._update(); this._update();
@@ -49,7 +46,7 @@ UInt160.prototype.parse_json = function(j) {
// Allow raw numbers - DEPRECATED // Allow raw numbers - DEPRECATED
// This is used mostly by the test suite and is supported // This is used mostly by the test suite and is supported
// as a legacy feature only. DO NOT RELY ON THIS BEHAVIOR. // 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; this._version_byte = Base.VER_ACCOUNT_ID;
} else if (typeof j !== 'string') { } else if (typeof j !== 'string') {
this._value = NaN; this._value = NaN;
@@ -83,7 +80,7 @@ UInt160.prototype.parse_generic = function(j) {
UInt160.prototype.to_json = function(opts) { UInt160.prototype.to_json = function(opts) {
opts = opts || {}; opts = opts || {};
if (this._value instanceof BigInteger) { if (this.is_valid()) {
// If this value has a type, return a Base58 encoded string. // If this value has a type, return a Base58 encoded string.
if (typeof this._version_byte === 'number') { if (typeof this._version_byte === 'number') {
var output = Base.encode_check(this._version_byte, this.to_bytes()); var output = Base.encode_check(this._version_byte, this.to_bytes());

View File

@@ -7,7 +7,6 @@ var UInt = require('./uint').UInt;
// //
var UInt256 = extend(function() { var UInt256 = extend(function() {
// Internal form: NaN or BigInteger
this._value = NaN; this._value = NaN;
}, UInt); }, UInt);

View File

@@ -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) { function filterErr(code, done) {
return function(e) { return function(e) {
done(e.code !== code ? e : void(0)); done(e.code !== code ? e : void(0));
@@ -69,6 +81,13 @@ function hexToArray(h) {
return stringToArray(hexToString(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) { function chunkString(str, n, leftAlign) {
var ret = []; var ret = [];
var i=0, len=str.length; var i=0, len=str.length;
@@ -144,15 +163,16 @@ exports.hexToString = hexToString;
exports.hexToArray = hexToArray; exports.hexToArray = hexToArray;
exports.stringToArray = stringToArray; exports.stringToArray = stringToArray;
exports.stringToHex = stringToHex; exports.stringToHex = stringToHex;
exports.arrayToHex = arrayToHex;
exports.chunkString = chunkString; exports.chunkString = chunkString;
exports.assert = assert; exports.assert = assert;
exports.arrayUnique = arrayUnique; exports.arrayUnique = arrayUnique;
exports.toTimestamp = toTimestamp; exports.toTimestamp = toTimestamp;
exports.fromTimestamp = fromTimestamp; exports.fromTimestamp = fromTimestamp;
exports.getMantissaDecimalString = getMantissaDecimalString;
// Going up three levels is needed to escape the src-cov folder used for the // Going up three levels is needed to escape the src-cov folder used for the
// test coverage stuff. // test coverage stuff.
exports.sjcl = require('../../../build/sjcl'); exports.sjcl = require('../../../build/sjcl');
exports.jsbn = require('../../../src/js/jsbn/jsbn');
// vim:sw=2:sts=2:ts=8:et // vim:sw=2:sts=2:ts=8:et

View File

@@ -1,5 +1,4 @@
var assert = require('assert'); var assert = require('assert');
var BigInteger = require('ripple-lib').jsbn.BigInteger;
var Amount = require('ripple-lib').Amount; var Amount = require('ripple-lib').Amount;
var UInt160 = require('ripple-lib').UInt160; var UInt160 = require('ripple-lib').UInt160;
var load_config = require('ripple-lib').config.load; var load_config = require('ripple-lib').config.load;
@@ -127,6 +126,9 @@ describe('Amount', function() {
it('1 XRP human', function() { it('1 XRP human', function() {
assert.strictEqual(Amount.from_human("1 XRP").to_human_full(), '1/XRP'); 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() { it('0.1 XRP', function() {
assert.strictEqual(Amount.from_human("0.1 XRP").to_text_full(), '0.1/XRP'); assert.strictEqual(Amount.from_human("0.1 XRP").to_text_full(), '0.1/XRP');
}); });
@@ -281,14 +283,11 @@ describe('Amount', function() {
}); });
}); });
describe('UInt160', function() { describe('UInt160', function() {
it('Parse 0', function () {
assert.deepEqual(new BigInteger(), UInt160.from_generic('0')._value);
});
it('Parse 0 export', function () { it('Parse 0 export', function () {
assert.strictEqual(UInt160.ACCOUNT_ZERO, UInt160.from_generic('0').set_version(0).to_json()); assert.strictEqual(UInt160.ACCOUNT_ZERO, UInt160.from_generic('0').set_version(0).to_json());
}); });
it('Parse 1', function () { 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 () { it('Parse rrrrrrrrrrrrrrrrrrrrrhoLvTp export', function () {
assert.strictEqual(UInt160.ACCOUNT_ZERO, UInt160.from_json('rrrrrrrrrrrrrrrrrrrrrhoLvTp').to_json()); 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'); 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 () { 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 () { it('Multiply 0 XRP with 0 XRP human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').product_human(Amount.from_json('0')).to_human_full()); assert.strictEqual('0/XRP', Amount.from_json('0').product_human(Amount.from_json('0')).to_human_full());
@@ -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'); 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 () { 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() { it ('from_json minimum IOU', function() {
var amt = Amount.from_json('-1e-81/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); 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(), '-1000000000000000e-96');
assert.strictEqual(amt.to_text(), Amount.min_value); assert.strictEqual(amt.to_text(), Amount.min_value);
}); });
@@ -1233,7 +1231,6 @@ describe('Amount', function() {
it ('from_json maximum IOU', function() { it ('from_json maximum IOU', function() {
var amt = Amount.from_json('9999999999999999e80/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); 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'); 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() { it ('from_json normalize mantissa to valid max range, lost significant digits', function() {
var amt = Amount.from_json('99999999999999999999999999999999/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); 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'); assert.strictEqual(amt.to_text(), '9999999999999999e16');
}); });
it ('from_json normalize mantissa to min valid range, lost significant digits', function() { it ('from_json normalize mantissa to min valid range, lost significant digits', function() {
var amt = Amount.from_json('-0.0000000000000000000000001/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); 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'); assert.strictEqual(amt.to_text(), '-1000000000000000e-40');
}); });
}); });

View File

@@ -1566,8 +1566,8 @@ describe('OrderBook', function() {
}, },
index: 'B6BC3B0F87976370EE11F5575593FE63AA5DC1D602830DC96F04B2D597F044BF', index: 'B6BC3B0F87976370EE11F5575593FE63AA5DC1D602830DC96F04B2D597F044BF',
owner_funds: '0.1129267125000245', owner_funds: '0.1129267125000245',
taker_gets_funded: '0.1127013098802639', taker_gets_funded: '0.112701309880264',
taker_pays_funded: '55.95620035555102', taker_pays_funded: '55.95620035555106',
is_fully_funded: false }, is_fully_funded: false },
{ Account: 'raudnGKfTK23YKfnS7ixejHrqGERTYNFXk', { Account: 'raudnGKfTK23YKfnS7ixejHrqGERTYNFXk',

View File

@@ -2,7 +2,7 @@ var assert = require('assert');
var SerializedObject = require('ripple-lib').SerializedObject; var SerializedObject = require('ripple-lib').SerializedObject;
var types = require('ripple-lib').types; var types = require('ripple-lib').types;
var Amount = require('ripple-lib').Amount; var Amount = require('ripple-lib').Amount;
var BigInteger = require('ripple-lib').jsbn.BigInteger; var sjcl = require('ripple-lib').sjcl;
describe('Serialized types', function() { describe('Serialized types', function() {
describe('Int8', function() { describe('Int8', function() {
@@ -287,7 +287,7 @@ describe('Serialized types', function() {
var so = new SerializedObject("8B2386F26F8E232B"); var so = new SerializedObject("8B2386F26F8E232B");
var num = types.Int64.parse(so); var num = types.Int64.parse(so);
// We get a positive number // We get a positive number
assert.strictEqual(num.toString(16), '8b2386f26f8e232b'); assert.strictEqual(num.toString(), '0x8b2386f26f8e232b');
}); });
it('Serialize "0123456789ABCDEF"', function () { it('Serialize "0123456789ABCDEF"', function () {
var so = new SerializedObject(); var so = new SerializedObject();
@@ -299,15 +299,15 @@ describe('Serialized types', function() {
types.Int64.serialize(so, 'F0E1D2C3B4A59687'); types.Int64.serialize(so, 'F0E1D2C3B4A59687');
assert.strictEqual(so.to_hex(), 'F0E1D2C3B4A59687'); assert.strictEqual(so.to_hex(), 'F0E1D2C3B4A59687');
}); });
it('Serialize BigInteger("FFEEDDCCBBAA9988")', function () { it('Serialize bn("FFEEDDCCBBAA9988")', function () {
var so = new SerializedObject(); 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'); assert.strictEqual(so.to_hex(), 'FFEEDDCCBBAA9988');
}); });
it('Fail to serialize BigInteger("-1")', function () { it('Fail to serialize BigNumber("-1")', function () {
var so = new SerializedObject(); var so = new SerializedObject();
assert.throws(function () { 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 () { it('Fail to serialize "10000000000000000"', function () {
@@ -343,7 +343,7 @@ describe('Serialized types', function() {
it('Parse "0123456789ABCDEF"', function () { it('Parse "0123456789ABCDEF"', function () {
var so = new SerializedObject("0123456789ABCDEF"); var so = new SerializedObject("0123456789ABCDEF");
var num = types.Int64.parse(so); var num = types.Int64.parse(so);
assert.strictEqual(num.toString(10), '81985529216486895'); assert.strictEqual(num.toString(), '0x123456789abcdef');
}); });
}); });

View File

@@ -9,8 +9,8 @@ describe('UInt', function() {
assert.strictEqual(val.to_hex(), '00000000000000000000000000000000'); assert.strictEqual(val.to_hex(), '00000000000000000000000000000000');
}); });
it('should create 00000000000000000000000000000001 when called with 1', function () { it('should create 00000000000000000000000000000001 when called with 1', function () {
var val = UInt128.from_number(0); var val = UInt128.from_number(1);
assert.strictEqual(val.to_hex(), '00000000000000000000000000000000'); assert.strictEqual(val.to_hex(), '00000000000000000000000000000001');
}); });
it('should create 000000000000000000000000FFFFFFFF when called with 0xFFFFFFFF', function () { it('should create 000000000000000000000000FFFFFFFF when called with 0xFFFFFFFF', function () {
var val = UInt128.from_number(0xFFFFFFFF); var val = UInt128.from_number(0xFFFFFFFF);