mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-21 12:45:50 +00:00
Lint
This commit is contained in:
@@ -9,11 +9,11 @@
|
|||||||
// balance_proposed
|
// balance_proposed
|
||||||
//
|
//
|
||||||
|
|
||||||
// var network = require("./network.js");
|
// var network = require('./network.js');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var EventEmitter = require('events').EventEmitter;
|
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var extend = require('extend');
|
var extend = require('extend');
|
||||||
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var Amount = require('./amount').Amount;
|
var Amount = require('./amount').Amount;
|
||||||
var UInt160 = require('./uint160').UInt160;
|
var UInt160 = require('./uint160').UInt160;
|
||||||
var TransactionManager = require('./transactionmanager').TransactionManager;
|
var TransactionManager = require('./transactionmanager').TransactionManager;
|
||||||
@@ -75,7 +75,9 @@ function Account(remote, account) {
|
|||||||
this._remote.on('prepare_subscribe', attachAccount);
|
this._remote.on('prepare_subscribe', attachAccount);
|
||||||
|
|
||||||
function handleTransaction(transaction) {
|
function handleTransaction(transaction) {
|
||||||
if (!transaction.mmeta) return;
|
if (!transaction.mmeta) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var changed = false;
|
var changed = false;
|
||||||
|
|
||||||
@@ -137,7 +139,7 @@ Account.prototype.getInfo = function(callback) {
|
|||||||
* Retrieve the current AccountRoot entry.
|
* Retrieve the current AccountRoot entry.
|
||||||
*
|
*
|
||||||
* To keep up-to-date with changes to the AccountRoot entry, subscribe to the
|
* To keep up-to-date with changes to the AccountRoot entry, subscribe to the
|
||||||
* "entry" event.
|
* 'entry' event.
|
||||||
*
|
*
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
@@ -164,11 +166,14 @@ Account.prototype.entry = function(callback) {
|
|||||||
Account.prototype.getNextSequence = function(callback) {
|
Account.prototype.getNextSequence = function(callback) {
|
||||||
var callback = typeof callback === 'function' ? callback : function(){};
|
var callback = typeof callback === 'function' ? callback : function(){};
|
||||||
|
|
||||||
|
function isNotFound(err) {
|
||||||
|
return err && typeof err === 'object'
|
||||||
|
&& typeof err.remote === 'object'
|
||||||
|
&& err.remote.error === 'actNotFound';
|
||||||
|
};
|
||||||
|
|
||||||
function accountInfo(err, info) {
|
function accountInfo(err, info) {
|
||||||
if (err &&
|
if (isNotFound(err)) {
|
||||||
"object" === typeof err &&
|
|
||||||
"object" === typeof err.remote &&
|
|
||||||
err.remote.error === "actNotFound") {
|
|
||||||
// New accounts will start out as sequence zero
|
// New accounts will start out as sequence zero
|
||||||
callback(null, 0);
|
callback(null, 0);
|
||||||
} else if (err) {
|
} else if (err) {
|
||||||
@@ -187,7 +192,7 @@ Account.prototype.getNextSequence = function(callback) {
|
|||||||
* Retrieve this account's Ripple trust lines.
|
* Retrieve this account's Ripple trust lines.
|
||||||
*
|
*
|
||||||
* To keep up-to-date with changes to the AccountRoot entry, subscribe to the
|
* To keep up-to-date with changes to the AccountRoot entry, subscribe to the
|
||||||
* "lines" event. (Not yet implemented.)
|
* 'lines' event. (Not yet implemented.)
|
||||||
*
|
*
|
||||||
* @param {function(err, lines)} callback Called with the result
|
* @param {function(err, lines)} callback Called with the result
|
||||||
*/
|
*/
|
||||||
@@ -220,23 +225,27 @@ Account.prototype.lines = function(callback) {
|
|||||||
* @returns {Account}
|
* @returns {Account}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.line = function(currency,address,callback) {
|
Account.prototype.line = function(currency, address, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var found;
|
|
||||||
var callback = typeof callback === 'function' ? callback : function(){};
|
var callback = typeof callback === 'function' ? callback : function(){};
|
||||||
|
|
||||||
self.lines(function(err, data) {
|
self.lines(function(err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback(err);
|
return callback(err);
|
||||||
} else {
|
}
|
||||||
var line = data.lines.filter(function(line) {
|
|
||||||
if (line.account === address && line.currency === currency) {
|
var line;
|
||||||
return line;
|
|
||||||
|
top:
|
||||||
|
for (var i=0; i<data.lines.length; i++) {
|
||||||
|
var l = data.lines[i];
|
||||||
|
if (l.account === address && l.currency === currency) {
|
||||||
|
line = l;
|
||||||
|
break top;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})[0];
|
|
||||||
|
|
||||||
callback(null, line);
|
callback(null, line);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@@ -256,17 +265,21 @@ Account.prototype.notifyTx = function(transaction) {
|
|||||||
// Only trigger the event if the account object is actually
|
// Only trigger the event if the account object is actually
|
||||||
// subscribed - this prevents some weird phantom events from
|
// subscribed - this prevents some weird phantom events from
|
||||||
// occurring.
|
// occurring.
|
||||||
if (this._subs) {
|
if (!this._subs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.emit('transaction', transaction);
|
this.emit('transaction', transaction);
|
||||||
|
|
||||||
var account = transaction.transaction.Account;
|
var account = transaction.transaction.Account;
|
||||||
|
|
||||||
if (!account) return;
|
if (!account) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var isThisAccount = account === this._account_id;
|
var isThisAccount = (account === this._account_id);
|
||||||
|
|
||||||
this.emit(isThisAccount ? 'transaction-outbound' : 'transaction-inbound', transaction);
|
this.emit(isThisAccount ? 'transaction-outbound' : 'transaction-inbound', transaction);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -292,10 +305,9 @@ Account.prototype.submit = function(transaction) {
|
|||||||
* @param {Boolean} true if the public key is valid and active, false otherwise
|
* @param {Boolean} true if the public key is valid and active, false otherwise
|
||||||
*/
|
*/
|
||||||
Account.prototype.publicKeyIsActive = function(public_key, callback) {
|
Account.prototype.publicKeyIsActive = function(public_key, callback) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var public_key_as_uint160;
|
var public_key_as_uint160;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
public_key_as_uint160 = Account._publicKeyToAddress(public_key);
|
public_key_as_uint160 = Account._publicKeyToAddress(public_key);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -334,20 +346,13 @@ Account.prototype.publicKeyIsActive = function(public_key, callback) {
|
|||||||
// if the public key matches the account address and the lsfDisableMaster is not set
|
// if the public key matches the account address and the lsfDisableMaster is not set
|
||||||
if (account_info.RegularKey &&
|
if (account_info.RegularKey &&
|
||||||
account_info.RegularKey === public_key_as_uint160) {
|
account_info.RegularKey === public_key_as_uint160) {
|
||||||
|
|
||||||
async_callback(null, true);
|
async_callback(null, true);
|
||||||
|
|
||||||
} else if (account_info.Account === public_key_as_uint160 &&
|
} else if (account_info.Account === public_key_as_uint160 &&
|
||||||
((account_info.Flags & 0x00100000) === 0)) {
|
((account_info.Flags & 0x00100000) === 0)) {
|
||||||
|
|
||||||
async_callback(null, true);
|
async_callback(null, true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
async_callback(null, false);
|
async_callback(null, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var steps = [
|
var steps = [
|
||||||
@@ -356,7 +361,6 @@ Account.prototype.publicKeyIsActive = function(public_key, callback) {
|
|||||||
];
|
];
|
||||||
|
|
||||||
async.waterfall(steps, callback);
|
async.waterfall(steps, callback);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -368,36 +372,25 @@ Account.prototype.publicKeyIsActive = function(public_key, callback) {
|
|||||||
* @returns {RippleAddress}
|
* @returns {RippleAddress}
|
||||||
*/
|
*/
|
||||||
Account._publicKeyToAddress = function(public_key) {
|
Account._publicKeyToAddress = function(public_key) {
|
||||||
|
|
||||||
// Based on functions in /src/js/ripple/keypair.js
|
// Based on functions in /src/js/ripple/keypair.js
|
||||||
function hexToUInt160(public_key) {
|
function hexToUInt160(public_key) {
|
||||||
|
|
||||||
var bits = sjcl.codec.hex.toBits(public_key);
|
var bits = sjcl.codec.hex.toBits(public_key);
|
||||||
var hash = sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));
|
var hash = sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));
|
||||||
var address = UInt160.from_bits(hash);
|
var address = UInt160.from_bits(hash);
|
||||||
address.set_version(Base.VER_ACCOUNT_ID);
|
address.set_version(Base.VER_ACCOUNT_ID);
|
||||||
|
|
||||||
return address.to_json();
|
return address.to_json();
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
if (UInt160.is_valid(public_key)) {
|
if (UInt160.is_valid(public_key)) {
|
||||||
|
|
||||||
return public_key;
|
return public_key;
|
||||||
|
|
||||||
} else if (/^[0-9a-fA-F]+$/.test(public_key)) {
|
} else if (/^[0-9a-fA-F]+$/.test(public_key)) {
|
||||||
|
|
||||||
return hexToUInt160(public_key);
|
return hexToUInt160(public_key);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
throw new Error('Public key is invalid. Must be a UInt160 or a hex string');
|
||||||
throw(new Error('Public key is invalid. Must be a UInt160 or a hex string'));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.Account = Account;
|
exports.Account = Account;
|
||||||
|
|
||||||
// vim:sw=2:sts=2:ts=8:et
|
// vim:sw=2:sts=2:ts=8:et
|
||||||
|
|||||||
@@ -54,52 +54,52 @@ function Amount() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Given '100/USD/mtgox' return the a string with mtgox remapped.
|
// Given '100/USD/mtgox' return the a string with mtgox remapped.
|
||||||
Amount.text_full_rewrite = function (j) {
|
Amount.text_full_rewrite = function(j) {
|
||||||
return Amount.from_json(j).to_text_full();
|
return Amount.from_json(j).to_text_full();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Given '100/USD/mtgox' return the json.
|
// Given '100/USD/mtgox' return the json.
|
||||||
Amount.json_rewrite = function (j) {
|
Amount.json_rewrite = function(j) {
|
||||||
return Amount.from_json(j).to_json();
|
return Amount.from_json(j).to_json();
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.from_number = function (n) {
|
Amount.from_number = function(n) {
|
||||||
return (new Amount()).parse_number(n);
|
return (new Amount()).parse_number(n);
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.from_json = function (j) {
|
Amount.from_json = function(j) {
|
||||||
return (new Amount()).parse_json(j);
|
return (new Amount()).parse_json(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.from_quality = function (quality, currency, issuer, opts) {
|
Amount.from_quality = function(quality, currency, issuer, opts) {
|
||||||
return (new Amount()).parse_quality(quality, currency, issuer, opts);
|
return (new Amount()).parse_quality(quality, currency, issuer, opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.from_human = function (j, opts) {
|
Amount.from_human = function(j, opts) {
|
||||||
return (new Amount()).parse_human(j, opts);
|
return (new Amount()).parse_human(j, opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.is_valid = function (j) {
|
Amount.is_valid = function(j) {
|
||||||
return Amount.from_json(j).is_valid();
|
return Amount.from_json(j).is_valid();
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.is_valid_full = function (j) {
|
Amount.is_valid_full = function(j) {
|
||||||
return Amount.from_json(j).is_valid_full();
|
return Amount.from_json(j).is_valid_full();
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.NaN = function () {
|
Amount.NaN = function() {
|
||||||
var result = new Amount();
|
var result = new Amount();
|
||||||
result._value = NaN;
|
result._value = NaN;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns a new value which is the absolute value of this.
|
// Returns a new value which is the absolute value of this.
|
||||||
Amount.prototype.abs = function () {
|
Amount.prototype.abs = function() {
|
||||||
return this.clone(this.is_negative());
|
return this.clone(this.is_negative());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Result in terms of this' currency and issuer.
|
// Result in terms of this' currency and issuer.
|
||||||
Amount.prototype.add = function (v) {
|
Amount.prototype.add = function(v) {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
v = Amount.from_json(v);
|
v = Amount.from_json(v);
|
||||||
@@ -164,7 +164,7 @@ Amount.prototype.add = function (v) {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
Amount.prototype._invert = function () {
|
Amount.prototype._invert = function() {
|
||||||
this._value = consts.bi_1e32.divide(this._value);
|
this._value = consts.bi_1e32.divide(this._value);
|
||||||
this._offset = -32 - this._offset;
|
this._offset = -32 - this._offset;
|
||||||
this.canonicalize();
|
this.canonicalize();
|
||||||
@@ -178,11 +178,11 @@ Amount.prototype._invert = function () {
|
|||||||
* @return {Amount} New Amount object with same currency and issuer, but the
|
* @return {Amount} New Amount object with same currency and issuer, but the
|
||||||
* inverse of the value.
|
* inverse of the value.
|
||||||
*/
|
*/
|
||||||
Amount.prototype.invert = function () {
|
Amount.prototype.invert = function() {
|
||||||
return this.copy()._invert();
|
return this.copy()._invert();
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.canonicalize = function () {
|
Amount.prototype.canonicalize = function() {
|
||||||
if (!(this._value instanceof BigInteger)) {
|
if (!(this._value instanceof BigInteger)) {
|
||||||
// NaN.
|
// NaN.
|
||||||
// nothing
|
// nothing
|
||||||
@@ -226,11 +226,11 @@ Amount.prototype.canonicalize = function () {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.clone = function (negate) {
|
Amount.prototype.clone = function(negate) {
|
||||||
return this.copyTo(new Amount(), negate);
|
return this.copyTo(new Amount(), negate);
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.compareTo = function (v) {
|
Amount.prototype.compareTo = function(v) {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
if (!this.is_comparable(v)) {
|
if (!this.is_comparable(v)) {
|
||||||
@@ -262,7 +262,7 @@ Amount.prototype.compareTo = function (v) {
|
|||||||
|
|
||||||
// Make d a copy of this. Returns d.
|
// Make d a copy of this. Returns d.
|
||||||
// Modification of objects internally refered to is not allowed.
|
// Modification of objects internally refered to is not allowed.
|
||||||
Amount.prototype.copyTo = function (d, negate) {
|
Amount.prototype.copyTo = function(d, negate) {
|
||||||
if (typeof this._value === 'object') {
|
if (typeof this._value === 'object') {
|
||||||
this._value.copyTo(d._value);
|
this._value.copyTo(d._value);
|
||||||
} else {
|
} else {
|
||||||
@@ -286,11 +286,11 @@ Amount.prototype.copyTo = function (d, negate) {
|
|||||||
return d;
|
return d;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.currency = function () {
|
Amount.prototype.currency = function() {
|
||||||
return this._currency;
|
return this._currency;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.equals = function (d, ignore_issuer) {
|
Amount.prototype.equals = function(d, ignore_issuer) {
|
||||||
if (typeof d === 'string') {
|
if (typeof d === 'string') {
|
||||||
return this.equals(Amount.from_json(d));
|
return this.equals(Amount.from_json(d));
|
||||||
}
|
}
|
||||||
@@ -301,17 +301,17 @@ Amount.prototype.equals = function (d, ignore_issuer) {
|
|||||||
|| (this._is_native !== d._is_native)
|
|| (this._is_native !== d._is_native)
|
||||||
|| (!this._value.equals(d._value) || this._offset !== d._offset)
|
|| (!this._value.equals(d._value) || this._offset !== d._offset)
|
||||||
|| (this._is_negative !== d._is_negative)
|
|| (this._is_negative !== d._is_negative)
|
||||||
|| (!this._is_native && (!this._currency.equals(d._currency) || !ignore_issuer && !this._issuer.equals(d._issuer))))
|
|| (!this._is_native && (!this._currency.equals(d._currency) || !ignore_issuer && !this._issuer.equals(d._issuer))));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Result in terms of this' currency and issuer.
|
// Result in terms of this' currency and issuer.
|
||||||
Amount.prototype.divide = function (d) {
|
Amount.prototype.divide = function(d) {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
if (d.is_zero()) {
|
if (d.is_zero()) {
|
||||||
throw 'divide by zero';
|
throw new Error('divide by zero');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.is_zero()) {
|
if (this.is_zero()) {
|
||||||
@@ -377,7 +377,7 @@ Amount.prototype.divide = function (d) {
|
|||||||
* should be applied. Can be given as JavaScript Date or int for Ripple epoch.
|
* should be applied. Can be given as JavaScript Date or int for Ripple epoch.
|
||||||
* @return {Amount} The resulting ratio. Unit will be the same as numerator.
|
* @return {Amount} The resulting ratio. Unit will be the same as numerator.
|
||||||
*/
|
*/
|
||||||
Amount.prototype.ratio_human = function (denominator, opts) {
|
Amount.prototype.ratio_human = function(denominator, opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
if (typeof denominator === 'number' && parseInt(denominator, 10) === denominator) {
|
if (typeof denominator === 'number' && parseInt(denominator, 10) === denominator) {
|
||||||
@@ -443,7 +443,7 @@ Amount.prototype.ratio_human = function (denominator, opts) {
|
|||||||
* should be applied. Can be given as JavaScript Date or int for Ripple epoch.
|
* should be applied. Can be given as JavaScript Date or int for Ripple epoch.
|
||||||
* @return {Amount} The product. Unit will be the same as the first factor.
|
* @return {Amount} The product. Unit will be the same as the first factor.
|
||||||
*/
|
*/
|
||||||
Amount.prototype.product_human = function (factor, opts) {
|
Amount.prototype.product_human = function(factor, opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
if (typeof factor === 'number' && parseInt(factor, 10) === factor) {
|
if (typeof factor === 'number' && parseInt(factor, 10) === factor) {
|
||||||
@@ -478,49 +478,49 @@ Amount.prototype.product_human = function (factor, opts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return product;
|
return product;
|
||||||
}
|
};
|
||||||
|
|
||||||
// True if Amounts are valid and both native or non-native.
|
// True if Amounts are valid and both native or non-native.
|
||||||
Amount.prototype.is_comparable = function (v) {
|
Amount.prototype.is_comparable = function(v) {
|
||||||
return this._value instanceof BigInteger
|
return this._value instanceof BigInteger
|
||||||
&& v._value instanceof BigInteger
|
&& v._value instanceof BigInteger
|
||||||
&& this._is_native === v._is_native;
|
&& this._is_native === v._is_native;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.is_native = function () {
|
Amount.prototype.is_native = function() {
|
||||||
return this._is_native;
|
return this._is_native;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.is_negative = function () {
|
Amount.prototype.is_negative = function() {
|
||||||
return this._value instanceof BigInteger
|
return this._value instanceof BigInteger
|
||||||
? this._is_negative
|
? this._is_negative
|
||||||
: false; // NaN is not negative
|
: false; // NaN is not negative
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.is_positive = function () {
|
Amount.prototype.is_positive = function() {
|
||||||
return !this.is_zero() && !this.is_negative();
|
return !this.is_zero() && !this.is_negative();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only checks the value. Not the currency and issuer.
|
// Only checks the value. Not the currency and issuer.
|
||||||
Amount.prototype.is_valid = function () {
|
Amount.prototype.is_valid = function() {
|
||||||
return this._value instanceof BigInteger;
|
return this._value instanceof BigInteger;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.is_valid_full = function () {
|
Amount.prototype.is_valid_full = function() {
|
||||||
return this.is_valid() && this._currency.is_valid() && this._issuer.is_valid();
|
return this.is_valid() && this._currency.is_valid() && this._issuer.is_valid();
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.is_zero = function () {
|
Amount.prototype.is_zero = function() {
|
||||||
return this._value instanceof BigInteger ? this._value.equals(BigInteger.ZERO) : false;
|
return this._value instanceof BigInteger ? this._value.equals(BigInteger.ZERO) : false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.issuer = function () {
|
Amount.prototype.issuer = function() {
|
||||||
return this._issuer;
|
return this._issuer;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Result in terms of this' currency and issuer.
|
// Result in terms of this' currency and issuer.
|
||||||
// XXX Diverges from cpp.
|
// XXX Diverges from cpp.
|
||||||
Amount.prototype.multiply = function (v) {
|
Amount.prototype.multiply = function(v) {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
if (this.is_zero()) {
|
if (this.is_zero()) {
|
||||||
@@ -563,7 +563,7 @@ Amount.prototype.multiply = function (v) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Return a new value.
|
// Return a new value.
|
||||||
Amount.prototype.negate = function () {
|
Amount.prototype.negate = function() {
|
||||||
return this.clone('NEGATE');
|
return this.clone('NEGATE');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -573,7 +573,7 @@ Amount.prototype.negate = function () {
|
|||||||
* Creates a new Amount object as a copy of the current one (including the same
|
* 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.
|
* unit (currency & issuer), inverts it (1/x) and returns the result.
|
||||||
*/
|
*/
|
||||||
Amount.prototype.invert = function () {
|
Amount.prototype.invert = function() {
|
||||||
var one = this.clone();
|
var one = this.clone();
|
||||||
one._value = BigInteger.ONE;
|
one._value = BigInteger.ONE;
|
||||||
one._offset = 0;
|
one._offset = 0;
|
||||||
@@ -596,7 +596,7 @@ Amount.prototype.invert = function () {
|
|||||||
*/
|
*/
|
||||||
Amount.human_RE = /^\s*([a-z]{3})?\s*(-)?(\d+)(?:\.(\d*))?\s*([a-f0-9]{40}|[a-z0-9]{3})?\s*$/i;
|
Amount.human_RE = /^\s*([a-z]{3})?\s*(-)?(\d+)(?:\.(\d*))?\s*([a-f0-9]{40}|[a-z0-9]{3})?\s*$/i;
|
||||||
|
|
||||||
Amount.prototype.parse_human = function (j, opts) {
|
Amount.prototype.parse_human = function(j, opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
var m = String(j).match(Amount.human_RE);
|
var m = String(j).match(Amount.human_RE);
|
||||||
@@ -646,7 +646,7 @@ Amount.prototype.parse_human = function (j, opts) {
|
|||||||
// The correct way to solve this is probably to switch to a proper
|
// The correct way to solve this is probably to switch to a proper
|
||||||
// BigDecimal for our internal representation and then use that across
|
// BigDecimal for our internal representation and then use that across
|
||||||
// the board instead of instantiating these dummy Amount objects.
|
// the board instead of instantiating these dummy Amount objects.
|
||||||
var interestTempAmount = Amount.from_json(""+interest+"/1/1");
|
var interestTempAmount = Amount.from_json(''+interest+'/1/1');
|
||||||
|
|
||||||
if (interestTempAmount.is_valid()) {
|
if (interestTempAmount.is_valid()) {
|
||||||
var ref = this.divide(interestTempAmount);
|
var ref = this.divide(interestTempAmount);
|
||||||
@@ -661,7 +661,7 @@ Amount.prototype.parse_human = function (j, opts) {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.parse_issuer = function (issuer) {
|
Amount.prototype.parse_issuer = function(issuer) {
|
||||||
this._issuer = UInt160.from_json(issuer);
|
this._issuer = UInt160.from_json(issuer);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@@ -699,7 +699,7 @@ Amount.prototype.parse_issuer = function (issuer) {
|
|||||||
* For human use however, we want to think of 1000000 drops as 1 XRP and
|
* For human use however, we want to think of 1000000 drops as 1 XRP and
|
||||||
* prices as per-XRP instead of per-drop.
|
* prices as per-XRP instead of per-drop.
|
||||||
*/
|
*/
|
||||||
Amount.prototype.parse_quality = function (quality, counterCurrency, counterIssuer, opts)
|
Amount.prototype.parse_quality = function(quality, counterCurrency, counterIssuer, opts)
|
||||||
{
|
{
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
@@ -733,7 +733,7 @@ Amount.prototype.parse_quality = function (quality, counterCurrency, counterIssu
|
|||||||
var interest = baseCurrency.get_interest_at(opts.reference_date);
|
var interest = baseCurrency.get_interest_at(opts.reference_date);
|
||||||
|
|
||||||
// XXX If we had better math utilities, we wouldn't need this hack.
|
// XXX If we had better math utilities, we wouldn't need this hack.
|
||||||
var interestTempAmount = Amount.from_json(""+interest+"/1/1");
|
var interestTempAmount = Amount.from_json(''+interest+'/1/1');
|
||||||
|
|
||||||
if (interestTempAmount.is_valid()) {
|
if (interestTempAmount.is_valid()) {
|
||||||
var v = this.divide(interestTempAmount);
|
var v = this.divide(interestTempAmount);
|
||||||
@@ -743,9 +743,9 @@ Amount.prototype.parse_quality = function (quality, counterCurrency, counterIssu
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
};
|
||||||
|
|
||||||
Amount.prototype.parse_number = function (n) {
|
Amount.prototype.parse_number = function(n) {
|
||||||
this._is_native = false;
|
this._is_native = false;
|
||||||
this._currency = Currency.from_json(1);
|
this._currency = Currency.from_json(1);
|
||||||
this._issuer = UInt160.from_json(1);
|
this._issuer = UInt160.from_json(1);
|
||||||
@@ -759,7 +759,7 @@ Amount.prototype.parse_number = function (n) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// <-> j
|
// <-> j
|
||||||
Amount.prototype.parse_json = function (j) {
|
Amount.prototype.parse_json = function(j) {
|
||||||
switch (typeof j) {
|
switch (typeof j) {
|
||||||
case 'string':
|
case 'string':
|
||||||
// .../.../... notation is not a wire format. But allowed for easier testing.
|
// .../.../... notation is not a wire format. But allowed for easier testing.
|
||||||
@@ -785,7 +785,10 @@ Amount.prototype.parse_json = function (j) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'object':
|
case 'object':
|
||||||
if (j === null) break;
|
if (j === null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (j instanceof Amount) {
|
if (j instanceof Amount) {
|
||||||
j.copyTo(this);
|
j.copyTo(this);
|
||||||
} else if (j.hasOwnProperty('value')) {
|
} else if (j.hasOwnProperty('value')) {
|
||||||
@@ -811,7 +814,7 @@ Amount.prototype.parse_json = function (j) {
|
|||||||
// - integer = raw units
|
// - integer = raw units
|
||||||
// - float = with precision 6
|
// - float = with precision 6
|
||||||
// XXX Improvements: disallow leading zeros.
|
// XXX Improvements: disallow leading zeros.
|
||||||
Amount.prototype.parse_native = function (j) {
|
Amount.prototype.parse_native = function(j) {
|
||||||
var m;
|
var m;
|
||||||
|
|
||||||
if (typeof j === 'string') {
|
if (typeof j === 'string') {
|
||||||
@@ -846,7 +849,7 @@ Amount.prototype.parse_native = function (j) {
|
|||||||
|
|
||||||
// Parse a non-native value for the json wire format.
|
// Parse a non-native value for the json wire format.
|
||||||
// Requires _currency to be set!
|
// Requires _currency to be set!
|
||||||
Amount.prototype.parse_value = function (j) {
|
Amount.prototype.parse_value = function(j) {
|
||||||
this._is_native = false;
|
this._is_native = false;
|
||||||
|
|
||||||
switch (typeof j) {
|
switch (typeof j) {
|
||||||
@@ -900,14 +903,14 @@ Amount.prototype.parse_value = function (j) {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.set_currency = function (c) {
|
Amount.prototype.set_currency = function(c) {
|
||||||
this._currency = Currency.from_json(c);
|
this._currency = Currency.from_json(c);
|
||||||
this._is_native = this._currency.is_native();
|
this._is_native = this._currency.is_native();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.set_issuer = function (issuer) {
|
Amount.prototype.set_issuer = function(issuer) {
|
||||||
if (issuer instanceof UInt160) {
|
if (issuer instanceof UInt160) {
|
||||||
this._issuer = issuer;
|
this._issuer = issuer;
|
||||||
} else {
|
} else {
|
||||||
@@ -918,18 +921,18 @@ Amount.prototype.set_issuer = function (issuer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Result in terms of this' currency and issuer.
|
// Result in terms of this' currency and issuer.
|
||||||
Amount.prototype.subtract = function (v) {
|
Amount.prototype.subtract = function(v) {
|
||||||
// Correctness over speed, less code has less bugs, reuse add code.
|
// 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(v).negate());
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.to_number = function (allow_nan) {
|
Amount.prototype.to_number = function(allow_nan) {
|
||||||
var s = this.to_text(allow_nan);
|
var s = this.to_text(allow_nan);
|
||||||
return typeof s === 'string' ? Number(s) : s;
|
return typeof s === 'string' ? Number(s) : s;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert only value to JSON wire format.
|
// Convert only value to JSON wire format.
|
||||||
Amount.prototype.to_text = function (allow_nan) {
|
Amount.prototype.to_text = function(allow_nan) {
|
||||||
var result = NaN;
|
var result = NaN;
|
||||||
|
|
||||||
if (this._is_native) {
|
if (this._is_native) {
|
||||||
@@ -975,7 +978,7 @@ Amount.prototype.to_text = function (allow_nan) {
|
|||||||
* should be applied. Can be given as JavaScript Date or int for Ripple epoch.
|
* should be applied. Can be given as JavaScript Date or int for Ripple epoch.
|
||||||
* @return {Amount} The amount with interest applied.
|
* @return {Amount} The amount with interest applied.
|
||||||
*/
|
*/
|
||||||
Amount.prototype.applyInterest = function (referenceDate) {
|
Amount.prototype.applyInterest = function(referenceDate) {
|
||||||
if (this._currency.has_interest()) {
|
if (this._currency.has_interest()) {
|
||||||
var interest = this._currency.get_interest_at(referenceDate);
|
var interest = this._currency.get_interest_at(referenceDate);
|
||||||
|
|
||||||
@@ -986,7 +989,7 @@ Amount.prototype.applyInterest = function (referenceDate) {
|
|||||||
// The correct way to solve this is probably to switch to a proper
|
// The correct way to solve this is probably to switch to a proper
|
||||||
// BigDecimal for our internal representation and then use that across
|
// BigDecimal for our internal representation and then use that across
|
||||||
// the board instead of instantiating these dummy Amount objects.
|
// the board instead of instantiating these dummy Amount objects.
|
||||||
var interestTempAmount = Amount.from_json(""+interest+"/1/1");
|
var interestTempAmount = Amount.from_json(String(interest) + '/1/1');
|
||||||
|
|
||||||
if (interestTempAmount.is_valid()) {
|
if (interestTempAmount.is_valid()) {
|
||||||
return this.multiply(interestTempAmount);
|
return this.multiply(interestTempAmount);
|
||||||
@@ -1018,14 +1021,20 @@ Amount.prototype.applyInterest = function (referenceDate) {
|
|||||||
* @param opts.reference_date {Date|Number} Date based on which demurrage/interest
|
* @param opts.reference_date {Date|Number} Date based on which demurrage/interest
|
||||||
* should be applied. Can be given as JavaScript Date or int for Ripple epoch.
|
* should be applied. Can be given as JavaScript Date or int for Ripple epoch.
|
||||||
*/
|
*/
|
||||||
Amount.prototype.to_human = function (opts) {
|
Amount.prototype.to_human = function(opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
if (!this.is_valid()) return '';
|
if (!this.is_valid()) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
// Default options
|
// Default options
|
||||||
if (typeof opts.signed === 'undefined') opts.signed = true;
|
if (typeof opts.signed === 'undefined') {
|
||||||
if (typeof opts.group_sep === 'undefined') opts.group_sep = true;
|
opts.signed = true;
|
||||||
|
}
|
||||||
|
if (typeof opts.group_sep === 'undefined') {
|
||||||
|
opts.group_sep = true;
|
||||||
|
}
|
||||||
|
|
||||||
opts.group_width = opts.group_width || 3;
|
opts.group_width = opts.group_width || 3;
|
||||||
|
|
||||||
@@ -1080,7 +1089,9 @@ Amount.prototype.to_human = function (opts) {
|
|||||||
rounding = Math.min(rounding, fraction_part.length);
|
rounding = Math.min(rounding, fraction_part.length);
|
||||||
|
|
||||||
// Now we cut `rounding` digits off the right.
|
// Now we cut `rounding` digits off the right.
|
||||||
if (rounding > 0) fraction_part = fraction_part.slice(0, -rounding);
|
if (rounding > 0) {
|
||||||
|
fraction_part = fraction_part.slice(0, -rounding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce the minimum number of decimal digits (min_precision)
|
// Enforce the minimum number of decimal digits (min_precision)
|
||||||
@@ -1112,7 +1123,7 @@ Amount.prototype.to_human = function (opts) {
|
|||||||
return formatted;
|
return formatted;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.to_human_full = function (opts) {
|
Amount.prototype.to_human_full = function(opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
var a = this.to_human(opts);
|
var a = this.to_human(opts);
|
||||||
var c = this._currency.to_human();
|
var c = this._currency.to_human();
|
||||||
@@ -1121,7 +1132,7 @@ Amount.prototype.to_human_full = function (opts) {
|
|||||||
return o;
|
return o;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.to_json = function () {
|
Amount.prototype.to_json = function() {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
if (this._is_native) {
|
if (this._is_native) {
|
||||||
@@ -1140,7 +1151,7 @@ Amount.prototype.to_json = function () {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
Amount.prototype.to_text_full = function (opts) {
|
Amount.prototype.to_text_full = function(opts) {
|
||||||
return this._value instanceof BigInteger
|
return this._value instanceof BigInteger
|
||||||
? this._is_native
|
? this._is_native
|
||||||
? this.to_human() + '/XRP'
|
? this.to_human() + '/XRP'
|
||||||
@@ -1149,12 +1160,17 @@ Amount.prototype.to_text_full = function (opts) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// For debugging.
|
// For debugging.
|
||||||
Amount.prototype.not_equals_why = function (d, ignore_issuer) {
|
Amount.prototype.not_equals_why = function(d, ignore_issuer) {
|
||||||
|
if (typeof d === 'string') {
|
||||||
|
return this.not_equals_why(Amount.from_json(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(d instanceof Amount)) {
|
||||||
|
return 'Not an Amount';
|
||||||
|
}
|
||||||
|
|
||||||
var result = false;
|
var result = false;
|
||||||
|
|
||||||
if (typeof d === 'string') {
|
|
||||||
result = this.not_equals_why(Amount.from_json(d));
|
|
||||||
} else if (d instanceof Amount) {
|
|
||||||
if (!this.is_valid() || !d.is_valid()) {
|
if (!this.is_valid() || !d.is_valid()) {
|
||||||
result = 'Invalid amount.';
|
result = 'Invalid amount.';
|
||||||
} else if (this._is_native !== d._is_native) {
|
} else if (this._is_native !== d._is_native) {
|
||||||
@@ -1174,9 +1190,6 @@ Amount.prototype.not_equals_why = function (d, ignore_issuer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
result = 'Wrong constructor.';
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ var BigInteger = utils.jsbn.BigInteger;
|
|||||||
var Base = {};
|
var Base = {};
|
||||||
|
|
||||||
var alphabets = Base.alphabets = {
|
var alphabets = Base.alphabets = {
|
||||||
ripple : "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz",
|
ripple: 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz',
|
||||||
tipple : "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz",
|
tipple: 'RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz',
|
||||||
bitcoin : "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
bitcoin: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
||||||
};
|
};
|
||||||
|
|
||||||
extend(Base, {
|
extend(Base, {
|
||||||
@@ -33,7 +33,7 @@ function sha256hash(bytes) {
|
|||||||
|
|
||||||
// --> 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'];
|
var alphabet = alphabets[alpha || 'ripple'];
|
||||||
var bi_base = new BigInteger(String(alphabet.length));
|
var bi_base = new BigInteger(String(alphabet.length));
|
||||||
var bi_q = new BigInteger();
|
var bi_q = new BigInteger();
|
||||||
@@ -56,7 +56,7 @@ Base.encode = function (input, alpha) {
|
|||||||
|
|
||||||
// --> input: String
|
// --> input: String
|
||||||
// <-- array of bytes or undefined.
|
// <-- array of bytes or undefined.
|
||||||
Base.decode = function (input, alpha) {
|
Base.decode = function(input, alpha) {
|
||||||
if (typeof input !== 'string') {
|
if (typeof input !== 'string') {
|
||||||
return void(0);
|
return void(0);
|
||||||
}
|
}
|
||||||
@@ -66,8 +66,8 @@ Base.decode = function (input, alpha) {
|
|||||||
var bi_value = new BigInteger();
|
var bi_value = new BigInteger();
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
for (i = 0; i != input.length && input[i] === alphabet[0]; i += 1)
|
for (i = 0; i !== input.length && input[i] === alphabet[0]; i += 1) {
|
||||||
;
|
}
|
||||||
|
|
||||||
for (; i !== input.length; i += 1) {
|
for (; i !== input.length; i += 1) {
|
||||||
var v = alphabet.indexOf(input[i]);
|
var v = alphabet.indexOf(input[i]);
|
||||||
@@ -84,10 +84,10 @@ Base.decode = function (input, alpha) {
|
|||||||
// toByteArray:
|
// toByteArray:
|
||||||
// - Returns leading zeros!
|
// - Returns leading zeros!
|
||||||
// - Returns signed bytes!
|
// - Returns signed bytes!
|
||||||
var bytes = bi_value.toByteArray().map(function (b) { return b ? b < 0 ? 256+b : b : 0; });
|
var bytes = bi_value.toByteArray().map(function(b) { return b ? b < 0 ? 256+b : b : 0; });
|
||||||
var extra = 0;
|
var extra = 0;
|
||||||
|
|
||||||
while (extra != bytes.length && !bytes[extra]) {
|
while (extra !== bytes.length && !bytes[extra]) {
|
||||||
extra += 1;
|
extra += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ Base.decode = function (input, alpha) {
|
|||||||
return [].concat(utils.arraySet(zeros, 0), bytes);
|
return [].concat(utils.arraySet(zeros, 0), bytes);
|
||||||
};
|
};
|
||||||
|
|
||||||
Base.verify_checksum = function (bytes) {
|
Base.verify_checksum = function(bytes) {
|
||||||
var computed = sha256hash(bytes.slice(0, -4)).slice(0, 4);
|
var computed = sha256hash(bytes.slice(0, -4)).slice(0, 4);
|
||||||
var checksum = bytes.slice(-4);
|
var checksum = bytes.slice(-4);
|
||||||
var result = true;
|
var result = true;
|
||||||
@@ -121,7 +121,7 @@ Base.verify_checksum = function (bytes) {
|
|||||||
|
|
||||||
// --> input: Array
|
// --> input: Array
|
||||||
// <-- String
|
// <-- String
|
||||||
Base.encode_check = function (version, input, alphabet) {
|
Base.encode_check = function(version, input, alphabet) {
|
||||||
var buffer = [].concat(version, input);
|
var buffer = [].concat(version, input);
|
||||||
var check = sha256(sha256(buffer)).slice(0, 4);
|
var check = sha256(sha256(buffer)).slice(0, 4);
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ Base.encode_check = function (version, input, alphabet) {
|
|||||||
|
|
||||||
// --> input : String
|
// --> input : String
|
||||||
// <-- NaN || BigInteger
|
// <-- NaN || BigInteger
|
||||||
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);
|
||||||
|
|
||||||
if (!buffer || buffer.length < 5) {
|
if (!buffer || buffer.length < 5) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// This object serves as a singleton to store config options
|
// This object serves as a singleton to store config options
|
||||||
|
|
||||||
var extend = require("extend");
|
var extend = require('extend');
|
||||||
|
|
||||||
var config = module.exports = {
|
var config = module.exports = {
|
||||||
load: function (newOpts) {
|
load: function (newOpts) {
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
|
|
||||||
var extend = require('extend');
|
var extend = require('extend');
|
||||||
|
|
||||||
var UInt160 = require('./uint160').UInt160;
|
var UInt160 = require('./uint160').UInt160;
|
||||||
var Float = require('./float').Float;
|
var Float = require('./float').Float;
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
@@ -9,7 +7,7 @@ var utils = require('./utils');
|
|||||||
// Currency support
|
// Currency support
|
||||||
//
|
//
|
||||||
|
|
||||||
var Currency = extend(function () {
|
var Currency = extend(function() {
|
||||||
// Internal form: 0 = XRP. 3 letter-code.
|
// Internal form: 0 = XRP. 3 letter-code.
|
||||||
// XXX Internal should be 0 or hex with three letter annotation when valid.
|
// XXX Internal should be 0 or hex with three letter annotation when valid.
|
||||||
|
|
||||||
@@ -26,9 +24,9 @@ var Currency = extend(function () {
|
|||||||
Currency.prototype = extend({}, UInt160.prototype);
|
Currency.prototype = extend({}, UInt160.prototype);
|
||||||
Currency.prototype.constructor = Currency;
|
Currency.prototype.constructor = Currency;
|
||||||
|
|
||||||
Currency.HEX_CURRENCY_BAD = "0000000000000000000000005852500000000000";
|
Currency.HEX_CURRENCY_BAD = '0000000000000000000000005852500000000000';
|
||||||
|
|
||||||
Currency.from_json = function (j, shouldInterpretXrpAsIou) {
|
Currency.from_json = function(j, shouldInterpretXrpAsIou) {
|
||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
} else {
|
} else {
|
||||||
@@ -37,7 +35,7 @@ Currency.from_json = function (j, shouldInterpretXrpAsIou) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// this._value = NaN on error.
|
// this._value = NaN on error.
|
||||||
Currency.prototype.parse_json = function (j, shouldInterpretXrpAsIou) {
|
Currency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) {
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
|
|
||||||
switch (typeof j) {
|
switch (typeof j) {
|
||||||
@@ -82,14 +80,14 @@ Currency.prototype.parse_json = function (j, shouldInterpretXrpAsIou) {
|
|||||||
*
|
*
|
||||||
* You should never need to call this.
|
* You should never need to call this.
|
||||||
*/
|
*/
|
||||||
Currency.prototype._update = function () {
|
Currency.prototype._update = function() {
|
||||||
var bytes = this.to_bytes();
|
var bytes = this.to_bytes();
|
||||||
|
|
||||||
// is it 0 everywhere except 12, 13, 14?
|
// is it 0 everywhere except 12, 13, 14?
|
||||||
var isZeroExceptInStandardPositions = true;
|
var isZeroExceptInStandardPositions = true;
|
||||||
|
|
||||||
if (!bytes) {
|
if (!bytes) {
|
||||||
return "XRP";
|
return 'XRP';
|
||||||
}
|
}
|
||||||
|
|
||||||
this._native = false;
|
this._native = false;
|
||||||
@@ -107,9 +105,9 @@ Currency.prototype._update = function () {
|
|||||||
+ String.fromCharCode(bytes[13])
|
+ String.fromCharCode(bytes[13])
|
||||||
+ String.fromCharCode(bytes[14]);
|
+ String.fromCharCode(bytes[14]);
|
||||||
|
|
||||||
if (this._iso_code === "\0\0\0") {
|
if (this._iso_code === '\0\0\0') {
|
||||||
this._native = true;
|
this._native = true;
|
||||||
this._iso_code = "XRP";
|
this._iso_code = 'XRP';
|
||||||
}
|
}
|
||||||
|
|
||||||
this._type = 0;
|
this._type = 0;
|
||||||
@@ -129,7 +127,7 @@ Currency.prototype._update = function () {
|
|||||||
|
|
||||||
// XXX Probably not needed anymore?
|
// XXX Probably not needed anymore?
|
||||||
/*
|
/*
|
||||||
Currency.prototype.parse_bytes = function (byte_array) {
|
Currency.prototype.parse_bytes = function(byte_array) {
|
||||||
if (Array.isArray(byte_array) && byte_array.length === 20) {
|
if (Array.isArray(byte_array) && byte_array.length === 20) {
|
||||||
var result;
|
var result;
|
||||||
// is it 0 everywhere except 12, 13, 14?
|
// is it 0 everywhere except 12, 13, 14?
|
||||||
@@ -143,9 +141,9 @@ Currency.prototype.parse_bytes = function (byte_array) {
|
|||||||
var currencyCode = String.fromCharCode(byte_array[12])
|
var currencyCode = String.fromCharCode(byte_array[12])
|
||||||
+ String.fromCharCode(byte_array[13])
|
+ String.fromCharCode(byte_array[13])
|
||||||
+ String.fromCharCode(byte_array[14]);
|
+ String.fromCharCode(byte_array[14]);
|
||||||
if (/^[A-Z0-9]{3}$/.test(currencyCode) && currencyCode !== "XRP" ) {
|
if (/^[A-Z0-9]{3}$/.test(currencyCode) && currencyCode !== 'XRP' ) {
|
||||||
this._value = currencyCode;
|
this._value = currencyCode;
|
||||||
} else if (currencyCode === "\0\0\0") {
|
} else if (currencyCode === '\0\0\0') {
|
||||||
this._value = 0;
|
this._value = 0;
|
||||||
} else {
|
} else {
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
@@ -161,19 +159,21 @@ Currency.prototype.parse_bytes = function (byte_array) {
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Currency.prototype.is_native = function () {
|
Currency.prototype.is_native = function() {
|
||||||
return this._native;
|
return this._native;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this currency is an interest-bearing/demurring currency.
|
* Whether this currency is an interest-bearing/demurring currency.
|
||||||
*/
|
*/
|
||||||
Currency.prototype.has_interest = function () {
|
Currency.prototype.has_interest = function() {
|
||||||
return this._type === 1 && this._interest_start && !isNaN(this._interest_period);
|
return this._type === 1 && this._interest_start && !isNaN(this._interest_period);
|
||||||
};
|
};
|
||||||
|
|
||||||
Currency.prototype.get_interest_at = function (referenceDate) {
|
Currency.prototype.get_interest_at = function(referenceDate) {
|
||||||
if (!this.has_interest) return 1;
|
if (!this.has_interest) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (referenceDate instanceof Date) {
|
if (referenceDate instanceof Date) {
|
||||||
referenceDate = utils.fromTimestamp(referenceDate.getTime());
|
referenceDate = utils.fromTimestamp(referenceDate.getTime());
|
||||||
@@ -187,14 +187,14 @@ Currency.prototype.get_interest_at = function (referenceDate) {
|
|||||||
// We could be doing further checks into the internal format of the
|
// We could be doing further checks into the internal format of the
|
||||||
// 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 this._value instanceof BigInteger && ...;
|
||||||
//};
|
//};
|
||||||
|
|
||||||
Currency.prototype.to_json = function () {
|
Currency.prototype.to_json = function() {
|
||||||
if (!this.is_valid()) {
|
if (!this.is_valid()) {
|
||||||
// XXX This is backwards compatible behavior, but probably not very good.
|
// XXX This is backwards compatible behavior, but probably not very good.
|
||||||
return "XRP";
|
return 'XRP';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any currency with standard properties and a valid code can be abbreviated
|
// Any currency with standard properties and a valid code can be abbreviated
|
||||||
@@ -216,7 +216,7 @@ Currency.prototype.to_json = function () {
|
|||||||
return currencyHex;
|
return currencyHex;
|
||||||
};
|
};
|
||||||
|
|
||||||
Currency.prototype.to_human = function () {
|
Currency.prototype.to_human = function() {
|
||||||
// to_human() will always print the human-readable currency code if available.
|
// to_human() will always print the human-readable currency code if available.
|
||||||
if (/^[A-Z0-9]{3}$/.test(this._iso_code)) {
|
if (/^[A-Z0-9]{3}$/.test(this._iso_code)) {
|
||||||
return this._iso_code;
|
return this._iso_code;
|
||||||
|
|||||||
@@ -8,12 +8,17 @@ var Float = exports.Float = {};
|
|||||||
var allZeros = /^0+$/;
|
var allZeros = /^0+$/;
|
||||||
var allOnes = /^1+$/;
|
var allOnes = /^1+$/;
|
||||||
|
|
||||||
Float.fromBytes = function (bytes) {
|
Float.fromBytes = function(bytes) {
|
||||||
// Render in binary. Hackish.
|
// Render in binary. Hackish.
|
||||||
var b = "";
|
var b = '';
|
||||||
|
|
||||||
for (var i = 0, n = bytes.length; i < n; i++) {
|
for (var i = 0, n = bytes.length; i < n; i++) {
|
||||||
var bits = (bytes[i] & 0xff).toString(2);
|
var bits = (bytes[i] & 0xff).toString(2);
|
||||||
while (bits.length < 8) bits = "0" + bits;
|
|
||||||
|
while (bits.length < 8) {
|
||||||
|
bits = '0' + bits;
|
||||||
|
}
|
||||||
|
|
||||||
b += bits;
|
b += bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,13 +34,11 @@ Float.fromBytes = function (bytes) {
|
|||||||
var m = b.substring(exponentBits + 1);
|
var m = b.substring(exponentBits + 1);
|
||||||
|
|
||||||
var value = 0;
|
var value = 0;
|
||||||
var multiplier = (s === "0" ? 1 : -1);
|
var multiplier = (s === '0' ? 1 : -1);
|
||||||
|
|
||||||
if (allZeros.test(e)) {
|
if (allZeros.test(e)) {
|
||||||
// Zero or denormalized
|
// Zero or denormalized
|
||||||
if (allZeros.test(m)) {
|
if (!allZeros.test(m)) {
|
||||||
// Value is zero
|
|
||||||
} else {
|
|
||||||
value = parseInt(m, 2) * Math.pow(2, minExponent);
|
value = parseInt(m, 2) * Math.pow(2, minExponent);
|
||||||
}
|
}
|
||||||
} else if (allOnes.test(e)) {
|
} else if (allOnes.test(e)) {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ exports.Meta = require('./meta').Meta;
|
|||||||
exports.SerializedObject = require('./serializedobject').SerializedObject;
|
exports.SerializedObject = require('./serializedobject').SerializedObject;
|
||||||
exports.RippleError = require('./rippleerror').RippleError;
|
exports.RippleError = require('./rippleerror').RippleError;
|
||||||
exports.Message = require('./message');
|
exports.Message = require('./message');
|
||||||
|
|
||||||
exports.binformat = require('./binformat');
|
exports.binformat = require('./binformat');
|
||||||
exports.utils = require('./utils');
|
exports.utils = require('./utils');
|
||||||
exports.Server = require('./server').Server;
|
exports.Server = require('./server').Server;
|
||||||
@@ -35,7 +34,9 @@ function attachUnderscored(c) {
|
|||||||
Object.keys(o.prototype).forEach(function(key) {
|
Object.keys(o.prototype).forEach(function(key) {
|
||||||
var UPPERCASE = /([A-Z]{1})[a-z]+/g;
|
var UPPERCASE = /([A-Z]{1})[a-z]+/g;
|
||||||
|
|
||||||
if (!UPPERCASE.test(key)) return;
|
if (!UPPERCASE.test(key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var underscored = key.replace(UPPERCASE, function(c) {
|
var underscored = key.replace(UPPERCASE, function(c) {
|
||||||
return '_' + c.toLowerCase();
|
return '_' + c.toLowerCase();
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ var UInt256 = require('./uint256').UInt256;
|
|||||||
var Base = require('./base').Base;
|
var Base = require('./base').Base;
|
||||||
|
|
||||||
function KeyPair() {
|
function KeyPair() {
|
||||||
this._curve = sjcl.ecc.curves['c256'];
|
this._curve = sjcl.ecc.curves.c256;
|
||||||
this._secret = null;
|
this._secret = null;
|
||||||
this._pubkey = null;
|
this._pubkey = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
KeyPair.from_bn_secret = function (j) {
|
KeyPair.from_bn_secret = function(j) {
|
||||||
return j instanceof this ? j.clone() : (new this()).parse_bn_secret(j);
|
return (j instanceof this) ? j.clone() : (new this()).parse_bn_secret(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
KeyPair.prototype.parse_bn_secret = function (j) {
|
KeyPair.prototype.parse_bn_secret = function(j) {
|
||||||
this._secret = new sjcl.ecc.ecdsa.secretKey(sjcl.ecc.curves['c256'], j);
|
this._secret = new sjcl.ecc.ecdsa.secretKey(sjcl.ecc.curves.c256, j);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ KeyPair.prototype.parse_bn_secret = function (j) {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
KeyPair.prototype._pub = function () {
|
KeyPair.prototype._pub = function() {
|
||||||
var curve = this._curve;
|
var curve = this._curve;
|
||||||
|
|
||||||
if (!this._pubkey && this._secret) {
|
if (!this._pubkey && this._secret) {
|
||||||
@@ -40,7 +40,7 @@ KeyPair.prototype._pub = function () {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
KeyPair.prototype._pub_bits = function () {
|
KeyPair.prototype._pub_bits = function() {
|
||||||
var pub = this._pub();
|
var pub = this._pub();
|
||||||
|
|
||||||
if (!pub) {
|
if (!pub) {
|
||||||
@@ -60,7 +60,7 @@ KeyPair.prototype._pub_bits = function () {
|
|||||||
*
|
*
|
||||||
* Key will be returned as a compressed pubkey - 33 bytes converted to hex.
|
* Key will be returned as a compressed pubkey - 33 bytes converted to hex.
|
||||||
*/
|
*/
|
||||||
KeyPair.prototype.to_hex_pub = function () {
|
KeyPair.prototype.to_hex_pub = function() {
|
||||||
var bits = this._pub_bits();
|
var bits = this._pub_bits();
|
||||||
|
|
||||||
if (!bits) {
|
if (!bits) {
|
||||||
@@ -74,7 +74,7 @@ function SHA256_RIPEMD160(bits) {
|
|||||||
return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));
|
return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyPair.prototype.get_address = function () {
|
KeyPair.prototype.get_address = function() {
|
||||||
var bits = this._pub_bits();
|
var bits = this._pub_bits();
|
||||||
|
|
||||||
if (!bits) {
|
if (!bits) {
|
||||||
@@ -88,7 +88,7 @@ KeyPair.prototype.get_address = function () {
|
|||||||
return address;
|
return address;
|
||||||
};
|
};
|
||||||
|
|
||||||
KeyPair.prototype.sign = function (hash) {
|
KeyPair.prototype.sign = function(hash) {
|
||||||
hash = UInt256.from_json(hash);
|
hash = UInt256.from_json(hash);
|
||||||
var sig = this._secret.sign(hash.to_bits(), 0);
|
var sig = this._secret.sign(hash.to_bits(), 0);
|
||||||
sig = this._secret.canonicalizeSignature(sig);
|
sig = this._secret.canonicalizeSignature(sig);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* Logging functionality for ripple-lib and any applications built on it.
|
* Logging functionality for ripple-lib and any applications built on it.
|
||||||
*/
|
*/
|
||||||
var Log = function (namespace) {
|
function Log(namespace) {
|
||||||
if (!namespace) {
|
if (!namespace) {
|
||||||
this._namespace = [];
|
this._namespace = [];
|
||||||
} else if (Array.isArray(namespace)) {
|
} else if (Array.isArray(namespace)) {
|
||||||
this._namespace = namespace;
|
this._namespace = namespace;
|
||||||
} else {
|
} else {
|
||||||
this._namespace = [""+namespace];
|
this._namespace = [''+namespace];
|
||||||
}
|
}
|
||||||
|
|
||||||
this._prefix = this._namespace.concat(['']).join(': ');
|
this._prefix = this._namespace.concat(['']).join(': ');
|
||||||
@@ -23,25 +23,29 @@ var Log = function (namespace) {
|
|||||||
* var log = require('ripple').log.sub('server');
|
* var log = require('ripple').log.sub('server');
|
||||||
*
|
*
|
||||||
* log.info('connection successful');
|
* log.info('connection successful');
|
||||||
* // prints: "server: connection successful"
|
* // prints: 'server: connection successful'
|
||||||
*/
|
*/
|
||||||
Log.prototype.sub = function (namespace) {
|
Log.prototype.sub = function(namespace) {
|
||||||
var subNamespace = this._namespace.slice();
|
var subNamespace = this._namespace.slice();
|
||||||
if (namespace && "string" === typeof namespace) subNamespace.push(namespace);
|
|
||||||
|
if (namespace && typeof namespace === 'string') {
|
||||||
|
subNamespace.push(namespace);
|
||||||
|
}
|
||||||
|
|
||||||
var subLogger = new Log(subNamespace);
|
var subLogger = new Log(subNamespace);
|
||||||
subLogger._setParent(this);
|
subLogger._setParent(this);
|
||||||
return subLogger;
|
return subLogger;
|
||||||
};
|
};
|
||||||
|
|
||||||
Log.prototype._setParent = function (parentLogger) {
|
Log.prototype._setParent = function(parentLogger) {
|
||||||
this._parent = parentLogger;
|
this._parent = parentLogger;
|
||||||
};
|
};
|
||||||
|
|
||||||
Log.makeLevel = function (level) {
|
Log.makeLevel = function(level) {
|
||||||
return function () {
|
return function() {
|
||||||
arguments[0] = this._prefix + arguments[0];
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
args[0] = this._prefix + args[0];
|
||||||
Log.engine.logObject.apply(Log, Array.prototype.slice.call(arguments));
|
Log.engine.logObject.apply(Log, args);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -53,7 +57,7 @@ Log.prototype.error = Log.makeLevel(4);
|
|||||||
/**
|
/**
|
||||||
* Basic logging connector.
|
* Basic logging connector.
|
||||||
*
|
*
|
||||||
* This engine has no formatting and works with the most basic of "console.log"
|
* This engine has no formatting and works with the most basic of 'console.log'
|
||||||
* implementations. This is the logging engine used in Node.js.
|
* implementations. This is the logging engine used in Node.js.
|
||||||
*/
|
*/
|
||||||
var BasicLogEngine = {
|
var BasicLogEngine = {
|
||||||
@@ -77,12 +81,14 @@ var BasicLogEngine = {
|
|||||||
* available.
|
* available.
|
||||||
*/
|
*/
|
||||||
var NullLogEngine = {
|
var NullLogEngine = {
|
||||||
logObject: function () {}
|
logObject: function() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Log.engine = NullLogEngine;
|
Log.engine = NullLogEngine;
|
||||||
|
|
||||||
if (console && console.log) Log.engine = BasicLogEngine;
|
if (console && console.log) {
|
||||||
|
Log.engine = BasicLogEngine;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide a root logger as our main export.
|
* Provide a root logger as our main export.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ function Meta(raw_data) {
|
|||||||
raw_data.AffectedNodes.forEach(function(an) {
|
raw_data.AffectedNodes.forEach(function(an) {
|
||||||
var result = { };
|
var result = { };
|
||||||
|
|
||||||
if (result.diffType = self.diffType(an)) {
|
if ((result.diffType = self.diffType(an))) {
|
||||||
an = an[result.diffType];
|
an = an[result.diffType];
|
||||||
|
|
||||||
result.entryType = an.LedgerEntryType;
|
result.entryType = an.LedgerEntryType;
|
||||||
@@ -88,7 +88,7 @@ Meta.prototype.diffType = function(an) {
|
|||||||
* The second parameter to the callback is the index of the node in the metadata
|
* The second parameter to the callback is the index of the node in the metadata
|
||||||
* (first entry is index 0).
|
* (first entry is index 0).
|
||||||
*/
|
*/
|
||||||
Meta.prototype.each = function (fn) {
|
Meta.prototype.each = function(fn) {
|
||||||
for (var i = 0, l = this.nodes.length; i < l; i++) {
|
for (var i = 0, l = this.nodes.length; i < l; i++) {
|
||||||
fn(this.nodes[i], i);
|
fn(this.nodes[i], i);
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ Meta.prototype.each = function (fn) {
|
|||||||
]).forEach(function(fn) {
|
]).forEach(function(fn) {
|
||||||
Meta.prototype[fn] = function() {
|
Meta.prototype[fn] = function() {
|
||||||
return Array.prototype[fn].apply(this.nodes, arguments);
|
return Array.prototype[fn].apply(this.nodes, arguments);
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
var amountFieldsAffectingIssuer = [
|
var amountFieldsAffectingIssuer = [
|
||||||
@@ -113,12 +113,12 @@ var amountFieldsAffectingIssuer = [
|
|||||||
'TakerGets'
|
'TakerGets'
|
||||||
];
|
];
|
||||||
|
|
||||||
Meta.prototype.getAffectedAccounts = function () {
|
Meta.prototype.getAffectedAccounts = function() {
|
||||||
var accounts = [ ];
|
var accounts = [ ];
|
||||||
|
|
||||||
// This code should match the behavior of the C++ method:
|
// This code should match the behavior of the C++ method:
|
||||||
// TransactionMetaSet::getAffectedAccounts
|
// TransactionMetaSet::getAffectedAccounts
|
||||||
this.nodes.forEach(function (an) {
|
this.nodes.forEach(function(an) {
|
||||||
var fields = (an.diffType === 'CreatedNode') ? an.fieldsNew : an.fieldsFinal;
|
var fields = (an.diffType === 'CreatedNode') ? an.fieldsNew : an.fieldsFinal;
|
||||||
for (var i in fields) {
|
for (var i in fields) {
|
||||||
var field = fields[i];
|
var field = fields[i];
|
||||||
@@ -137,20 +137,26 @@ Meta.prototype.getAffectedAccounts = function () {
|
|||||||
return utils.arrayUnique(accounts);
|
return utils.arrayUnique(accounts);
|
||||||
};
|
};
|
||||||
|
|
||||||
Meta.prototype.getAffectedBooks = function () {
|
Meta.prototype.getAffectedBooks = function() {
|
||||||
var books = [ ];
|
var books = [ ];
|
||||||
|
|
||||||
this.nodes.forEach(function (an) {
|
this.nodes.forEach(function(an) {
|
||||||
if (an.entryType !== 'Offer') return;
|
if (an.entryType !== 'Offer') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var gets = Amount.from_json(an.fields.TakerGets);
|
var gets = Amount.from_json(an.fields.TakerGets);
|
||||||
var pays = Amount.from_json(an.fields.TakerPays);
|
var pays = Amount.from_json(an.fields.TakerPays);
|
||||||
|
|
||||||
var getsKey = gets.currency().to_json();
|
var getsKey = gets.currency().to_json();
|
||||||
if (getsKey !== 'XRP') getsKey += '/' + gets.issuer().to_json();
|
if (getsKey !== 'XRP') {
|
||||||
|
getsKey += '/' + gets.issuer().to_json();
|
||||||
|
}
|
||||||
|
|
||||||
var paysKey = pays.currency().to_json();
|
var paysKey = pays.currency().to_json();
|
||||||
if (paysKey !== 'XRP') paysKey += '/' + pays.issuer().to_json();
|
if (paysKey !== 'XRP') {
|
||||||
|
paysKey += '/' + pays.issuer().to_json();
|
||||||
|
}
|
||||||
|
|
||||||
var key = [ getsKey, paysKey ].join(':');
|
var key = [ getsKey, paysKey ].join(':');
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
// var network = require("./network.js");
|
// var network = require("./network.js");
|
||||||
|
|
||||||
var EventEmitter = require('events').EventEmitter;
|
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var extend = require('extend');
|
var extend = require('extend');
|
||||||
var Amount = require('./amount').Amount;
|
var Amount = require('./amount').Amount;
|
||||||
var UInt160 = require('./uint160').UInt160;
|
var UInt160 = require('./uint160').UInt160;
|
||||||
@@ -38,7 +38,7 @@ function OrderBook(remote, currency_gets, issuer_gets, currency_pays, issuer_pay
|
|||||||
function listenerAdded(type, listener) {
|
function listenerAdded(type, listener) {
|
||||||
if (~OrderBook.subscribe_events.indexOf(type)) {
|
if (~OrderBook.subscribe_events.indexOf(type)) {
|
||||||
self._subs += 1;
|
self._subs += 1;
|
||||||
if (self._subs == 1 && self._remote._connected) {
|
if (self._subs === 1 && self._remote._connected) {
|
||||||
self._subscribe();
|
self._subscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,11 +140,11 @@ OrderBook.prototype.to_json = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (this._currency_gets !== 'XRP') {
|
if (this._currency_gets !== 'XRP') {
|
||||||
json['taker_gets']['issuer'] = this._issuer_gets;
|
json.taker_gets.issuer = this._issuer_gets;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._currency_pays !== 'XRP') {
|
if (this._currency_pays !== 'XRP') {
|
||||||
json['taker_pays']['issuer'] = this._issuer_pays;
|
json.taker_pays.issuer = this._issuer_pays;
|
||||||
}
|
}
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
@@ -188,7 +188,9 @@ OrderBook.prototype.notify = function (message) {
|
|||||||
var trade_pays = this.trade('pays');
|
var trade_pays = this.trade('pays');
|
||||||
|
|
||||||
function handleTransaction(an) {
|
function handleTransaction(an) {
|
||||||
if (an.entryType !== 'Offer' || an.bookKey !== self._key) return;
|
if (an.entryType !== 'Offer' || an.bookKey !== self._key) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var i, l, offer;
|
var i, l, offer;
|
||||||
|
|
||||||
@@ -197,8 +199,9 @@ OrderBook.prototype.notify = function (message) {
|
|||||||
case 'ModifiedNode':
|
case 'ModifiedNode':
|
||||||
var deletedNode = an.diffType === 'DeletedNode';
|
var deletedNode = an.diffType === 'DeletedNode';
|
||||||
|
|
||||||
for (i = 0, l = self._offers.length; i < l; i++) {
|
for (i=0, l=self._offers.length; i<l; i++) {
|
||||||
offer = self._offers[i];
|
offer = self._offers[i];
|
||||||
|
|
||||||
if (offer.index === an.ledgerIndex) {
|
if (offer.index === an.ledgerIndex) {
|
||||||
if (deletedNode) {
|
if (deletedNode) {
|
||||||
self._offers.splice(i, 1);
|
self._offers.splice(i, 1);
|
||||||
@@ -207,13 +210,16 @@ OrderBook.prototype.notify = function (message) {
|
|||||||
// safe assumption, but should be checked.
|
// safe assumption, but should be checked.
|
||||||
extend(offer, an.fieldsFinal);
|
extend(offer, an.fieldsFinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't want to count a OfferCancel as a trade
|
// We don't want to count a OfferCancel as a trade
|
||||||
if (message.transaction.TransactionType === 'OfferCancel') return;
|
if (message.transaction.TransactionType === 'OfferCancel') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
trade_gets = trade_gets.add(an.fieldsPrev.TakerGets);
|
trade_gets = trade_gets.add(an.fieldsPrev.TakerGets);
|
||||||
trade_pays = trade_pays.add(an.fieldsPrev.TakerPays);
|
trade_pays = trade_pays.add(an.fieldsPrev.TakerPays);
|
||||||
@@ -272,6 +278,7 @@ OrderBook.prototype.notifyTx = OrderBook.prototype.notify;
|
|||||||
*/
|
*/
|
||||||
OrderBook.prototype.offers = function (callback) {
|
OrderBook.prototype.offers = function (callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (typeof callback === 'function') {
|
if (typeof callback === 'function') {
|
||||||
if (this._sync) {
|
if (this._sync) {
|
||||||
callback(this._offers);
|
callback(this._offers);
|
||||||
@@ -279,6 +286,7 @@ OrderBook.prototype.offers = function (callback) {
|
|||||||
this.once('model', callback);
|
this.once('model', callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -102,8 +102,8 @@ function Remote(opts, trace) {
|
|||||||
this.retry = void(0);
|
this.retry = void(0);
|
||||||
this._connection_count = 0;
|
this._connection_count = 0;
|
||||||
this._connected = false;
|
this._connected = false;
|
||||||
this._connection_offset = 1000 * (typeof opts.connection_offset === 'number' ? opts.connection_offset : 5)
|
this._connection_offset = 1000 * (typeof opts.connection_offset === 'number' ? opts.connection_offset : 5);
|
||||||
this._submission_timeout = 1000 * (typeof opts.submission_timeout === 'number' ? opts.submission_timeout : 10)
|
this._submission_timeout = 1000 * (typeof opts.submission_timeout === 'number' ? opts.submission_timeout : 10);
|
||||||
|
|
||||||
this._received_tx = LRU({ max: 100 });
|
this._received_tx = LRU({ max: 100 });
|
||||||
this._cur_path_find = null;
|
this._cur_path_find = null;
|
||||||
@@ -239,7 +239,9 @@ function Remote(opts, trace) {
|
|||||||
|
|
||||||
function getPendingTransactions() {
|
function getPendingTransactions() {
|
||||||
self.storage.getPendingTransactions(function(err, transactions) {
|
self.storage.getPendingTransactions(function(err, transactions) {
|
||||||
if (err || !Array.isArray(transactions)) return;
|
if (err || !Array.isArray(transactions)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function resubmitTransaction(tx) {
|
function resubmitTransaction(tx) {
|
||||||
var transaction = self.transaction();
|
var transaction = self.transaction();
|
||||||
@@ -510,7 +512,9 @@ Remote.prototype._handleMessage = function(message, server) {
|
|||||||
// XXX Also need to consider a slow server or out of order response.
|
// XXX Also need to consider a slow server or out of order response.
|
||||||
// XXX Be more defensive fields could be missing or of wrong type.
|
// XXX Be more defensive fields could be missing or of wrong type.
|
||||||
// YYY Might want to do some cache management.
|
// YYY Might want to do some cache management.
|
||||||
if (!Remote.isValidLedgerData(message)) return;
|
if (!Remote.isValidLedgerData(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (message.ledger_index >= this._ledger_current_index) {
|
if (message.ledger_index >= this._ledger_current_index) {
|
||||||
this._ledger_time = message.ledger_time;
|
this._ledger_time = message.ledger_time;
|
||||||
@@ -549,13 +553,17 @@ Remote.prototype._handleMessage = function(message, server) {
|
|||||||
// Pass the event on to any related Account objects
|
// Pass the event on to any related Account objects
|
||||||
message.mmeta.getAffectedAccounts().forEach(function(account) {
|
message.mmeta.getAffectedAccounts().forEach(function(account) {
|
||||||
account = self._accounts[account];
|
account = self._accounts[account];
|
||||||
if (account) account.notify(message);
|
if (account) {
|
||||||
|
account.notify(message);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pass the event on to any related OrderBooks
|
// Pass the event on to any related OrderBooks
|
||||||
message.mmeta.getAffectedBooks().forEach(function(book) {
|
message.mmeta.getAffectedBooks().forEach(function(book) {
|
||||||
book = self._books[book];
|
book = self._books[book];
|
||||||
if (book) book.notify(message);
|
if (book) {
|
||||||
|
book.notify(message);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
[ 'Account', 'Destination' ].forEach(function(prop) {
|
[ 'Account', 'Destination' ].forEach(function(prop) {
|
||||||
@@ -659,7 +667,9 @@ Remote.prototype._getServer = function() {
|
|||||||
// <-> request: what to send, consumed.
|
// <-> request: what to send, consumed.
|
||||||
Remote.prototype.request = function(request) {
|
Remote.prototype.request = function(request) {
|
||||||
if (typeof request === 'string') {
|
if (typeof request === 'string') {
|
||||||
if (!/^request_/.test(request)) request = 'request_' + request;
|
if (!/^request_/.test(request)) {
|
||||||
|
request = 'request_' + request;
|
||||||
|
}
|
||||||
if (typeof this[request] === 'function') {
|
if (typeof this[request] === 'function') {
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
var args = Array.prototype.slice.call(arguments, 1);
|
||||||
return this[request].apply(this, args);
|
return this[request].apply(this, args);
|
||||||
@@ -678,7 +688,7 @@ Remote.prototype.request = function(request) {
|
|||||||
} else {
|
} else {
|
||||||
var server = request.server || this._getServer();
|
var server = request.server || this._getServer();
|
||||||
if (server) {
|
if (server) {
|
||||||
server.request(request);
|
server._request(request);
|
||||||
} else {
|
} else {
|
||||||
request.emit('error', new Error('No servers available'));
|
request.emit('error', new Error('No servers available'));
|
||||||
}
|
}
|
||||||
@@ -1147,7 +1157,7 @@ Remote.prototype.requestBookOffers = function(gets, pays, taker, callback) {
|
|||||||
|
|
||||||
request.message.taker_pays = {
|
request.message.taker_pays = {
|
||||||
currency: Currency.json_rewrite(pays.currency)
|
currency: Currency.json_rewrite(pays.currency)
|
||||||
}
|
};
|
||||||
|
|
||||||
if (request.message.taker_pays.currency !== 'XRP') {
|
if (request.message.taker_pays.currency !== 'XRP') {
|
||||||
request.message.taker_pays.issuer = UInt160.json_rewrite(pays.issuer);
|
request.message.taker_pays.issuer = UInt160.json_rewrite(pays.issuer);
|
||||||
@@ -1396,7 +1406,7 @@ Remote.prototype.accountSeq = function(account, advance) {
|
|||||||
var accountInfo = this.accounts[account];
|
var accountInfo = this.accounts[account];
|
||||||
var seq;
|
var seq;
|
||||||
|
|
||||||
if (account_info && account_info.seq) {
|
if (accountInfo && accountInfo.seq) {
|
||||||
seq = accountInfo.seq;
|
seq = accountInfo.seq;
|
||||||
var change = { ADVANCE: 1, REWIND: -1 }[advance.toUpperCase()] || 0;
|
var change = { ADVANCE: 1, REWIND: -1 }[advance.toUpperCase()] || 0;
|
||||||
accountInfo.seq += change;
|
accountInfo.seq += change;
|
||||||
@@ -1657,7 +1667,7 @@ Remote.prototype.transaction = function(source, options, callback) {
|
|||||||
offercreate: 'offerCreate',
|
offercreate: 'offerCreate',
|
||||||
offercancel: 'offerCancel',
|
offercancel: 'offerCancel',
|
||||||
sign: 'sign'
|
sign: 'sign'
|
||||||
}
|
};
|
||||||
|
|
||||||
var transactionType;
|
var transactionType;
|
||||||
|
|
||||||
@@ -1705,7 +1715,13 @@ Remote.prototype.transaction = function(source, options, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Remote.prototype.feeTx = function(units) {
|
Remote.prototype.feeTx = function(units) {
|
||||||
return this._getServer().feeTx(units);
|
var server = this._getServer();
|
||||||
|
|
||||||
|
if (!server) {
|
||||||
|
throw new Error('No connected servers');
|
||||||
|
}
|
||||||
|
|
||||||
|
return server._feeTx(units);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1718,7 +1734,13 @@ Remote.prototype.feeTx = function(units) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Remote.prototype.feeTxUnit = function() {
|
Remote.prototype.feeTxUnit = function() {
|
||||||
return this._getServer().feeTxUnit();
|
var server = this._getServer();
|
||||||
|
|
||||||
|
if (!server) {
|
||||||
|
throw new Error('No connected servers');
|
||||||
|
}
|
||||||
|
|
||||||
|
return server._feeTxUnit();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1728,7 +1750,13 @@ Remote.prototype.feeTxUnit = function() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Remote.prototype.reserve = function(owner_count) {
|
Remote.prototype.reserve = function(owner_count) {
|
||||||
return this._getServer().reserve(owner_count);
|
var server = this._getServer();
|
||||||
|
|
||||||
|
if (!server) {
|
||||||
|
throw new Error('No connected servers');
|
||||||
|
}
|
||||||
|
|
||||||
|
return server._reserve(owner_count);
|
||||||
};
|
};
|
||||||
|
|
||||||
Remote.prototype.requestPing =
|
Remote.prototype.requestPing =
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ var EventEmitter = require('events').EventEmitter;
|
|||||||
var util = require('util');
|
var util = require('util');
|
||||||
var UInt160 = require('./uint160').UInt160;
|
var UInt160 = require('./uint160').UInt160;
|
||||||
var Currency = require('./currency').Currency;
|
var Currency = require('./currency').Currency;
|
||||||
var Transaction = require('./transaction').Transaction;
|
|
||||||
var Account = require('./account').Account;
|
|
||||||
var Meta = require('./meta').Meta;
|
|
||||||
var OrderBook = require('./orderbook').OrderBook;
|
|
||||||
var RippleError = require('./rippleerror').RippleError;
|
var RippleError = require('./rippleerror').RippleError;
|
||||||
var Server = require('./server').Server;
|
var Server = require('./server').Server;
|
||||||
|
|
||||||
@@ -20,7 +16,11 @@ function Request(remote, command) {
|
|||||||
|
|
||||||
this.remote = remote;
|
this.remote = remote;
|
||||||
this.requested = false;
|
this.requested = false;
|
||||||
this.message = { command: command, id: void(0) };
|
|
||||||
|
this.message = {
|
||||||
|
command: command,
|
||||||
|
id: void(0)
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
util.inherits(Request, EventEmitter);
|
util.inherits(Request, EventEmitter);
|
||||||
@@ -32,11 +32,13 @@ Request.prototype.broadcast = function() {
|
|||||||
|
|
||||||
// Send the request to a remote.
|
// Send the request to a remote.
|
||||||
Request.prototype.request = function(remote) {
|
Request.prototype.request = function(remote) {
|
||||||
if (this.requested) return;
|
if (this.requested) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.requested = true;
|
this.requested = true;
|
||||||
|
|
||||||
this.on('error', new Function);
|
this.on('error', function(){});
|
||||||
this.emit('request', remote);
|
this.emit('request', remote);
|
||||||
|
|
||||||
if (this._broadcast) {
|
if (this._broadcast) {
|
||||||
@@ -93,7 +95,11 @@ Request.prototype.timeout = function(duration, callback) {
|
|||||||
|
|
||||||
var timeout = setTimeout(function() {
|
var timeout = setTimeout(function() {
|
||||||
timed_out = true;
|
timed_out = true;
|
||||||
if (typeof callback === 'function') callback();
|
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
emit.call(self, 'timeout');
|
emit.call(self, 'timeout');
|
||||||
}, duration);
|
}, duration);
|
||||||
|
|
||||||
@@ -119,7 +125,7 @@ Request.prototype.setServer = function(server) {
|
|||||||
// Find server with hostname string
|
// Find server with hostname string
|
||||||
var servers = this.remote._servers;
|
var servers = this.remote._servers;
|
||||||
|
|
||||||
for (var i=0, s; s=servers[i]; i++) {
|
for (var i=0, s; (s=servers[i]); i++) {
|
||||||
if (s._host === server) {
|
if (s._host === server) {
|
||||||
selected = s;
|
selected = s;
|
||||||
break;
|
break;
|
||||||
@@ -148,7 +154,7 @@ Request.prototype.buildPath = function(build) {
|
|||||||
} else {
|
} else {
|
||||||
// ND: rippled currently intreprets the mere presence of `build_path` as the
|
// ND: rippled currently intreprets the mere presence of `build_path` as the
|
||||||
// value being `truthy`
|
// value being `truthy`
|
||||||
delete this.message.build_path
|
delete this.message.build_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@@ -184,13 +190,13 @@ Request.prototype.ledgerSelect = function(ledger) {
|
|||||||
case 'current':
|
case 'current':
|
||||||
case 'closed':
|
case 'closed':
|
||||||
case 'verified':
|
case 'verified':
|
||||||
this.message.ledger_index = ledger_spec;
|
this.message.ledger_index = ledger;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (isNaN(ledger)) {
|
if (isNaN(ledger)) {
|
||||||
this.message.ledger_hash = ledger;
|
this.message.ledger_hash = ledger;
|
||||||
} else if (ledger = Number(ledger)) {
|
} else if ((ledger = Number(ledger))) {
|
||||||
this.message.ledger_index = ledger;
|
this.message.ledger_index = ledger;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -303,7 +309,7 @@ Request.prototype.books = function(books, snapshot) {
|
|||||||
// Reset list of books (this method overwrites the current list)
|
// Reset list of books (this method overwrites the current list)
|
||||||
this.message.books = [ ];
|
this.message.books = [ ];
|
||||||
|
|
||||||
for (var i = 0, l = books.length; i < l; i++) {
|
for (var i=0, l=books.length; i<l; i++) {
|
||||||
var book = books[i];
|
var book = books[i];
|
||||||
this.addBook(book, snapshot);
|
this.addBook(book, snapshot);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ function RippleError(code, message) {
|
|||||||
case 'object':
|
case 'object':
|
||||||
extend(this, code);
|
extend(this, code);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'string':
|
case 'string':
|
||||||
this.result = code;
|
this.result = code;
|
||||||
this.result_message = message;
|
this.result_message = message;
|
||||||
@@ -17,11 +18,13 @@ function RippleError(code, message) {
|
|||||||
this.result_message = this.message = (this.result_message);
|
this.result_message = this.message = (this.result_message);
|
||||||
|
|
||||||
var stack;
|
var stack;
|
||||||
if (!!Error.captureStackTrace)
|
|
||||||
|
if (!!Error.captureStackTrace) {
|
||||||
Error.captureStackTrace(this, code || this);
|
Error.captureStackTrace(this, code || this);
|
||||||
else if (stack = new Error().stack)
|
} else if ((stack = new Error().stack)) {
|
||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
util.inherits(RippleError, Error);
|
util.inherits(RippleError, Error);
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
// Seed support
|
// Seed support
|
||||||
//
|
//
|
||||||
|
|
||||||
|
var extend = require('extend');
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
var sjcl = utils.sjcl;
|
var sjcl = utils.sjcl;
|
||||||
var extend = require('extend');
|
|
||||||
|
|
||||||
var BigInteger = utils.jsbn.BigInteger;
|
var BigInteger = utils.jsbn.BigInteger;
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ var KeyPair = require('./keypair').KeyPair;
|
|||||||
|
|
||||||
var Seed = extend(function () {
|
var Seed = extend(function () {
|
||||||
// Internal form: NaN or BigInteger
|
// Internal form: NaN or BigInteger
|
||||||
this._curve = sjcl.ecc.curves['c256'];
|
this._curve = sjcl.ecc.curves.c256;
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
}, UInt);
|
}, UInt);
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ Seed.prototype.parse_json = function (j) {
|
|||||||
if (!j.length) {
|
if (!j.length) {
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
// XXX Should actually always try and continue if it failed.
|
// XXX Should actually always try and continue if it failed.
|
||||||
} else if (j[0] === "s") {
|
} else if (j[0] === 's') {
|
||||||
this._value = Base.decode_check(Base.VER_FAMILY_SEED, j);
|
this._value = Base.decode_check(Base.VER_FAMILY_SEED, j);
|
||||||
} else if (j.length === 32) {
|
} else if (j.length === 32) {
|
||||||
this._value = this.parse_hex(j);
|
this._value = this.parse_hex(j);
|
||||||
@@ -47,7 +47,7 @@ Seed.prototype.parse_json = function (j) {
|
|||||||
|
|
||||||
Seed.prototype.parse_passphrase = function (j) {
|
Seed.prototype.parse_passphrase = function (j) {
|
||||||
if (typeof j !== 'string') {
|
if (typeof j !== 'string') {
|
||||||
throw new Error("Passphrase must be a string");
|
throw new Error('Passphrase must be a string');
|
||||||
}
|
}
|
||||||
|
|
||||||
var hash = sjcl.hash.sha512.hash(sjcl.codec.utf8String.toBits(j));
|
var hash = sjcl.hash.sha512.hash(sjcl.codec.utf8String.toBits(j));
|
||||||
@@ -85,8 +85,9 @@ function SHA256_RIPEMD160(bits) {
|
|||||||
|
|
||||||
Seed.prototype.get_key = function (account_id) {
|
Seed.prototype.get_key = function (account_id) {
|
||||||
if (!this.is_valid()) {
|
if (!this.is_valid()) {
|
||||||
throw new Error("Cannot generate keys from invalid seed!");
|
throw new Error('Cannot generate keys from invalid seed!');
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Should loop over keys until we find the right one
|
// XXX Should loop over keys until we find the right one
|
||||||
|
|
||||||
var private_gen, public_gen;
|
var private_gen, public_gen;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
var binformat = require('./binformat');
|
var assert = require('assert');
|
||||||
var extend = require('extend');
|
var extend = require('extend');
|
||||||
|
var binformat = require('./binformat');
|
||||||
var stypes = require('./serializedtypes');
|
var stypes = require('./serializedtypes');
|
||||||
var UInt256 = require('./uint256').UInt256;
|
var UInt256 = require('./uint256').UInt256;
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
|
|
||||||
var sjcl = utils.sjcl;
|
var sjcl = utils.sjcl;
|
||||||
var BigInteger = utils.jsbn.BigInteger;
|
var BigInteger = utils.jsbn.BigInteger;
|
||||||
|
|
||||||
@@ -39,33 +39,31 @@ function SerializedObject(buf) {
|
|||||||
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({}, obj);
|
var obj = extend({}, obj);
|
||||||
var so = new SerializedObject;
|
var so = new SerializedObject();
|
||||||
var typedef;
|
var typedef;
|
||||||
|
|
||||||
if ("number" === typeof obj.TransactionType) {
|
if (typeof obj.TransactionType === 'number') {
|
||||||
obj.TransactionType = SerializedObject.lookup_type_tx(obj.TransactionType);
|
obj.TransactionType = SerializedObject.lookup_type_tx(obj.TransactionType);
|
||||||
|
|
||||||
if (!obj.TransactionType) {
|
if (!obj.TransactionType) {
|
||||||
throw new Error('Transaction type ID is invalid.');
|
throw new Error('Transaction type ID is invalid.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("string" === typeof obj.TransactionType) {
|
if (typeof obj.TransactionType === 'string') {
|
||||||
typedef = binformat.tx[obj.TransactionType];
|
typedef = binformat.tx[obj.TransactionType];
|
||||||
|
|
||||||
if (!Array.isArray(typedef)) {
|
if (!Array.isArray(typedef)) {
|
||||||
throw new Error('Transaction type is invalid');
|
throw new Error('Transaction type is invalid');
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef = typedef.slice();
|
typedef = typedef.slice();
|
||||||
obj.TransactionType = typedef.shift();
|
obj.TransactionType = typedef.shift();
|
||||||
} else if ("undefined" !== typeof obj.LedgerEntryType) {
|
} else if (typeof obj.LedgerEntryType !== 'undefined') {
|
||||||
// XXX: TODO
|
// XXX: TODO
|
||||||
throw new Error('Ledger entry binary format not yet implemented.');
|
throw new Error('Ledger entry binary format not yet implemented.');
|
||||||
} else if ("object" === typeof obj.AffectedNodes) {
|
} else if (typeof obj.AffectedNodes === 'object') {
|
||||||
typedef = binformat.metadata;
|
typedef = binformat.metadata;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Object to be serialized must contain either' +
|
throw new Error('Object to be serialized must contain either' +
|
||||||
@@ -79,42 +77,44 @@ SerializedObject.from_json = function (obj) {
|
|||||||
return so;
|
return so;
|
||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.check_no_missing_fields = function (typedef, obj) {
|
SerializedObject.check_no_missing_fields = function(typedef, obj) {
|
||||||
var missing_fields = [];
|
var missing_fields = [];
|
||||||
|
|
||||||
for (var i = typedef.length - 1; i >= 0; i--) {
|
for (var i=typedef.length - 1; i>=0; i--) {
|
||||||
var spec = typedef[i];
|
var spec = typedef[i];
|
||||||
var field = spec[0]
|
var field = spec[0];
|
||||||
var requirement = spec[1];
|
var requirement = spec[1];
|
||||||
|
|
||||||
if (binformat.REQUIRED === requirement && obj[field] == null) {
|
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;
|
||||||
if (obj.TransactionType != null) {
|
|
||||||
|
if (obj.TransactionType !== void(0)) {
|
||||||
object_name = SerializedObject.lookup_type_tx(obj.TransactionType);
|
object_name = SerializedObject.lookup_type_tx(obj.TransactionType);
|
||||||
} else {
|
} else {
|
||||||
object_name = "TransactionMetaData";
|
object_name = 'TransactionMetaData';
|
||||||
} /*else {
|
} /*else {
|
||||||
TODO: LedgerEntryType ...
|
TODO: LedgerEntryType ...
|
||||||
}*/
|
}*/
|
||||||
throw new Error(object_name + " is missing fields: " +
|
|
||||||
JSON.stringify(missing_fields));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
SerializedObject.prototype.append = function (bytes) {
|
throw new Error(object_name + ' is missing fields: ' + JSON.stringify(missing_fields));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
SerializedObject.prototype.append = function(bytes) {
|
||||||
if (bytes instanceof SerializedObject) {
|
if (bytes instanceof SerializedObject) {
|
||||||
bytes = bytes.buffer;
|
bytes = bytes.buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.buffer = this.buffer.concat(bytes);
|
this.buffer = this.buffer.concat(bytes);
|
||||||
this.pointer += bytes.length;
|
this.pointer += bytes.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.prototype.resetPointer = function () {
|
SerializedObject.prototype.resetPointer = function() {
|
||||||
this.pointer = 0;
|
this.pointer = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,18 +134,18 @@ function readOrPeek(advance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.prototype.read = readOrPeek(true);
|
SerializedObject.prototype.read = readOrPeek(true);
|
||||||
|
|
||||||
SerializedObject.prototype.peek = readOrPeek(false);
|
SerializedObject.prototype.peek = readOrPeek(false);
|
||||||
|
|
||||||
SerializedObject.prototype.to_bits = function () {
|
SerializedObject.prototype.to_bits = function() {
|
||||||
return sjcl.codec.bytes.toBits(this.buffer);
|
return sjcl.codec.bytes.toBits(this.buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.prototype.to_hex = function () {
|
SerializedObject.prototype.to_hex = function() {
|
||||||
return sjcl.codec.hex.fromBits(this.to_bits()).toUpperCase();
|
return sjcl.codec.hex.fromBits(this.to_bits()).toUpperCase();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ SerializedObject.prototype.to_json = function() {
|
|||||||
this.pointer = old_pointer;
|
this.pointer = old_pointer;
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
};
|
||||||
|
|
||||||
SerializedObject.jsonify_structure = function(structure, field_name) {
|
SerializedObject.jsonify_structure = function(structure, field_name) {
|
||||||
var output;
|
var output;
|
||||||
@@ -186,14 +186,20 @@ SerializedObject.jsonify_structure = function(structure, field_name) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'object':
|
case 'object':
|
||||||
if (!structure) break; //null
|
if (structure === null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
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 BigInteger) {
|
||||||
output = structure.toString(16).toUpperCase();
|
output = structure.toString(16).toUpperCase();
|
||||||
} else {
|
} else {
|
||||||
output = new structure.constructor; //new Array or Object
|
//new Array or Object
|
||||||
|
output = new structure.constructor();
|
||||||
|
|
||||||
var keys = Object.keys(structure);
|
var keys = Object.keys(structure);
|
||||||
|
|
||||||
for (var i=0, l=keys.length; i<l; i++) {
|
for (var i=0, l=keys.length; i<l; i++) {
|
||||||
var key = keys[i];
|
var key = keys[i];
|
||||||
output[key] = SerializedObject.jsonify_structure(structure[key], key);
|
output[key] = SerializedObject.jsonify_structure(structure[key], key);
|
||||||
@@ -207,7 +213,7 @@ SerializedObject.jsonify_structure = function(structure, field_name) {
|
|||||||
return output;
|
return output;
|
||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.prototype.serialize = function (typedef, obj) {
|
SerializedObject.prototype.serialize = function(typedef, obj) {
|
||||||
// Serialize object without end marker
|
// Serialize object without end marker
|
||||||
stypes.Object.serialize(this, obj, true);
|
stypes.Object.serialize(this, obj, true);
|
||||||
|
|
||||||
@@ -223,7 +229,7 @@ SerializedObject.prototype.serialize = function (typedef, obj) {
|
|||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.prototype.hash = function (prefix) {
|
SerializedObject.prototype.hash = function(prefix) {
|
||||||
var sign_buffer = new SerializedObject();
|
var sign_buffer = new SerializedObject();
|
||||||
stypes.Int32.serialize(sign_buffer, prefix);
|
stypes.Int32.serialize(sign_buffer, prefix);
|
||||||
sign_buffer.append(this.buffer);
|
sign_buffer.append(this.buffer);
|
||||||
@@ -233,13 +239,13 @@ SerializedObject.prototype.hash = function (prefix) {
|
|||||||
// DEPRECATED
|
// DEPRECATED
|
||||||
SerializedObject.prototype.signing_hash = SerializedObject.prototype.hash;
|
SerializedObject.prototype.signing_hash = SerializedObject.prototype.hash;
|
||||||
|
|
||||||
SerializedObject.prototype.hash_sha512_half = function () {
|
SerializedObject.prototype.hash_sha512_half = function() {
|
||||||
var bits = sjcl.codec.bytes.toBits(this.buffer);
|
var bits = sjcl.codec.bytes.toBits(this.buffer);
|
||||||
var hash = sjcl.bitArray.bitSlice(sjcl.hash.sha512.hash(bits), 0, 256);
|
var hash = sjcl.bitArray.bitSlice(sjcl.hash.sha512.hash(bits), 0, 256);
|
||||||
return UInt256.from_hex(sjcl.codec.hex.fromBits(hash));
|
return UInt256.from_hex(sjcl.codec.hex.fromBits(hash));
|
||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.prototype.serialize_field = function (spec, obj) {
|
SerializedObject.prototype.serialize_field = function(spec, obj) {
|
||||||
var name = spec[0];
|
var name = spec[0];
|
||||||
var presence = spec[1];
|
var presence = spec[1];
|
||||||
var field_id = spec[2];
|
var field_id = spec[2];
|
||||||
@@ -262,7 +268,7 @@ SerializedObject.prototype.serialize_field = function (spec, obj) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.get_field_header = function (type_id, field_id) {
|
SerializedObject.get_field_header = function(type_id, field_id) {
|
||||||
var buffer = [ 0 ];
|
var buffer = [ 0 ];
|
||||||
|
|
||||||
if (type_id > 0xF) {
|
if (type_id > 0xF) {
|
||||||
@@ -280,7 +286,7 @@ SerializedObject.get_field_header = function (type_id, field_id) {
|
|||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.sort_typedef = function (typedef) {
|
SerializedObject.sort_typedef = function(typedef) {
|
||||||
assert(Array.isArray(typedef));
|
assert(Array.isArray(typedef));
|
||||||
|
|
||||||
function sort_field_compare(a, b) {
|
function sort_field_compare(a, b) {
|
||||||
@@ -291,8 +297,8 @@ SerializedObject.sort_typedef = function (typedef) {
|
|||||||
return typedef.sort(sort_field_compare);
|
return typedef.sort(sort_field_compare);
|
||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.lookup_type_tx = function (id) {
|
SerializedObject.lookup_type_tx = function(id) {
|
||||||
assert(typeof id === 'number');
|
assert.strictEqual(typeof id, 'number');
|
||||||
return TRANSACTION_TYPES[id];
|
return TRANSACTION_TYPES[id];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -79,11 +79,7 @@ SerializedType.serialize_varint = function (so, val) {
|
|||||||
so.append([193 + (val >>> 8), val & 0xff]);
|
so.append([193 + (val >>> 8), val & 0xff]);
|
||||||
} else if (val <= 918744) {
|
} else if (val <= 918744) {
|
||||||
val -= 12481;
|
val -= 12481;
|
||||||
so.append([
|
so.append([ 241 + (val >>> 16), val >>> 8 & 0xff, val & 0xff ]);
|
||||||
241 + (val >>> 16),
|
|
||||||
val >>> 8 & 0xff,
|
|
||||||
val & 0xff
|
|
||||||
]);
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Variable integer overflow.');
|
throw new Error('Variable integer overflow.');
|
||||||
}
|
}
|
||||||
@@ -105,7 +101,7 @@ SerializedType.prototype.parse_varint = function (so) {
|
|||||||
} else if (b1 <= 254) {
|
} else if (b1 <= 254) {
|
||||||
b2 = so.read(1)[0];
|
b2 = so.read(1)[0];
|
||||||
b3 = so.read(1)[0];
|
b3 = so.read(1)[0];
|
||||||
result = 12481 + (b1 - 241) * 65536 + b2 * 256 + b3
|
result = 12481 + (b1 - 241) * 65536 + b2 * 256 + b3;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -142,7 +138,7 @@ function readAndSum(so, bytes) {
|
|||||||
var sum = 0;
|
var sum = 0;
|
||||||
|
|
||||||
if (bytes > 4) {
|
if (bytes > 4) {
|
||||||
throw new Error("This function only supports up to four bytes.");
|
throw new Error('This function only supports up to four bytes.');
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i=0; i<bytes; i++) {
|
for (var i=0; i<bytes; i++) {
|
||||||
@@ -328,7 +324,10 @@ var STAmount = exports.Amount = new SerializedType({
|
|||||||
// 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.
|
||||||
valueBytes[0] &= 0x3f;
|
valueBytes[0] &= 0x3f;
|
||||||
if (!amount.is_negative()) valueBytes[0] |= 0x40;
|
|
||||||
|
if (!amount.is_negative()) {
|
||||||
|
valueBytes[0] |= 0x40;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var hi = 0, lo = 0;
|
var hi = 0, lo = 0;
|
||||||
|
|
||||||
@@ -337,7 +336,10 @@ var STAmount = exports.Amount = new SerializedType({
|
|||||||
|
|
||||||
if (!amount.is_zero()) {
|
if (!amount.is_zero()) {
|
||||||
// Second bit: non-negative?
|
// Second bit: non-negative?
|
||||||
if (!amount.is_negative()) hi |= 1 << 30;
|
if (!amount.is_negative()) {
|
||||||
|
hi |= 1 << 30;
|
||||||
|
}
|
||||||
|
|
||||||
// Next eight bits: offset/exponent
|
// Next eight bits: offset/exponent
|
||||||
hi |= ((97 + amount._offset) & 0xff) << 22;
|
hi |= ((97 + amount._offset) & 0xff) << 22;
|
||||||
// Remaining 52 bits: mantissa
|
// Remaining 52 bits: mantissa
|
||||||
@@ -465,11 +467,18 @@ var STPathSet = exports.PathSet = new SerializedType({
|
|||||||
//if (entry.hasOwnProperty('_value')) {entry = entry._value;}
|
//if (entry.hasOwnProperty('_value')) {entry = entry._value;}
|
||||||
var type = 0;
|
var type = 0;
|
||||||
|
|
||||||
if (entry.account) type |= this.typeAccount;
|
if (entry.account) {
|
||||||
if (entry.currency) type |= this.typeCurrency;
|
type |= this.typeAccount;
|
||||||
if (entry.issuer) type |= this.typeIssuer;
|
}
|
||||||
|
if (entry.currency) {
|
||||||
|
type |= this.typeCurrency;
|
||||||
|
}
|
||||||
|
if (entry.issuer) {
|
||||||
|
type |= this.typeIssuer;
|
||||||
|
}
|
||||||
|
|
||||||
STInt8.serialize(so, type);
|
STInt8.serialize(so, type);
|
||||||
|
|
||||||
if (entry.account) {
|
if (entry.account) {
|
||||||
so.append(UInt160.from_json(entry.account).to_bytes());
|
so.append(UInt160.from_json(entry.account).to_bytes());
|
||||||
}
|
}
|
||||||
@@ -484,6 +493,7 @@ var STPathSet = exports.PathSet = new SerializedType({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STInt8.serialize(so, this.typeEnd);
|
STInt8.serialize(so, this.typeEnd);
|
||||||
},
|
},
|
||||||
parse: function (so) {
|
parse: function (so) {
|
||||||
@@ -512,8 +522,10 @@ var STPathSet = exports.PathSet = new SerializedType({
|
|||||||
if (current_path) { //close the current path, if there is one,
|
if (current_path) { //close the current path, if there is one,
|
||||||
path_list.push(current_path);
|
path_list.push(current_path);
|
||||||
}
|
}
|
||||||
current_path = []; //and start a new one.
|
current_path = [ ]; //and start a new one.
|
||||||
} else {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//It's an entry-begin tag.
|
//It's an entry-begin tag.
|
||||||
//console.log('It's an entry-begin tag.');
|
//console.log('It's an entry-begin tag.');
|
||||||
var entry = {};
|
var entry = {};
|
||||||
@@ -528,8 +540,7 @@ var STPathSet = exports.PathSet = new SerializedType({
|
|||||||
if (tag_byte & this.typeCurrency) {
|
if (tag_byte & this.typeCurrency) {
|
||||||
//console.log('entry.currency');
|
//console.log('entry.currency');
|
||||||
entry.currency = STCurrency.parse(so);
|
entry.currency = STCurrency.parse(so);
|
||||||
if (entry.currency.to_json() === "XRP" &&
|
if (entry.currency.to_json() === 'XRP' && !entry.currency.is_native()) {
|
||||||
!entry.currency.is_native()) {
|
|
||||||
entry.non_native = true;
|
entry.non_native = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -547,7 +558,6 @@ var STPathSet = exports.PathSet = new SerializedType({
|
|||||||
throw new Error('Invalid path entry'); //It must have at least something in it.
|
throw new Error('Invalid path entry'); //It must have at least something in it.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (current_path) {
|
if (current_path) {
|
||||||
//close the current path, if there is one,
|
//close the current path, if there is one,
|
||||||
@@ -591,11 +601,11 @@ function serialize(so, field_name, value) {
|
|||||||
var field_bits = field_coordinates[1];
|
var field_bits = field_coordinates[1];
|
||||||
var tag_byte = (type_bits < 16 ? type_bits << 4 : 0) | (field_bits < 16 ? field_bits : 0);
|
var tag_byte = (type_bits < 16 ? type_bits << 4 : 0) | (field_bits < 16 ? field_bits : 0);
|
||||||
|
|
||||||
if (field_name === "LedgerEntryType" && "string" === typeof value) {
|
if (field_name === 'LedgerEntryType' && 'string' === typeof value) {
|
||||||
value = binformat.ledger[value][0];
|
value = binformat.ledger[value][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field_name === "TransactionResult" && "string" === typeof value) {
|
if (field_name === 'TransactionResult' && 'string' === typeof value) {
|
||||||
value = binformat.ter[value];
|
value = binformat.ter[value];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,8 +678,8 @@ var STObject = exports.Object = new SerializedType({
|
|||||||
});
|
});
|
||||||
|
|
||||||
keys.forEach(function (key) {
|
keys.forEach(function (key) {
|
||||||
if ("undefined" === typeof binformat.fieldsInverseMap[key]) {
|
if (typeof binformat.fieldsInverseMap[key] === 'undefined') {
|
||||||
throw new Error("JSON contains unknown field: '" + key + "'");
|
throw new Error('JSON contains unknown field: "' + key + '"');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -679,7 +689,11 @@ var STObject = exports.Object = new SerializedType({
|
|||||||
for (var i=0; i<keys.length; i++) {
|
for (var i=0; i<keys.length; i++) {
|
||||||
serialize(so, keys[i], val[keys[i]]);
|
serialize(so, keys[i], val[keys[i]]);
|
||||||
}
|
}
|
||||||
if (!no_marker) STInt8.serialize(so, 0xe1); //Object ending marker
|
|
||||||
|
if (!no_marker) {
|
||||||
|
//Object ending marker
|
||||||
|
STInt8.serialize(so, 0xe1);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
parse: function (so) {
|
parse: function (so) {
|
||||||
@@ -708,7 +722,9 @@ var STArray = exports.Array = new SerializedType({
|
|||||||
var value = val[i][field_name];
|
var value = val[i][field_name];
|
||||||
serialize(so, field_name, value);
|
serialize(so, field_name, value);
|
||||||
}
|
}
|
||||||
STInt8.serialize(so, 0xf1); //Array ending marker
|
|
||||||
|
//Array ending marker
|
||||||
|
STInt8.serialize(so, 0xf1);
|
||||||
},
|
},
|
||||||
|
|
||||||
parse: function (so) {
|
parse: function (so) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
var util = require('util');
|
var util = require('util');
|
||||||
|
var url = require('url');
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var Transaction = require('./transaction').Transaction;
|
|
||||||
var Amount = require('./amount').Amount;
|
var Amount = require('./amount').Amount;
|
||||||
var utils = require('./utils');
|
var Transaction = require('./transaction').Transaction;
|
||||||
var log = require('./log').internal.sub('server');
|
var log = require('./log').internal.sub('server');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,34 +18,47 @@ var log = require('./log').internal.sub('server');
|
|||||||
function Server(remote, opts) {
|
function Server(remote, opts) {
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
if (typeof opts === 'string') {
|
||||||
|
var parsedUrl = url.parse(opts);
|
||||||
|
opts = {
|
||||||
|
host: parsedUrl.hostname,
|
||||||
|
port: parsedUrl.port,
|
||||||
|
secure: (parsedUrl.protocol === 'ws:') ? false : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof opts !== 'object') {
|
if (typeof opts !== 'object') {
|
||||||
throw new TypeError('Server configuration is not an Object');
|
throw new TypeError('Server configuration is not an Object');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opts.host) opts.host = opts.websocket_ip;
|
if (!opts.host) {
|
||||||
if (!opts.port) opts.port = opts.websocket_port;
|
opts.host = opts.websocket_ip;
|
||||||
if (!opts.secure) opts.secure = opts.websocket_ssl;
|
}
|
||||||
|
if (!opts.port) {
|
||||||
if (typeof opts.secure === 'undefined') {
|
opts.port = opts.websocket_port;
|
||||||
opts.secure = false;
|
}
|
||||||
|
if (!opts.secure) {
|
||||||
|
opts.secure = opts.websocket_ssl;
|
||||||
}
|
}
|
||||||
|
|
||||||
var domainRE = /^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$/;
|
if (isNaN(opts.port)) {
|
||||||
|
throw new TypeError('Server port must be a number');
|
||||||
|
}
|
||||||
|
|
||||||
if (!domainRE.test(opts.host)) {
|
if (!Server.domainRE.test(opts.host)) {
|
||||||
throw new Error('Server host is malformed, use "host" and "port" server configuration');
|
throw new Error('Server host is malformed, use "host" and "port" server configuration');
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to allow integer strings as valid port numbers for backward
|
if (typeof opts.secure !== 'boolean') {
|
||||||
// compatibility.
|
opts.secure = false;
|
||||||
if (typeof opts.port === 'string') {
|
|
||||||
opts.port = parseFloat(opts.port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof opts.port !== 'number' ||
|
// We want to allow integer strings as valid port numbers for backward compatibility
|
||||||
opts.port >>> 0 !== parseFloat(opts.port) || // is integer?
|
if (typeof opts.port !== 'number') {
|
||||||
opts.port < 1 ||
|
opts.port = Number(opts.port);
|
||||||
opts.port > 65535) {
|
}
|
||||||
|
|
||||||
|
if (opts.port < 1 || opts.port > 65535) {
|
||||||
throw new TypeError('Server "port" must be an integer in range 1-65535');
|
throw new TypeError('Server "port" must be an integer in range 1-65535');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +99,9 @@ function Server(remote, opts) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function checkServerActivity() {
|
function checkServerActivity() {
|
||||||
if (isNaN(self._lastLedgerClose)) return;
|
if (isNaN(self._lastLedgerClose)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var delta = (Date.now() - self._lastLedgerClose);
|
var delta = (Date.now() - self._lastLedgerClose);
|
||||||
|
|
||||||
@@ -111,6 +126,8 @@ function Server(remote, opts) {
|
|||||||
|
|
||||||
util.inherits(Server, EventEmitter);
|
util.inherits(Server, EventEmitter);
|
||||||
|
|
||||||
|
Server.domainRE = /^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|[-_]){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|[-_]){0,61}[0-9A-Za-z])?)*\.?$/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server states that we will treat as the server being online.
|
* Server states that we will treat as the server being online.
|
||||||
*
|
*
|
||||||
@@ -135,7 +152,10 @@ Server.onlineStates = [
|
|||||||
|
|
||||||
Server.prototype._setState = function(state) {
|
Server.prototype._setState = function(state) {
|
||||||
if (state !== this._state) {
|
if (state !== this._state) {
|
||||||
this._remote.trace && log.info('set_state:', state);
|
if (this._remote.trace) {
|
||||||
|
log.info('set_state:', state);
|
||||||
|
}
|
||||||
|
|
||||||
this._state = state;
|
this._state = state;
|
||||||
this.emit('state', state);
|
this.emit('state', state);
|
||||||
|
|
||||||
@@ -158,7 +178,11 @@ Server.prototype._setState = function(state) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Server.prototype._remoteAddress = function() {
|
Server.prototype._remoteAddress = function() {
|
||||||
try { var address = this._ws._socket.remoteAddress; } catch (e) { }
|
var address;
|
||||||
|
try {
|
||||||
|
address = this._ws._socket.remoteAddress;
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
return address;
|
return address;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -187,7 +211,9 @@ Server.websocketConstructor = function() {
|
|||||||
Server.prototype.disconnect = function() {
|
Server.prototype.disconnect = function() {
|
||||||
this._shouldConnect = false;
|
this._shouldConnect = false;
|
||||||
this._setState('offline');
|
this._setState('offline');
|
||||||
if (this._ws) this._ws.close();
|
if (this._ws) {
|
||||||
|
this._ws.close();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -218,12 +244,18 @@ Server.prototype.connect = function() {
|
|||||||
// recently received a message from the server and the WebSocket has not
|
// recently received a message from the server and the WebSocket has not
|
||||||
// reported any issues either. If we do fail to ping or the connection drops,
|
// reported any issues either. If we do fail to ping or the connection drops,
|
||||||
// we will automatically reconnect.
|
// we will automatically reconnect.
|
||||||
if (this._connected) return;
|
if (this._connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this._remote.trace && log.info('connect:', this._opts.url);
|
if (this._remote.trace) {
|
||||||
|
log.info('connect:', this._opts.url);
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure any existing socket is given the command to close first.
|
// Ensure any existing socket is given the command to close first.
|
||||||
if (this._ws) this._ws.close();
|
if (this._ws) {
|
||||||
|
this._ws.close();
|
||||||
|
}
|
||||||
|
|
||||||
var WebSocket = Server.websocketConstructor();
|
var WebSocket = Server.websocketConstructor();
|
||||||
|
|
||||||
@@ -246,7 +278,7 @@ Server.prototype.connect = function() {
|
|||||||
if (ws === self._ws) {
|
if (ws === self._ws) {
|
||||||
self.emit('socket_open');
|
self.emit('socket_open');
|
||||||
// Subscribe to events
|
// Subscribe to events
|
||||||
self.request(self._remote._serverPrepareSubscribe());
|
self._request(self._remote._serverPrepareSubscribe());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -254,7 +286,10 @@ Server.prototype.connect = function() {
|
|||||||
// If we are no longer the active socket, simply ignore any event
|
// If we are no longer the active socket, simply ignore any event
|
||||||
if (ws === self._ws) {
|
if (ws === self._ws) {
|
||||||
self.emit('socket_error');
|
self.emit('socket_error');
|
||||||
self._remote.trace && log.info('onerror:', self._opts.url, e.data || e);
|
|
||||||
|
if (self._remote.trace) {
|
||||||
|
log.info('onerror:', self._opts.url, e.data || e);
|
||||||
|
}
|
||||||
|
|
||||||
// Most connection errors for WebSockets are conveyed as 'close' events with
|
// Most connection errors for WebSockets are conveyed as 'close' events with
|
||||||
// code 1006. This is done for security purposes and therefore unlikely to
|
// code 1006. This is done for security purposes and therefore unlikely to
|
||||||
@@ -278,7 +313,9 @@ Server.prototype.connect = function() {
|
|||||||
ws.onclose = function onClose() {
|
ws.onclose = function onClose() {
|
||||||
// If we are no longer the active socket, simply ignore any event
|
// If we are no longer the active socket, simply ignore any event
|
||||||
if (ws === self._ws) {
|
if (ws === self._ws) {
|
||||||
self._remote.trace && log.info('onclose:', self._opts.url, ws.readyState);
|
if (self._remote.trace) {
|
||||||
|
log.info('onclose:', self._opts.url, ws.readyState);
|
||||||
|
}
|
||||||
self._handleClose();
|
self._handleClose();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -305,7 +342,9 @@ Server.prototype._retryConnect = function() {
|
|||||||
|
|
||||||
function connectionRetry() {
|
function connectionRetry() {
|
||||||
if (self._shouldConnect) {
|
if (self._shouldConnect) {
|
||||||
self._remote.trace && log.info('retry', self._opts.url);
|
if (self._remote.trace) {
|
||||||
|
log.info('retry', self._opts.url);
|
||||||
|
}
|
||||||
self.connect();
|
self.connect();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -344,9 +383,14 @@ Server.prototype._handleClose = function() {
|
|||||||
Server.prototype._handleMessage = function(message) {
|
Server.prototype._handleMessage = function(message) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
try { message = JSON.parse(message); } catch(e) { }
|
try {
|
||||||
|
message = JSON.parse(message);
|
||||||
|
} catch(e) {
|
||||||
|
}
|
||||||
|
|
||||||
if (!Server.isValidMessage(message)) return;
|
if (!Server.isValidMessage(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'ledgerClosed':
|
case 'ledgerClosed':
|
||||||
@@ -364,10 +408,8 @@ Server.prototype._handleMessage = function(message) {
|
|||||||
self.emit('load', message, self);
|
self.emit('load', message, self);
|
||||||
self._remote.emit('load', message, self);
|
self._remote.emit('load', message, self);
|
||||||
|
|
||||||
var loadChanged = ((message.load_base !== self._load_base) ||
|
if (message.load_base !== self._load_base || message.load_factor !== self._load_factor) {
|
||||||
(message.load_factor !== self._load_factor));
|
// Load changed
|
||||||
|
|
||||||
if (loadChanged) {
|
|
||||||
self._load_base = message.load_base;
|
self._load_base = message.load_base;
|
||||||
self._load_factor = message.load_factor;
|
self._load_factor = message.load_factor;
|
||||||
self.emit('load_changed', message, self);
|
self.emit('load_changed', message, self);
|
||||||
@@ -382,9 +424,16 @@ Server.prototype._handleMessage = function(message) {
|
|||||||
delete self._requests[message.id];
|
delete self._requests[message.id];
|
||||||
|
|
||||||
if (!request) {
|
if (!request) {
|
||||||
this._remote.trace && log.info('UNEXPECTED:', self._opts.url, message);
|
if (this._remote.trace) {
|
||||||
} else if (message.status === 'success') {
|
log.info('UNEXPECTED:', self._opts.url, message);
|
||||||
this._remote.trace && log.info('response:', self._opts.url, message);
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.status === 'success') {
|
||||||
|
if (this._remote.trace) {
|
||||||
|
log.info('response:', self._opts.url, message);
|
||||||
|
}
|
||||||
|
|
||||||
request.emit('success', message.result);
|
request.emit('success', message.result);
|
||||||
|
|
||||||
@@ -392,20 +441,23 @@ Server.prototype._handleMessage = function(message) {
|
|||||||
emitter.emit('response_' + request.message.command, message.result, request, message);
|
emitter.emit('response_' + request.message.command, message.result, request, message);
|
||||||
});
|
});
|
||||||
} else if (message.error) {
|
} else if (message.error) {
|
||||||
this._remote.trace && log.info('error:', self._opts.url, message);
|
if (this._remote.trace) {
|
||||||
|
log.info('error:', self._opts.url, message);
|
||||||
|
}
|
||||||
|
|
||||||
request.emit('error', {
|
request.emit('error', {
|
||||||
error : 'remoteError',
|
error: 'remoteError',
|
||||||
error_message : 'Remote reported an error.',
|
error_message: 'Remote reported an error.',
|
||||||
remote : message
|
remote: message
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'path_find':
|
case 'path_find':
|
||||||
this._remote.trace && log.info('path_find:', self._opts.url, message);
|
if (this._remote.trace) {
|
||||||
|
log.info('path_find:', self._opts.url, message);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -460,9 +512,11 @@ Server.prototype._handleResponseSubscribe = function(message) {
|
|||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Server.prototype.sendMessage = function(message) {
|
Server.prototype._sendMessage = function(message) {
|
||||||
if (this._ws) {
|
if (this._ws) {
|
||||||
this._remote.trace && log.info('request:', this._opts.url, message);
|
if (this._remote.trace) {
|
||||||
|
log.info('request:', this._opts.url, message);
|
||||||
|
}
|
||||||
this._ws.send(JSON.stringify(message));
|
this._ws.send(JSON.stringify(message));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -477,12 +531,14 @@ Server.prototype.sendMessage = function(message) {
|
|||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Server.prototype.request = function(request) {
|
Server.prototype._request = function(request) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
// Only bother if we are still connected.
|
// Only bother if we are still connected.
|
||||||
if (!this._ws) {
|
if (!this._ws) {
|
||||||
this._remote.trace && log.info('request: DROPPING:', self._opts.url, request.message);
|
if (this._remote.trace) {
|
||||||
|
log.info('request: DROPPING:', self._opts.url, request.message);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,14 +550,15 @@ Server.prototype.request = function(request) {
|
|||||||
// Advance message ID
|
// Advance message ID
|
||||||
this._id++;
|
this._id++;
|
||||||
|
|
||||||
|
function sendRequest() {
|
||||||
|
self._sendMessage(request.message);
|
||||||
|
};
|
||||||
|
|
||||||
if (this._isConnected(request)) {
|
if (this._isConnected(request)) {
|
||||||
this.sendMessage(request.message);
|
sendRequest();
|
||||||
} else {
|
} else {
|
||||||
// XXX There are many ways to make this smarter.
|
// XXX There are many ways to make this smarter.
|
||||||
function serverReconnected() {
|
this.once('connect', sendRequest);
|
||||||
self.sendMessage(request.message);
|
|
||||||
}
|
|
||||||
this.once('connect', serverReconnected);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -521,7 +578,7 @@ Server.prototype._isConnected = function(request) {
|
|||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Server.prototype.computeFee = function(transaction) {
|
Server.prototype._computeFee = function(transaction) {
|
||||||
var units;
|
var units;
|
||||||
|
|
||||||
if (transaction instanceof Transaction) {
|
if (transaction instanceof Transaction) {
|
||||||
@@ -532,7 +589,7 @@ Server.prototype.computeFee = function(transaction) {
|
|||||||
throw new Error('Invalid argument');
|
throw new Error('Invalid argument');
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.feeTx(units).to_json();
|
return this._feeTx(units).to_json();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -544,8 +601,8 @@ Server.prototype.computeFee = function(transaction) {
|
|||||||
* @return {Amount} Final fee in XRP for specified number of fee units.
|
* @return {Amount} Final fee in XRP for specified number of fee units.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Server.prototype.feeTx = function(units) {
|
Server.prototype._feeTx = function(units) {
|
||||||
var fee_unit = this.feeTxUnit();
|
var fee_unit = this._feeTxUnit();
|
||||||
return Amount.from_json(String(Math.ceil(units * fee_unit)));
|
return Amount.from_json(String(Math.ceil(units * fee_unit)));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -558,7 +615,7 @@ Server.prototype.feeTx = function(units) {
|
|||||||
* @return {Number} Recommended amount for one fee unit as float.
|
* @return {Number} Recommended amount for one fee unit as float.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Server.prototype.feeTxUnit = function() {
|
Server.prototype._feeTxUnit = function() {
|
||||||
var fee_unit = this._fee_base / this._fee_ref;
|
var fee_unit = this._fee_base / this._fee_ref;
|
||||||
|
|
||||||
// Apply load fees
|
// Apply load fees
|
||||||
@@ -576,10 +633,10 @@ Server.prototype.feeTxUnit = function() {
|
|||||||
* Returns the base reserve with load fees and safety margin applied.
|
* Returns the base reserve with load fees and safety margin applied.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Server.prototype.reserve = function(owner_count) {
|
Server.prototype._reserve = function(ownerCount) {
|
||||||
var reserve_base = Amount.from_json(String(this._reserve_base));
|
var reserve_base = Amount.from_json(String(this._reserve_base));
|
||||||
var reserve_inc = Amount.from_json(String(this._reserve_inc));
|
var reserve_inc = Amount.from_json(String(this._reserve_inc));
|
||||||
var owner_count = owner_count || 0;
|
var owner_count = ownerCount || 0;
|
||||||
|
|
||||||
if (owner_count < 0) {
|
if (owner_count < 0) {
|
||||||
throw new Error('Owner count must not be negative.');
|
throw new Error('Owner count must not be negative.');
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ function SHAMap() {
|
|||||||
this.root = new SHAMapTreeNodeInner();
|
this.root = new SHAMapTreeNodeInner();
|
||||||
};
|
};
|
||||||
|
|
||||||
SHAMap.prototype.add_item = function (tag, node, type) {
|
SHAMap.prototype.add_item = function(tag, node, type) {
|
||||||
var node = new SHAMapTreeNodeLeaf(tag, node, type);
|
var node = new SHAMapTreeNodeLeaf(tag, node, type);
|
||||||
this.root.add_item(tag, node);
|
this.root.add_item(tag, node);
|
||||||
};
|
};
|
||||||
|
|
||||||
SHAMap.prototype.hash = function () {
|
SHAMap.prototype.hash = function() {
|
||||||
return this.root.hash();
|
return this.root.hash();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -24,21 +24,19 @@ SHAMap.prototype.hash = function () {
|
|||||||
*
|
*
|
||||||
* Can be either SHAMapTreeNodeInner or SHAMapTreeNodeLeaf.
|
* Can be either SHAMapTreeNodeInner or SHAMapTreeNodeLeaf.
|
||||||
*/
|
*/
|
||||||
function SHAMapTreeNode() {
|
function SHAMapTreeNode() { };
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
SHAMapTreeNode.TYPE_INNER = 1;
|
SHAMapTreeNode.TYPE_INNER = 1;
|
||||||
SHAMapTreeNode.TYPE_TRANSACTION_NM = 2;
|
SHAMapTreeNode.TYPE_TRANSACTION_NM = 2;
|
||||||
SHAMapTreeNode.TYPE_TRANSACTION_MD = 3;
|
SHAMapTreeNode.TYPE_TRANSACTION_MD = 3;
|
||||||
SHAMapTreeNode.TYPE_ACCOUNT_STATE = 4;
|
SHAMapTreeNode.TYPE_ACCOUNT_STATE = 4;
|
||||||
|
|
||||||
SHAMapTreeNode.prototype.add_item = function (tag_segment, node) {
|
SHAMapTreeNode.prototype.add_item = function(tag_segment, node) {
|
||||||
throw new Error("Called unimplemented virtual method SHAMapTreeNode#add_item.");
|
throw new Error('Called unimplemented virtual method SHAMapTreeNode#add_item.');
|
||||||
};
|
};
|
||||||
|
|
||||||
SHAMapTreeNode.prototype.hash = function () {
|
SHAMapTreeNode.prototype.hash = function() {
|
||||||
throw new Error("Called unimplemented virtual method SHAMapTreeNode#hash.");
|
throw new Error('Called unimplemented virtual method SHAMapTreeNode#hash.');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +54,7 @@ function SHAMapTreeNodeInner() {
|
|||||||
|
|
||||||
util.inherits(SHAMapTreeNodeInner, SHAMapTreeNode);
|
util.inherits(SHAMapTreeNodeInner, SHAMapTreeNode);
|
||||||
|
|
||||||
SHAMapTreeNodeInner.prototype.add_item = function (tag_segment, node) {
|
SHAMapTreeNodeInner.prototype.add_item = function(tag_segment, node) {
|
||||||
var current_node = this.get_node(tag_segment[0]);
|
var current_node = this.get_node(tag_segment[0]);
|
||||||
|
|
||||||
if (current_node) {
|
if (current_node) {
|
||||||
@@ -67,7 +65,7 @@ SHAMapTreeNodeInner.prototype.add_item = function (tag_segment, node) {
|
|||||||
current_node.add_item(tag_segment.slice(1), node);
|
current_node.add_item(tag_segment.slice(1), node);
|
||||||
} else if (current_node.get_segment() === tag_segment) {
|
} else if (current_node.get_segment() === tag_segment) {
|
||||||
// Collision
|
// Collision
|
||||||
throw new Error("Tried to add a node to a SHAMap that was already in there.");
|
throw new Error('Tried to add a node to a SHAMap that was already in there.');
|
||||||
} else {
|
} else {
|
||||||
// Turn it into an inner node
|
// Turn it into an inner node
|
||||||
var new_inner_node = new SHAMapTreeNodeInner();
|
var new_inner_node = new SHAMapTreeNodeInner();
|
||||||
@@ -92,28 +90,31 @@ SHAMapTreeNodeInner.prototype.add_item = function (tag_segment, node) {
|
|||||||
/**
|
/**
|
||||||
* Overwrite the node that is currently in a given slot.
|
* Overwrite the node that is currently in a given slot.
|
||||||
*/
|
*/
|
||||||
SHAMapTreeNodeInner.prototype.set_node = function (slot, node) {
|
SHAMapTreeNodeInner.prototype.set_node = function(slot, node) {
|
||||||
this.leaves[slot] = node;
|
this.leaves[slot] = node;
|
||||||
this.empty = false;
|
this.empty = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
SHAMapTreeNodeInner.prototype.get_node = function (slot) {
|
SHAMapTreeNodeInner.prototype.get_node = function(slot) {
|
||||||
return this.leaves[slot];
|
return this.leaves[slot];
|
||||||
};
|
};
|
||||||
|
|
||||||
SHAMapTreeNodeInner.prototype.hash = function () {
|
SHAMapTreeNodeInner.prototype.hash = function() {
|
||||||
if (this.empty) {
|
if (this.empty) {
|
||||||
return UInt256.from_hex(UInt256.HEX_ZERO);
|
return UInt256.from_hex(UInt256.HEX_ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
var hash_buffer = new SerializedObject();
|
var hash_buffer = new SerializedObject();
|
||||||
var buffer = [];
|
var buffer = [ ];
|
||||||
for (var i = 0; i < 16; i++) {
|
|
||||||
|
for (var i=0; i<16; i++) {
|
||||||
var leafHash = UInt256.from_hex(UInt256.HEX_ZERO);
|
var leafHash = UInt256.from_hex(UInt256.HEX_ZERO);
|
||||||
var slot = i.toString(16).toUpperCase();
|
var slot = i.toString(16).toUpperCase();
|
||||||
if ("object" === typeof this.leaves[slot]) {
|
|
||||||
|
if (typeof this.leaves[slot] === 'object') {
|
||||||
leafHash = this.leaves[slot].hash();
|
leafHash = this.leaves[slot].hash();
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_buffer.append(leafHash.to_bytes());
|
hash_buffer.append(leafHash.to_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,32 +129,30 @@ SHAMapTreeNodeInner.prototype.hash = function () {
|
|||||||
function SHAMapTreeNodeLeaf(tag, node, type) {
|
function SHAMapTreeNodeLeaf(tag, node, type) {
|
||||||
SHAMapTreeNode.call(this);
|
SHAMapTreeNode.call(this);
|
||||||
|
|
||||||
if ("string" === typeof tag) {
|
if (typeof tag === 'string') {
|
||||||
tag = UInt256.from_hex(tag);
|
tag = UInt256.from_hex(tag);
|
||||||
} else if (tag instanceof UInt256) {
|
} else if (!(tag instanceof UInt256)){
|
||||||
// Type is already the right one
|
throw new Error('Tag is unexpected type.');
|
||||||
} else {
|
|
||||||
throw new Error("Tag is unexpected type.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.tag_segment = null;
|
this.tag_segment = null;
|
||||||
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
this.node = node;
|
this.node = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
util.inherits(SHAMapTreeNodeLeaf, SHAMapTreeNode);
|
util.inherits(SHAMapTreeNodeLeaf, SHAMapTreeNode);
|
||||||
|
|
||||||
SHAMapTreeNodeLeaf.prototype.get_segment = function (segment) {
|
SHAMapTreeNodeLeaf.prototype.get_segment = function(segment) {
|
||||||
return this.tag_segment;
|
return this.tag_segment;
|
||||||
};
|
};
|
||||||
|
|
||||||
SHAMapTreeNodeLeaf.prototype.set_segment = function (segment) {
|
SHAMapTreeNodeLeaf.prototype.set_segment = function(segment) {
|
||||||
this.tag_segment = segment;
|
this.tag_segment = segment;
|
||||||
};
|
};
|
||||||
|
|
||||||
SHAMapTreeNodeLeaf.prototype.hash = function () {
|
SHAMapTreeNodeLeaf.prototype.hash = function() {
|
||||||
var buffer = new SerializedObject();
|
var buffer = new SerializedObject();
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case SHAMapTreeNode.TYPE_TRANSACTION_NM:
|
case SHAMapTreeNode.TYPE_TRANSACTION_NM:
|
||||||
@@ -163,7 +162,7 @@ SHAMapTreeNodeLeaf.prototype.hash = function () {
|
|||||||
buffer.append(this.tag.to_bytes());
|
buffer.append(this.tag.to_bytes());
|
||||||
return buffer.hash(hashprefixes.HASH_TX_NODE);
|
return buffer.hash(hashprefixes.HASH_TX_NODE);
|
||||||
default:
|
default:
|
||||||
throw new Error("Tried to hash a SHAMap node of unknown type.");
|
throw new Error('Tried to hash a SHAMap node of unknown type.');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -71,11 +71,12 @@ function Transaction(remote) {
|
|||||||
this.state = 'unsubmitted';
|
this.state = 'unsubmitted';
|
||||||
this.finalized = false;
|
this.finalized = false;
|
||||||
this.previousSigningHash = void(0);
|
this.previousSigningHash = void(0);
|
||||||
|
|
||||||
// Index at which transaction was submitted
|
// Index at which transaction was submitted
|
||||||
this.submitIndex = void(0);
|
this.submitIndex = void(0);
|
||||||
|
|
||||||
// Canonical signing setting defaults to the Remote's configuration
|
// Canonical signing setting defaults to the Remote's configuration
|
||||||
this.canonical = "object" === typeof remote ? !!remote.canonical_signing : true;
|
this.canonical = (typeof remote === 'object') ? !!remote.canonical_signing : true;
|
||||||
|
|
||||||
// We aren't clever enough to eschew preventative measures so we keep an array
|
// We aren't clever enough to eschew preventative measures so we keep an array
|
||||||
// of all submitted transactionIDs (which can change due to load_factor
|
// of all submitted transactionIDs (which can change due to load_factor
|
||||||
@@ -261,11 +262,16 @@ Transaction.prototype._getServer = function() {
|
|||||||
|
|
||||||
for (var i=0; i<servers.length; i++) {
|
for (var i=0; i<servers.length; i++) {
|
||||||
var server = servers[i];
|
var server = servers[i];
|
||||||
if (!server._connected) continue;
|
|
||||||
var n = server.computeFee(this);
|
if (!server._connected) {
|
||||||
if (n < fee) {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var serverFee = server._computeFee(this);
|
||||||
|
|
||||||
|
if (serverFee < fee) {
|
||||||
result = server;
|
result = server;
|
||||||
fee = n;
|
fee = serverFee;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,12 +316,12 @@ Transaction.prototype.complete = function() {
|
|||||||
if (this.remote && typeof this.tx_json.Fee === 'undefined') {
|
if (this.remote && typeof this.tx_json.Fee === 'undefined') {
|
||||||
if (this.remote.local_fee || !this.remote.trusted) {
|
if (this.remote.local_fee || !this.remote.trusted) {
|
||||||
this._server = this._getServer();
|
this._server = this._getServer();
|
||||||
this.tx_json.Fee = this._server.computeFee(this);
|
this.tx_json.Fee = this._server._computeFee(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Number(this.tx_json.Fee) > this._maxFee) {
|
if (Number(this.tx_json.Fee) > this._maxFee) {
|
||||||
tx.emit('error', new RippleError('tejMaxFeeExceeded', 'Max fee exceeded'));
|
this.emit('error', new RippleError('tejMaxFeeExceeded', 'Max fee exceeded'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +352,7 @@ Transaction.prototype.hash = function(prefix, as_uint256) {
|
|||||||
}
|
}
|
||||||
prefix = hashprefixes[prefix];
|
prefix = hashprefixes[prefix];
|
||||||
} else if (!prefix) {
|
} else if (!prefix) {
|
||||||
prefix = hashprefixes['HASH_TX_ID'];
|
prefix = hashprefixes.HASH_TX_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hash = SerializedObject.from_json(this.tx_json).hash(prefix);
|
var hash = SerializedObject.from_json(this.tx_json).hash(prefix);
|
||||||
@@ -403,7 +409,9 @@ Transaction.prototype.findId = function(cache) {
|
|||||||
|
|
||||||
for (var i=0; i<this.submittedIDs.length; i++) {
|
for (var i=0; i<this.submittedIDs.length; i++) {
|
||||||
var hash = this.submittedIDs[i];
|
var hash = this.submittedIDs[i];
|
||||||
if (result = cache[hash]) break;
|
if ((result = cache[hash])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -432,7 +440,9 @@ Transaction.prototype.destinationTag = function(tag) {
|
|||||||
|
|
||||||
Transaction.prototype.invoiceID = function(id) {
|
Transaction.prototype.invoiceID = function(id) {
|
||||||
if (typeof id === 'string') {
|
if (typeof id === 'string') {
|
||||||
while (id.length < 64) id += '0';
|
while (id.length < 64) {
|
||||||
|
id += '0';
|
||||||
|
}
|
||||||
this.tx_json.InvoiceID = id;
|
this.tx_json.InvoiceID = id;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
@@ -473,7 +483,7 @@ Transaction._pathRewrite = function(path) {
|
|||||||
newNode.type_hex = node.type_hex;
|
newNode.type_hex = node.type_hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
return newNode
|
return newNode;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -533,7 +543,14 @@ Transaction.prototype.transferRate = function(rate) {
|
|||||||
// Add flags to a transaction.
|
// Add flags to a transaction.
|
||||||
// --> flags: undefined, _flag_, or [ _flags_ ]
|
// --> flags: undefined, _flag_, or [ _flags_ ]
|
||||||
Transaction.prototype.setFlags = function(flags) {
|
Transaction.prototype.setFlags = function(flags) {
|
||||||
if (!flags) return this;
|
if (flags === void(0)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof flags === 'number') {
|
||||||
|
this.tx_json.Flags = flags;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
var flag_set = Array.isArray(flags) ? flags : Array.prototype.slice.call(arguments);
|
var flag_set = Array.isArray(flags) ? flags : Array.prototype.slice.call(arguments);
|
||||||
var transaction_flags = Transaction.flags[this.tx_json.TransactionType] || { };
|
var transaction_flags = Transaction.flags[this.tx_json.TransactionType] || { };
|
||||||
@@ -919,7 +936,7 @@ Transaction.summary = function() {
|
|||||||
state: this.state,
|
state: this.state,
|
||||||
server: this._server ? this._server._opts.url : void(0),
|
server: this._server ? this._server._opts.url : void(0),
|
||||||
finalized: this.finalized
|
finalized: this.finalized
|
||||||
}
|
};
|
||||||
|
|
||||||
if (this.result) {
|
if (this.result) {
|
||||||
result.result = {
|
result.result = {
|
||||||
@@ -928,7 +945,7 @@ Transaction.summary = function() {
|
|||||||
ledger_hash : this.result.ledger_hash,
|
ledger_hash : this.result.ledger_hash,
|
||||||
ledger_index : this.result.ledger_index,
|
ledger_index : this.result.ledger_index,
|
||||||
transaction_hash : this.result.tx_json.hash
|
transaction_hash : this.result.tx_json.hash
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ var EventEmitter = require('events').EventEmitter;
|
|||||||
var Transaction = require('./transaction').Transaction;
|
var Transaction = require('./transaction').Transaction;
|
||||||
var RippleError = require('./rippleerror').RippleError;
|
var RippleError = require('./rippleerror').RippleError;
|
||||||
var PendingQueue = require('./transactionqueue').TransactionQueue;
|
var PendingQueue = require('./transactionqueue').TransactionQueue;
|
||||||
|
var log = require('./log').internal.sub('transactionmanager');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor TransactionManager
|
* @constructor TransactionManager
|
||||||
@@ -20,24 +21,28 @@ function TransactionManager(account) {
|
|||||||
this._nextSequence = void(0);
|
this._nextSequence = void(0);
|
||||||
this._maxFee = this._remote.max_fee;
|
this._maxFee = this._remote.max_fee;
|
||||||
this._submissionTimeout = this._remote._submission_timeout;
|
this._submissionTimeout = this._remote._submission_timeout;
|
||||||
this._pending = new PendingQueue;
|
this._pending = new PendingQueue();
|
||||||
|
|
||||||
// Query remote server for next account sequence number
|
// Query remote server for next account sequence number
|
||||||
this._loadSequence();
|
this._loadSequence();
|
||||||
|
|
||||||
function transactionReceived(res) {
|
function transactionReceived(res) {
|
||||||
var transaction = TransactionManager.normalizeTransaction(res);
|
var transaction = TransactionManager.normalizeTransaction(res);
|
||||||
var sequence = transaction.transaction.Sequence;
|
var sequence = transaction.tx_json.Sequence;
|
||||||
var hash = transaction.transaction.hash;
|
var hash = transaction.tx_json.hash;
|
||||||
|
|
||||||
if (!transaction.validated) return;
|
if (!transaction.validated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self._pending.addReceivedSequence(sequence);
|
self._pending.addReceivedSequence(sequence);
|
||||||
|
|
||||||
// ND: we need to check against all submissions IDs
|
// ND: we need to check against all submissions IDs
|
||||||
var submission = self._pending.getSubmission(hash);
|
var submission = self._pending.getSubmission(hash);
|
||||||
|
|
||||||
self._remote._trace('transactionmanager: transaction_received:', transaction.transaction);
|
if (self._remote.trace) {
|
||||||
|
log.info('transaction received:', transaction.transaction);
|
||||||
|
}
|
||||||
|
|
||||||
if (submission) {
|
if (submission) {
|
||||||
// ND: A `success` handler will `finalize` this later
|
// ND: A `success` handler will `finalize` this later
|
||||||
@@ -52,10 +57,13 @@ function TransactionManager(account) {
|
|||||||
function adjustFees(loadData, server) {
|
function adjustFees(loadData, server) {
|
||||||
// ND: note, that `Fee` is a component of a transactionID
|
// ND: note, that `Fee` is a component of a transactionID
|
||||||
self._pending.forEach(function(pending) {
|
self._pending.forEach(function(pending) {
|
||||||
var shouldAdjust = pending._server === server
|
if (pending._server !== server) {
|
||||||
&& self._remote.local_fee && pending.tx_json.Fee;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!shouldAdjust) return;
|
if (!(self._remote.local_fee && pending.tx_json.Fee)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var oldFee = pending.tx_json.Fee;
|
var oldFee = pending.tx_json.Fee;
|
||||||
var newFee = server.computeFee(pending);
|
var newFee = server.computeFee(pending);
|
||||||
@@ -69,7 +77,9 @@ function TransactionManager(account) {
|
|||||||
pending.tx_json.Fee = newFee;
|
pending.tx_json.Fee = newFee;
|
||||||
pending.emit('fee_adjusted', oldFee, newFee);
|
pending.emit('fee_adjusted', oldFee, newFee);
|
||||||
|
|
||||||
self._remote._trace('transactionmanager: adjusting_fees:', pending.tx_json, oldFee, newFee);
|
if (self._remote.trace) {
|
||||||
|
log.info('fee adjusted:', pending.tx_json, oldFee, newFee);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,7 +90,6 @@ function TransactionManager(account) {
|
|||||||
switch (ledger.ledger_index - pending.submitIndex) {
|
switch (ledger.ledger_index - pending.submitIndex) {
|
||||||
case 8:
|
case 8:
|
||||||
pending.emit('lost', ledger);
|
pending.emit('lost', ledger);
|
||||||
self._remote._trace('transactionmanager: update_pending:', pending.tx_json);
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
pending.emit('missing', ledger);
|
pending.emit('missing', ledger);
|
||||||
@@ -106,7 +115,7 @@ function TransactionManager(account) {
|
|||||||
binary: true,
|
binary: true,
|
||||||
limit: 100,
|
limit: 100,
|
||||||
filter: 'outbound'
|
filter: 'outbound'
|
||||||
}
|
};
|
||||||
|
|
||||||
function accountTx(err, transactions) {
|
function accountTx(err, transactions) {
|
||||||
if (!err && Array.isArray(transactions.transactions)) {
|
if (!err && Array.isArray(transactions.transactions)) {
|
||||||
@@ -116,9 +125,7 @@ function TransactionManager(account) {
|
|||||||
self._remote.on('ledger_closed', updatePendingStatus);
|
self._remote.on('ledger_closed', updatePendingStatus);
|
||||||
|
|
||||||
//Load next transaction sequence
|
//Load next transaction sequence
|
||||||
self._loadSequence(function sequenceLoaded() {
|
self._loadSequence(self._resubmit.bind(self));
|
||||||
self._resubmit();
|
|
||||||
});
|
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
@@ -149,29 +156,40 @@ util.inherits(TransactionManager, EventEmitter);
|
|||||||
//Normalize transactions received from account
|
//Normalize transactions received from account
|
||||||
//transaction stream and account_tx
|
//transaction stream and account_tx
|
||||||
TransactionManager.normalizeTransaction = function(tx) {
|
TransactionManager.normalizeTransaction = function(tx) {
|
||||||
var transaction = tx;
|
var transaction = { };
|
||||||
|
|
||||||
|
Object.keys(tx).forEach(function(key) {
|
||||||
|
transaction[key] = tx[key];
|
||||||
|
});
|
||||||
|
|
||||||
if (!tx.engine_result) {
|
if (!tx.engine_result) {
|
||||||
// account_tx
|
// account_tx
|
||||||
transaction = {
|
transaction = {
|
||||||
engine_result: tx.meta.TransactionResult,
|
engine_result: tx.meta.TransactionResult,
|
||||||
transaction: tx.tx,
|
tx_json: tx.tx,
|
||||||
hash: tx.tx.hash,
|
hash: tx.tx.hash,
|
||||||
ledger_index: tx.tx.ledger_index,
|
ledger_index: tx.tx.ledger_index,
|
||||||
meta: tx.meta,
|
meta: tx.meta,
|
||||||
type: 'transaction',
|
type: 'transaction',
|
||||||
validated: true
|
validated: true
|
||||||
}
|
};
|
||||||
|
|
||||||
transaction.result = transaction.engine_result;
|
transaction.result = transaction.engine_result;
|
||||||
transaction.result_message = transaction.engine_result_message;
|
transaction.result_message = transaction.engine_result_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!transaction.metadata) {
|
||||||
transaction.metadata = transaction.meta;
|
transaction.metadata = transaction.meta;
|
||||||
|
}
|
||||||
|
|
||||||
if (!transaction.tx_json) {
|
if (!transaction.tx_json) {
|
||||||
transaction.tx_json = transaction.transaction;
|
transaction.tx_json = transaction.transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete transaction.transaction;
|
||||||
|
delete transaction.mmeta;
|
||||||
|
delete transaction.meta;
|
||||||
|
|
||||||
return transaction;
|
return transaction;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -202,7 +220,9 @@ TransactionManager.prototype._fillSequence = function(tx, callback) {
|
|||||||
var submitted = 0;
|
var submitted = 0;
|
||||||
|
|
||||||
;(function nextFill(sequence) {
|
;(function nextFill(sequence) {
|
||||||
if (sequence >= tx.tx_json.Sequence) return;
|
if (sequence >= tx.tx_json.Sequence) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
submitFill(sequence, function() {
|
submitFill(sequence, function() {
|
||||||
if (++submitted === sequenceDif) {
|
if (++submitted === sequenceDif) {
|
||||||
@@ -250,7 +270,9 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
|
|||||||
|
|
||||||
var hashCached = pending.findId(self._pending._idCache);
|
var hashCached = pending.findId(self._pending._idCache);
|
||||||
|
|
||||||
self._remote._trace('transactionmanager: resubmit:', pending.tx_json);
|
if (self._remote.trace) {
|
||||||
|
log.info('resubmit:', pending.tx_json);
|
||||||
|
}
|
||||||
|
|
||||||
if (hashCached) {
|
if (hashCached) {
|
||||||
return pending.emit('success', hashCached);
|
return pending.emit('success', hashCached);
|
||||||
@@ -259,7 +281,9 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
|
|||||||
while (self._pending.hasSequence(pending.tx_json.Sequence)) {
|
while (self._pending.hasSequence(pending.tx_json.Sequence)) {
|
||||||
//Sequence number has been consumed by another transaction
|
//Sequence number has been consumed by another transaction
|
||||||
pending.tx_json.Sequence += 1;
|
pending.tx_json.Sequence += 1;
|
||||||
self._remote._trace('transactionmanager: incrementing sequence:', pending.tx_json);
|
if (self._remote.trace) {
|
||||||
|
log.info('incrementing sequence:', pending.tx_json);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self._request(pending);
|
self._request(pending);
|
||||||
@@ -269,14 +293,18 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
|
|||||||
;(function nextTransaction(i) {
|
;(function nextTransaction(i) {
|
||||||
var transaction = pending[i];
|
var transaction = pending[i];
|
||||||
|
|
||||||
if (!(transaction instanceof Transaction)) return;
|
if (!(transaction instanceof Transaction)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
transaction.once('submitted', function(m) {
|
transaction.once('submitted', function(m) {
|
||||||
transaction.emit('resubmitted', m);
|
transaction.emit('resubmitted', m);
|
||||||
|
|
||||||
self._loadSequence();
|
self._loadSequence();
|
||||||
|
|
||||||
if (++i < pending.length) nextTransaction(i);
|
if (++i < pending.length) {
|
||||||
|
nextTransaction(i);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
resubmitTransaction(transaction);
|
resubmitTransaction(transaction);
|
||||||
@@ -287,16 +315,20 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TransactionManager.prototype._waitLedgers = function(ledgers, callback) {
|
TransactionManager.prototype._waitLedgers = function(ledgers, callback) {
|
||||||
if (ledgers < 1) return callback();
|
if (ledgers < 1) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var closes = 0;
|
var closes = 0;
|
||||||
|
|
||||||
function ledgerClosed() {
|
function ledgerClosed() {
|
||||||
if (++closes === ledgers) {
|
if (++closes < ledgers) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self._remote.removeListener('ledger_closed', ledgerClosed);
|
self._remote.removeListener('ledger_closed', ledgerClosed);
|
||||||
callback();
|
callback();
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this._remote.on('ledger_closed', ledgerClosed);
|
this._remote.on('ledger_closed', ledgerClosed);
|
||||||
@@ -326,19 +358,30 @@ TransactionManager.prototype._request = function(tx) {
|
|||||||
|
|
||||||
tx.emit('presubmit');
|
tx.emit('presubmit');
|
||||||
|
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
remote._trace('transactionmanager: submit:', tx.tx_json);
|
if (remote.trace) {
|
||||||
|
log.info('submit transaction:', tx.tx_json);
|
||||||
|
}
|
||||||
|
|
||||||
function transactionProposed(message) {
|
function transactionProposed(message) {
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If server is honest, don't expect a final if rejected.
|
// If server is honest, don't expect a final if rejected.
|
||||||
message.rejected = tx.isRejected(message.engine_result_code);
|
message.rejected = tx.isRejected(message.engine_result_code);
|
||||||
|
|
||||||
tx.emit('proposed', message);
|
tx.emit('proposed', message);
|
||||||
};
|
};
|
||||||
|
|
||||||
function transactionFailed(message) {
|
function transactionFailed(message) {
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (message.engine_result) {
|
switch (message.engine_result) {
|
||||||
case 'tefPAST_SEQ':
|
case 'tefPAST_SEQ':
|
||||||
self._resubmit(1, tx);
|
self._resubmit(1, tx);
|
||||||
@@ -349,7 +392,9 @@ TransactionManager.prototype._request = function(tx) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function transactionRetry(message) {
|
function transactionRetry(message) {
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self._fillSequence(tx, function() {
|
self._fillSequence(tx, function() {
|
||||||
self._resubmit(1, tx);
|
self._resubmit(1, tx);
|
||||||
@@ -357,17 +402,19 @@ TransactionManager.prototype._request = function(tx) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function transactionFeeClaimed(message) {
|
function transactionFeeClaimed(message) {
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tx.emit('error', message);
|
tx.emit('error', message);
|
||||||
};
|
};
|
||||||
|
|
||||||
function transactionFailedLocal(message) {
|
function transactionFailedLocal(message) {
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var shouldAdjustFee = self._remote.local_fee
|
if (self._remote.local_fee && (message.engine_result === 'telINSUF_FEE_P')) {
|
||||||
&& (message.engine_result === 'telINSUF_FEE_P');
|
|
||||||
|
|
||||||
if (shouldAdjustFee) {
|
|
||||||
self._resubmit(1, tx);
|
self._resubmit(1, tx);
|
||||||
} else {
|
} else {
|
||||||
submissionError(message);
|
submissionError(message);
|
||||||
@@ -376,7 +423,9 @@ TransactionManager.prototype._request = function(tx) {
|
|||||||
|
|
||||||
function submissionError(error) {
|
function submissionError(error) {
|
||||||
// Finalized (e.g. aborted) transactions must stop all activity
|
// Finalized (e.g. aborted) transactions must stop all activity
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (TransactionManager._isTooBusy(error)) {
|
if (TransactionManager._isTooBusy(error)) {
|
||||||
self._resubmit(1, tx);
|
self._resubmit(1, tx);
|
||||||
@@ -388,7 +437,9 @@ TransactionManager.prototype._request = function(tx) {
|
|||||||
|
|
||||||
function submitted(message) {
|
function submitted(message) {
|
||||||
// Finalized (e.g. aborted) transactions must stop all activity
|
// Finalized (e.g. aborted) transactions must stop all activity
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// ND: If for some unknown reason our hash wasn't computed correctly this is
|
// ND: If for some unknown reason our hash wasn't computed correctly this is
|
||||||
// an extra measure.
|
// an extra measure.
|
||||||
@@ -400,7 +451,9 @@ TransactionManager.prototype._request = function(tx) {
|
|||||||
|
|
||||||
tx.result = message;
|
tx.result = message;
|
||||||
|
|
||||||
remote._trace('transactionmanager: submit_response:', message);
|
if (remote.trace) {
|
||||||
|
log.info('submit response:', message);
|
||||||
|
}
|
||||||
|
|
||||||
tx.emit('submitted', message);
|
tx.emit('submitted', message);
|
||||||
|
|
||||||
@@ -480,18 +533,24 @@ TransactionManager.prototype._request = function(tx) {
|
|||||||
// that ALL transactionIDs sent over network are tracked.
|
// that ALL transactionIDs sent over network are tracked.
|
||||||
|
|
||||||
// Finalized (e.g. aborted) transactions must stop all activity
|
// Finalized (e.g. aborted) transactions must stop all activity
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tx.emit('timeout');
|
tx.emit('timeout');
|
||||||
|
|
||||||
if (remote._connected) {
|
if (remote._connected) {
|
||||||
remote._trace('transactionmanager: timeout:', tx.tx_json);
|
if (remote.trace) {
|
||||||
|
log.info('timeout:', tx.tx_json);
|
||||||
|
}
|
||||||
self._resubmit(3, tx);
|
self._resubmit(3, tx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function submitTransaction() {
|
function submitTransaction() {
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
submitRequest.timeout(self._submissionTimeout, requestTimeout);
|
submitRequest.timeout(self._submissionTimeout, requestTimeout);
|
||||||
submitRequest.request();
|
submitRequest.request();
|
||||||
@@ -557,22 +616,23 @@ TransactionManager.prototype.submit = function(tx) {
|
|||||||
var remote = this._remote;
|
var remote = this._remote;
|
||||||
|
|
||||||
// If sequence number is not yet known, defer until it is.
|
// If sequence number is not yet known, defer until it is.
|
||||||
if (typeof this._nextSequence === 'undefined') {
|
if (typeof this._nextSequence !== 'number') {
|
||||||
function sequenceLoaded() {
|
this.once('sequence_loaded', this.submit.bind(this, tx));
|
||||||
self.submit(tx);
|
|
||||||
};
|
|
||||||
this.once('sequence_loaded', sequenceLoaded);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalized (e.g. aborted) transactions must stop all activity
|
// Finalized (e.g. aborted) transactions must stop all activity
|
||||||
if (tx.finalized) return;
|
if (tx.finalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function cleanup(message) {
|
function cleanup(message) {
|
||||||
// ND: We can just remove this `tx` by identity
|
// ND: We can just remove this `tx` by identity
|
||||||
self._pending.remove(tx);
|
self._pending.remove(tx);
|
||||||
tx.emit('final', message);
|
tx.emit('final', message);
|
||||||
remote._trace('transactionmanager: finalize_transaction:', tx.tx_json);
|
if (remote.trace) {
|
||||||
|
log.info('transaction finalized:', tx.tx_json, self._pending.getLength());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tx.once('cleanup', cleanup);
|
tx.once('cleanup', cleanup);
|
||||||
|
|||||||
@@ -3,27 +3,12 @@
|
|||||||
* Manager for pending transactions
|
* Manager for pending transactions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Transaction = require('./transaction').Transaction;
|
|
||||||
var LRU = require('lru-cache');
|
var LRU = require('lru-cache');
|
||||||
|
|
||||||
function TransactionQueue() {
|
function TransactionQueue() {
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this._queue = [ ];
|
this._queue = [ ];
|
||||||
this._idCache = LRU({ max: 100 });
|
this._idCache = LRU();
|
||||||
this._sequenceCache = LRU({ max: 100 });
|
this._sequenceCache = LRU();
|
||||||
this._save = void(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
TransactionQueue.prototype.save = function() {
|
|
||||||
if (typeof this._save !== 'function') return;
|
|
||||||
|
|
||||||
this._save(this._queue.map(function(tx) {
|
|
||||||
return {
|
|
||||||
tx_json: tx.tx_json,
|
|
||||||
submittedIDs: tx.submittedIDs
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,10 +49,10 @@ TransactionQueue.prototype.hasSequence = function(sequence) {
|
|||||||
* may have multiple associated IDs.
|
* may have multiple associated IDs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TransactionQueue.prototype.getSubmission = function(id, callback) {
|
TransactionQueue.prototype.getSubmission = function(id) {
|
||||||
var result = false;
|
var result = false;
|
||||||
|
|
||||||
for (var i=0, tx; tx=this._queue[i]; i++) {
|
for (var i=0, tx; (tx=this._queue[i]); i++) {
|
||||||
if (~tx.submittedIDs.indexOf(id)) {
|
if (~tx.submittedIDs.indexOf(id)) {
|
||||||
result = tx;
|
result = tx;
|
||||||
break;
|
break;
|
||||||
@@ -91,20 +76,18 @@ TransactionQueue.prototype.remove = function(tx) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.save();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TransactionQueue.prototype.push = function(tx) {
|
TransactionQueue.prototype.push = function(tx) {
|
||||||
this._queue.push(tx);
|
this._queue.push(tx);
|
||||||
this.save();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TransactionQueue.prototype.forEach = function(fn) {
|
TransactionQueue.prototype.forEach = function(fn) {
|
||||||
this._queue.forEach(fn);
|
this._queue.forEach(fn);
|
||||||
};
|
};
|
||||||
|
|
||||||
TransactionQueue.prototype.length = function() {
|
TransactionQueue.prototype.length =
|
||||||
|
TransactionQueue.prototype.getLength = function() {
|
||||||
return this._queue.length;
|
return this._queue.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,27 +4,25 @@ var config = require('./config');
|
|||||||
|
|
||||||
var BigInteger = utils.jsbn.BigInteger;
|
var BigInteger = utils.jsbn.BigInteger;
|
||||||
|
|
||||||
var Base = require('./base').Base;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Abstract UInt class
|
// Abstract UInt class
|
||||||
//
|
//
|
||||||
// Base class for UInt??? classes
|
// Base class for UInt classes
|
||||||
//
|
//
|
||||||
|
|
||||||
var UInt = function () {
|
var UInt = function() {
|
||||||
// Internal form: NaN or BigInteger
|
// Internal form: NaN or BigInteger
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
|
|
||||||
this._update();
|
this._update();
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt.json_rewrite = function (j, opts) {
|
UInt.json_rewrite = function(j, opts) {
|
||||||
return this.from_json(j).to_json(opts);
|
return this.from_json(j).to_json(opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return a new UInt from j.
|
// Return a new UInt from j.
|
||||||
UInt.from_generic = function (j) {
|
UInt.from_generic = function(j) {
|
||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
} else {
|
} else {
|
||||||
@@ -33,7 +31,7 @@ UInt.from_generic = function (j) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Return a new UInt from j.
|
// Return a new UInt from j.
|
||||||
UInt.from_hex = function (j) {
|
UInt.from_hex = function(j) {
|
||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
} else {
|
} else {
|
||||||
@@ -42,7 +40,7 @@ UInt.from_hex = function (j) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Return a new UInt from j.
|
// Return a new UInt from j.
|
||||||
UInt.from_json = function (j) {
|
UInt.from_json = function(j) {
|
||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
} else {
|
} else {
|
||||||
@@ -51,7 +49,7 @@ UInt.from_json = function (j) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Return a new UInt from j.
|
// Return a new UInt from j.
|
||||||
UInt.from_bits = function (j) {
|
UInt.from_bits = function(j) {
|
||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
} else {
|
} else {
|
||||||
@@ -60,7 +58,7 @@ UInt.from_bits = function (j) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Return a new UInt from j.
|
// Return a new UInt from j.
|
||||||
UInt.from_bytes = function (j) {
|
UInt.from_bytes = function(j) {
|
||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
} else {
|
} else {
|
||||||
@@ -69,7 +67,7 @@ UInt.from_bytes = function (j) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Return a new UInt from j.
|
// Return a new UInt from j.
|
||||||
UInt.from_bn = function (j) {
|
UInt.from_bn = function(j) {
|
||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
} else {
|
} else {
|
||||||
@@ -78,7 +76,7 @@ UInt.from_bn = function (j) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Return a new UInt from j.
|
// Return a new UInt from j.
|
||||||
UInt.from_number = function (j) {
|
UInt.from_number = function(j) {
|
||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
} else {
|
} else {
|
||||||
@@ -86,32 +84,34 @@ UInt.from_number = function (j) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt.is_valid = function (j) {
|
UInt.is_valid = function(j) {
|
||||||
return this.from_json(j).is_valid();
|
return this.from_json(j).is_valid();
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt.prototype.clone = function () {
|
UInt.prototype.clone = function() {
|
||||||
return this.copyTo(new this.constructor());
|
return this.copyTo(new this.constructor());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns copy.
|
// Returns copy.
|
||||||
UInt.prototype.copyTo = function (d) {
|
UInt.prototype.copyTo = function(d) {
|
||||||
d._value = this._value;
|
d._value = this._value;
|
||||||
|
|
||||||
if ("function" === typeof d._update) d._update();
|
if (typeof d._update === 'function') {
|
||||||
|
d._update();
|
||||||
|
}
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt.prototype.equals = function (d) {
|
UInt.prototype.equals = function(d) {
|
||||||
return this._value instanceof BigInteger && d._value instanceof BigInteger && this._value.equals(d._value);
|
return this._value instanceof BigInteger && 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 BigInteger;
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt.prototype.is_zero = function () {
|
UInt.prototype.is_zero = function() {
|
||||||
return this._value.equals(BigInteger.ZERO);
|
return this._value.equals(BigInteger.ZERO);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -125,45 +125,42 @@ UInt.prototype.is_zero = function () {
|
|||||||
* The reason for keeping this mechanism in this class is so every subclass can
|
* The reason for keeping this mechanism in this class is so every subclass can
|
||||||
* call it whenever it modifies the internal state.
|
* call it whenever it modifies the internal state.
|
||||||
*/
|
*/
|
||||||
UInt.prototype._update = function () {
|
UInt.prototype._update = function() {
|
||||||
// Nothing to do by default. Subclasses will override this.
|
// Nothing to do by default. Subclasses will override this.
|
||||||
};
|
};
|
||||||
|
|
||||||
// value = NaN on error.
|
// value = NaN on error.
|
||||||
UInt.prototype.parse_generic = function (j) {
|
UInt.prototype.parse_generic = function(j) {
|
||||||
// Canonicalize and validate
|
// Canonicalize and validate
|
||||||
if (config.accounts && j in config.accounts)
|
if (config.accounts && (j in config.accounts)) {
|
||||||
j = config.accounts[j].account;
|
j = config.accounts[j].account;
|
||||||
|
}
|
||||||
|
|
||||||
switch (j) {
|
switch (j) {
|
||||||
case undefined:
|
case undefined:
|
||||||
case "0":
|
case '0':
|
||||||
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 = BigInteger.valueOf();
|
||||||
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 BigInteger([1]);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if ('string' !== typeof j) {
|
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);
|
this._value = new BigInteger(utils.stringToArray(j), 256);
|
||||||
}
|
} 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 BigInteger(j, 16);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,9 +170,8 @@ UInt.prototype.parse_generic = function (j) {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt.prototype.parse_hex = function (j) {
|
UInt.prototype.parse_hex = function(j) {
|
||||||
if ('string' === typeof j &&
|
if (typeof j === 'string' && j.length === (this.constructor.width * 2)) {
|
||||||
j.length === (this.constructor.width * 2)) {
|
|
||||||
this._value = new BigInteger(j, 16);
|
this._value = new BigInteger(j, 16);
|
||||||
} else {
|
} else {
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
@@ -186,7 +182,7 @@ UInt.prototype.parse_hex = function (j) {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt.prototype.parse_bits = function (j) {
|
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 {
|
||||||
@@ -200,7 +196,7 @@ UInt.prototype.parse_bits = function (j) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
UInt.prototype.parse_bytes = function (j) {
|
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 {
|
||||||
@@ -215,9 +211,8 @@ UInt.prototype.parse_bytes = function (j) {
|
|||||||
|
|
||||||
UInt.prototype.parse_json = UInt.prototype.parse_hex;
|
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 &&
|
if ((j instanceof sjcl.bn) && j.bitLength() <= this.constructor.width * 8) {
|
||||||
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 BigInteger(bytes, 256);
|
||||||
} else {
|
} else {
|
||||||
@@ -229,14 +224,11 @@ UInt.prototype.parse_bn = function (j) {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt.prototype.parse_number = function (j) {
|
UInt.prototype.parse_number = function(j) {
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
|
|
||||||
if ("number" === typeof j &&
|
if (typeof j === 'number' && isFinite(j) && j >= 0) {
|
||||||
j === +j &&
|
this._value = new BigInteger(String(j));
|
||||||
j >= 0) {
|
|
||||||
// XXX Better, faster way to get BigInteger from JS int?
|
|
||||||
this._value = new BigInteger(""+j);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._update();
|
this._update();
|
||||||
@@ -245,24 +237,33 @@ 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._value instanceof BigInteger)) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var bytes = this._value.toByteArray();
|
var bytes = this._value.toByteArray();
|
||||||
bytes = bytes.map(function (b) { return (b+256) % 256; });
|
|
||||||
|
bytes = bytes.map(function(b) {
|
||||||
|
return (b + 256) % 256;
|
||||||
|
});
|
||||||
|
|
||||||
var target = this.constructor.width;
|
var target = this.constructor.width;
|
||||||
|
|
||||||
// XXX Make sure only trim off leading zeros.
|
// XXX Make sure only trim off leading zeros.
|
||||||
bytes = bytes.slice(-target);
|
bytes = bytes.slice(-target);
|
||||||
while (bytes.length < target) bytes.unshift(0);
|
|
||||||
|
while (bytes.length < target) {
|
||||||
|
bytes.unshift(0);
|
||||||
|
}
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt.prototype.to_hex = function () {
|
UInt.prototype.to_hex = function() {
|
||||||
if (!(this._value instanceof BigInteger))
|
if (!(this._value instanceof BigInteger)) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var bytes = this.to_bytes();
|
var bytes = this.to_bytes();
|
||||||
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(bytes)).toUpperCase();
|
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(bytes)).toUpperCase();
|
||||||
@@ -270,18 +271,20 @@ UInt.prototype.to_hex = function () {
|
|||||||
|
|
||||||
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._value instanceof BigInteger)) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var bytes = this.to_bytes();
|
var bytes = this.to_bytes();
|
||||||
|
|
||||||
return sjcl.codec.bytes.toBits(bytes);
|
return sjcl.codec.bytes.toBits(bytes);
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt.prototype.to_bn = function () {
|
UInt.prototype.to_bn = function() {
|
||||||
if (!(this._value instanceof BigInteger))
|
if (!(this._value instanceof BigInteger)) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var bits = this.to_bits();
|
var bits = this.to_bits();
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
var sjcl = require('./utils').sjcl;
|
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
var config = require('./config');
|
|
||||||
var extend = require('extend');
|
var extend = require('extend');
|
||||||
|
var UInt = require('./uint').UInt;
|
||||||
var BigInteger = utils.jsbn.BigInteger;
|
|
||||||
|
|
||||||
var UInt = require('./uint').UInt,
|
|
||||||
Base = require('./base').Base;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// UInt128 support
|
// UInt128 support
|
||||||
@@ -21,8 +15,8 @@ UInt128.width = 16;
|
|||||||
UInt128.prototype = extend({}, UInt.prototype);
|
UInt128.prototype = extend({}, UInt.prototype);
|
||||||
UInt128.prototype.constructor = UInt128;
|
UInt128.prototype.constructor = UInt128;
|
||||||
|
|
||||||
var HEX_ZERO = UInt128.HEX_ZERO = "00000000000000000000000000000000";
|
var HEX_ZERO = UInt128.HEX_ZERO = '00000000000000000000000000000000';
|
||||||
var HEX_ONE = UInt128.HEX_ONE = "00000000000000000000000000000000";
|
var HEX_ONE = UInt128.HEX_ONE = '00000000000000000000000000000000';
|
||||||
var STR_ZERO = UInt128.STR_ZERO = utils.hexToString(HEX_ZERO);
|
var STR_ZERO = UInt128.STR_ZERO = utils.hexToString(HEX_ZERO);
|
||||||
var STR_ONE = UInt128.STR_ONE = utils.hexToString(HEX_ONE);
|
var STR_ONE = UInt128.STR_ONE = utils.hexToString(HEX_ONE);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
var sjcl = require('./utils').sjcl;
|
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
var config = require('./config');
|
var config = require('./config');
|
||||||
var extend = require('extend');
|
var extend = require('extend');
|
||||||
@@ -12,11 +11,10 @@ var Base = require('./base').Base;
|
|||||||
// UInt160 support
|
// UInt160 support
|
||||||
//
|
//
|
||||||
|
|
||||||
var UInt160 = extend(function () {
|
var UInt160 = extend(function() {
|
||||||
// Internal form: NaN or BigInteger
|
// 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();
|
||||||
}, UInt);
|
}, UInt);
|
||||||
|
|
||||||
@@ -31,20 +29,19 @@ var HEX_ONE = UInt160.HEX_ONE = '0000000000000000000000000000000000000
|
|||||||
var STR_ZERO = UInt160.STR_ZERO = utils.hexToString(HEX_ZERO);
|
var STR_ZERO = UInt160.STR_ZERO = utils.hexToString(HEX_ZERO);
|
||||||
var STR_ONE = UInt160.STR_ONE = utils.hexToString(HEX_ONE);
|
var STR_ONE = UInt160.STR_ONE = utils.hexToString(HEX_ONE);
|
||||||
|
|
||||||
UInt160.prototype.set_version = function (j) {
|
UInt160.prototype.set_version = function(j) {
|
||||||
this._version_byte = j;
|
this._version_byte = j;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt160.prototype.get_version = function () {
|
UInt160.prototype.get_version = function() {
|
||||||
return this._version_byte;
|
return this._version_byte;
|
||||||
};
|
};
|
||||||
|
|
||||||
// value = NaN on error.
|
// value = NaN on error.
|
||||||
UInt160.prototype.parse_json = function (j) {
|
UInt160.prototype.parse_json = function(j) {
|
||||||
// Canonicalize and validate
|
// Canonicalize and validate
|
||||||
if (config.accounts && j in config.accounts) {
|
if (config.accounts && (j in config.accounts)) {
|
||||||
j = config.accounts[j].account;
|
j = config.accounts[j].account;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,11 +65,11 @@ UInt160.prototype.parse_json = function (j) {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt160.prototype.parse_generic = function (j) {
|
UInt160.prototype.parse_generic = function(j) {
|
||||||
UInt.prototype.parse_generic.call(this, j);
|
UInt.prototype.parse_generic.call(this, j);
|
||||||
|
|
||||||
if (isNaN(this._value)) {
|
if (isNaN(this._value)) {
|
||||||
if ("string" === typeof j && j[0] === 'r') {
|
if ((typeof j === 'string') && j[0] === 'r') {
|
||||||
this._value = Base.decode_check(Base.VER_ACCOUNT_ID, j);
|
this._value = Base.decode_check(Base.VER_ACCOUNT_ID, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,13 +80,14 @@ UInt160.prototype.parse_generic = function (j) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// XXX Json form should allow 0 and 1, C++ doesn't currently allow it.
|
// XXX Json form should allow 0 and 1, C++ doesn't currently allow it.
|
||||||
UInt160.prototype.to_json = function (opts) {
|
UInt160.prototype.to_json = function(opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
if (this._value instanceof BigInteger) {
|
if (this._value instanceof BigInteger) {
|
||||||
// If this value has a type, return a Base58 encoded string.
|
// If this value has a type, return a Base58 encoded string.
|
||||||
if ("number" === typeof this._version_byte) {
|
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());
|
||||||
|
|
||||||
if (opts.gateways && output in opts.gateways) {
|
if (opts.gateways && output in opts.gateways) {
|
||||||
output = opts.gateways[output];
|
output = opts.gateways[output];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
var sjcl = require('./utils').sjcl;
|
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
var config = require('./config');
|
|
||||||
var extend = require('extend');
|
var extend = require('extend');
|
||||||
|
var UInt = require('./uint').UInt;
|
||||||
var BigInteger = utils.jsbn.BigInteger;
|
|
||||||
|
|
||||||
var UInt = require('./uint').UInt,
|
|
||||||
Base = require('./base').Base;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// UInt256 support
|
// UInt256 support
|
||||||
//
|
//
|
||||||
|
|
||||||
var UInt256 = extend(function () {
|
var UInt256 = extend(function() {
|
||||||
// Internal form: NaN or BigInteger
|
// Internal form: NaN or BigInteger
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
}, UInt);
|
}, UInt);
|
||||||
@@ -21,10 +15,8 @@ UInt256.width = 32;
|
|||||||
UInt256.prototype = extend({}, UInt.prototype);
|
UInt256.prototype = extend({}, UInt.prototype);
|
||||||
UInt256.prototype.constructor = UInt256;
|
UInt256.prototype.constructor = UInt256;
|
||||||
|
|
||||||
var HEX_ZERO = UInt256.HEX_ZERO = "00000000000000000000000000000000" +
|
var HEX_ZERO = UInt256.HEX_ZERO = '00000000000000000000000000000000' + '00000000000000000000000000000000';
|
||||||
"00000000000000000000000000000000";
|
var HEX_ONE = UInt256.HEX_ONE = '00000000000000000000000000000000' + '00000000000000000000000000000001';
|
||||||
var HEX_ONE = UInt256.HEX_ONE = "00000000000000000000000000000000" +
|
|
||||||
"00000000000000000000000000000001";
|
|
||||||
var STR_ZERO = UInt256.STR_ZERO = utils.hexToString(HEX_ZERO);
|
var STR_ZERO = UInt256.STR_ZERO = utils.hexToString(HEX_ZERO);
|
||||||
var STR_ONE = UInt256.STR_ONE = utils.hexToString(HEX_ONE);
|
var STR_ONE = UInt256.STR_ONE = utils.hexToString(HEX_ONE);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
Function.prototype.method = function(name, func) {
|
|
||||||
this.prototype[name] = func;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
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));
|
||||||
@@ -20,7 +15,7 @@ function throwErr(done) {
|
|||||||
|
|
||||||
function trace(comment, func) {
|
function trace(comment, func) {
|
||||||
return function() {
|
return function() {
|
||||||
console.log("%s: %s", trace, arguments.toString);
|
console.log('%s: %s', trace, arguments.toString);
|
||||||
func(arguments);
|
func(arguments);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -94,7 +89,7 @@ function chunkString(str, n, leftAlign) {
|
|||||||
|
|
||||||
function assert(assertion, msg) {
|
function assert(assertion, msg) {
|
||||||
if (!assertion) {
|
if (!assertion) {
|
||||||
throw new Error("Assertion failed" + (msg ? ": "+msg : "."));
|
throw new Error('Assertion failed' + (msg ? ': ' + msg : '.'));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user