mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 12:15:51 +00:00
[FIX] cap IOU Amounts to their max and min value
respect rippled's limits
This commit is contained in:
@@ -54,7 +54,9 @@ var consts = {
|
|||||||
|
|
||||||
// Maximum possible amount for non-XRP currencies using the maximum mantissa
|
// Maximum possible amount for non-XRP currencies using the maximum mantissa
|
||||||
// with maximum exponent. Corresponds to hex 0xEC6386F26FC0FFFF.
|
// with maximum exponent. Corresponds to hex 0xEC6386F26FC0FFFF.
|
||||||
max_value: '9999999999999999e80'
|
max_value: '9999999999999999e80',
|
||||||
|
// Minimum possible amount for non-XRP currencies.
|
||||||
|
min_value: '-1000000000000000e-96'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add constants to Amount class
|
// Add constants to Amount class
|
||||||
@@ -424,6 +426,33 @@ Amount.prototype.invert = function() {
|
|||||||
return this.copy()._invert();
|
return this.copy()._invert();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Canonicalize amount value
|
||||||
|
*
|
||||||
|
* Mirrors rippled's internal Amount representation
|
||||||
|
* From https://github.com/ripple/rippled/blob/develop/src/ripple/data/protocol/STAmount.h#L31-L40
|
||||||
|
*
|
||||||
|
* Internal form:
|
||||||
|
* 1: If amount is zero, then value is zero and offset is -100
|
||||||
|
* 2: Otherwise:
|
||||||
|
* legal offset range is -96 to +80 inclusive
|
||||||
|
* value range is 10^15 to (10^16 - 1) inclusive
|
||||||
|
* amount = value * [10 ^ offset]
|
||||||
|
*
|
||||||
|
* -------------------
|
||||||
|
*
|
||||||
|
* The amount can be epxresses as A x 10^B
|
||||||
|
* Where:
|
||||||
|
* - A must be an integer between 10^15 and (10^16)-1 inclusive
|
||||||
|
* - B must be between -96 and 80 inclusive
|
||||||
|
*
|
||||||
|
* This results
|
||||||
|
* - minumum: 10^15 x 10^-96 -> 10^-81 -> -1e-81
|
||||||
|
* - maximum: (10^16)-1 x 10^80 -> 9999999999999999e80
|
||||||
|
*
|
||||||
|
* @returns {Amount}
|
||||||
|
* @throws {Error} if offset exceeds legal ranges, meaning the amount value is bigger than supported
|
||||||
|
*/
|
||||||
Amount.prototype.canonicalize = function() {
|
Amount.prototype.canonicalize = function() {
|
||||||
if (!(this._value instanceof BigInteger)) {
|
if (!(this._value instanceof BigInteger)) {
|
||||||
// NaN.
|
// NaN.
|
||||||
@@ -447,9 +476,8 @@ Amount.prototype.canonicalize = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Make sure not bigger than supported. Throw if so.
|
|
||||||
} else if (this.is_zero()) {
|
} else if (this.is_zero()) {
|
||||||
this._offset = -100;
|
this._offset = Amount.cMinOffset;
|
||||||
this._is_negative = false;
|
this._is_negative = false;
|
||||||
} else {
|
} else {
|
||||||
// Normalize mantissa to valid range.
|
// Normalize mantissa to valid range.
|
||||||
@@ -465,6 +493,16 @@ Amount.prototype.canonicalize = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure not bigger than supported. Throw if so.
|
||||||
|
if (this.is_negative() && this._offset < Amount.cMinOffset) {
|
||||||
|
throw new Error('Exceeding min value of ' + Amount.min_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure not smaller than supported. Throw if so.
|
||||||
|
if (!this.is_negative() && this._offset > Amount.cMaxOffset) {
|
||||||
|
throw new Error('Exceeding max value of ' + Amount.max_value);
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -539,9 +577,7 @@ Amount.prototype.equals = function(d, ignore_issuer) {
|
|||||||
return this.equals(Amount.from_json(d));
|
return this.equals(Amount.from_json(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = true;
|
var result = !((!this.is_valid() || !d.is_valid())
|
||||||
|
|
||||||
result = !((!this.is_valid() || !d.is_valid())
|
|
||||||
|| (this._is_native !== d._is_native)
|
|| (this._is_native !== d._is_native)
|
||||||
|| (!this._value.equals(d._value) || this._offset !== d._offset)
|
|| (!this._value.equals(d._value) || this._offset !== d._offset)
|
||||||
|| (this._is_negative !== d._is_negative)
|
|| (this._is_negative !== d._is_negative)
|
||||||
|
|||||||
@@ -1162,4 +1162,80 @@ describe('Amount', function() {
|
|||||||
assert.strictEqual(demAmount.to_human_full(), '10.75853086191915/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
assert.strictEqual(demAmount.to_human_full(), '10.75853086191915/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('amount limits', function() {
|
||||||
|
it ('max JSON wire limite', function() {
|
||||||
|
assert.strictEqual(Amount.bi_xns_max.toString(), '9000000000000000000');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('max JSON wire limite', function() {
|
||||||
|
assert.strictEqual(Amount.bi_xns_min.toString(), '-9000000000000000000');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('max mantissa value', function() {
|
||||||
|
assert.strictEqual(Amount.bi_man_max_value.toString(), '9999999999999999');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('min mantissa value', function() {
|
||||||
|
assert.strictEqual(Amount.bi_man_min_value.toString(), '1000000000000000');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('from_json minimum XRP', function() {
|
||||||
|
console.log('max', Amount.bi_xns_max.toString());
|
||||||
|
var amt = Amount.from_json('-9000000000000000000');
|
||||||
|
assert.strictEqual(amt.to_json(), '-9000000000000000000');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('from_json maximum XRP', function() {
|
||||||
|
var amt = Amount.from_json('-9000000000000000000');
|
||||||
|
assert.strictEqual(amt.to_json(), '-9000000000000000000');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('from_json less than minimum XRP', function() {
|
||||||
|
var amt = Amount.from_json('-9000000000000000001');
|
||||||
|
assert.strictEqual(amt.to_json(), '0');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('from_json more than maximum XRP', function() {
|
||||||
|
var amt = Amount.from_json('9000000000000000001');
|
||||||
|
assert.strictEqual(amt.to_json(), '0');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('from_json minimum IOU', function() {
|
||||||
|
var amt = Amount.from_json('-1e-81/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||||
|
assert.strictEqual(amt._value.toString(), Amount.bi_man_min_value.toString());
|
||||||
|
assert.strictEqual(amt.to_text(), '-1000000000000000e-96');
|
||||||
|
assert.strictEqual(amt.to_text(), Amount.min_value);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('from_json exceed minimum IOU', function() {
|
||||||
|
assert.throws(function() {
|
||||||
|
Amount.from_json('-1e-82/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')
|
||||||
|
}, 'Exceeding min value of ' + Amount.min_value);
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('from_json maximum IOU', function() {
|
||||||
|
var amt = Amount.from_json('9999999999999999e80/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||||
|
assert.strictEqual(amt._value.toString(), Amount.bi_man_max_value.toString());
|
||||||
|
assert.strictEqual(amt.to_text(), '9999999999999999e80');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('from_json exceed maximum IOU', function() {
|
||||||
|
assert.throws(function() {
|
||||||
|
Amount.from_json('9999999999999999e81/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')
|
||||||
|
}, 'Exceeding max value of ' + Amount.max_value);
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('from_json normalize mantissa to valid max range, lost significant digits', function() {
|
||||||
|
var amt = Amount.from_json('99999999999999999999999999999999/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||||
|
assert.strictEqual(amt._value.toString(), Amount.bi_man_max_value.toString());
|
||||||
|
assert.strictEqual(amt.to_text(), '9999999999999999e16');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('from_json normalize mantissa to min valid range, lost significant digits', function() {
|
||||||
|
var amt = Amount.from_json('-0.0000000000000000000000001/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
|
||||||
|
assert.strictEqual(amt._value.toString(), Amount.bi_man_min_value.toString());
|
||||||
|
assert.strictEqual(amt.to_text(), '-1000000000000000e-40');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user