mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 20:25:48 +00:00
Merge pull request #133 from ripple/develop
Track unfunded orders in the orderbook
This commit is contained in:
@@ -160,150 +160,55 @@ Amount.prototype.add = function(v) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
// Result in terms of this currency and issuer.
|
||||||
* Turn this amount into its inverse.
|
Amount.prototype.subtract = function(v) {
|
||||||
*
|
// Correctness over speed, less code has less bugs, reuse add code.
|
||||||
* @private
|
return this.add(Amount.from_json(v).negate());
|
||||||
*/
|
|
||||||
Amount.prototype._invert = function() {
|
|
||||||
this._value = consts.bi_1e32.divide(this._value);
|
|
||||||
this._offset = -32 - this._offset;
|
|
||||||
this.canonicalize();
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
// Result in terms of this' currency and issuer.
|
||||||
* Return the inverse of this amount.
|
// XXX Diverges from cpp.
|
||||||
*
|
Amount.prototype.multiply = function(v) {
|
||||||
* @return {Amount} New Amount object with same currency and issuer, but the
|
|
||||||
* inverse of the value.
|
|
||||||
*/
|
|
||||||
Amount.prototype.invert = function() {
|
|
||||||
return this.copy()._invert();
|
|
||||||
};
|
|
||||||
|
|
||||||
Amount.prototype.canonicalize = function() {
|
|
||||||
if (!(this._value instanceof BigInteger)) {
|
|
||||||
// NaN.
|
|
||||||
// nothing
|
|
||||||
} else if (this._is_native) {
|
|
||||||
// Native.
|
|
||||||
if (this._value.equals(BigInteger.ZERO)) {
|
|
||||||
this._offset = 0;
|
|
||||||
this._is_negative = false;
|
|
||||||
} else {
|
|
||||||
// Normalize _offset to 0.
|
|
||||||
|
|
||||||
while (this._offset < 0) {
|
|
||||||
this._value = this._value.divide(consts.bi_10);
|
|
||||||
this._offset += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (this._offset > 0) {
|
|
||||||
this._value = this._value.multiply(consts.bi_10);
|
|
||||||
this._offset -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX Make sure not bigger than supported. Throw if so.
|
|
||||||
} else if (this.is_zero()) {
|
|
||||||
this._offset = -100;
|
|
||||||
this._is_negative = false;
|
|
||||||
} else {
|
|
||||||
// Normalize mantissa to valid range.
|
|
||||||
|
|
||||||
while (this._value.compareTo(consts.bi_man_min_value) < 0) {
|
|
||||||
this._value = this._value.multiply(consts.bi_10);
|
|
||||||
this._offset -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (this._value.compareTo(consts.bi_man_max_value) > 0) {
|
|
||||||
this._value = this._value.divide(consts.bi_10);
|
|
||||||
this._offset += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Amount.prototype.clone = function(negate) {
|
|
||||||
return this.copyTo(new Amount(), negate);
|
|
||||||
};
|
|
||||||
|
|
||||||
Amount.prototype.compareTo = function(v) {
|
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
if (!this.is_comparable(v)) {
|
v = Amount.from_json(v);
|
||||||
result = Amount.NaN();
|
|
||||||
} else if (this._is_negative !== v._is_negative) {
|
if (this.is_zero()) {
|
||||||
// Different sign.
|
result = this;
|
||||||
result = this._is_negative ? -1 : 1;
|
} else if (v.is_zero()) {
|
||||||
} else if (this._value.equals(BigInteger.ZERO)) {
|
result = this.clone();
|
||||||
// Same sign: positive.
|
result._value = BigInteger.ZERO;
|
||||||
result = v._value.equals(BigInteger.ZERO) ? 0 : -1;
|
|
||||||
} else if (v._value.equals(BigInteger.ZERO)) {
|
|
||||||
// Same sign: positive.
|
|
||||||
result = 1;
|
|
||||||
} else if (!this._is_native && this._offset > v._offset) {
|
|
||||||
result = this._is_negative ? -1 : 1;
|
|
||||||
} else if (!this._is_native && this._offset < v._offset) {
|
|
||||||
result = this._is_negative ? 1 : -1;
|
|
||||||
} else {
|
} else {
|
||||||
result = this._value.compareTo(v._value);
|
var v1 = this._value;
|
||||||
if (result > 0) {
|
var o1 = this._offset;
|
||||||
result = this._is_negative ? -1 : 1;
|
var v2 = v._value;
|
||||||
} else if (result < 0) {
|
var o2 = v._offset;
|
||||||
result = this._is_negative ? 1 : -1;
|
|
||||||
|
if (this.is_native()) {
|
||||||
|
while (v1.compareTo(consts.bi_man_min_value) < 0) {
|
||||||
|
v1 = v1.multiply(consts.bi_10);
|
||||||
|
o1 -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
if (v.is_native()) {
|
||||||
};
|
while (v2.compareTo(consts.bi_man_min_value) < 0) {
|
||||||
|
v2 = v2.multiply(consts.bi_10);
|
||||||
// Make d a copy of this. Returns d.
|
o2 -= 1;
|
||||||
// Modification of objects internally refered to is not allowed.
|
}
|
||||||
Amount.prototype.copyTo = function(d, negate) {
|
|
||||||
if (typeof this._value === 'object') {
|
|
||||||
this._value.copyTo(d._value);
|
|
||||||
} else {
|
|
||||||
d._value = this._value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d._offset = this._offset;
|
result = new Amount();
|
||||||
d._is_native = this._is_native;
|
result._offset = o1 + o2 + 14;
|
||||||
d._is_negative = negate
|
result._value = v1.multiply(v2).divide(consts.bi_1e14).add(consts.bi_7);
|
||||||
? !this._is_negative // Negating.
|
result._is_native = this._is_native;
|
||||||
: this._is_negative; // Just copying.
|
result._is_negative = this._is_negative !== v._is_negative;
|
||||||
|
result._currency = this._currency;
|
||||||
|
result._issuer = this._issuer;
|
||||||
|
|
||||||
d._currency = this._currency;
|
result.canonicalize();
|
||||||
d._issuer = this._issuer;
|
|
||||||
|
|
||||||
// Prevent negative zero
|
|
||||||
if (d.is_zero()) {
|
|
||||||
d._is_negative = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return d;
|
|
||||||
};
|
|
||||||
|
|
||||||
Amount.prototype.currency = function() {
|
|
||||||
return this._currency;
|
|
||||||
};
|
|
||||||
|
|
||||||
Amount.prototype.equals = function(d, ignore_issuer) {
|
|
||||||
if (typeof d === 'string') {
|
|
||||||
return this.equals(Amount.from_json(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = true;
|
|
||||||
|
|
||||||
result = !((!this.is_valid() || !d.is_valid())
|
|
||||||
|| (this._is_native !== d._is_native)
|
|
||||||
|| (!this._value.equals(d._value) || this._offset !== d._offset)
|
|
||||||
|| (this._is_negative !== d._is_negative)
|
|
||||||
|| (!this._is_native && (!this._currency.equals(d._currency) || !ignore_issuer && !this._issuer.equals(d._issuer))));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -311,6 +216,8 @@ Amount.prototype.equals = function(d, ignore_issuer) {
|
|||||||
Amount.prototype.divide = function(d) {
|
Amount.prototype.divide = function(d) {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
|
d = Amount.from_json(d);
|
||||||
|
|
||||||
if (d.is_zero()) {
|
if (d.is_zero()) {
|
||||||
throw new Error('divide by zero');
|
throw new Error('divide by zero');
|
||||||
}
|
}
|
||||||
@@ -359,8 +266,6 @@ Amount.prototype.divide = function(d) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate a ratio between two amounts.
|
|
||||||
*
|
|
||||||
* This function calculates a ratio - such as a price - between two Amount
|
* This function calculates a ratio - such as a price - between two Amount
|
||||||
* objects.
|
* objects.
|
||||||
*
|
*
|
||||||
@@ -382,14 +287,15 @@ Amount.prototype.divide = function(d) {
|
|||||||
Amount.prototype.ratio_human = function(denominator, opts) {
|
Amount.prototype.ratio_human = function(denominator, opts) {
|
||||||
opts = extend({ }, opts);
|
opts = extend({ }, opts);
|
||||||
|
|
||||||
|
var numerator = this;
|
||||||
|
|
||||||
if (typeof denominator === 'number' && parseInt(denominator, 10) === denominator) {
|
if (typeof denominator === 'number' && parseInt(denominator, 10) === denominator) {
|
||||||
// Special handling of integer arguments
|
// Special handling of integer arguments
|
||||||
denominator = Amount.from_json('' + denominator + '.0');
|
denominator = Amount.from_json(String(denominator) + '.0');
|
||||||
} else {
|
} else {
|
||||||
denominator = Amount.from_json(denominator);
|
denominator = Amount.from_json(denominator);
|
||||||
}
|
}
|
||||||
|
|
||||||
var numerator = this;
|
|
||||||
denominator = Amount.from_json(denominator);
|
denominator = Amount.from_json(denominator);
|
||||||
|
|
||||||
// If either operand is NaN, the result is NaN.
|
// If either operand is NaN, the result is NaN.
|
||||||
@@ -397,6 +303,10 @@ Amount.prototype.ratio_human = function(denominator, opts) {
|
|||||||
return Amount.NaN();
|
return Amount.NaN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (denominator.is_zero()) {
|
||||||
|
return Amount.NaN();
|
||||||
|
}
|
||||||
|
|
||||||
// Apply interest/demurrage
|
// Apply interest/demurrage
|
||||||
//
|
//
|
||||||
// We only need to apply it to the second factor, because the currency unit of
|
// We only need to apply it to the second factor, because the currency unit of
|
||||||
@@ -482,6 +392,155 @@ Amount.prototype.product_human = function(factor, opts) {
|
|||||||
return product;
|
return product;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn this amount into its inverse.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
Amount.prototype._invert = function() {
|
||||||
|
this._value = consts.bi_1e32.divide(this._value);
|
||||||
|
this._offset = -32 - this._offset;
|
||||||
|
this.canonicalize();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the inverse of this amount.
|
||||||
|
*
|
||||||
|
* @return {Amount} New Amount object with same currency and issuer, but the
|
||||||
|
* inverse of the value.
|
||||||
|
*/
|
||||||
|
Amount.prototype.invert = function() {
|
||||||
|
return this.copy()._invert();
|
||||||
|
};
|
||||||
|
|
||||||
|
Amount.prototype.canonicalize = function() {
|
||||||
|
if (!(this._value instanceof BigInteger)) {
|
||||||
|
// NaN.
|
||||||
|
// nothing
|
||||||
|
} else if (this._is_native) {
|
||||||
|
// Native.
|
||||||
|
if (this._value.equals(BigInteger.ZERO)) {
|
||||||
|
this._offset = 0;
|
||||||
|
this._is_negative = false;
|
||||||
|
} else {
|
||||||
|
// Normalize _offset to 0.
|
||||||
|
|
||||||
|
while (this._offset < 0) {
|
||||||
|
this._value = this._value.divide(consts.bi_10);
|
||||||
|
this._offset += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (this._offset > 0) {
|
||||||
|
this._value = this._value.multiply(consts.bi_10);
|
||||||
|
this._offset -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX Make sure not bigger than supported. Throw if so.
|
||||||
|
} else if (this.is_zero()) {
|
||||||
|
this._offset = -100;
|
||||||
|
this._is_negative = false;
|
||||||
|
} else {
|
||||||
|
// Normalize mantissa to valid range.
|
||||||
|
|
||||||
|
while (this._value.compareTo(consts.bi_man_min_value) < 0) {
|
||||||
|
this._value = this._value.multiply(consts.bi_10);
|
||||||
|
this._offset -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (this._value.compareTo(consts.bi_man_max_value) > 0) {
|
||||||
|
this._value = this._value.divide(consts.bi_10);
|
||||||
|
this._offset += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amount.prototype.clone = function(negate) {
|
||||||
|
return this.copyTo(new Amount(), negate);
|
||||||
|
};
|
||||||
|
|
||||||
|
Amount.prototype.compareTo = function(v) {
|
||||||
|
var result;
|
||||||
|
|
||||||
|
v = Amount.from_json(v);
|
||||||
|
|
||||||
|
if (!this.is_comparable(v)) {
|
||||||
|
result = Amount.NaN();
|
||||||
|
} else if (this._is_negative !== v._is_negative) {
|
||||||
|
// Different sign.
|
||||||
|
result = this._is_negative ? -1 : 1;
|
||||||
|
} else if (this._value.equals(BigInteger.ZERO)) {
|
||||||
|
// Same sign: positive.
|
||||||
|
result = v._value.equals(BigInteger.ZERO) ? 0 : -1;
|
||||||
|
} else if (v._value.equals(BigInteger.ZERO)) {
|
||||||
|
// Same sign: positive.
|
||||||
|
result = 1;
|
||||||
|
} else if (!this._is_native && this._offset > v._offset) {
|
||||||
|
result = this._is_negative ? -1 : 1;
|
||||||
|
} else if (!this._is_native && this._offset < v._offset) {
|
||||||
|
result = this._is_negative ? 1 : -1;
|
||||||
|
} else {
|
||||||
|
result = this._value.compareTo(v._value);
|
||||||
|
if (result > 0) {
|
||||||
|
result = this._is_negative ? -1 : 1;
|
||||||
|
} else if (result < 0) {
|
||||||
|
result = this._is_negative ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make d a copy of this. Returns d.
|
||||||
|
// Modification of objects internally refered to is not allowed.
|
||||||
|
Amount.prototype.copyTo = function(d, negate) {
|
||||||
|
if (typeof this._value === 'object') {
|
||||||
|
this._value.copyTo(d._value);
|
||||||
|
} else {
|
||||||
|
d._value = this._value;
|
||||||
|
}
|
||||||
|
|
||||||
|
d._offset = this._offset;
|
||||||
|
d._is_native = this._is_native;
|
||||||
|
d._is_negative = negate
|
||||||
|
? !this._is_negative // Negating.
|
||||||
|
: this._is_negative; // Just copying.
|
||||||
|
|
||||||
|
d._currency = this._currency;
|
||||||
|
d._issuer = this._issuer;
|
||||||
|
|
||||||
|
// Prevent negative zero
|
||||||
|
if (d.is_zero()) {
|
||||||
|
d._is_negative = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amount.prototype.currency = function() {
|
||||||
|
return this._currency;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amount.prototype.equals = function(d, ignore_issuer) {
|
||||||
|
if (typeof d === 'string') {
|
||||||
|
return this.equals(Amount.from_json(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = true;
|
||||||
|
|
||||||
|
result = !((!this.is_valid() || !d.is_valid())
|
||||||
|
|| (this._is_native !== d._is_native)
|
||||||
|
|| (!this._value.equals(d._value) || this._offset !== d._offset)
|
||||||
|
|| (this._is_negative !== d._is_negative)
|
||||||
|
|| (!this._is_native && (!this._currency.equals(d._currency) || !ignore_issuer && !this._issuer.equals(d._issuer))));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
// 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
|
||||||
@@ -520,50 +579,6 @@ Amount.prototype.issuer = function() {
|
|||||||
return this._issuer;
|
return this._issuer;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Result in terms of this' currency and issuer.
|
|
||||||
// XXX Diverges from cpp.
|
|
||||||
Amount.prototype.multiply = function(v) {
|
|
||||||
var result;
|
|
||||||
|
|
||||||
if (this.is_zero()) {
|
|
||||||
result = this;
|
|
||||||
} else if (v.is_zero()) {
|
|
||||||
result = this.clone();
|
|
||||||
result._value = BigInteger.ZERO;
|
|
||||||
} else {
|
|
||||||
var v1 = this._value;
|
|
||||||
var o1 = this._offset;
|
|
||||||
var v2 = v._value;
|
|
||||||
var o2 = v._offset;
|
|
||||||
|
|
||||||
if (this.is_native()) {
|
|
||||||
while (v1.compareTo(consts.bi_man_min_value) < 0) {
|
|
||||||
v1 = v1.multiply(consts.bi_10);
|
|
||||||
o1 -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v.is_native()) {
|
|
||||||
while (v2.compareTo(consts.bi_man_min_value) < 0) {
|
|
||||||
v2 = v2.multiply(consts.bi_10);
|
|
||||||
o2 -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = new Amount();
|
|
||||||
result._offset = o1 + o2 + 14;
|
|
||||||
result._value = v1.multiply(v2).divide(consts.bi_1e14).add(consts.bi_7);
|
|
||||||
result._is_native = this._is_native;
|
|
||||||
result._is_negative = this._is_negative !== v._is_negative;
|
|
||||||
result._currency = this._currency;
|
|
||||||
result._issuer = this._issuer;
|
|
||||||
|
|
||||||
result.canonicalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Return a new value.
|
// Return a new value.
|
||||||
Amount.prototype.negate = function() {
|
Amount.prototype.negate = function() {
|
||||||
return this.clone('NEGATE');
|
return this.clone('NEGATE');
|
||||||
@@ -953,12 +968,6 @@ Amount.prototype.set_issuer = function(issuer) {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Result in terms of this' currency and issuer.
|
|
||||||
Amount.prototype.subtract = function(v) {
|
|
||||||
// Correctness over speed, less code has less bugs, reuse add code.
|
|
||||||
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;
|
||||||
|
|||||||
@@ -5,47 +5,51 @@ var Amount = require('./amount').Amount;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Meta data processing facility
|
* Meta data processing facility
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} transaction metadata
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Meta(raw_data) {
|
function Meta(data) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.nodes = [ ];
|
this.nodes = [ ];
|
||||||
|
|
||||||
raw_data.AffectedNodes.forEach(function(an) {
|
if (typeof data !== 'object') {
|
||||||
var result = { };
|
throw new TypeError('Missing metadata');
|
||||||
|
|
||||||
if ((result.diffType = self.diffType(an))) {
|
|
||||||
an = an[result.diffType];
|
|
||||||
|
|
||||||
result.entryType = an.LedgerEntryType;
|
|
||||||
result.ledgerIndex = an.LedgerIndex;
|
|
||||||
result.fields = extend({}, an.PreviousFields, an.NewFields, an.FinalFields);
|
|
||||||
result.fieldsPrev = an.PreviousFields || {};
|
|
||||||
result.fieldsNew = an.NewFields || {};
|
|
||||||
result.fieldsFinal = an.FinalFields || {};
|
|
||||||
|
|
||||||
// getAffectedBooks will set this
|
|
||||||
// result.bookKey = undefined;
|
|
||||||
|
|
||||||
self.nodes.push(result);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
if (!Array.isArray(data.AffectedNodes)) {
|
||||||
|
throw new TypeError('Metadata missing AffectedNodes');
|
||||||
|
}
|
||||||
|
|
||||||
|
data.AffectedNodes.forEach(this.addNode, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
Meta.node_types = [
|
Meta.nodeTypes = [
|
||||||
'CreatedNode',
|
'CreatedNode',
|
||||||
'ModifiedNode',
|
'ModifiedNode',
|
||||||
'DeletedNode'
|
'DeletedNode'
|
||||||
];
|
];
|
||||||
|
|
||||||
Meta.prototype.diffType = function(an) {
|
Meta.amountFieldsAffectingIssuer = [
|
||||||
var result = false;
|
'LowLimit',
|
||||||
|
'HighLimit',
|
||||||
|
'TakerPays',
|
||||||
|
'TakerGets'
|
||||||
|
];
|
||||||
|
|
||||||
for (var i=0; i<Meta.node_types.length; i++) {
|
/**
|
||||||
var x = Meta.node_types[i];
|
* @api private
|
||||||
if (an.hasOwnProperty(x)) {
|
*/
|
||||||
result = x;
|
|
||||||
|
Meta.prototype.getNodeType = function(node) {
|
||||||
|
var result = null;
|
||||||
|
|
||||||
|
for (var i=0; i<Meta.nodeTypes.length; i++) {
|
||||||
|
var type = Meta.nodeTypes[i];
|
||||||
|
if (node.hasOwnProperty(type)) {
|
||||||
|
result = type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,6 +57,63 @@ Meta.prototype.diffType = function(an) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add node to metadata
|
||||||
|
*
|
||||||
|
* @param {Object} node
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
Meta.prototype.addNode = function(node) {
|
||||||
|
this._affectedAccounts = void(0);
|
||||||
|
this._affectedBooks = void(0);
|
||||||
|
|
||||||
|
var result = { };
|
||||||
|
|
||||||
|
if ((result.nodeType = this.getNodeType(node))) {
|
||||||
|
node = node[result.nodeType];
|
||||||
|
|
||||||
|
result.diffType = result.nodeType;
|
||||||
|
result.entryType = node.LedgerEntryType;
|
||||||
|
result.ledgerIndex = node.LedgerIndex;
|
||||||
|
result.fields = extend({ }, node.PreviousFields, node.NewFields, node.FinalFields);
|
||||||
|
result.fieldsPrev = node.PreviousFields || { };
|
||||||
|
result.fieldsNew = node.NewFields || { };
|
||||||
|
result.fieldsFinal = node.FinalFields || { };
|
||||||
|
|
||||||
|
// getAffectedBooks will set this
|
||||||
|
// result.bookKey = undefined;
|
||||||
|
|
||||||
|
this.nodes.push(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get affected nodes array
|
||||||
|
*
|
||||||
|
* @param {Object} filter options
|
||||||
|
* @return {Array} nodes
|
||||||
|
*/
|
||||||
|
|
||||||
|
Meta.prototype.getNodes = function(options) {
|
||||||
|
if (typeof options === 'object') {
|
||||||
|
return this.nodes.filter(function(node) {
|
||||||
|
if (options.nodeType && options.nodeType !== node.nodeType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (options.entryType && options.entryType !== node.entryType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (options.bookKey && options.bookKey !== node.bookKey) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return this.nodes;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a function on each affected node.
|
* Execute a function on each affected node.
|
||||||
*
|
*
|
||||||
@@ -61,7 +122,7 @@ Meta.prototype.diffType = function(an) {
|
|||||||
*
|
*
|
||||||
* {
|
* {
|
||||||
* // Type of diff, e.g. CreatedNode, ModifiedNode
|
* // Type of diff, e.g. CreatedNode, ModifiedNode
|
||||||
* diffType: 'CreatedNode'
|
* nodeType: 'CreatedNode'
|
||||||
*
|
*
|
||||||
* // Type of node affected, e.g. RippleState, AccountRoot
|
* // Type of node affected, e.g. RippleState, AccountRoot
|
||||||
* entryType: 'RippleState',
|
* entryType: 'RippleState',
|
||||||
@@ -72,7 +133,7 @@ Meta.prototype.diffType = function(an) {
|
|||||||
* // Contains all fields with later versions taking precedence
|
* // Contains all fields with later versions taking precedence
|
||||||
* //
|
* //
|
||||||
* // This is a shorthand for doing things like checking which account
|
* // This is a shorthand for doing things like checking which account
|
||||||
* // this affected without having to check the diffType.
|
* // this affected without having to check the nodeType.
|
||||||
* fields: {...},
|
* fields: {...},
|
||||||
*
|
*
|
||||||
* // Old fields (before the change)
|
* // Old fields (before the change)
|
||||||
@@ -88,43 +149,39 @@ 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) {
|
|
||||||
for (var i = 0, l = this.nodes.length; i < l; i++) {
|
|
||||||
fn(this.nodes[i], i);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
([
|
[
|
||||||
'forEach',
|
'forEach',
|
||||||
'map',
|
'map',
|
||||||
'filter',
|
'filter',
|
||||||
'every',
|
'every',
|
||||||
|
'some',
|
||||||
'reduce'
|
'reduce'
|
||||||
]).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 = [
|
Meta.prototype.each = Meta.prototype.forEach;
|
||||||
'LowLimit',
|
|
||||||
'HighLimit',
|
Meta.prototype.getAffectedAccounts = function(from) {
|
||||||
'TakerPays',
|
if (this._affectedAccounts) {
|
||||||
'TakerGets'
|
return this._affectedAccounts;
|
||||||
];
|
}
|
||||||
|
|
||||||
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) {
|
for (var i=0; i<this.nodes.length; i++) {
|
||||||
var fields = (an.diffType === 'CreatedNode') ? an.fieldsNew : an.fieldsFinal;
|
var node = this.nodes[i];
|
||||||
for (var i in fields) {
|
var fields = (node.nodeType === 'CreatedNode') ? node.fieldsNew : node.fieldsFinal;
|
||||||
var field = fields[i];
|
for (var fieldName in fields) {
|
||||||
|
var field = fields[fieldName];
|
||||||
if (typeof field === 'string' && UInt160.is_valid(field)) {
|
if (typeof field === 'string' && UInt160.is_valid(field)) {
|
||||||
accounts.push(field);
|
accounts.push(field);
|
||||||
} else if (amountFieldsAffectingIssuer.indexOf(i) !== -1) {
|
} else if (~Meta.amountFieldsAffectingIssuer.indexOf(fieldName)) {
|
||||||
var amount = Amount.from_json(field);
|
var amount = Amount.from_json(field);
|
||||||
var issuer = amount.issuer();
|
var issuer = amount.issuer();
|
||||||
if (issuer.is_valid() && !issuer.is_zero()) {
|
if (issuer.is_valid() && !issuer.is_zero()) {
|
||||||
@@ -132,43 +189,53 @@ Meta.prototype.getAffectedAccounts = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
return utils.arrayUnique(accounts);
|
this._affectedAccounts = utils.arrayUnique(accounts);
|
||||||
|
|
||||||
|
return this._affectedAccounts;
|
||||||
};
|
};
|
||||||
|
|
||||||
Meta.prototype.getAffectedBooks = function() {
|
Meta.prototype.getAffectedBooks = function() {
|
||||||
var books = [ ];
|
if (this._affectedBooks) {
|
||||||
|
return this._affectedBooks;
|
||||||
this.nodes.forEach(function(an) {
|
|
||||||
if (an.entryType !== 'Offer') {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var gets = Amount.from_json(an.fields.TakerGets);
|
var books = [ ];
|
||||||
var pays = Amount.from_json(an.fields.TakerPays);
|
|
||||||
|
|
||||||
|
for (var i=0; i<this.nodes.length; i++) {
|
||||||
|
var node = this.nodes[i];
|
||||||
|
|
||||||
|
if (node.entryType !== 'Offer') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var gets = Amount.from_json(node.fields.TakerGets);
|
||||||
|
var pays = Amount.from_json(node.fields.TakerPays);
|
||||||
var getsKey = gets.currency().to_json();
|
var getsKey = gets.currency().to_json();
|
||||||
|
var paysKey = pays.currency().to_json();
|
||||||
|
|
||||||
if (getsKey !== 'XRP') {
|
if (getsKey !== 'XRP') {
|
||||||
getsKey += '/' + gets.issuer().to_json();
|
getsKey += '/' + gets.issuer().to_json();
|
||||||
}
|
}
|
||||||
|
|
||||||
var paysKey = pays.currency().to_json();
|
|
||||||
if (paysKey !== 'XRP') {
|
if (paysKey !== 'XRP') {
|
||||||
paysKey += '/' + pays.issuer().to_json();
|
paysKey += '/' + pays.issuer().to_json();
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = [ getsKey, paysKey ].join(':');
|
var key = getsKey + ':' + paysKey;
|
||||||
|
|
||||||
// Hell of a lot of work, so we are going to cache this. We can use this
|
// Hell of a lot of work, so we are going to cache this. We can use this
|
||||||
// later to good effect in OrderBook.notify to make sure we only process
|
// later to good effect in OrderBook.notify to make sure we only process
|
||||||
// pertinent offers.
|
// pertinent offers.
|
||||||
an.bookKey = key;
|
node.bookKey = key;
|
||||||
|
|
||||||
books.push(key);
|
books.push(key);
|
||||||
});
|
}
|
||||||
|
|
||||||
return utils.arrayUnique(books);
|
this._affectedBooks = utils.arrayUnique(books);
|
||||||
|
|
||||||
|
return this._affectedBooks;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Meta = Meta;
|
exports.Meta = Meta;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1480,19 +1480,19 @@ Remote.prototype.requestTxHistory = function(start, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Remote.prototype.requestBookOffers = function(gets, pays, taker, callback) {
|
Remote.prototype.requestBookOffers = function(gets, pays, taker, callback) {
|
||||||
|
var lastArg = arguments[arguments.length - 1];
|
||||||
|
|
||||||
if (gets.hasOwnProperty('gets') || gets.hasOwnProperty('taker_gets')) {
|
if (gets.hasOwnProperty('gets') || gets.hasOwnProperty('taker_gets')) {
|
||||||
var options = gets;
|
var options = gets;
|
||||||
// This would mutate the `lastArg` in `arguments` to be `null` and is
|
// This would mutate the `lastArg` in `arguments` to be `null` and is
|
||||||
// redundant. Once upon a time, some awkward code was written f(g, null,
|
// redundant. Once upon a time, some awkward code was written f(g, null,
|
||||||
// null, cb) ...
|
// null, cb) ...
|
||||||
// callback = pays;
|
callback = pays;
|
||||||
taker = options.taker;
|
taker = options.taker;
|
||||||
pays = options.pays || options.taker_pays;
|
pays = options.pays || options.taker_pays;
|
||||||
gets = options.gets || options.taker_gets;
|
gets = options.gets || options.taker_gets;
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastArg = arguments[arguments.length - 1];
|
|
||||||
|
|
||||||
if (typeof lastArg === 'function') {
|
if (typeof lastArg === 'function') {
|
||||||
callback = lastArg;
|
callback = lastArg;
|
||||||
}
|
}
|
||||||
|
|||||||
1057
test/orderbook-test.js
Normal file
1057
test/orderbook-test.js
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user