mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-21 20:55:48 +00:00
Lint
This commit is contained in:
@@ -9,11 +9,11 @@
|
||||
// balance_proposed
|
||||
//
|
||||
|
||||
// var network = require("./network.js");
|
||||
// var network = require('./network.js');
|
||||
var async = require('async');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var util = require('util');
|
||||
var extend = require('extend');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var Amount = require('./amount').Amount;
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
var TransactionManager = require('./transactionmanager').TransactionManager;
|
||||
@@ -75,7 +75,9 @@ function Account(remote, account) {
|
||||
this._remote.on('prepare_subscribe', attachAccount);
|
||||
|
||||
function handleTransaction(transaction) {
|
||||
if (!transaction.mmeta) return;
|
||||
if (!transaction.mmeta) {
|
||||
return;
|
||||
}
|
||||
|
||||
var changed = false;
|
||||
|
||||
@@ -137,7 +139,7 @@ Account.prototype.getInfo = function(callback) {
|
||||
* Retrieve the current AccountRoot entry.
|
||||
*
|
||||
* To keep up-to-date with changes to the AccountRoot entry, subscribe to the
|
||||
* "entry" event.
|
||||
* 'entry' event.
|
||||
*
|
||||
* @param {Function} callback
|
||||
*/
|
||||
@@ -164,11 +166,14 @@ Account.prototype.entry = function(callback) {
|
||||
Account.prototype.getNextSequence = function(callback) {
|
||||
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) {
|
||||
if (err &&
|
||||
"object" === typeof err &&
|
||||
"object" === typeof err.remote &&
|
||||
err.remote.error === "actNotFound") {
|
||||
if (isNotFound(err)) {
|
||||
// New accounts will start out as sequence zero
|
||||
callback(null, 0);
|
||||
} else if (err) {
|
||||
@@ -187,7 +192,7 @@ Account.prototype.getNextSequence = function(callback) {
|
||||
* Retrieve this account's Ripple trust lines.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
@@ -222,21 +227,25 @@ Account.prototype.lines = function(callback) {
|
||||
|
||||
Account.prototype.line = function(currency, address, callback) {
|
||||
var self = this;
|
||||
var found;
|
||||
var callback = typeof callback === 'function' ? callback : function(){};
|
||||
|
||||
self.lines(function(err, data) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
var line = data.lines.filter(function(line) {
|
||||
if (line.account === address && line.currency === currency) {
|
||||
return line;
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var 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);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
@@ -256,17 +265,21 @@ Account.prototype.notifyTx = function(transaction) {
|
||||
// Only trigger the event if the account object is actually
|
||||
// subscribed - this prevents some weird phantom events from
|
||||
// occurring.
|
||||
if (this._subs) {
|
||||
if (!this._subs) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('transaction', transaction);
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -292,10 +305,9 @@ Account.prototype.submit = function(transaction) {
|
||||
* @param {Boolean} true if the public key is valid and active, false otherwise
|
||||
*/
|
||||
Account.prototype.publicKeyIsActive = function(public_key, callback) {
|
||||
|
||||
var self = this;
|
||||
|
||||
var public_key_as_uint160;
|
||||
|
||||
try {
|
||||
public_key_as_uint160 = Account._publicKeyToAddress(public_key);
|
||||
} 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 (account_info.RegularKey &&
|
||||
account_info.RegularKey === public_key_as_uint160) {
|
||||
|
||||
async_callback(null, true);
|
||||
|
||||
} else if (account_info.Account === public_key_as_uint160 &&
|
||||
((account_info.Flags & 0x00100000) === 0)) {
|
||||
|
||||
async_callback(null, true);
|
||||
|
||||
} else {
|
||||
|
||||
async_callback(null, false);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var steps = [
|
||||
@@ -356,7 +361,6 @@ Account.prototype.publicKeyIsActive = function(public_key, callback) {
|
||||
];
|
||||
|
||||
async.waterfall(steps, callback);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -368,35 +372,24 @@ Account.prototype.publicKeyIsActive = function(public_key, callback) {
|
||||
* @returns {RippleAddress}
|
||||
*/
|
||||
Account._publicKeyToAddress = function(public_key) {
|
||||
|
||||
// Based on functions in /src/js/ripple/keypair.js
|
||||
function hexToUInt160(public_key) {
|
||||
|
||||
var bits = sjcl.codec.hex.toBits(public_key);
|
||||
var hash = sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));
|
||||
var address = UInt160.from_bits(hash);
|
||||
address.set_version(Base.VER_ACCOUNT_ID);
|
||||
|
||||
return address.to_json();
|
||||
|
||||
}
|
||||
|
||||
if (UInt160.is_valid(public_key)) {
|
||||
|
||||
return public_key;
|
||||
|
||||
} else if (/^[0-9a-fA-F]+$/.test(public_key)) {
|
||||
|
||||
return hexToUInt160(public_key);
|
||||
|
||||
} else {
|
||||
|
||||
throw(new Error('Public key is invalid. Must be a UInt160 or a hex string'));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (UInt160.is_valid(public_key)) {
|
||||
return public_key;
|
||||
} else if (/^[0-9a-fA-F]+$/.test(public_key)) {
|
||||
return hexToUInt160(public_key);
|
||||
} else {
|
||||
throw new Error('Public key is invalid. Must be a UInt160 or a hex string');
|
||||
}
|
||||
};
|
||||
|
||||
exports.Account = Account;
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ Amount.prototype.equals = function (d, ignore_issuer) {
|
||||
|| (this._is_native !== d._is_native)
|
||||
|| (!this._value.equals(d._value) || this._offset !== d._offset)
|
||||
|| (this._is_negative !== d._is_negative)
|
||||
|| (!this._is_native && (!this._currency.equals(d._currency) || !ignore_issuer && !this._issuer.equals(d._issuer))))
|
||||
|| (!this._is_native && (!this._currency.equals(d._currency) || !ignore_issuer && !this._issuer.equals(d._issuer))));
|
||||
|
||||
return result;
|
||||
};
|
||||
@@ -311,7 +311,7 @@ Amount.prototype.divide = function (d) {
|
||||
var result;
|
||||
|
||||
if (d.is_zero()) {
|
||||
throw 'divide by zero';
|
||||
throw new Error('divide by zero');
|
||||
}
|
||||
|
||||
if (this.is_zero()) {
|
||||
@@ -478,7 +478,7 @@ Amount.prototype.product_human = function (factor, opts) {
|
||||
}
|
||||
|
||||
return product;
|
||||
}
|
||||
};
|
||||
|
||||
// True if Amounts are valid and both native or non-native.
|
||||
Amount.prototype.is_comparable = function(v) {
|
||||
@@ -646,7 +646,7 @@ Amount.prototype.parse_human = function (j, opts) {
|
||||
// The correct way to solve this is probably to switch to a proper
|
||||
// BigDecimal for our internal representation and then use that across
|
||||
// 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()) {
|
||||
var ref = this.divide(interestTempAmount);
|
||||
@@ -733,7 +733,7 @@ Amount.prototype.parse_quality = function (quality, counterCurrency, counterIssu
|
||||
var interest = baseCurrency.get_interest_at(opts.reference_date);
|
||||
|
||||
// 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()) {
|
||||
var v = this.divide(interestTempAmount);
|
||||
@@ -743,7 +743,7 @@ Amount.prototype.parse_quality = function (quality, counterCurrency, counterIssu
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
Amount.prototype.parse_number = function(n) {
|
||||
this._is_native = false;
|
||||
@@ -785,7 +785,10 @@ Amount.prototype.parse_json = function (j) {
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
if (j === null) break;
|
||||
if (j === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (j instanceof Amount) {
|
||||
j.copyTo(this);
|
||||
} else if (j.hasOwnProperty('value')) {
|
||||
@@ -986,7 +989,7 @@ Amount.prototype.applyInterest = function (referenceDate) {
|
||||
// The correct way to solve this is probably to switch to a proper
|
||||
// BigDecimal for our internal representation and then use that across
|
||||
// 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()) {
|
||||
return this.multiply(interestTempAmount);
|
||||
@@ -1021,11 +1024,17 @@ Amount.prototype.applyInterest = function (referenceDate) {
|
||||
Amount.prototype.to_human = function(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
if (!this.is_valid()) return '';
|
||||
if (!this.is_valid()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Default options
|
||||
if (typeof opts.signed === 'undefined') opts.signed = true;
|
||||
if (typeof opts.group_sep === 'undefined') opts.group_sep = true;
|
||||
if (typeof opts.signed === 'undefined') {
|
||||
opts.signed = true;
|
||||
}
|
||||
if (typeof opts.group_sep === 'undefined') {
|
||||
opts.group_sep = true;
|
||||
}
|
||||
|
||||
opts.group_width = opts.group_width || 3;
|
||||
|
||||
@@ -1080,7 +1089,9 @@ Amount.prototype.to_human = function (opts) {
|
||||
rounding = Math.min(rounding, fraction_part.length);
|
||||
|
||||
// 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)
|
||||
@@ -1150,11 +1161,16 @@ Amount.prototype.to_text_full = function (opts) {
|
||||
|
||||
// For debugging.
|
||||
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;
|
||||
|
||||
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()) {
|
||||
result = 'Invalid amount.';
|
||||
} 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;
|
||||
};
|
||||
|
||||
@@ -7,9 +7,9 @@ var BigInteger = utils.jsbn.BigInteger;
|
||||
var Base = {};
|
||||
|
||||
var alphabets = Base.alphabets = {
|
||||
ripple : "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz",
|
||||
tipple : "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz",
|
||||
bitcoin : "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||
ripple: 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz',
|
||||
tipple: 'RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz',
|
||||
bitcoin: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
||||
};
|
||||
|
||||
extend(Base, {
|
||||
@@ -66,8 +66,8 @@ Base.decode = function (input, alpha) {
|
||||
var bi_value = new BigInteger();
|
||||
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) {
|
||||
var v = alphabet.indexOf(input[i]);
|
||||
@@ -87,7 +87,7 @@ Base.decode = function (input, alpha) {
|
||||
var bytes = bi_value.toByteArray().map(function(b) { return b ? b < 0 ? 256+b : b : 0; });
|
||||
var extra = 0;
|
||||
|
||||
while (extra != bytes.length && !bytes[extra]) {
|
||||
while (extra !== bytes.length && !bytes[extra]) {
|
||||
extra += 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This object serves as a singleton to store config options
|
||||
|
||||
var extend = require("extend");
|
||||
var extend = require('extend');
|
||||
|
||||
var config = module.exports = {
|
||||
load: function (newOpts) {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
|
||||
var extend = require('extend');
|
||||
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
var Float = require('./float').Float;
|
||||
var utils = require('./utils');
|
||||
@@ -26,7 +24,7 @@ var Currency = extend(function () {
|
||||
Currency.prototype = extend({}, UInt160.prototype);
|
||||
Currency.prototype.constructor = Currency;
|
||||
|
||||
Currency.HEX_CURRENCY_BAD = "0000000000000000000000005852500000000000";
|
||||
Currency.HEX_CURRENCY_BAD = '0000000000000000000000005852500000000000';
|
||||
|
||||
Currency.from_json = function(j, shouldInterpretXrpAsIou) {
|
||||
if (j instanceof this) {
|
||||
@@ -89,7 +87,7 @@ Currency.prototype._update = function () {
|
||||
var isZeroExceptInStandardPositions = true;
|
||||
|
||||
if (!bytes) {
|
||||
return "XRP";
|
||||
return 'XRP';
|
||||
}
|
||||
|
||||
this._native = false;
|
||||
@@ -107,9 +105,9 @@ Currency.prototype._update = function () {
|
||||
+ String.fromCharCode(bytes[13])
|
||||
+ String.fromCharCode(bytes[14]);
|
||||
|
||||
if (this._iso_code === "\0\0\0") {
|
||||
if (this._iso_code === '\0\0\0') {
|
||||
this._native = true;
|
||||
this._iso_code = "XRP";
|
||||
this._iso_code = 'XRP';
|
||||
}
|
||||
|
||||
this._type = 0;
|
||||
@@ -143,9 +141,9 @@ Currency.prototype.parse_bytes = function (byte_array) {
|
||||
var currencyCode = String.fromCharCode(byte_array[12])
|
||||
+ String.fromCharCode(byte_array[13])
|
||||
+ String.fromCharCode(byte_array[14]);
|
||||
if (/^[A-Z0-9]{3}$/.test(currencyCode) && currencyCode !== "XRP" ) {
|
||||
if (/^[A-Z0-9]{3}$/.test(currencyCode) && currencyCode !== 'XRP' ) {
|
||||
this._value = currencyCode;
|
||||
} else if (currencyCode === "\0\0\0") {
|
||||
} else if (currencyCode === '\0\0\0') {
|
||||
this._value = 0;
|
||||
} else {
|
||||
this._value = NaN;
|
||||
@@ -173,7 +171,9 @@ Currency.prototype.has_interest = function () {
|
||||
};
|
||||
|
||||
Currency.prototype.get_interest_at = function(referenceDate) {
|
||||
if (!this.has_interest) return 1;
|
||||
if (!this.has_interest) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (referenceDate instanceof Date) {
|
||||
referenceDate = utils.fromTimestamp(referenceDate.getTime());
|
||||
@@ -194,7 +194,7 @@ Currency.prototype.get_interest_at = function (referenceDate) {
|
||||
Currency.prototype.to_json = function() {
|
||||
if (!this.is_valid()) {
|
||||
// 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
|
||||
|
||||
@@ -10,10 +10,15 @@ var allOnes = /^1+$/;
|
||||
|
||||
Float.fromBytes = function(bytes) {
|
||||
// Render in binary. Hackish.
|
||||
var b = "";
|
||||
var b = '';
|
||||
|
||||
for (var i = 0, n = bytes.length; i < n; i++) {
|
||||
var bits = (bytes[i] & 0xff).toString(2);
|
||||
while (bits.length < 8) bits = "0" + bits;
|
||||
|
||||
while (bits.length < 8) {
|
||||
bits = '0' + bits;
|
||||
}
|
||||
|
||||
b += bits;
|
||||
}
|
||||
|
||||
@@ -29,13 +34,11 @@ Float.fromBytes = function (bytes) {
|
||||
var m = b.substring(exponentBits + 1);
|
||||
|
||||
var value = 0;
|
||||
var multiplier = (s === "0" ? 1 : -1);
|
||||
var multiplier = (s === '0' ? 1 : -1);
|
||||
|
||||
if (allZeros.test(e)) {
|
||||
// Zero or denormalized
|
||||
if (allZeros.test(m)) {
|
||||
// Value is zero
|
||||
} else {
|
||||
if (!allZeros.test(m)) {
|
||||
value = parseInt(m, 2) * Math.pow(2, minExponent);
|
||||
}
|
||||
} else if (allOnes.test(e)) {
|
||||
|
||||
@@ -12,7 +12,6 @@ exports.Meta = require('./meta').Meta;
|
||||
exports.SerializedObject = require('./serializedobject').SerializedObject;
|
||||
exports.RippleError = require('./rippleerror').RippleError;
|
||||
exports.Message = require('./message');
|
||||
|
||||
exports.binformat = require('./binformat');
|
||||
exports.utils = require('./utils');
|
||||
exports.Server = require('./server').Server;
|
||||
@@ -35,7 +34,9 @@ function attachUnderscored(c) {
|
||||
Object.keys(o.prototype).forEach(function(key) {
|
||||
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) {
|
||||
return '_' + c.toLowerCase();
|
||||
|
||||
@@ -5,17 +5,17 @@ var UInt256 = require('./uint256').UInt256;
|
||||
var Base = require('./base').Base;
|
||||
|
||||
function KeyPair() {
|
||||
this._curve = sjcl.ecc.curves['c256'];
|
||||
this._curve = sjcl.ecc.curves.c256;
|
||||
this._secret = null;
|
||||
this._pubkey = null;
|
||||
};
|
||||
|
||||
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) {
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* Logging functionality for ripple-lib and any applications built on it.
|
||||
*/
|
||||
var Log = function (namespace) {
|
||||
function Log(namespace) {
|
||||
if (!namespace) {
|
||||
this._namespace = [];
|
||||
} else if (Array.isArray(namespace)) {
|
||||
this._namespace = namespace;
|
||||
} else {
|
||||
this._namespace = [""+namespace];
|
||||
this._namespace = [''+namespace];
|
||||
}
|
||||
|
||||
this._prefix = this._namespace.concat(['']).join(': ');
|
||||
@@ -23,11 +23,15 @@ var Log = function (namespace) {
|
||||
* var log = require('ripple').log.sub('server');
|
||||
*
|
||||
* log.info('connection successful');
|
||||
* // prints: "server: connection successful"
|
||||
* // prints: 'server: connection successful'
|
||||
*/
|
||||
Log.prototype.sub = function(namespace) {
|
||||
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);
|
||||
subLogger._setParent(this);
|
||||
return subLogger;
|
||||
@@ -39,9 +43,9 @@ Log.prototype._setParent = function (parentLogger) {
|
||||
|
||||
Log.makeLevel = function(level) {
|
||||
return function() {
|
||||
arguments[0] = this._prefix + arguments[0];
|
||||
|
||||
Log.engine.logObject.apply(Log, Array.prototype.slice.call(arguments));
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
args[0] = this._prefix + args[0];
|
||||
Log.engine.logObject.apply(Log, args);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -53,7 +57,7 @@ Log.prototype.error = Log.makeLevel(4);
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
var BasicLogEngine = {
|
||||
@@ -82,7 +86,9 @@ var 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.
|
||||
|
||||
@@ -15,7 +15,7 @@ function Meta(raw_data) {
|
||||
raw_data.AffectedNodes.forEach(function(an) {
|
||||
var result = { };
|
||||
|
||||
if (result.diffType = self.diffType(an)) {
|
||||
if ((result.diffType = self.diffType(an))) {
|
||||
an = an[result.diffType];
|
||||
|
||||
result.entryType = an.LedgerEntryType;
|
||||
@@ -103,7 +103,7 @@ Meta.prototype.each = function (fn) {
|
||||
]).forEach(function(fn) {
|
||||
Meta.prototype[fn] = function() {
|
||||
return Array.prototype[fn].apply(this.nodes, arguments);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
var amountFieldsAffectingIssuer = [
|
||||
@@ -141,16 +141,22 @@ Meta.prototype.getAffectedBooks = function () {
|
||||
var books = [ ];
|
||||
|
||||
this.nodes.forEach(function(an) {
|
||||
if (an.entryType !== 'Offer') return;
|
||||
if (an.entryType !== 'Offer') {
|
||||
return;
|
||||
}
|
||||
|
||||
var gets = Amount.from_json(an.fields.TakerGets);
|
||||
var pays = Amount.from_json(an.fields.TakerPays);
|
||||
|
||||
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();
|
||||
if (paysKey !== 'XRP') paysKey += '/' + pays.issuer().to_json();
|
||||
if (paysKey !== 'XRP') {
|
||||
paysKey += '/' + pays.issuer().to_json();
|
||||
}
|
||||
|
||||
var key = [ getsKey, paysKey ].join(':');
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
// var network = require("./network.js");
|
||||
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var util = require('util');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var extend = require('extend');
|
||||
var Amount = require('./amount').Amount;
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
@@ -38,7 +38,7 @@ function OrderBook(remote, currency_gets, issuer_gets, currency_pays, issuer_pay
|
||||
function listenerAdded(type, listener) {
|
||||
if (~OrderBook.subscribe_events.indexOf(type)) {
|
||||
self._subs += 1;
|
||||
if (self._subs == 1 && self._remote._connected) {
|
||||
if (self._subs === 1 && self._remote._connected) {
|
||||
self._subscribe();
|
||||
}
|
||||
}
|
||||
@@ -140,11 +140,11 @@ OrderBook.prototype.to_json = function () {
|
||||
};
|
||||
|
||||
if (this._currency_gets !== 'XRP') {
|
||||
json['taker_gets']['issuer'] = this._issuer_gets;
|
||||
json.taker_gets.issuer = this._issuer_gets;
|
||||
}
|
||||
|
||||
if (this._currency_pays !== 'XRP') {
|
||||
json['taker_pays']['issuer'] = this._issuer_pays;
|
||||
json.taker_pays.issuer = this._issuer_pays;
|
||||
}
|
||||
|
||||
return json;
|
||||
@@ -188,7 +188,9 @@ OrderBook.prototype.notify = function (message) {
|
||||
var trade_pays = this.trade('pays');
|
||||
|
||||
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;
|
||||
|
||||
@@ -199,6 +201,7 @@ OrderBook.prototype.notify = function (message) {
|
||||
|
||||
for (i=0, l=self._offers.length; i<l; i++) {
|
||||
offer = self._offers[i];
|
||||
|
||||
if (offer.index === an.ledgerIndex) {
|
||||
if (deletedNode) {
|
||||
self._offers.splice(i, 1);
|
||||
@@ -207,13 +210,16 @@ OrderBook.prototype.notify = function (message) {
|
||||
// safe assumption, but should be checked.
|
||||
extend(offer, an.fieldsFinal);
|
||||
}
|
||||
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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_pays = trade_pays.add(an.fieldsPrev.TakerPays);
|
||||
@@ -272,6 +278,7 @@ OrderBook.prototype.notifyTx = OrderBook.prototype.notify;
|
||||
*/
|
||||
OrderBook.prototype.offers = function (callback) {
|
||||
var self = this;
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
if (this._sync) {
|
||||
callback(this._offers);
|
||||
@@ -279,6 +286,7 @@ OrderBook.prototype.offers = function (callback) {
|
||||
this.once('model', callback);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
@@ -102,8 +102,8 @@ function Remote(opts, trace) {
|
||||
this.retry = void(0);
|
||||
this._connection_count = 0;
|
||||
this._connected = false;
|
||||
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._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._received_tx = LRU({ max: 100 });
|
||||
this._cur_path_find = null;
|
||||
@@ -239,7 +239,9 @@ function Remote(opts, trace) {
|
||||
|
||||
function getPendingTransactions() {
|
||||
self.storage.getPendingTransactions(function(err, transactions) {
|
||||
if (err || !Array.isArray(transactions)) return;
|
||||
if (err || !Array.isArray(transactions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
function resubmitTransaction(tx) {
|
||||
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 Be more defensive fields could be missing or of wrong type.
|
||||
// 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) {
|
||||
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
|
||||
message.mmeta.getAffectedAccounts().forEach(function(account) {
|
||||
account = self._accounts[account];
|
||||
if (account) account.notify(message);
|
||||
if (account) {
|
||||
account.notify(message);
|
||||
}
|
||||
});
|
||||
|
||||
// Pass the event on to any related OrderBooks
|
||||
message.mmeta.getAffectedBooks().forEach(function(book) {
|
||||
book = self._books[book];
|
||||
if (book) book.notify(message);
|
||||
if (book) {
|
||||
book.notify(message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
[ 'Account', 'Destination' ].forEach(function(prop) {
|
||||
@@ -659,7 +667,9 @@ Remote.prototype._getServer = function() {
|
||||
// <-> request: what to send, consumed.
|
||||
Remote.prototype.request = function(request) {
|
||||
if (typeof request === 'string') {
|
||||
if (!/^request_/.test(request)) request = 'request_' + request;
|
||||
if (!/^request_/.test(request)) {
|
||||
request = 'request_' + request;
|
||||
}
|
||||
if (typeof this[request] === 'function') {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this[request].apply(this, args);
|
||||
@@ -678,7 +688,7 @@ Remote.prototype.request = function(request) {
|
||||
} else {
|
||||
var server = request.server || this._getServer();
|
||||
if (server) {
|
||||
server.request(request);
|
||||
server._request(request);
|
||||
} else {
|
||||
request.emit('error', new Error('No servers available'));
|
||||
}
|
||||
@@ -1147,7 +1157,7 @@ Remote.prototype.requestBookOffers = function(gets, pays, taker, callback) {
|
||||
|
||||
request.message.taker_pays = {
|
||||
currency: Currency.json_rewrite(pays.currency)
|
||||
}
|
||||
};
|
||||
|
||||
if (request.message.taker_pays.currency !== 'XRP') {
|
||||
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 seq;
|
||||
|
||||
if (account_info && account_info.seq) {
|
||||
if (accountInfo && accountInfo.seq) {
|
||||
seq = accountInfo.seq;
|
||||
var change = { ADVANCE: 1, REWIND: -1 }[advance.toUpperCase()] || 0;
|
||||
accountInfo.seq += change;
|
||||
@@ -1657,7 +1667,7 @@ Remote.prototype.transaction = function(source, options, callback) {
|
||||
offercreate: 'offerCreate',
|
||||
offercancel: 'offerCancel',
|
||||
sign: 'sign'
|
||||
}
|
||||
};
|
||||
|
||||
var transactionType;
|
||||
|
||||
@@ -1705,7 +1715,13 @@ Remote.prototype.transaction = function(source, options, callback) {
|
||||
*/
|
||||
|
||||
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() {
|
||||
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) {
|
||||
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 =
|
||||
|
||||
@@ -2,10 +2,6 @@ var EventEmitter = require('events').EventEmitter;
|
||||
var util = require('util');
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
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 Server = require('./server').Server;
|
||||
|
||||
@@ -20,7 +16,11 @@ function Request(remote, command) {
|
||||
|
||||
this.remote = remote;
|
||||
this.requested = false;
|
||||
this.message = { command: command, id: void(0) };
|
||||
|
||||
this.message = {
|
||||
command: command,
|
||||
id: void(0)
|
||||
};
|
||||
};
|
||||
|
||||
util.inherits(Request, EventEmitter);
|
||||
@@ -32,11 +32,13 @@ Request.prototype.broadcast = function() {
|
||||
|
||||
// Send the request to a remote.
|
||||
Request.prototype.request = function(remote) {
|
||||
if (this.requested) return;
|
||||
if (this.requested) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.requested = true;
|
||||
|
||||
this.on('error', new Function);
|
||||
this.on('error', function(){});
|
||||
this.emit('request', remote);
|
||||
|
||||
if (this._broadcast) {
|
||||
@@ -93,7 +95,11 @@ Request.prototype.timeout = function(duration, callback) {
|
||||
|
||||
var timeout = setTimeout(function() {
|
||||
timed_out = true;
|
||||
if (typeof callback === 'function') callback();
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
|
||||
emit.call(self, 'timeout');
|
||||
}, duration);
|
||||
|
||||
@@ -119,7 +125,7 @@ Request.prototype.setServer = function(server) {
|
||||
// Find server with hostname string
|
||||
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) {
|
||||
selected = s;
|
||||
break;
|
||||
@@ -148,7 +154,7 @@ Request.prototype.buildPath = function(build) {
|
||||
} else {
|
||||
// ND: rippled currently intreprets the mere presence of `build_path` as the
|
||||
// value being `truthy`
|
||||
delete this.message.build_path
|
||||
delete this.message.build_path;
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -184,13 +190,13 @@ Request.prototype.ledgerSelect = function(ledger) {
|
||||
case 'current':
|
||||
case 'closed':
|
||||
case 'verified':
|
||||
this.message.ledger_index = ledger_spec;
|
||||
this.message.ledger_index = ledger;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isNaN(ledger)) {
|
||||
this.message.ledger_hash = ledger;
|
||||
} else if (ledger = Number(ledger)) {
|
||||
} else if ((ledger = Number(ledger))) {
|
||||
this.message.ledger_index = ledger;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -6,6 +6,7 @@ function RippleError(code, message) {
|
||||
case 'object':
|
||||
extend(this, code);
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
this.result = code;
|
||||
this.result_message = message;
|
||||
@@ -17,11 +18,13 @@ function RippleError(code, message) {
|
||||
this.result_message = this.message = (this.result_message);
|
||||
|
||||
var stack;
|
||||
if (!!Error.captureStackTrace)
|
||||
|
||||
if (!!Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, code || this);
|
||||
else if (stack = new Error().stack)
|
||||
} else if ((stack = new Error().stack)) {
|
||||
this.stack = stack;
|
||||
}
|
||||
};
|
||||
|
||||
util.inherits(RippleError, Error);
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// Seed support
|
||||
//
|
||||
|
||||
var extend = require('extend');
|
||||
var utils = require('./utils');
|
||||
var sjcl = utils.sjcl;
|
||||
var extend = require('extend');
|
||||
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
@@ -15,7 +15,7 @@ var KeyPair = require('./keypair').KeyPair;
|
||||
|
||||
var Seed = extend(function () {
|
||||
// Internal form: NaN or BigInteger
|
||||
this._curve = sjcl.ecc.curves['c256'];
|
||||
this._curve = sjcl.ecc.curves.c256;
|
||||
this._value = NaN;
|
||||
}, UInt);
|
||||
|
||||
@@ -30,7 +30,7 @@ Seed.prototype.parse_json = function (j) {
|
||||
if (!j.length) {
|
||||
this._value = NaN;
|
||||
// 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);
|
||||
} else if (j.length === 32) {
|
||||
this._value = this.parse_hex(j);
|
||||
@@ -47,7 +47,7 @@ Seed.prototype.parse_json = function (j) {
|
||||
|
||||
Seed.prototype.parse_passphrase = function (j) {
|
||||
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));
|
||||
@@ -85,8 +85,9 @@ function SHA256_RIPEMD160(bits) {
|
||||
|
||||
Seed.prototype.get_key = function (account_id) {
|
||||
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
|
||||
|
||||
var private_gen, public_gen;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
var binformat = require('./binformat');
|
||||
var assert = require('assert');
|
||||
var extend = require('extend');
|
||||
var binformat = require('./binformat');
|
||||
var stypes = require('./serializedtypes');
|
||||
var UInt256 = require('./uint256').UInt256;
|
||||
var assert = require('assert');
|
||||
|
||||
var utils = require('./utils');
|
||||
|
||||
var sjcl = utils.sjcl;
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
@@ -42,30 +42,28 @@ function SerializedObject(buf) {
|
||||
SerializedObject.from_json = function(obj) {
|
||||
// Create a copy of the object so we don't modify it
|
||||
var obj = extend({}, obj);
|
||||
var so = new SerializedObject;
|
||||
var so = new SerializedObject();
|
||||
var typedef;
|
||||
|
||||
if ("number" === typeof obj.TransactionType) {
|
||||
if (typeof obj.TransactionType === 'number') {
|
||||
obj.TransactionType = SerializedObject.lookup_type_tx(obj.TransactionType);
|
||||
|
||||
if (!obj.TransactionType) {
|
||||
throw new Error('Transaction type ID is invalid.');
|
||||
}
|
||||
}
|
||||
|
||||
if ("string" === typeof obj.TransactionType) {
|
||||
if (typeof obj.TransactionType === 'string') {
|
||||
typedef = binformat.tx[obj.TransactionType];
|
||||
|
||||
if (!Array.isArray(typedef)) {
|
||||
throw new Error('Transaction type is invalid');
|
||||
}
|
||||
|
||||
typedef = typedef.slice();
|
||||
obj.TransactionType = typedef.shift();
|
||||
} else if ("undefined" !== typeof obj.LedgerEntryType) {
|
||||
} else if (typeof obj.LedgerEntryType !== 'undefined') {
|
||||
// XXX: TODO
|
||||
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;
|
||||
} else {
|
||||
throw new Error('Object to be serialized must contain either' +
|
||||
@@ -84,32 +82,34 @@ SerializedObject.check_no_missing_fields = function (typedef, obj) {
|
||||
|
||||
for (var i=typedef.length - 1; i>=0; i--) {
|
||||
var spec = typedef[i];
|
||||
var field = spec[0]
|
||||
var field = spec[0];
|
||||
var requirement = spec[1];
|
||||
|
||||
if (binformat.REQUIRED === requirement && obj[field] == null) {
|
||||
if (binformat.REQUIRED === requirement && obj[field] === void(0)) {
|
||||
missing_fields.push(field);
|
||||
};
|
||||
};
|
||||
|
||||
if (missing_fields.length > 0) {
|
||||
var object_name;
|
||||
if (obj.TransactionType != null) {
|
||||
|
||||
if (obj.TransactionType !== void(0)) {
|
||||
object_name = SerializedObject.lookup_type_tx(obj.TransactionType);
|
||||
} else {
|
||||
object_name = "TransactionMetaData";
|
||||
object_name = 'TransactionMetaData';
|
||||
} /*else {
|
||||
TODO: LedgerEntryType ...
|
||||
}*/
|
||||
throw new Error(object_name + " is missing fields: " +
|
||||
JSON.stringify(missing_fields));
|
||||
|
||||
throw new Error(object_name + ' is missing fields: ' + JSON.stringify(missing_fields));
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
SerializedObject.prototype.append = function(bytes) {
|
||||
if (bytes instanceof SerializedObject) {
|
||||
bytes = bytes.buffer;
|
||||
}
|
||||
|
||||
this.buffer = this.buffer.concat(bytes);
|
||||
this.pointer += bytes.length;
|
||||
};
|
||||
@@ -134,7 +134,7 @@ function readOrPeek(advance) {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
SerializedObject.prototype.read = readOrPeek(true);
|
||||
@@ -164,7 +164,7 @@ SerializedObject.prototype.to_json = function() {
|
||||
this.pointer = old_pointer;
|
||||
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
SerializedObject.jsonify_structure = function(structure, field_name) {
|
||||
var output;
|
||||
@@ -186,14 +186,20 @@ SerializedObject.jsonify_structure = function(structure, field_name) {
|
||||
}
|
||||
break;
|
||||
case 'object':
|
||||
if (!structure) break; //null
|
||||
if (structure === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (typeof structure.to_json === 'function') {
|
||||
output = structure.to_json();
|
||||
} else if (structure instanceof BigInteger) {
|
||||
output = structure.toString(16).toUpperCase();
|
||||
} else {
|
||||
output = new structure.constructor; //new Array or Object
|
||||
//new Array or Object
|
||||
output = new structure.constructor();
|
||||
|
||||
var keys = Object.keys(structure);
|
||||
|
||||
for (var i=0, l=keys.length; i<l; i++) {
|
||||
var key = keys[i];
|
||||
output[key] = SerializedObject.jsonify_structure(structure[key], key);
|
||||
@@ -292,7 +298,7 @@ SerializedObject.sort_typedef = function (typedef) {
|
||||
};
|
||||
|
||||
SerializedObject.lookup_type_tx = function(id) {
|
||||
assert(typeof id === 'number');
|
||||
assert.strictEqual(typeof id, 'number');
|
||||
return TRANSACTION_TYPES[id];
|
||||
};
|
||||
|
||||
|
||||
@@ -79,11 +79,7 @@ SerializedType.serialize_varint = function (so, val) {
|
||||
so.append([193 + (val >>> 8), val & 0xff]);
|
||||
} else if (val <= 918744) {
|
||||
val -= 12481;
|
||||
so.append([
|
||||
241 + (val >>> 16),
|
||||
val >>> 8 & 0xff,
|
||||
val & 0xff
|
||||
]);
|
||||
so.append([ 241 + (val >>> 16), val >>> 8 & 0xff, val & 0xff ]);
|
||||
} else {
|
||||
throw new Error('Variable integer overflow.');
|
||||
}
|
||||
@@ -105,7 +101,7 @@ SerializedType.prototype.parse_varint = function (so) {
|
||||
} else if (b1 <= 254) {
|
||||
b2 = 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;
|
||||
@@ -142,7 +138,7 @@ function readAndSum(so, bytes) {
|
||||
var sum = 0;
|
||||
|
||||
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++) {
|
||||
@@ -328,7 +324,10 @@ var STAmount = exports.Amount = new SerializedType({
|
||||
// Amount enforces the range correctly, but we'll clear them anyway just
|
||||
// so this code can make certain guarantees about the encoded value.
|
||||
valueBytes[0] &= 0x3f;
|
||||
if (!amount.is_negative()) valueBytes[0] |= 0x40;
|
||||
|
||||
if (!amount.is_negative()) {
|
||||
valueBytes[0] |= 0x40;
|
||||
}
|
||||
} else {
|
||||
var hi = 0, lo = 0;
|
||||
|
||||
@@ -337,7 +336,10 @@ var STAmount = exports.Amount = new SerializedType({
|
||||
|
||||
if (!amount.is_zero()) {
|
||||
// Second bit: non-negative?
|
||||
if (!amount.is_negative()) hi |= 1 << 30;
|
||||
if (!amount.is_negative()) {
|
||||
hi |= 1 << 30;
|
||||
}
|
||||
|
||||
// Next eight bits: offset/exponent
|
||||
hi |= ((97 + amount._offset) & 0xff) << 22;
|
||||
// Remaining 52 bits: mantissa
|
||||
@@ -465,11 +467,18 @@ var STPathSet = exports.PathSet = new SerializedType({
|
||||
//if (entry.hasOwnProperty('_value')) {entry = entry._value;}
|
||||
var type = 0;
|
||||
|
||||
if (entry.account) type |= this.typeAccount;
|
||||
if (entry.currency) type |= this.typeCurrency;
|
||||
if (entry.issuer) type |= this.typeIssuer;
|
||||
if (entry.account) {
|
||||
type |= this.typeAccount;
|
||||
}
|
||||
if (entry.currency) {
|
||||
type |= this.typeCurrency;
|
||||
}
|
||||
if (entry.issuer) {
|
||||
type |= this.typeIssuer;
|
||||
}
|
||||
|
||||
STInt8.serialize(so, type);
|
||||
|
||||
if (entry.account) {
|
||||
so.append(UInt160.from_json(entry.account).to_bytes());
|
||||
}
|
||||
@@ -484,6 +493,7 @@ var STPathSet = exports.PathSet = new SerializedType({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STInt8.serialize(so, this.typeEnd);
|
||||
},
|
||||
parse: function (so) {
|
||||
@@ -513,7 +523,9 @@ var STPathSet = exports.PathSet = new SerializedType({
|
||||
path_list.push(current_path);
|
||||
}
|
||||
current_path = [ ]; //and start a new one.
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
//It's an entry-begin tag.
|
||||
//console.log('It's an entry-begin tag.');
|
||||
var entry = {};
|
||||
@@ -528,8 +540,7 @@ var STPathSet = exports.PathSet = new SerializedType({
|
||||
if (tag_byte & this.typeCurrency) {
|
||||
//console.log('entry.currency');
|
||||
entry.currency = STCurrency.parse(so);
|
||||
if (entry.currency.to_json() === "XRP" &&
|
||||
!entry.currency.is_native()) {
|
||||
if (entry.currency.to_json() === 'XRP' && !entry.currency.is_native()) {
|
||||
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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_path) {
|
||||
//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 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];
|
||||
}
|
||||
|
||||
if (field_name === "TransactionResult" && "string" === typeof value) {
|
||||
if (field_name === 'TransactionResult' && 'string' === typeof value) {
|
||||
value = binformat.ter[value];
|
||||
}
|
||||
|
||||
@@ -668,8 +678,8 @@ var STObject = exports.Object = new SerializedType({
|
||||
});
|
||||
|
||||
keys.forEach(function (key) {
|
||||
if ("undefined" === typeof binformat.fieldsInverseMap[key]) {
|
||||
throw new Error("JSON contains unknown field: '" + key + "'");
|
||||
if (typeof binformat.fieldsInverseMap[key] === 'undefined') {
|
||||
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++) {
|
||||
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) {
|
||||
@@ -708,7 +722,9 @@ var STArray = exports.Array = new SerializedType({
|
||||
var value = val[i][field_name];
|
||||
serialize(so, field_name, value);
|
||||
}
|
||||
STInt8.serialize(so, 0xf1); //Array ending marker
|
||||
|
||||
//Array ending marker
|
||||
STInt8.serialize(so, 0xf1);
|
||||
},
|
||||
|
||||
parse: function (so) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
var util = require('util');
|
||||
var url = require('url');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var Transaction = require('./transaction').Transaction;
|
||||
var Amount = require('./amount').Amount;
|
||||
var utils = require('./utils');
|
||||
var Transaction = require('./transaction').Transaction;
|
||||
var log = require('./log').internal.sub('server');
|
||||
|
||||
/**
|
||||
@@ -18,34 +18,47 @@ var log = require('./log').internal.sub('server');
|
||||
function Server(remote, opts) {
|
||||
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') {
|
||||
throw new TypeError('Server configuration is not an Object');
|
||||
}
|
||||
|
||||
if (!opts.host) opts.host = opts.websocket_ip;
|
||||
if (!opts.port) opts.port = opts.websocket_port;
|
||||
if (!opts.secure) opts.secure = opts.websocket_ssl;
|
||||
|
||||
if (typeof opts.secure === 'undefined') {
|
||||
opts.secure = false;
|
||||
if (!opts.host) {
|
||||
opts.host = opts.websocket_ip;
|
||||
}
|
||||
if (!opts.port) {
|
||||
opts.port = opts.websocket_port;
|
||||
}
|
||||
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');
|
||||
}
|
||||
|
||||
// We want to allow integer strings as valid port numbers for backward
|
||||
// compatibility.
|
||||
if (typeof opts.port === 'string') {
|
||||
opts.port = parseFloat(opts.port);
|
||||
if (typeof opts.secure !== 'boolean') {
|
||||
opts.secure = false;
|
||||
}
|
||||
|
||||
if (typeof opts.port !== 'number' ||
|
||||
opts.port >>> 0 !== parseFloat(opts.port) || // is integer?
|
||||
opts.port < 1 ||
|
||||
opts.port > 65535) {
|
||||
// We want to allow integer strings as valid port numbers for backward compatibility
|
||||
if (typeof opts.port !== 'number') {
|
||||
opts.port = Number(opts.port);
|
||||
}
|
||||
|
||||
if (opts.port < 1 || opts.port > 65535) {
|
||||
throw new TypeError('Server "port" must be an integer in range 1-65535');
|
||||
}
|
||||
|
||||
@@ -86,7 +99,9 @@ function Server(remote, opts) {
|
||||
});
|
||||
|
||||
function checkServerActivity() {
|
||||
if (isNaN(self._lastLedgerClose)) return;
|
||||
if (isNaN(self._lastLedgerClose)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var delta = (Date.now() - self._lastLedgerClose);
|
||||
|
||||
@@ -111,6 +126,8 @@ function Server(remote, opts) {
|
||||
|
||||
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.
|
||||
*
|
||||
@@ -135,7 +152,10 @@ Server.onlineStates = [
|
||||
|
||||
Server.prototype._setState = function(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.emit('state', state);
|
||||
|
||||
@@ -158,7 +178,11 @@ Server.prototype._setState = function(state) {
|
||||
*/
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -187,7 +211,9 @@ Server.websocketConstructor = function() {
|
||||
Server.prototype.disconnect = function() {
|
||||
this._shouldConnect = false;
|
||||
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
|
||||
// reported any issues either. If we do fail to ping or the connection drops,
|
||||
// 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.
|
||||
if (this._ws) this._ws.close();
|
||||
if (this._ws) {
|
||||
this._ws.close();
|
||||
}
|
||||
|
||||
var WebSocket = Server.websocketConstructor();
|
||||
|
||||
@@ -246,7 +278,7 @@ Server.prototype.connect = function() {
|
||||
if (ws === self._ws) {
|
||||
self.emit('socket_open');
|
||||
// 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 (ws === self._ws) {
|
||||
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
|
||||
// code 1006. This is done for security purposes and therefore unlikely to
|
||||
@@ -278,7 +313,9 @@ Server.prototype.connect = function() {
|
||||
ws.onclose = function onClose() {
|
||||
// If we are no longer the active socket, simply ignore any event
|
||||
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();
|
||||
}
|
||||
};
|
||||
@@ -305,7 +342,9 @@ Server.prototype._retryConnect = function() {
|
||||
|
||||
function connectionRetry() {
|
||||
if (self._shouldConnect) {
|
||||
self._remote.trace && log.info('retry', self._opts.url);
|
||||
if (self._remote.trace) {
|
||||
log.info('retry', self._opts.url);
|
||||
}
|
||||
self.connect();
|
||||
}
|
||||
};
|
||||
@@ -344,9 +383,14 @@ Server.prototype._handleClose = function() {
|
||||
Server.prototype._handleMessage = function(message) {
|
||||
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) {
|
||||
case 'ledgerClosed':
|
||||
@@ -364,10 +408,8 @@ Server.prototype._handleMessage = function(message) {
|
||||
self.emit('load', message, self);
|
||||
self._remote.emit('load', message, self);
|
||||
|
||||
var loadChanged = ((message.load_base !== self._load_base) ||
|
||||
(message.load_factor !== self._load_factor));
|
||||
|
||||
if (loadChanged) {
|
||||
if (message.load_base !== self._load_base || message.load_factor !== self._load_factor) {
|
||||
// Load changed
|
||||
self._load_base = message.load_base;
|
||||
self._load_factor = message.load_factor;
|
||||
self.emit('load_changed', message, self);
|
||||
@@ -382,9 +424,16 @@ Server.prototype._handleMessage = function(message) {
|
||||
delete self._requests[message.id];
|
||||
|
||||
if (!request) {
|
||||
this._remote.trace && log.info('UNEXPECTED:', self._opts.url, message);
|
||||
} else if (message.status === 'success') {
|
||||
this._remote.trace && log.info('response:', self._opts.url, message);
|
||||
if (this._remote.trace) {
|
||||
log.info('UNEXPECTED:', 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);
|
||||
|
||||
@@ -392,7 +441,9 @@ Server.prototype._handleMessage = function(message) {
|
||||
emitter.emit('response_' + request.message.command, message.result, request, message);
|
||||
});
|
||||
} 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', {
|
||||
error: 'remoteError',
|
||||
@@ -403,9 +454,10 @@ Server.prototype._handleMessage = function(message) {
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -460,9 +512,11 @@ Server.prototype._handleResponseSubscribe = function(message) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Server.prototype.sendMessage = function(message) {
|
||||
Server.prototype._sendMessage = function(message) {
|
||||
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));
|
||||
}
|
||||
};
|
||||
@@ -477,12 +531,14 @@ Server.prototype.sendMessage = function(message) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Server.prototype.request = function(request) {
|
||||
Server.prototype._request = function(request) {
|
||||
var self = this;
|
||||
|
||||
// Only bother if we are still connected.
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -494,14 +550,15 @@ Server.prototype.request = function(request) {
|
||||
// Advance message ID
|
||||
this._id++;
|
||||
|
||||
function sendRequest() {
|
||||
self._sendMessage(request.message);
|
||||
};
|
||||
|
||||
if (this._isConnected(request)) {
|
||||
this.sendMessage(request.message);
|
||||
sendRequest();
|
||||
} else {
|
||||
// XXX There are many ways to make this smarter.
|
||||
function serverReconnected() {
|
||||
self.sendMessage(request.message);
|
||||
}
|
||||
this.once('connect', serverReconnected);
|
||||
this.once('connect', sendRequest);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -521,7 +578,7 @@ Server.prototype._isConnected = function(request) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Server.prototype.computeFee = function(transaction) {
|
||||
Server.prototype._computeFee = function(transaction) {
|
||||
var units;
|
||||
|
||||
if (transaction instanceof Transaction) {
|
||||
@@ -532,7 +589,7 @@ Server.prototype.computeFee = function(transaction) {
|
||||
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.
|
||||
*/
|
||||
|
||||
Server.prototype.feeTx = function(units) {
|
||||
var fee_unit = this.feeTxUnit();
|
||||
Server.prototype._feeTx = function(units) {
|
||||
var fee_unit = this._feeTxUnit();
|
||||
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.
|
||||
*/
|
||||
|
||||
Server.prototype.feeTxUnit = function() {
|
||||
Server.prototype._feeTxUnit = function() {
|
||||
var fee_unit = this._fee_base / this._fee_ref;
|
||||
|
||||
// Apply load fees
|
||||
@@ -576,10 +633,10 @@ Server.prototype.feeTxUnit = function() {
|
||||
* 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_inc = Amount.from_json(String(this._reserve_inc));
|
||||
var owner_count = owner_count || 0;
|
||||
var owner_count = ownerCount || 0;
|
||||
|
||||
if (owner_count < 0) {
|
||||
throw new Error('Owner count must not be negative.');
|
||||
|
||||
@@ -24,9 +24,7 @@ SHAMap.prototype.hash = function () {
|
||||
*
|
||||
* Can be either SHAMapTreeNodeInner or SHAMapTreeNodeLeaf.
|
||||
*/
|
||||
function SHAMapTreeNode() {
|
||||
|
||||
};
|
||||
function SHAMapTreeNode() { };
|
||||
|
||||
SHAMapTreeNode.TYPE_INNER = 1;
|
||||
SHAMapTreeNode.TYPE_TRANSACTION_NM = 2;
|
||||
@@ -34,11 +32,11 @@ SHAMapTreeNode.TYPE_TRANSACTION_MD = 3;
|
||||
SHAMapTreeNode.TYPE_ACCOUNT_STATE = 4;
|
||||
|
||||
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() {
|
||||
throw new Error("Called unimplemented virtual method SHAMapTreeNode#hash.");
|
||||
throw new Error('Called unimplemented virtual method SHAMapTreeNode#hash.');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -67,7 +65,7 @@ SHAMapTreeNodeInner.prototype.add_item = function (tag_segment, node) {
|
||||
current_node.add_item(tag_segment.slice(1), node);
|
||||
} else if (current_node.get_segment() === tag_segment) {
|
||||
// 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 {
|
||||
// Turn it into an inner node
|
||||
var new_inner_node = new SHAMapTreeNodeInner();
|
||||
@@ -108,12 +106,15 @@ SHAMapTreeNodeInner.prototype.hash = function () {
|
||||
|
||||
var hash_buffer = new SerializedObject();
|
||||
var buffer = [ ];
|
||||
|
||||
for (var i=0; i<16; i++) {
|
||||
var leafHash = UInt256.from_hex(UInt256.HEX_ZERO);
|
||||
var slot = i.toString(16).toUpperCase();
|
||||
if ("object" === typeof this.leaves[slot]) {
|
||||
|
||||
if (typeof this.leaves[slot] === 'object') {
|
||||
leafHash = this.leaves[slot].hash();
|
||||
}
|
||||
|
||||
hash_buffer.append(leafHash.to_bytes());
|
||||
}
|
||||
|
||||
@@ -128,21 +129,19 @@ SHAMapTreeNodeInner.prototype.hash = function () {
|
||||
function SHAMapTreeNodeLeaf(tag, node, type) {
|
||||
SHAMapTreeNode.call(this);
|
||||
|
||||
if ("string" === typeof tag) {
|
||||
if (typeof tag === 'string') {
|
||||
tag = UInt256.from_hex(tag);
|
||||
} else if (tag instanceof UInt256) {
|
||||
// Type is already the right one
|
||||
} else {
|
||||
throw new Error("Tag is unexpected type.");
|
||||
} else if (!(tag instanceof UInt256)){
|
||||
throw new Error('Tag is unexpected type.');
|
||||
}
|
||||
|
||||
this.tag = tag;
|
||||
this.tag_segment = null;
|
||||
|
||||
this.type = type;
|
||||
|
||||
this.node = node;
|
||||
}
|
||||
};
|
||||
|
||||
util.inherits(SHAMapTreeNodeLeaf, SHAMapTreeNode);
|
||||
|
||||
SHAMapTreeNodeLeaf.prototype.get_segment = function(segment) {
|
||||
@@ -163,7 +162,7 @@ SHAMapTreeNodeLeaf.prototype.hash = function () {
|
||||
buffer.append(this.tag.to_bytes());
|
||||
return buffer.hash(hashprefixes.HASH_TX_NODE);
|
||||
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.finalized = false;
|
||||
this.previousSigningHash = void(0);
|
||||
|
||||
// Index at which transaction was submitted
|
||||
this.submitIndex = void(0);
|
||||
|
||||
// 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
|
||||
// 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++) {
|
||||
var server = servers[i];
|
||||
if (!server._connected) continue;
|
||||
var n = server.computeFee(this);
|
||||
if (n < fee) {
|
||||
|
||||
if (!server._connected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var serverFee = server._computeFee(this);
|
||||
|
||||
if (serverFee < fee) {
|
||||
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.local_fee || !this.remote.trusted) {
|
||||
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) {
|
||||
tx.emit('error', new RippleError('tejMaxFeeExceeded', 'Max fee exceeded'));
|
||||
this.emit('error', new RippleError('tejMaxFeeExceeded', 'Max fee exceeded'));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -346,7 +352,7 @@ Transaction.prototype.hash = function(prefix, as_uint256) {
|
||||
}
|
||||
prefix = hashprefixes[prefix];
|
||||
} else if (!prefix) {
|
||||
prefix = hashprefixes['HASH_TX_ID'];
|
||||
prefix = hashprefixes.HASH_TX_ID;
|
||||
}
|
||||
|
||||
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++) {
|
||||
var hash = this.submittedIDs[i];
|
||||
if (result = cache[hash]) break;
|
||||
if ((result = cache[hash])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -432,7 +440,9 @@ Transaction.prototype.destinationTag = function(tag) {
|
||||
|
||||
Transaction.prototype.invoiceID = function(id) {
|
||||
if (typeof id === 'string') {
|
||||
while (id.length < 64) id += '0';
|
||||
while (id.length < 64) {
|
||||
id += '0';
|
||||
}
|
||||
this.tx_json.InvoiceID = id;
|
||||
}
|
||||
return this;
|
||||
@@ -473,7 +483,7 @@ Transaction._pathRewrite = function(path) {
|
||||
newNode.type_hex = node.type_hex;
|
||||
}
|
||||
|
||||
return newNode
|
||||
return newNode;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -533,7 +543,14 @@ Transaction.prototype.transferRate = function(rate) {
|
||||
// Add flags to a transaction.
|
||||
// --> flags: undefined, _flag_, or [ _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 transaction_flags = Transaction.flags[this.tx_json.TransactionType] || { };
|
||||
@@ -919,7 +936,7 @@ Transaction.summary = function() {
|
||||
state: this.state,
|
||||
server: this._server ? this._server._opts.url : void(0),
|
||||
finalized: this.finalized
|
||||
}
|
||||
};
|
||||
|
||||
if (this.result) {
|
||||
result.result = {
|
||||
@@ -928,7 +945,7 @@ Transaction.summary = function() {
|
||||
ledger_hash : this.result.ledger_hash,
|
||||
ledger_index : this.result.ledger_index,
|
||||
transaction_hash : this.result.tx_json.hash
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -3,6 +3,7 @@ var EventEmitter = require('events').EventEmitter;
|
||||
var Transaction = require('./transaction').Transaction;
|
||||
var RippleError = require('./rippleerror').RippleError;
|
||||
var PendingQueue = require('./transactionqueue').TransactionQueue;
|
||||
var log = require('./log').internal.sub('transactionmanager');
|
||||
|
||||
/**
|
||||
* @constructor TransactionManager
|
||||
@@ -20,24 +21,28 @@ function TransactionManager(account) {
|
||||
this._nextSequence = void(0);
|
||||
this._maxFee = this._remote.max_fee;
|
||||
this._submissionTimeout = this._remote._submission_timeout;
|
||||
this._pending = new PendingQueue;
|
||||
this._pending = new PendingQueue();
|
||||
|
||||
// Query remote server for next account sequence number
|
||||
this._loadSequence();
|
||||
|
||||
function transactionReceived(res) {
|
||||
var transaction = TransactionManager.normalizeTransaction(res);
|
||||
var sequence = transaction.transaction.Sequence;
|
||||
var hash = transaction.transaction.hash;
|
||||
var sequence = transaction.tx_json.Sequence;
|
||||
var hash = transaction.tx_json.hash;
|
||||
|
||||
if (!transaction.validated) return;
|
||||
if (!transaction.validated) {
|
||||
return;
|
||||
}
|
||||
|
||||
self._pending.addReceivedSequence(sequence);
|
||||
|
||||
// ND: we need to check against all submissions IDs
|
||||
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) {
|
||||
// ND: A `success` handler will `finalize` this later
|
||||
@@ -52,10 +57,13 @@ function TransactionManager(account) {
|
||||
function adjustFees(loadData, server) {
|
||||
// ND: note, that `Fee` is a component of a transactionID
|
||||
self._pending.forEach(function(pending) {
|
||||
var shouldAdjust = pending._server === server
|
||||
&& self._remote.local_fee && pending.tx_json.Fee;
|
||||
if (pending._server !== server) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shouldAdjust) return;
|
||||
if (!(self._remote.local_fee && pending.tx_json.Fee)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var oldFee = pending.tx_json.Fee;
|
||||
var newFee = server.computeFee(pending);
|
||||
@@ -69,7 +77,9 @@ function TransactionManager(account) {
|
||||
pending.tx_json.Fee = 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) {
|
||||
case 8:
|
||||
pending.emit('lost', ledger);
|
||||
self._remote._trace('transactionmanager: update_pending:', pending.tx_json);
|
||||
break;
|
||||
case 4:
|
||||
pending.emit('missing', ledger);
|
||||
@@ -106,7 +115,7 @@ function TransactionManager(account) {
|
||||
binary: true,
|
||||
limit: 100,
|
||||
filter: 'outbound'
|
||||
}
|
||||
};
|
||||
|
||||
function accountTx(err, transactions) {
|
||||
if (!err && Array.isArray(transactions.transactions)) {
|
||||
@@ -116,9 +125,7 @@ function TransactionManager(account) {
|
||||
self._remote.on('ledger_closed', updatePendingStatus);
|
||||
|
||||
//Load next transaction sequence
|
||||
self._loadSequence(function sequenceLoaded() {
|
||||
self._resubmit();
|
||||
});
|
||||
self._loadSequence(self._resubmit.bind(self));
|
||||
|
||||
callback();
|
||||
};
|
||||
@@ -149,29 +156,40 @@ util.inherits(TransactionManager, EventEmitter);
|
||||
//Normalize transactions received from account
|
||||
//transaction stream and account_tx
|
||||
TransactionManager.normalizeTransaction = function(tx) {
|
||||
var transaction = tx;
|
||||
var transaction = { };
|
||||
|
||||
Object.keys(tx).forEach(function(key) {
|
||||
transaction[key] = tx[key];
|
||||
});
|
||||
|
||||
if (!tx.engine_result) {
|
||||
// account_tx
|
||||
transaction = {
|
||||
engine_result: tx.meta.TransactionResult,
|
||||
transaction: tx.tx,
|
||||
tx_json: tx.tx,
|
||||
hash: tx.tx.hash,
|
||||
ledger_index: tx.tx.ledger_index,
|
||||
meta: tx.meta,
|
||||
type: 'transaction',
|
||||
validated: true
|
||||
}
|
||||
};
|
||||
|
||||
transaction.result = transaction.engine_result;
|
||||
transaction.result_message = transaction.engine_result_message;
|
||||
}
|
||||
|
||||
if (!transaction.metadata) {
|
||||
transaction.metadata = transaction.meta;
|
||||
}
|
||||
|
||||
if (!transaction.tx_json) {
|
||||
transaction.tx_json = transaction.transaction;
|
||||
}
|
||||
|
||||
delete transaction.transaction;
|
||||
delete transaction.mmeta;
|
||||
delete transaction.meta;
|
||||
|
||||
return transaction;
|
||||
};
|
||||
|
||||
@@ -202,7 +220,9 @@ TransactionManager.prototype._fillSequence = function(tx, callback) {
|
||||
var submitted = 0;
|
||||
|
||||
;(function nextFill(sequence) {
|
||||
if (sequence >= tx.tx_json.Sequence) return;
|
||||
if (sequence >= tx.tx_json.Sequence) {
|
||||
return;
|
||||
}
|
||||
|
||||
submitFill(sequence, function() {
|
||||
if (++submitted === sequenceDif) {
|
||||
@@ -250,7 +270,9 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
|
||||
|
||||
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) {
|
||||
return pending.emit('success', hashCached);
|
||||
@@ -259,7 +281,9 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
|
||||
while (self._pending.hasSequence(pending.tx_json.Sequence)) {
|
||||
//Sequence number has been consumed by another transaction
|
||||
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);
|
||||
@@ -269,14 +293,18 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
|
||||
;(function nextTransaction(i) {
|
||||
var transaction = pending[i];
|
||||
|
||||
if (!(transaction instanceof Transaction)) return;
|
||||
if (!(transaction instanceof Transaction)) {
|
||||
return;
|
||||
}
|
||||
|
||||
transaction.once('submitted', function(m) {
|
||||
transaction.emit('resubmitted', m);
|
||||
|
||||
self._loadSequence();
|
||||
|
||||
if (++i < pending.length) nextTransaction(i);
|
||||
if (++i < pending.length) {
|
||||
nextTransaction(i);
|
||||
}
|
||||
});
|
||||
|
||||
resubmitTransaction(transaction);
|
||||
@@ -287,16 +315,20 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
|
||||
};
|
||||
|
||||
TransactionManager.prototype._waitLedgers = function(ledgers, callback) {
|
||||
if (ledgers < 1) return callback();
|
||||
if (ledgers < 1) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var closes = 0;
|
||||
|
||||
function ledgerClosed() {
|
||||
if (++closes === ledgers) {
|
||||
if (++closes < ledgers) {
|
||||
return;
|
||||
}
|
||||
|
||||
self._remote.removeListener('ledger_closed', ledgerClosed);
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
this._remote.on('ledger_closed', ledgerClosed);
|
||||
@@ -326,19 +358,30 @@ TransactionManager.prototype._request = function(tx) {
|
||||
|
||||
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) {
|
||||
if (tx.finalized) return;
|
||||
if (tx.finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If server is honest, don't expect a final if rejected.
|
||||
message.rejected = tx.isRejected(message.engine_result_code);
|
||||
|
||||
tx.emit('proposed', message);
|
||||
};
|
||||
|
||||
function transactionFailed(message) {
|
||||
if (tx.finalized) return;
|
||||
if (tx.finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.engine_result) {
|
||||
case 'tefPAST_SEQ':
|
||||
self._resubmit(1, tx);
|
||||
@@ -349,7 +392,9 @@ TransactionManager.prototype._request = function(tx) {
|
||||
};
|
||||
|
||||
function transactionRetry(message) {
|
||||
if (tx.finalized) return;
|
||||
if (tx.finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
self._fillSequence(tx, function() {
|
||||
self._resubmit(1, tx);
|
||||
@@ -357,17 +402,19 @@ TransactionManager.prototype._request = function(tx) {
|
||||
};
|
||||
|
||||
function transactionFeeClaimed(message) {
|
||||
if (tx.finalized) return;
|
||||
if (tx.finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
tx.emit('error', message);
|
||||
};
|
||||
|
||||
function transactionFailedLocal(message) {
|
||||
if (tx.finalized) return;
|
||||
if (tx.finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
var shouldAdjustFee = self._remote.local_fee
|
||||
&& (message.engine_result === 'telINSUF_FEE_P');
|
||||
|
||||
if (shouldAdjustFee) {
|
||||
if (self._remote.local_fee && (message.engine_result === 'telINSUF_FEE_P')) {
|
||||
self._resubmit(1, tx);
|
||||
} else {
|
||||
submissionError(message);
|
||||
@@ -376,7 +423,9 @@ TransactionManager.prototype._request = function(tx) {
|
||||
|
||||
function submissionError(error) {
|
||||
// Finalized (e.g. aborted) transactions must stop all activity
|
||||
if (tx.finalized) return;
|
||||
if (tx.finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (TransactionManager._isTooBusy(error)) {
|
||||
self._resubmit(1, tx);
|
||||
@@ -388,7 +437,9 @@ TransactionManager.prototype._request = function(tx) {
|
||||
|
||||
function submitted(message) {
|
||||
// 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
|
||||
// an extra measure.
|
||||
@@ -400,7 +451,9 @@ TransactionManager.prototype._request = function(tx) {
|
||||
|
||||
tx.result = message;
|
||||
|
||||
remote._trace('transactionmanager: submit_response:', message);
|
||||
if (remote.trace) {
|
||||
log.info('submit response:', message);
|
||||
}
|
||||
|
||||
tx.emit('submitted', message);
|
||||
|
||||
@@ -480,18 +533,24 @@ TransactionManager.prototype._request = function(tx) {
|
||||
// that ALL transactionIDs sent over network are tracked.
|
||||
|
||||
// Finalized (e.g. aborted) transactions must stop all activity
|
||||
if (tx.finalized) return;
|
||||
if (tx.finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
tx.emit('timeout');
|
||||
|
||||
if (remote._connected) {
|
||||
remote._trace('transactionmanager: timeout:', tx.tx_json);
|
||||
if (remote.trace) {
|
||||
log.info('timeout:', tx.tx_json);
|
||||
}
|
||||
self._resubmit(3, tx);
|
||||
}
|
||||
};
|
||||
|
||||
function submitTransaction() {
|
||||
if (tx.finalized) return;
|
||||
if (tx.finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
submitRequest.timeout(self._submissionTimeout, requestTimeout);
|
||||
submitRequest.request();
|
||||
@@ -557,22 +616,23 @@ TransactionManager.prototype.submit = function(tx) {
|
||||
var remote = this._remote;
|
||||
|
||||
// If sequence number is not yet known, defer until it is.
|
||||
if (typeof this._nextSequence === 'undefined') {
|
||||
function sequenceLoaded() {
|
||||
self.submit(tx);
|
||||
};
|
||||
this.once('sequence_loaded', sequenceLoaded);
|
||||
if (typeof this._nextSequence !== 'number') {
|
||||
this.once('sequence_loaded', this.submit.bind(this, tx));
|
||||
return;
|
||||
}
|
||||
|
||||
// Finalized (e.g. aborted) transactions must stop all activity
|
||||
if (tx.finalized) return;
|
||||
if (tx.finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
function cleanup(message) {
|
||||
// ND: We can just remove this `tx` by identity
|
||||
self._pending.remove(tx);
|
||||
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);
|
||||
|
||||
@@ -3,27 +3,12 @@
|
||||
* Manager for pending transactions
|
||||
*/
|
||||
|
||||
var Transaction = require('./transaction').Transaction;
|
||||
var LRU = require('lru-cache');
|
||||
|
||||
function TransactionQueue() {
|
||||
var self = this;
|
||||
|
||||
this._queue = [ ];
|
||||
this._idCache = LRU({ max: 100 });
|
||||
this._sequenceCache = LRU({ max: 100 });
|
||||
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
|
||||
}
|
||||
}));
|
||||
this._idCache = LRU();
|
||||
this._sequenceCache = LRU();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -64,10 +49,10 @@ TransactionQueue.prototype.hasSequence = function(sequence) {
|
||||
* may have multiple associated IDs.
|
||||
*/
|
||||
|
||||
TransactionQueue.prototype.getSubmission = function(id, callback) {
|
||||
TransactionQueue.prototype.getSubmission = function(id) {
|
||||
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)) {
|
||||
result = tx;
|
||||
break;
|
||||
@@ -91,20 +76,18 @@ TransactionQueue.prototype.remove = function(tx) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.save();
|
||||
};
|
||||
|
||||
TransactionQueue.prototype.push = function(tx) {
|
||||
this._queue.push(tx);
|
||||
this.save();
|
||||
};
|
||||
|
||||
TransactionQueue.prototype.forEach = function(fn) {
|
||||
this._queue.forEach(fn);
|
||||
};
|
||||
|
||||
TransactionQueue.prototype.length = function() {
|
||||
TransactionQueue.prototype.length =
|
||||
TransactionQueue.prototype.getLength = function() {
|
||||
return this._queue.length;
|
||||
};
|
||||
|
||||
|
||||
@@ -4,12 +4,10 @@ var config = require('./config');
|
||||
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
var Base = require('./base').Base;
|
||||
|
||||
//
|
||||
// Abstract UInt class
|
||||
//
|
||||
// Base class for UInt??? classes
|
||||
// Base class for UInt classes
|
||||
//
|
||||
|
||||
var UInt = function() {
|
||||
@@ -98,7 +96,9 @@ UInt.prototype.clone = function () {
|
||||
UInt.prototype.copyTo = function(d) {
|
||||
d._value = this._value;
|
||||
|
||||
if ("function" === typeof d._update) d._update();
|
||||
if (typeof d._update === 'function') {
|
||||
d._update();
|
||||
}
|
||||
|
||||
return d;
|
||||
};
|
||||
@@ -132,38 +132,35 @@ UInt.prototype._update = function () {
|
||||
// value = NaN on error.
|
||||
UInt.prototype.parse_generic = function(j) {
|
||||
// Canonicalize and validate
|
||||
if (config.accounts && j in config.accounts)
|
||||
if (config.accounts && (j in config.accounts)) {
|
||||
j = config.accounts[j].account;
|
||||
}
|
||||
|
||||
switch (j) {
|
||||
case undefined:
|
||||
case "0":
|
||||
case '0':
|
||||
case this.constructor.STR_ZERO:
|
||||
case this.constructor.ACCOUNT_ZERO:
|
||||
case this.constructor.HEX_ZERO:
|
||||
this._value = BigInteger.valueOf();
|
||||
break;
|
||||
|
||||
case "1":
|
||||
case '1':
|
||||
case this.constructor.STR_ONE:
|
||||
case this.constructor.ACCOUNT_ONE:
|
||||
case this.constructor.HEX_ONE:
|
||||
this._value = new BigInteger([1]);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if ('string' !== typeof j) {
|
||||
if (typeof j !== 'string') {
|
||||
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);
|
||||
}
|
||||
else if ((this.constructor.width*2) === j.length) {
|
||||
} else if ((this.constructor.width * 2) === j.length) {
|
||||
// XXX Check char set!
|
||||
this._value = new BigInteger(j, 16);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this._value = NaN;
|
||||
}
|
||||
}
|
||||
@@ -174,8 +171,7 @@ UInt.prototype.parse_generic = function (j) {
|
||||
};
|
||||
|
||||
UInt.prototype.parse_hex = function(j) {
|
||||
if ('string' === typeof j &&
|
||||
j.length === (this.constructor.width * 2)) {
|
||||
if (typeof j === 'string' && j.length === (this.constructor.width * 2)) {
|
||||
this._value = new BigInteger(j, 16);
|
||||
} else {
|
||||
this._value = NaN;
|
||||
@@ -216,8 +212,7 @@ UInt.prototype.parse_bytes = function (j) {
|
||||
UInt.prototype.parse_json = UInt.prototype.parse_hex;
|
||||
|
||||
UInt.prototype.parse_bn = function(j) {
|
||||
if (j instanceof sjcl.bn &&
|
||||
j.bitLength() <= this.constructor.width * 8) {
|
||||
if ((j instanceof sjcl.bn) && j.bitLength() <= this.constructor.width * 8) {
|
||||
var bytes = sjcl.codec.bytes.fromBits(j.toBits());
|
||||
this._value = new BigInteger(bytes, 256);
|
||||
} else {
|
||||
@@ -232,11 +227,8 @@ UInt.prototype.parse_bn = function (j) {
|
||||
UInt.prototype.parse_number = function(j) {
|
||||
this._value = NaN;
|
||||
|
||||
if ("number" === typeof j &&
|
||||
j === +j &&
|
||||
j >= 0) {
|
||||
// XXX Better, faster way to get BigInteger from JS int?
|
||||
this._value = new BigInteger(""+j);
|
||||
if (typeof j === 'number' && isFinite(j) && j >= 0) {
|
||||
this._value = new BigInteger(String(j));
|
||||
}
|
||||
|
||||
this._update();
|
||||
@@ -246,23 +238,32 @@ UInt.prototype.parse_number = function (j) {
|
||||
|
||||
// Convert from internal form.
|
||||
UInt.prototype.to_bytes = function() {
|
||||
if (!(this._value instanceof BigInteger))
|
||||
if (!(this._value instanceof BigInteger)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// XXX Make sure only trim off leading zeros.
|
||||
bytes = bytes.slice(-target);
|
||||
while (bytes.length < target) bytes.unshift(0);
|
||||
|
||||
while (bytes.length < target) {
|
||||
bytes.unshift(0);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
};
|
||||
|
||||
UInt.prototype.to_hex = function() {
|
||||
if (!(this._value instanceof BigInteger))
|
||||
if (!(this._value instanceof BigInteger)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bytes = this.to_bytes();
|
||||
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(bytes)).toUpperCase();
|
||||
@@ -271,8 +272,9 @@ UInt.prototype.to_hex = function () {
|
||||
UInt.prototype.to_json = UInt.prototype.to_hex;
|
||||
|
||||
UInt.prototype.to_bits = function() {
|
||||
if (!(this._value instanceof BigInteger))
|
||||
if (!(this._value instanceof BigInteger)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bytes = this.to_bytes();
|
||||
|
||||
@@ -280,8 +282,9 @@ UInt.prototype.to_bits = function () {
|
||||
};
|
||||
|
||||
UInt.prototype.to_bn = function() {
|
||||
if (!(this._value instanceof BigInteger))
|
||||
if (!(this._value instanceof BigInteger)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bits = this.to_bits();
|
||||
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
var sjcl = require('./utils').sjcl;
|
||||
var utils = require('./utils');
|
||||
var config = require('./config');
|
||||
var extend = require('extend');
|
||||
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
var UInt = require('./uint').UInt,
|
||||
Base = require('./base').Base;
|
||||
var UInt = require('./uint').UInt;
|
||||
|
||||
//
|
||||
// UInt128 support
|
||||
@@ -21,8 +15,8 @@ UInt128.width = 16;
|
||||
UInt128.prototype = extend({}, UInt.prototype);
|
||||
UInt128.prototype.constructor = UInt128;
|
||||
|
||||
var HEX_ZERO = UInt128.HEX_ZERO = "00000000000000000000000000000000";
|
||||
var HEX_ONE = UInt128.HEX_ONE = "00000000000000000000000000000000";
|
||||
var HEX_ZERO = UInt128.HEX_ZERO = '00000000000000000000000000000000';
|
||||
var HEX_ONE = UInt128.HEX_ONE = '00000000000000000000000000000000';
|
||||
var STR_ZERO = UInt128.STR_ZERO = utils.hexToString(HEX_ZERO);
|
||||
var STR_ONE = UInt128.STR_ONE = utils.hexToString(HEX_ONE);
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
var sjcl = require('./utils').sjcl;
|
||||
var utils = require('./utils');
|
||||
var config = require('./config');
|
||||
var extend = require('extend');
|
||||
@@ -16,7 +15,6 @@ var UInt160 = extend(function () {
|
||||
// Internal form: NaN or BigInteger
|
||||
this._value = NaN;
|
||||
this._version_byte = void(0);
|
||||
|
||||
this._update();
|
||||
}, UInt);
|
||||
|
||||
@@ -33,7 +31,6 @@ var STR_ONE = UInt160.STR_ONE = utils.hexToString(HEX_ONE);
|
||||
|
||||
UInt160.prototype.set_version = function(j) {
|
||||
this._version_byte = j;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -44,7 +41,7 @@ UInt160.prototype.get_version = function () {
|
||||
// value = NaN on error.
|
||||
UInt160.prototype.parse_json = function(j) {
|
||||
// Canonicalize and validate
|
||||
if (config.accounts && j in config.accounts) {
|
||||
if (config.accounts && (j in config.accounts)) {
|
||||
j = config.accounts[j].account;
|
||||
}
|
||||
|
||||
@@ -72,7 +69,7 @@ UInt160.prototype.parse_generic = function (j) {
|
||||
UInt.prototype.parse_generic.call(this, j);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -88,8 +85,9 @@ UInt160.prototype.to_json = function (opts) {
|
||||
|
||||
if (this._value instanceof BigInteger) {
|
||||
// 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());
|
||||
|
||||
if (opts.gateways && output in opts.gateways) {
|
||||
output = opts.gateways[output];
|
||||
}
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
var sjcl = require('./utils').sjcl;
|
||||
var utils = require('./utils');
|
||||
var config = require('./config');
|
||||
var extend = require('extend');
|
||||
|
||||
var BigInteger = utils.jsbn.BigInteger;
|
||||
|
||||
var UInt = require('./uint').UInt,
|
||||
Base = require('./base').Base;
|
||||
var UInt = require('./uint').UInt;
|
||||
|
||||
//
|
||||
// UInt256 support
|
||||
@@ -21,10 +15,8 @@ UInt256.width = 32;
|
||||
UInt256.prototype = extend({}, UInt.prototype);
|
||||
UInt256.prototype.constructor = UInt256;
|
||||
|
||||
var HEX_ZERO = UInt256.HEX_ZERO = "00000000000000000000000000000000" +
|
||||
"00000000000000000000000000000000";
|
||||
var HEX_ONE = UInt256.HEX_ONE = "00000000000000000000000000000000" +
|
||||
"00000000000000000000000000000001";
|
||||
var HEX_ZERO = UInt256.HEX_ZERO = '00000000000000000000000000000000' + '00000000000000000000000000000000';
|
||||
var HEX_ONE = UInt256.HEX_ONE = '00000000000000000000000000000000' + '00000000000000000000000000000001';
|
||||
var STR_ZERO = UInt256.STR_ZERO = utils.hexToString(HEX_ZERO);
|
||||
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) {
|
||||
return function(e) {
|
||||
done(e.code !== code ? e : void(0));
|
||||
@@ -20,7 +15,7 @@ function throwErr(done) {
|
||||
|
||||
function trace(comment, func) {
|
||||
return function() {
|
||||
console.log("%s: %s", trace, arguments.toString);
|
||||
console.log('%s: %s', trace, arguments.toString);
|
||||
func(arguments);
|
||||
};
|
||||
};
|
||||
@@ -94,7 +89,7 @@ function chunkString(str, n, leftAlign) {
|
||||
|
||||
function assert(assertion, msg) {
|
||||
if (!assertion) {
|
||||
throw new Error("Assertion failed" + (msg ? ": "+msg : "."));
|
||||
throw new Error('Assertion failed' + (msg ? ': ' + msg : '.'));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user