Merge pull request #598 from clark800/remove-currency

Remove Currency class
This commit is contained in:
Chris Clark
2015-10-16 11:51:20 -07:00
16 changed files with 157 additions and 517 deletions

View File

@@ -6,10 +6,11 @@
const assert = require('assert');
const extend = require('extend');
const utils = require('./utils');
const Currency = require('./currency').Currency;
const normalizeCurrency = require('./currency').normalizeCurrency;
const {XRPValue, IOUValue} = require('ripple-lib-value');
const {isValidAddress} = require('ripple-address-codec');
const {ACCOUNT_ONE, ACCOUNT_ZERO} = require('./constants');
const {ACCOUNT_ONE, ACCOUNT_ZERO, CURRENCY_ONE}
= require('./constants');
type Value = XRPValue | IOUValue;
@@ -21,7 +22,7 @@ function Amount(value = new XRPValue(NaN)) {
this._value = value;
this._is_native = true; // Default to XRP. Only valid if value is not NaN.
this._currency = new Currency();
this._currency = null;
this._issuer = 'NaN';
}
@@ -105,7 +106,7 @@ Amount.NaN = function() {
return result; // but let's be careful
};
Amount.from_components_unsafe = function(value: Value, currency: Currency,
Amount.from_components_unsafe = function(value: Value, currency: string,
issuer: string, isNative: boolean
) {
const result = new Amount(value);
@@ -378,7 +379,7 @@ Amount.prototype.equals = function(d, ignore_issuer) {
return this.is_valid() && d.is_valid()
&& this._is_native === d._is_native
&& this._value.equals(d._value)
&& (this._is_native || (this._currency.equals(d._currency)
&& (this._is_native || ((this._currency === d._currency)
&& (ignore_issuer || this._issuer === d._issuer)));
};
@@ -405,7 +406,7 @@ Amount.prototype.is_valid = function() {
};
Amount.prototype.is_valid_full = function() {
return this.is_valid() && this._currency.is_valid()
return this.is_valid() && this._currency !== null
&& isValidAddress(this._issuer) && this._issuer !== ACCOUNT_ZERO;
};
@@ -540,7 +541,7 @@ Amount.prototype.parse_quality =
function(quality, counterCurrency, counterIssuer, opts) {
const options = opts || {};
const baseCurrency = Currency.from_json(options.base_currency);
const baseCurrency = options.base_currency;
const mantissa_hex = quality.substring(quality.length - 14);
const offset_hex = quality.substring(
@@ -548,11 +549,11 @@ function(quality, counterCurrency, counterIssuer, opts) {
const mantissa = new IOUValue(mantissa_hex, null, 16);
const offset = parseInt(offset_hex, 16) - 100;
this._currency = Currency.from_json(counterCurrency);
this._currency = normalizeCurrency(counterCurrency);
this._issuer = counterIssuer;
this._is_native = this._currency.is_native();
this._is_native = (this._currency === 'XRP');
if (this._is_native && baseCurrency.is_native()) {
if (this._is_native && baseCurrency === 'XRP') {
throw new Error('XRP/XRP quality is not allowed');
}
@@ -583,7 +584,7 @@ function(quality, counterCurrency, counterIssuer, opts) {
// pay:$price drops get:1 X
// pay:($price / 1,000,000) XRP get:1 X
nativeAdjusted = nativeAdjusted.divide(bi_xns_unit);
} else if (baseCurrency.is_valid() && baseCurrency.is_native()) {
} else if (baseCurrency === 'XRP') {
// pay:$price X get:1 drop
// pay:($price * 1,000,000) X get:1 XRP
nativeAdjusted = nativeAdjusted.multiply(bi_xns_unit);
@@ -602,7 +603,7 @@ function(quality, counterCurrency, counterIssuer, opts) {
Amount.prototype.parse_number = function(n) {
this._is_native = false;
this._currency = Currency.from_json(1);
this._currency = CURRENCY_ONE;
this._issuer = ACCOUNT_ONE;
this._set_value(new IOUValue(n));
return this;
@@ -617,7 +618,7 @@ Amount.prototype.parse_json = function(j) {
const m = j.match(/^([^/]+)\/([^/]+)(?:\/(.+))?$/);
if (m) {
this._currency = Currency.from_json(m[2]);
this._currency = normalizeCurrency(m[2]);
if (m[3]) {
this._issuer = m[3];
} else {
@@ -626,7 +627,7 @@ Amount.prototype.parse_json = function(j) {
this.parse_value(m[1]);
} else {
this.parse_native(j);
this._currency = Currency.from_json('0');
this._currency = 'XRP';
this._issuer = ACCOUNT_ZERO;
}
break;
@@ -643,8 +644,7 @@ Amount.prototype.parse_json = function(j) {
if (j instanceof Amount) {
j.copyTo(this);
} else if (j.hasOwnProperty('value')) {
// Parse the passed value to sanitize and copy it.
this._currency.parse_json(j.currency, true); // Never XRP.
this._currency = normalizeCurrency(j.currency);
if (typeof j.issuer !== 'string') {
throw new Error('issuer must be a string');
@@ -691,8 +691,8 @@ Amount.prototype.parse_value = function(j) {
};
Amount.prototype.set_currency = function(c) {
this._currency = Currency.from_json(c);
this._is_native = this._currency.is_native();
this._currency = normalizeCurrency(c);
this._is_native = (c === 'XRP');
return this;
};
@@ -869,7 +869,7 @@ Amount.prototype.to_human = function(options) {
Amount.prototype.to_human_full = function(options) {
const opts = options || {};
const value = this.to_human(opts);
const currency = this._currency.to_json();
const currency = this._currency;
const issuer = this._issuer;
const base = value + '/' + currency;
return this.is_native() ? base : (base + '/' + issuer);
@@ -882,7 +882,7 @@ Amount.prototype.to_json = function() {
const amount_json = {
value: this.to_text(),
currency: this._currency.to_json()
currency: this._currency
};
if (isValidAddress(this._issuer)) {
@@ -898,8 +898,7 @@ Amount.prototype.to_text_full = function() {
}
return this._is_native
? this.to_human() + '/XRP'
: this.to_text() + '/' + this._currency.to_json()
+ '/' + this._issuer;
: this.to_text() + '/' + this._currency + '/' + this._issuer;
};
// For debugging.
@@ -925,7 +924,7 @@ Amount.prototype.not_equals_why = function(d, ignore_issuer) {
return type + ' value differs.';
}
if (!this._is_native) {
if (!this._currency.equals(d._currency)) {
if (this._currency !== d._currency) {
return 'Non-XRP currency differs.';
}
if (!ignore_issuer && this._issuer !== d._issuer) {

View File

@@ -4,6 +4,7 @@ const _ = require('lodash');
const assert = require('assert');
const Amount = require('./amount').Amount;
const Utils = require('./orderbookutils');
const {toHexCurrency} = require('./currency');
function assertValidNumber(number, message) {
assert(!_.isNull(number) && !isNaN(number), message);
@@ -21,8 +22,8 @@ function AutobridgeCalculator(currencyGets, currencyPays,
) {
this._currencyGets = currencyGets;
this._currencyPays = currencyPays;
this._currencyGetsHex = currencyGets.to_hex();
this._currencyPaysHex = currencyPays.to_hex();
this._currencyGetsHex = toHexCurrency(currencyGets);
this._currencyPaysHex = toHexCurrency(currencyPays);
this._issuerGets = issuerGets;
this._issuerPays = issuerPays;
this.legOneOffers = _.cloneDeep(legOneOffers);

View File

@@ -2,5 +2,7 @@
module.exports = {
ACCOUNT_ZERO: 'rrrrrrrrrrrrrrrrrrrrrhoLvTp',
ACCOUNT_ONE: 'rrrrrrrrrrrrrrrrrrrrBZbvji'
ACCOUNT_ONE: 'rrrrrrrrrrrrrrrrrrrrBZbvji',
CURRENCY_ZERO: '0000000000000000000000000000000000000000',
CURRENCY_ONE: '0000000000000000000000000000000000000001'
};

View File

@@ -1,277 +1,58 @@
'use strict';
const _ = require('lodash');
const assert = require('assert');
const utils = require('./utils');
const BN = require('bn.js');
function Currency() {
// Internal form: 0 = XRP. 3 letter-code.
// XXX Internal should be 0 or hex with three letter annotation when valid.
// Json form:
// '', 'XRP', '0': 0
// 3-letter code: ...
// XXX Should support hex, C++ doesn't currently allow it.
this._value = NaN;
this._update();
function isISOCode(currency) {
return /^[A-Z0-9]{3}$/.test(currency);
}
Currency.width = 20;
Currency.HEX_CURRENCY_BAD = '0000000000000000000000005852500000000000';
Currency.HEX_ZERO = '0000000000000000000000000000000000000000';
Currency.HEX_ONE = '0000000000000000000000000000000000000001';
function isHexCurrency(currency) {
return /[A-Fa-f0-9]{40}/.test(currency);
}
Currency.from_json = function(j, shouldInterpretXrpAsIou) {
return (new Currency()).parse_json(j, shouldInterpretXrpAsIou);
};
Currency.from_hex = function(j) {
if (j instanceof this) {
return j.clone();
function getISOCode(hexCurrency) {
const bytes = new Buffer(hexCurrency, 'hex');
if (_.every(bytes, octet => octet === 0)) {
return 'XRP';
}
return (new this()).parse_hex(j);
};
Currency.from_bytes = function(j) {
if (j instanceof this) {
return j.clone();
}
return (new this()).parse_bytes(j);
};
Currency.prototype.to_hex = function() {
if (!this.is_valid()) {
if (!_.every(bytes, (octet, i) => octet === 0 || (i >= 12 && i <= 14))) {
return null;
}
const code = String.fromCharCode(bytes[12])
+ String.fromCharCode(bytes[13])
+ String.fromCharCode(bytes[14]);
return isISOCode(code) ? code : null;
}
return utils.arrayToHex(this.to_bytes());
};
Currency.json_rewrite = function(j, opts) {
return this.from_json(j).to_json(opts);
};
Currency.prototype.clone = function() {
return this.copyTo(new this.constructor());
};
Currency.prototype.equals = function(o) {
return this.is_valid() &&
o.is_valid() &&
// This throws but the expression will short circuit
this.cmp(o) === 0;
};
Currency.prototype.cmp = function(o) {
assert(this.is_valid() && o.is_valid());
return this._value.cmp(o._value);
};
// this._value = NaN on error.
Currency.prototype.parse_json = function(j, shouldInterpretXrpAsIou) {
this._value = NaN;
if (j instanceof Currency) {
this._value = j._value;
this._update();
return this;
function normalizeCurrency(currency) {
if (isISOCode(currency.toUpperCase())) {
return currency.toUpperCase();
} else if (isHexCurrency(currency)) {
const code = getISOCode(currency);
return code === null ? currency.toUpperCase() : code;
}
throw new Error('invalid currency');
}
switch (typeof j) {
case 'number':
if (!isNaN(j)) {
this.parse_number(j);
}
break;
case 'string':
if (!j || j === '0' || j === 'XRP') {
// Empty string or XRP
this.parse_hex(shouldInterpretXrpAsIou
? Currency.HEX_CURRENCY_BAD
: Currency.HEX_ZERO);
break;
}
if (j === '1') {
// 'no currency'
this.parse_hex(Currency.HEX_ONE);
break;
}
if (/^[A-F0-9]{40}$/.test(j)) {
// Hex format
this.parse_hex(j);
break;
}
const currencyCode = j.toUpperCase();
const currencyData = utils.arraySet(20, 0);
currencyData[12] = currencyCode.charCodeAt(0) & 0xff;
currencyData[13] = currencyCode.charCodeAt(1) & 0xff;
currencyData[14] = currencyCode.charCodeAt(2) & 0xff;
this.parse_bytes(currencyData);
break;
case 'undefined':
this.parse_hex(Currency.HEX_ZERO);
break;
}
this._update();
return this;
};
Currency.prototype.is_valid = function() {
return this._value instanceof BN;
};
Currency.prototype.parse_number = function(j) {
this._value = NaN;
if (typeof j === 'number' && isFinite(j) && j >= 0) {
this._value = new BN(j);
}
this._update();
return this;
};
Currency.prototype.parse_hex = function(j) {
if (new RegExp(`^[0-9A-Fa-f]{${this.constructor.width * 2}}$`).test(j)) {
this._value = new BN(j, 16);
} else {
this._value = NaN;
}
this._update();
return this;
};
Currency.prototype.to_bytes = function() {
if (!this.is_valid()) {
return null;
}
return this._value.toArray('be', this.constructor.width);
};
Currency.prototype._isISOCode = function() {
return _.every(this.to_bytes(), (octet, i) =>
octet === 0 || (i >= 12 && i <= 14))
&& /^[A-Z0-9]{3}$/.test(this._iso_code);
};
/**
* Recalculate internal representation.
*
* You should never need to call this.
*/
Currency.prototype._update = function() {
const bytes = this.to_bytes();
// is it 0 everywhere except 12, 13, 14?
let isZeroExceptInStandardPositions = true;
if (!bytes) {
return; // before being initialized
}
this._native = false;
this._type = -1;
this._iso_code = '';
for (let i = 0; i < 20; i++) {
isZeroExceptInStandardPositions = isZeroExceptInStandardPositions
&& (i === 12 || i === 13 || i === 14 || bytes[i] === 0);
}
if (isZeroExceptInStandardPositions) {
this._iso_code = String.fromCharCode(bytes[12])
+ String.fromCharCode(bytes[13])
+ String.fromCharCode(bytes[14]);
if (this._iso_code === '\u0000\u0000\u0000') {
this._native = true;
this._iso_code = 'XRP';
function toHexCurrency(currency) {
if (isISOCode(currency)) {
const bytes = new Buffer(20);
bytes.fill(0);
if (currency !== 'XRP') {
bytes[12] = currency.charCodeAt(0);
bytes[13] = currency.charCodeAt(1);
bytes[14] = currency.charCodeAt(2);
}
this._type = 0;
} else if (bytes[0] === 0x01) { // Demurrage currency
this._iso_code = String.fromCharCode(bytes[1])
+ String.fromCharCode(bytes[2])
+ String.fromCharCode(bytes[3]);
this._type = 1;
return bytes.toString('hex').toUpperCase();
} else if (isHexCurrency(currency)) {
return currency.toUpperCase();
}
};
throw new Error('invalid currency');
}
/**
* Returns copy.
*
* This copies code from UInt.copyTo so we do not call _update,
* bvecause to_bytes is very expensive.
*/
function isValidCurrency(currency) {
return isISOCode(currency.toUpperCase()) || isHexCurrency(currency);
}
Currency.prototype.copyTo = function(d) {
d._value = this._value;
if (this._version_byte !== undefined) {
d._version_byte = this._version_byte;
}
if (!d.is_valid()) {
return d;
}
d._native = this._native;
d._type = this._type;
d._iso_code = this._iso_code;
return d;
};
Currency.prototype.parse_bytes = function(j) {
if (Array.isArray(j) && j.length === this.constructor.width) {
this._value = new BN(j);
} else {
this._value = NaN;
}
this._update();
return this;
};
Currency.prototype.is_native = function() {
return this._native;
};
Currency.prototype.to_json = function(opts = {}) {
if (!this.is_valid()) {
throw new Error('Invalid currency object');
}
if (this._isISOCode() && !opts.force_hex) {
const fullName = opts && opts.full_name ? ' - ' + opts.full_name : '';
return this._iso_code + fullName;
}
const hex = this.to_hex();
// XXX This is to maintain backwards compatibility, but it is very, very
// odd behavior, so we should deprecate it and get rid of it as soon as
// possible.
return hex === Currency.HEX_ONE ? 1 : hex;
};
Currency.prototype.get_iso = function() {
return this._iso_code;
};
Currency.is_valid = function(j) {
return this.from_json(j).is_valid();
};
exports.Currency = Currency;
exports.normalizeCurrency = normalizeCurrency;
exports.isValidCurrency = isValidCurrency;
exports.toHexCurrency = toHexCurrency;

View File

@@ -184,8 +184,8 @@ Meta.prototype.getAffectedBooks = function() {
const gets = Amount.from_json(node.fields.TakerGets);
const pays = Amount.from_json(node.fields.TakerPays);
let getsKey = gets.currency().to_json();
let paysKey = pays.currency().to_json();
let getsKey = gets.currency();
let paysKey = pays.currency();
if (getsKey !== 'XRP') {
getsKey += '/' + gets.issuer();

View File

@@ -18,12 +18,12 @@ const async = require('async');
const EventEmitter = require('events').EventEmitter;
const {isValidAddress} = require('ripple-address-codec');
const Amount = require('./amount').Amount;
const Currency = require('./currency').Currency;
const AutobridgeCalculator = require('./autobridgecalculator');
const OrderBookUtils = require('./orderbookutils');
const log = require('./log').internal.sub('orderbook');
const {IOUValue} = require('ripple-lib-value');
const RippleError = require('./rippleerror').RippleError;
const {normalizeCurrency, isValidCurrency} = require('./currency');
function _sortOffersQuick(a, b) {
return a.qualityHex.localeCompare(b.qualityHex);
@@ -49,9 +49,9 @@ function OrderBook(remote,
const self = this;
this._remote = remote;
this._currencyGets = Currency.from_json(currencyGets);
this._currencyGets = normalizeCurrency(currencyGets);
this._issuerGets = issuerGets;
this._currencyPays = Currency.from_json(currencyPays);
this._currencyPays = normalizeCurrency(currencyPays);
this._issuerPays = issuerPays;
this._key = key;
this._subscribed = false;
@@ -89,8 +89,8 @@ function OrderBook(remote,
this.sortOffers = _sortOffersQuick;
this._isAutobridgeable = !this._currencyGets.is_native()
&& !this._currencyPays.is_native();
this._isAutobridgeable = this._currencyGets !== 'XRP'
&& this._currencyPays !== 'XRP';
function computeAutobridgedOffersWrapperOne() {
if (!self._gotOffersFromLegOne) {
@@ -424,7 +424,7 @@ OrderBook.prototype.requestTransferRate = function(callback) {
const self = this;
if (this._currencyGets.is_native()) {
if (this._currencyGets === 'XRP') {
// Transfer rate is default for the native currency
this._issuerTransferRate = OrderBook.DEFAULT_TRANSFER_RATE;
@@ -570,7 +570,7 @@ OrderBook.prototype.applyTransferRate = function(balance) {
OrderBook.prototype.getOwnerFunds = function(account) {
if (this.hasOwnerFunds(account)) {
if (this._currencyGets.is_native()) {
if (this._currencyGets === 'XRP') {
return Amount.from_json(this._ownerFunds[account]);
}
return OrderBookUtils.normalizeAmount(this._ownerFunds[account]);
@@ -690,7 +690,7 @@ OrderBook.prototype.getOwnerOfferTotal = function(account) {
if (amount) {
return amount;
}
if (this._currencyGets.is_native()) {
if (this._currencyGets === 'XRP') {
return OrderBook.ZERO_NATIVE_AMOUNT.clone();
}
return OrderBook.ZERO_NORMALIZED_AMOUNT.clone();
@@ -704,7 +704,7 @@ OrderBook.prototype.getOwnerOfferTotal = function(account) {
*/
OrderBook.prototype.resetOwnerOfferTotal = function(account) {
if (this._currencyGets.is_native()) {
if (this._currencyGets === 'XRP') {
this._ownerOffersTotal[account] = OrderBook.ZERO_NATIVE_AMOUNT.clone();
} else {
this._ownerOffersTotal[account] = OrderBook.ZERO_NORMALIZED_AMOUNT.clone();
@@ -746,7 +746,7 @@ OrderBook.prototype.setOfferFundedAmount = function(offer) {
OrderBookUtils.getOfferTakerGetsFunded(offer)
);
offer.taker_pays_funded = this._currencyPays.is_native()
offer.taker_pays_funded = (this._currencyPays === 'XRP')
? String(Math.floor(takerPaysFunded.to_number()))
: takerPaysFunded.to_json().value;
} else {
@@ -817,12 +817,12 @@ OrderBook.prototype.isBalanceChangeNode = function(node) {
}
// Check if taker gets currency is native and balance is not a number
if (this._currencyGets.is_native()) {
if (this._currencyGets === 'XRP') {
return !isNaN(node.fields.Balance);
}
// Check if balance change is not for taker gets currency
if (node.fields.Balance.currency !== this._currencyGets.to_json()) {
if (node.fields.Balance.currency !== this._currencyGets) {
return false;
}
@@ -873,7 +873,7 @@ OrderBook.prototype.onTransaction = function(transaction) {
OrderBook.prototype.updateFundedAmounts = function(transaction) {
const self = this;
if (!this._currencyGets.is_native() && !this._issuerTransferRate) {
if (this._currencyGets !== 'XRP' && !this._issuerTransferRate) {
if (this._remote.trace) {
log.info('waiting for transfer rate');
}
@@ -893,7 +893,7 @@ OrderBook.prototype.updateFundedAmounts = function(transaction) {
const affectedNodes = transaction.mmeta.getNodes({
nodeType: 'ModifiedNode',
entryType: this._currencyGets.is_native() ? 'AccountRoot' : 'RippleState'
entryType: this._currencyGets === 'XRP' ? 'AccountRoot' : 'RippleState'
});
_.each(affectedNodes, function(node) {
@@ -1004,15 +1004,14 @@ OrderBook.prototype.notify = function(transaction) {
}
let takerGetsTotal = Amount.from_json(
'0' + ((Currency.from_json(this._currencyGets).is_native())
'0' + (this._currencyGets === 'XRP'
? ''
: ('/' + this._currencyGets.to_json() + '/' + this._issuerGets))
: ('/' + this._currencyGets + '/' + this._issuerGets))
);
let takerPaysTotal = Amount.from_json(
'0' + ((Currency.from_json(this._currencyPays).is_native())
? ''
: ('/' + this._currencyPays.to_json() + '/' + this._issuerPays))
'0' + (this._currencyPays === 'XRP' ? ''
: ('/' + this._currencyPays + '/' + this._issuerPays))
);
const isOfferCancel =
@@ -1138,10 +1137,7 @@ OrderBook.prototype.insertOffer = function(node) {
*/
OrderBook.prototype.normalizeAmount = function(currency, amountObj) {
const value = currency.is_native()
? amountObj
: amountObj.value;
const value = (currency === 'XRP') ? amountObj : amountObj.value;
return OrderBookUtils.normalizeAmount(value);
};
@@ -1300,18 +1296,18 @@ OrderBook.prototype.toJSON =
OrderBook.prototype.to_json = function() {
const json = {
taker_gets: {
currency: this._currencyGets.to_hex()
currency: this._currencyGets
},
taker_pays: {
currency: this._currencyPays.to_hex()
currency: this._currencyPays
}
};
if (!this._currencyGets.is_native()) {
if (this._currencyGets !== 'XRP') {
json.taker_gets.issuer = this._issuerGets;
}
if (!this._currencyPays.is_native()) {
if (this._currencyPays !== 'XRP') {
json.taker_pays.issuer = this._issuerPays;
}
@@ -1331,11 +1327,11 @@ OrderBook.prototype.isValid =
OrderBook.prototype.is_valid = function() {
// XXX Should check for same currency (non-native) && same issuer
return (
this._currencyPays && this._currencyPays.is_valid() &&
(this._currencyPays.is_native() || isValidAddress(this._issuerPays)) &&
this._currencyGets && this._currencyGets.is_valid() &&
(this._currencyGets.is_native() || isValidAddress(this._issuerGets)) &&
!(this._currencyPays.is_native() && this._currencyGets.is_native())
this._currencyPays && isValidCurrency(this._currencyPays) &&
(this._currencyPays === 'XRP' || isValidAddress(this._issuerPays)) &&
this._currencyGets && isValidCurrency(this._currencyGets) &&
(this._currencyGets === 'XRP' || isValidAddress(this._issuerGets)) &&
!(this._currencyPays === 'XRP' && this._currencyGets === 'XRP')
);
};
@@ -1346,7 +1342,7 @@ OrderBook.prototype.is_valid = function() {
OrderBook.prototype.computeAutobridgedOffers = function(callback = function() {}
) {
assert(!this._currencyGets.is_native() && !this._currencyPays.is_native(),
assert(this._currencyGets !== 'XRP' && this._currencyPays !== 'XRP',
'Autobridging is only for IOU:IOU orderbooks');

View File

@@ -4,7 +4,6 @@ const _ = require('lodash');
const assert = require('assert');
const constants = require('./constants');
const Amount = require('./amount').Amount;
const Currency = require('./currency').Currency;
const {IOUValue} = require('ripple-lib-value');
const binary = require('ripple-binary-codec');
const OrderBookUtils = {};
@@ -21,12 +20,9 @@ function assertValidNumber(number, message) {
* @return JSON amount object
*/
function createAmount(value, currency_, counterparty) {
function createAmount(value, currency, counterparty) {
assert(_.isString(counterparty), 'counterparty must be a string');
const currency = currency_ instanceof Currency ?
currency_ :
Currency.from_json(currency_);
assert(_.isString(currency), 'currency must be a string');
return Amount.from_components_unsafe(new IOUValue(value),
currency, counterparty, false);
@@ -141,7 +137,7 @@ OrderBookUtils.convertOfferQualityToHexFromText = function(quality) {
return binary.encodeQuality(quality);
};
OrderBookUtils.CURRENCY_ONE = Currency.from_json(1);
OrderBookUtils.CURRENCY_ONE = constants.CURRENCY_ONE;
OrderBookUtils.ISSUER_ONE = constants.ACCOUNT_ONE;

View File

@@ -23,7 +23,7 @@ const EventEmitter = require('events').EventEmitter;
const Server = require('./server').Server;
const Request = require('./request').Request;
const Amount = require('./amount').Amount;
const Currency = require('./currency').Currency;
const {normalizeCurrency} = require('./currency');
const Transaction = require('./transaction').Transaction;
const Account = require('./account').Account;
const Meta = require('./meta').Meta;
@@ -1532,18 +1532,18 @@ Remote.prototype.requestBookOffers = function(options, callback) {
const request = new Request(this, 'book_offers');
request.message.taker_gets = {
currency: Currency.json_rewrite(taker_gets.currency, {force_hex: true})
currency: taker_gets.currency
};
if (!Currency.from_json(request.message.taker_gets.currency).is_native()) {
if (normalizeCurrency(request.message.taker_gets.currency) !== 'XRP') {
request.message.taker_gets.issuer = taker_gets.issuer;
}
request.message.taker_pays = {
currency: Currency.json_rewrite(taker_pays.currency, {force_hex: true})
currency: taker_pays.currency
};
if (!Currency.from_json(request.message.taker_pays.currency).is_native()) {
if (normalizeCurrency(request.message.taker_pays.currency) !== 'XRP') {
request.message.taker_pays.issuer = taker_pays.issuer;
}
@@ -1890,7 +1890,7 @@ Remote.prototype.createPathFind = function(options, callback) {
};
Remote.prepareTrade = function(currency, issuer) {
const suffix = Currency.from_json(currency).is_native() ? '' : ('/' + issuer);
const suffix = normalizeCurrency(currency) === 'XRP' ? '' : ('/' + issuer);
return currency + suffix;
};
@@ -2139,8 +2139,7 @@ Remote.prepareCurrencies = function(currency) {
}
if (currency.hasOwnProperty('currency')) {
newCurrency.currency =
Currency.json_rewrite(currency.currency, {force_hex: true});
newCurrency.currency = currency.currency;
}
return newCurrency;

View File

@@ -4,7 +4,7 @@ const _ = require('lodash');
const EventEmitter = require('events').EventEmitter;
const util = require('util');
const async = require('async');
const Currency = require('./currency').Currency;
const {normalizeCurrency} = require('./currency');
const RippleError = require('./rippleerror').RippleError;
// Request events emitted:
@@ -572,12 +572,10 @@ Request.prototype.addBook = function(book, snapshot) {
}
const obj = json[side] = {
currency: Currency.json_rewrite(book[side].currency, {
force_hex: true
})
currency: normalizeCurrency(book[side].currency)
};
if (!Currency.from_json(obj.currency).is_native()) {
if (obj.currency !== 'XRP') {
obj.issuer = book[side].issuer;
}
}

View File

@@ -8,7 +8,7 @@ const EventEmitter = require('events').EventEmitter;
const utils = require('./utils');
const sjclcodec = require('sjcl-codec');
const Amount = require('./amount').Amount;
const Currency = require('./currency').Currency;
const {normalizeCurrency, isValidCurrency} = require('./currency');
const RippleError = require('./rippleerror').RippleError;
const log = require('./log').internal.sub('transaction');
const {isValidAddress, decodeAddress} = require('ripple-address-codec');
@@ -699,12 +699,12 @@ Transaction.prototype._setAmount = function(name, amount, options_) {
throw new Error(name + ' value must be non-negative');
}
const isNative = parsedAmount.currency().is_native();
const isNative = parsedAmount.is_native();
if (isNative && options.no_native) {
throw new Error(name + ' must be a non-native amount');
}
if (!(isNative || parsedAmount.currency().is_valid())) {
if (!(isNative || isValidCurrency(parsedAmount.currency()))) {
throw new Error(name + ' must have a valid currency');
}
if (!(isNative || isValidAddress(parsedAmount.issuer()))) {
@@ -1168,7 +1168,7 @@ Transaction._rewritePath = function(path) {
}
if (node.hasOwnProperty('currency')) {
newNode.currency = Currency.json_rewrite(node.currency);
newNode.currency = normalizeCurrency(node.currency);
}
if (node.hasOwnProperty('type_hex')) {

View File

@@ -244,22 +244,22 @@ describe('Amount', function() {
});
describe('from_number', function() {
it('Number 1', function() {
assert.strictEqual(Amount.from_number(1).to_text_full(), '1/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
assert.strictEqual(Amount.from_number(1).to_text_full(), '1/0000000000000000000000000000000000000001/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Number 1 human', function() {
assert.strictEqual(Amount.from_number(1).to_human_full(), '1/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
assert.strictEqual(Amount.from_number(1).to_human_full(), '1/0000000000000000000000000000000000000001/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Number 2', function() {
assert.strictEqual(Amount.from_number(2).to_text_full(), '2/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
assert.strictEqual(Amount.from_number(2).to_text_full(), '2/0000000000000000000000000000000000000001/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Number 2 human', function() {
assert.strictEqual(Amount.from_number(2).to_human_full(), '2/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
assert.strictEqual(Amount.from_number(2).to_human_full(), '2/0000000000000000000000000000000000000001/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply 2 "1" with 3 "1", by product_human', function() {
assert.strictEqual(Amount.from_number(2).product_human(Amount.from_number(3)).to_text_full(), '6/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
assert.strictEqual(Amount.from_number(2).product_human(Amount.from_number(3)).to_text_full(), '6/0000000000000000000000000000000000000001/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply 2 "1" with 3 "1", by product_human human', function() {
assert.strictEqual(Amount.from_number(2).product_human(Amount.from_number(3)).to_human_full(), '6/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
assert.strictEqual(Amount.from_number(2).product_human(Amount.from_number(3)).to_human_full(), '6/0000000000000000000000000000000000000001/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply 3 USD with 3 "1"', function() {
assert.strictEqual(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_number(3)).to_text_full(), '9/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
@@ -268,16 +268,16 @@ describe('Amount', function() {
assert.strictEqual(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_number(3)).to_human_full(), '9/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Multiply -1 "1" with 3 USD', function() {
assert.strictEqual(Amount.from_number(-1).multiply(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_text_full(), '-3/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
assert.strictEqual(Amount.from_number(-1).multiply(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_text_full(), '-3/0000000000000000000000000000000000000001/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply -1 "1" with 3 USD human', function() {
assert.strictEqual(Amount.from_number(-1).multiply(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full(), '-3/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
assert.strictEqual(Amount.from_number(-1).multiply(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full(), '-3/0000000000000000000000000000000000000001/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply -1 "1" with 3 USD, by product_human', function() {
assert.strictEqual(Amount.from_number(-1).product_human(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_text_full(), '-3/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
assert.strictEqual(Amount.from_number(-1).product_human(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_text_full(), '-3/0000000000000000000000000000000000000001/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply -1 "1" with 3 USD, by product_human human', function() {
assert.strictEqual(Amount.from_number(-1).product_human(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full(), '-3/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
assert.strictEqual(Amount.from_number(-1).product_human(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full(), '-3/0000000000000000000000000000000000000001/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
});
describe('text_full_rewrite', function() {

View File

@@ -1,128 +0,0 @@
/*eslint-disable */
var assert = require('assert');
var currency = require('ripple-lib').Currency;
var timeUtil = require('ripple-lib').utils.time;
describe('Currency', function() {
describe('json_rewrite', function() {
it('json_rewrite("USD") == "USD"', function() {
assert.strictEqual('USD', currency.json_rewrite('USD'));
});
});
describe('from_json', function() {
it('from_json().to_json() == "XRP"', function() {
var r = currency.from_json();
assert.strictEqual('XRP', r.to_json());
});
it('from_json().to_json("") == "XRP"', function() {
var r = currency.from_json('');
assert(r.is_valid());
assert(r.is_native());
assert.strictEqual('XRP', r.to_json());
});
it('from_json("XRP").to_json() == "XRP"', function() {
var r = currency.from_json('XRP');
assert(r.is_valid());
assert(r.is_native());
assert.strictEqual('XRP', r.to_json());
});
it('from_json("0000000000000000000000000000000000000000").to_json() == "XRP"', function() {
var r = currency.from_json('0000000000000000000000000000000000000000');
assert(r.is_valid());
assert(r.is_native());
assert.strictEqual('XRP', r.to_json());
});
it('from_json("111").to_human()', function() {
var r = currency.from_json("111");
assert(r.is_valid());
assert.strictEqual('111', r.to_json());
});
it('from_json("1D2").to_human()', function() {
var r = currency.from_json("1D2");
assert(r.is_valid());
assert.strictEqual('1D2', r.to_json());
});
it('from_json("1").to_human()', function() {
var r = currency.from_json('1');
assert(r.is_valid());
assert.strictEqual(1, r.to_json());
});
it('from_json("#$%").to_human()', function() {
var r = currency.from_json('#$%');
assert(r.is_valid());
assert.strictEqual('0000000000000000000000002324250000000000', r.to_json());
});
it('from_json("XAU").to_json() hex', function() {
var r = currency.from_json("XAU");
assert.strictEqual('0000000000000000000000005841550000000000', r.to_json({force_hex: true}));
});
it('json_rewrite("015841550000000041F78E0A28CBF19200000000") hex', function() {
var r = currency.json_rewrite('015841550000000041F78E0A28CBF19200000000', {force_hex: true});
assert.strictEqual('015841550000000041F78E0A28CBF19200000000', r);
});
});
describe('from_hex', function() {
it('"015841551A748AD2C1F76FF6ECB0CCCD00000000" === "XAU (-0.5%pa)"', function() {
var cur = currency.from_hex('015841551A748AD2C1F76FF6ECB0CCCD00000000');
assert.strictEqual(cur.to_hex(), '015841551A748AD2C1F76FF6ECB0CCCD00000000');
});
});
describe('parse_json', function() {
it('should parse a currency object', function() {
assert.strictEqual('USD', new currency().parse_json(currency.from_json('USD')).to_json());
});
it('should clone for parse_json on itself', function() {
var cur = currency.from_json('USD');
var cur2 = currency.from_json(cur);
assert.strictEqual(cur.to_json(), cur2.to_json());
cur = currency.from_hex('015841551A748AD2C1F76FF6ECB0CCCD00000000');
cur2 = currency.from_json(cur);
assert.strictEqual(cur.to_json(), cur2.to_json());
});
it('should parse json 0', function() {
var cur = currency.from_json(0);
assert.strictEqual(cur.to_json(), 'XRP');
assert.strictEqual(cur.get_iso(), 'XRP');
});
it('should parse json 0', function() {
var cur = currency.from_json('0');
assert.strictEqual(cur.to_json(), 'XRP');
assert.strictEqual(cur.get_iso(), 'XRP');
});
});
describe('is_valid', function() {
it('Currency.is_valid("XRP")', function() {
assert(currency.is_valid('XRP'));
});
it('!Currency.is_valid(NaN)', function() {
assert(!currency.is_valid(NaN));
});
it('from_json("XRP").is_valid()', function() {
assert(currency.from_json('XRP').is_valid());
});
it('!from_json(NaN).is_valid()', function() {
assert(!currency.from_json(NaN).is_valid());
});
});
describe('clone', function() {
it('should clone currency object', function() {
var c = currency.from_json('XRP');
assert.strictEqual('XRP', c.clone().to_json());
});
});
describe('get_iso', function() {
it('should get "XRP" iso_code', function() {
assert.strictEqual('XRP', currency.from_json('XRP').get_iso());
});
it('should get iso_code', function() {
assert.strictEqual('USD', currency.from_json('USD - US Dollar').get_iso());
});
it('should get iso_code', function() {
assert.strictEqual('USD', currency.from_json('USD (0.5%pa)').get_iso());
});
});
});

View File

@@ -5,7 +5,6 @@
const _ = require('lodash');
const assert = require('assert-diff');
const Remote = require('ripple-lib').Remote;
const Currency = require('ripple-lib').Currency;
const OrderbookUtils = require('ripple-lib')._test.OrderbookUtils;
const addresses = require('./fixtures/addresses');
const fixtures = require('./fixtures/orderbook');
@@ -33,10 +32,10 @@ describe('OrderBook Autobridging', function() {
issuer_pays: addresses.ISSUER
});
assert.deepEqual(book._legOneBook._currencyGets.to_hex(), Currency.from_json('XRP').to_hex());
assert.deepEqual(book._legOneBook._currencyPays.to_hex(), Currency.from_json('USD').to_hex());
assert.deepEqual(book._legTwoBook._currencyGets.to_hex(), Currency.from_json('EUR').to_hex());
assert.deepEqual(book._legTwoBook._currencyPays.to_hex(), Currency.from_json('XRP').to_hex());
assert.deepEqual(book._legOneBook._currencyGets, 'XRP');
assert.deepEqual(book._legOneBook._currencyPays, 'USD');
assert.deepEqual(book._legTwoBook._currencyGets, 'EUR');
assert.deepEqual(book._legTwoBook._currencyPays, 'XRP');
});
it('Compute autobridged offers', function(done) {

View File

@@ -4,7 +4,6 @@
const assert = require('assert-diff');
const Remote = require('ripple-lib').Remote;
const Currency = require('ripple-lib').Currency;
const Amount = require('ripple-lib').Amount;
const Meta = require('ripple-lib').Meta;
const addresses = require('./fixtures/addresses');
@@ -32,10 +31,10 @@ describe('OrderBook', function() {
assert.deepEqual(book.toJSON(), {
taker_gets: {
currency: Currency.from_json('XRP').to_hex()
currency: 'XRP'
},
taker_pays: {
currency: Currency.from_json('BTC').to_hex(),
currency: 'BTC',
issuer: addresses.ISSUER
}
});
@@ -48,11 +47,11 @@ describe('OrderBook', function() {
assert.deepEqual(book.toJSON(), {
taker_gets: {
currency: Currency.from_json('BTC').to_hex(),
currency: 'BTC',
issuer: addresses.ISSUER
},
taker_pays: {
currency: Currency.from_json('XRP').to_hex()
currency: 'XRP'
}
});
});
@@ -2446,10 +2445,10 @@ describe('OrderBook', function() {
command: 'book_offers',
id: undefined,
taker_gets: {
currency: '0000000000000000000000000000000000000000'
currency: 'XRP'
},
taker_pays: {
currency: '0000000000000000000000005553440000000000',
currency: 'USD',
issuer: addresses.ISSUER
},
taker: 'rrrrrrrrrrrrrrrrrrrrBZbvji',

View File

@@ -7,7 +7,6 @@ const lodash = require('lodash');
const Remote = require('ripple-lib').Remote;
const Server = require('ripple-lib').Server;
const Transaction = require('ripple-lib').Transaction;
const Currency = require('ripple-lib').Currency;
const Amount = require('ripple-lib').Amount;
const PathFind = require('ripple-lib')._test.PathFind;
const Log = require('ripple-lib')._test.Log;
@@ -921,7 +920,7 @@ describe('Remote', function() {
value: 1
}), {
issuer: 'rGr9PjmVe7MqEXTSbd3njhgJc2s5vpHV54',
currency: '0000000000000000000000005553440000000000'
currency: 'USD'
});
});
@@ -1612,11 +1611,11 @@ describe('Remote', function() {
command: 'book_offers',
id: undefined,
taker_gets: {
currency: Currency.from_json('USD').to_hex(),
currency: 'USD',
issuer: ADDRESS
},
taker_pays: {
currency: Currency.from_json('XRP').to_hex()
currency: 'XRP'
},
taker: ACCOUNT_ONE
});
@@ -1639,11 +1638,11 @@ describe('Remote', function() {
command: 'book_offers',
id: undefined,
taker_gets: {
currency: Currency.from_json('USD').to_hex(),
currency: 'USD',
issuer: ADDRESS
},
taker_pays: {
currency: Currency.from_json('XRP').to_hex()
currency: 'XRP'
},
taker: ACCOUNT_ONE,
ledger_hash: LEDGER_HASH,
@@ -1902,7 +1901,7 @@ describe('Remote', function() {
},
source_currencies: [{
issuer: 'rwxBjBC9fPzyQ9GgPZw6YYLNeRTSx5c2W6',
currency: '0000000000000000000000004254430000000000'
currency: 'BTC'
}]
});
});
@@ -2028,7 +2027,7 @@ describe('Remote', function() {
},
source_currencies: [{
issuer: 'rwxBjBC9fPzyQ9GgPZw6YYLNeRTSx5c2W6',
currency: '0000000000000000000000004254430000000000'
currency: 'BTC'
}]
});
});

View File

@@ -3,7 +3,6 @@ const assert = require('assert');
const Request = require('ripple-lib').Request;
const Remote = require('ripple-lib').Remote;
const Server = require('ripple-lib').Server;
const Currency = require('ripple-lib').Currency;
const RippleError = require('ripple-lib').RippleError;
function makeServer(url) {
@@ -940,11 +939,11 @@ describe('Request', function() {
assert.deepEqual(request.message.books, [
{
'taker_gets': {
'currency': Currency.from_json('EUR').to_hex(),
'currency': 'EUR',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'taker_pays': {
'currency': Currency.from_json('USD').to_hex(),
'currency': 'USD',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'snapshot': true
@@ -972,11 +971,11 @@ describe('Request', function() {
assert.deepEqual(request.message.books, [
{
'taker_gets': {
'currency': Currency.from_json('CNY').to_hex(),
'currency': 'CNY',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'taker_pays': {
'currency': Currency.from_json('USD').to_hex(),
'currency': 'USD',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'snapshot': true
@@ -1001,11 +1000,11 @@ describe('Request', function() {
assert.deepEqual(request.message.books, [
{
'taker_gets': {
'currency': '0000000000000000000000004555520000000000', // EUR hex
'currency': 'EUR',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'taker_pays': {
'currency': '0000000000000000000000005553440000000000', // USD hex
'currency': 'USD',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'snapshot': true
@@ -1059,11 +1058,11 @@ describe('Request', function() {
assert.deepEqual(request.message.books, [{
'taker_gets': {
'currency': Currency.from_json('EUR').to_hex(),
'currency': 'EUR',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'taker_pays': {
'currency': Currency.from_json('USD').to_hex(),
'currency': 'USD',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'both': true,
@@ -1095,11 +1094,11 @@ describe('Request', function() {
assert.deepEqual(request.message.books, [{
'taker_gets': {
'currency': Currency.from_json('EUR').to_hex(),
'currency': 'EUR',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'taker_pays': {
'currency': Currency.from_json('USD').to_hex(),
'currency': 'USD',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'both': true
@@ -1150,11 +1149,11 @@ describe('Request', function() {
'books': [
{
'taker_gets': {
'currency': '0000000000000000000000004555520000000000',
'currency': 'EUR',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'taker_pays': {
'currency': '0000000000000000000000005553440000000000',
'currency': 'USD',
'issuer': 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
'snapshot': true