diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 0f307cd2..d3e28395 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -9,8 +9,8 @@ "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz" }, "babel-runtime": { - "version": "5.8.24", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.24.tgz", + "version": "5.8.25", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.25.tgz", "dependencies": { "core-js": { "version": "1.1.4", @@ -117,12 +117,12 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.2.tgz" }, "ripple-address-codec": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-1.6.0.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-2.0.1.tgz", "dependencies": { "x-address-codec": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/x-address-codec/-/x-address-codec-0.6.0.tgz", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/x-address-codec/-/x-address-codec-0.7.0.tgz", "dependencies": { "base-x": { "version": "1.0.1", @@ -149,6 +149,22 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } + }, + "ripple-address-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-1.6.0.tgz", + "dependencies": { + "x-address-codec": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/x-address-codec/-/x-address-codec-0.6.0.tgz", + "dependencies": { + "base-x": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-1.0.1.tgz" + } + } + } + } } } }, @@ -168,6 +184,20 @@ "version": "0.7.2", "resolved": "https://registry.npmjs.org/ws/-/ws-0.7.2.tgz", "dependencies": { + "bufferutil": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-1.1.0.tgz", + "dependencies": { + "bindings": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" + }, + "nan": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz" + } + } + }, "options": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz" @@ -175,6 +205,20 @@ "ultron": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz" + }, + "utf-8-validate": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-1.1.0.tgz", + "dependencies": { + "bindings": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" + }, + "nan": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz" + } + } } } } diff --git a/package.json b/package.json index d422f3cc..d1046bd7 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "is-my-json-valid": "^2.12.2", "lodash": "^3.1.0", "lru-cache": "~2.5.0", - "ripple-address-codec": "^1.6.0", + "ripple-address-codec": "^2.0.1", "ripple-keypairs": "^0.9.0", "ripple-lib-transactionparser": "^0.5.1", "ripple-lib-value": "0.1.0", diff --git a/src/core/account.js b/src/core/account.js index 3e3267bf..1af60f19 100644 --- a/src/core/account.js +++ b/src/core/account.js @@ -17,7 +17,7 @@ const util = require('util'); const {deriveAddress} = require('ripple-keypairs'); const {EventEmitter} = require('events'); const {TransactionManager} = require('./transactionmanager'); -const {UInt160} = require('./uint160'); +const {isValidAddress} = require('ripple-address-codec'); /** * @constructor Account @@ -25,14 +25,13 @@ const {UInt160} = require('./uint160'); * @param {String} account */ -function Account(remote, account) { +function Account(remote, address) { EventEmitter.call(this); const self = this; this._remote = remote; - this._account = UInt160.from_json(account); - this._account_id = this._account.to_json(); + this._address = address; this._subs = 0; // Ledger entry object @@ -43,7 +42,7 @@ function Account(remote, account) { if (_.includes(Account.subscribeEvents, type)) { if (!self._subs && self._remote._connected) { self._remote.requestSubscribe() - .addAccount(self._account_id) + .addAccount(self._address) .broadcast().request(); } self._subs += 1; @@ -57,7 +56,7 @@ function Account(remote, account) { self._subs -= 1; if (!self._subs && self._remote._connected) { self._remote.requestUnsubscribe() - .addAccount(self._account_id) + .addAccount(self._address) .broadcast().request(); } } @@ -66,8 +65,8 @@ function Account(remote, account) { this.on('removeListener', listenerRemoved); function attachAccount(request) { - if (self._account.is_valid() && self._subs) { - request.addAccount(self._account_id); + if (isValidAddress(self._address) && self._subs) { + request.addAccount(self._address); } } @@ -81,7 +80,7 @@ function Account(remote, account) { let changed = false; transaction.mmeta.each(function(an) { - const isAccount = an.fields.Account === self._account_id; + const isAccount = an.fields.Account === self._address; const isAccountRoot = isAccount && (an.entryType === 'AccountRoot'); if (isAccountRoot) { @@ -111,7 +110,7 @@ util.inherits(Account, EventEmitter); Account.subscribeEvents = ['transaction', 'entry']; Account.prototype.toJson = function() { - return this._account.to_json(); + return this._address; }; /** @@ -121,7 +120,7 @@ Account.prototype.toJson = function() { */ Account.prototype.isValid = function() { - return this._account.is_valid(); + return isValidAddress(this._address); }; /** @@ -131,7 +130,7 @@ Account.prototype.isValid = function() { */ Account.prototype.getInfo = function(callback) { - return this._remote.requestAccountInfo({account: this._account_id}, callback); + return this._remote.requestAccountInfo({account: this._address}, callback); }; /** @@ -210,7 +209,7 @@ Account.prototype.lines = function(callback_) { } } - this._remote.requestAccountLines({account: this._account_id}, accountLines); + this._remote.requestAccountLines({account: this._address}, accountLines); return this; }; @@ -275,7 +274,7 @@ Account.prototype.notifyTx = function(transaction) { return; } - const isThisAccount = (account === this._account_id); + const isThisAccount = (account === this._address); this.emit(isThisAccount ? 'transaction-outbound' : 'transaction-inbound', transaction); @@ -331,7 +330,7 @@ Account.prototype.publicKeyIsActive = function(public_key, callback) { // Catch the case of unfunded accounts if (!account_info_res) { - if (public_key_as_uint160 === self._account_id) { + if (public_key_as_uint160 === self._address) { async_callback(null, true); } else { async_callback(null, false); @@ -373,20 +372,17 @@ Account.prototype.publicKeyIsActive = function(public_key, callback) { * @returns {RippleAddress} Ripple Address */ Account._publicKeyToAddress = function(public_key) { - // Based on functions in /src/js/ripple/keypair.js - function hexToUInt160(publicKey) { - return deriveAddress(publicKey); - } - - if (UInt160.is_valid(public_key)) { + if (isValidAddress(public_key)) { return public_key; } else if (/^[0-9a-fA-F]+$/.test(public_key)) { - return hexToUInt160(public_key); + return deriveAddress(public_key); } else { // eslint-disable-line no-else-return throw new Error('Public key is invalid. Must be a UInt160 or a hex string'); } }; -exports.Account = Account; +module.exports = { + Account +}; // vim:sw=2:sts=2:ts=8:et diff --git a/src/core/amount.js b/src/core/amount.js index 0a7a1224..f2959d4d 100644 --- a/src/core/amount.js +++ b/src/core/amount.js @@ -6,9 +6,10 @@ const assert = require('assert'); const extend = require('extend'); const utils = require('./utils'); -const UInt160 = require('./uint160').UInt160; const Currency = require('./currency').Currency; const {XRPValue, IOUValue} = require('ripple-lib-value'); +const {isValidAddress} = require('ripple-address-codec'); +const {ACCOUNT_ONE, ACCOUNT_ZERO} = 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._issuer = new UInt160(); + this._issuer = 'NaN'; } /** @@ -105,7 +106,7 @@ Amount.NaN = function() { }; Amount.from_components_unsafe = function(value: Value, currency: Currency, - issuer: UInt160, isNative: boolean + issuer: string, isNative: boolean ) { const result = new Amount(value); result._is_native = isNative; @@ -402,7 +403,7 @@ Amount.prototype.equals = function(d, ignore_issuer) { && this._is_native === d._is_native && this._value.equals(d._value) && (this._is_native || (this._currency.equals(d._currency) - && (ignore_issuer || this._issuer.equals(d._issuer)))); + && (ignore_issuer || this._issuer === d._issuer))); }; // True if Amounts are valid and both native or non-native. @@ -428,9 +429,8 @@ Amount.prototype.is_valid = function() { }; Amount.prototype.is_valid_full = function() { - return this.is_valid() - && this._currency.is_valid() - && this._issuer.is_valid(); + return this.is_valid() && this._currency.is_valid() + && isValidAddress(this._issuer) && this._issuer !== ACCOUNT_ZERO; }; Amount.prototype.is_zero = function() { @@ -532,7 +532,7 @@ Amount.prototype.parse_human = function(j, options) { }; Amount.prototype.parse_issuer = function(issuer) { - this._issuer = UInt160.from_json(issuer); + this._issuer = issuer; return this; }; @@ -583,7 +583,7 @@ function(quality, counterCurrency, counterIssuer, opts) { const offset = parseInt(offset_hex, 16) - 100; this._currency = Currency.from_json(counterCurrency); - this._issuer = UInt160.from_json(counterIssuer); + this._issuer = counterIssuer; this._is_native = this._currency.is_native(); if (this._is_native && baseCurrency.is_native()) { @@ -643,7 +643,7 @@ function(quality, counterCurrency, counterIssuer, opts) { Amount.prototype.parse_number = function(n) { this._is_native = false; this._currency = Currency.from_json(1); - this._issuer = UInt160.from_json(1); + this._issuer = ACCOUNT_ONE; this._set_value(new IOUValue(n)); return this; }; @@ -659,15 +659,15 @@ Amount.prototype.parse_json = function(j) { if (m) { this._currency = Currency.from_json(m[2]); if (m[3]) { - this._issuer = UInt160.from_json(m[3]); + this._issuer = m[3]; } else { - this._issuer = UInt160.from_json('1'); + this._issuer = 'NaN'; } this.parse_value(m[1]); } else { this.parse_native(j); this._currency = Currency.from_json('0'); - this._issuer = UInt160.from_json('0'); + this._issuer = ACCOUNT_ZERO; } break; @@ -686,9 +686,10 @@ Amount.prototype.parse_json = function(j) { // Parse the passed value to sanitize and copy it. this._currency.parse_json(j.currency, true); // Never XRP. - if (typeof j.issuer === 'string') { - this._issuer.parse_json(j.issuer); + if (typeof j.issuer !== 'string') { + throw new Error('issuer must be a string'); } + this._issuer = j.issuer; this.parse_value(j.value); } @@ -736,12 +737,7 @@ Amount.prototype.set_currency = function(c) { }; Amount.prototype.set_issuer = function(issuer) { - if (issuer instanceof UInt160) { - this._issuer = issuer; - } else { - this._issuer = UInt160.from_json(issuer); - } - + this._issuer = issuer; return this; }; @@ -939,7 +935,7 @@ Amount.prototype.to_human_full = function(options) { const opts = options || {}; const value = this.to_human(opts); const currency = this._currency.to_human(); - const issuer = this._issuer.to_json(opts); + const issuer = this._issuer; const base = value + '/' + currency; return this.is_native() ? base : (base + '/' + issuer); }; @@ -955,21 +951,21 @@ Amount.prototype.to_json = function() { this._currency.to_hex() : this._currency.to_json() }; - if (this._issuer.is_valid()) { - amount_json.issuer = this._issuer.to_json(); + if (isValidAddress(this._issuer)) { + amount_json.issuer = this._issuer; } return amount_json; }; -Amount.prototype.to_text_full = function(opts) { +Amount.prototype.to_text_full = function() { if (!this.is_valid()) { return 'NaN'; } return this._is_native ? this.to_human() + '/XRP' : this.to_text() + '/' + this._currency.to_json() - + '/' + this._issuer.to_json(opts); + + '/' + this._issuer; }; // For debugging. @@ -998,11 +994,8 @@ Amount.prototype.not_equals_why = function(d, ignore_issuer) { if (!this._currency.equals(d._currency)) { return 'Non-XRP currency differs.'; } - if (!ignore_issuer && !this._issuer.equals(d._issuer)) { - return 'Non-XRP issuer differs: ' - + d._issuer.to_json() - + '/' - + this._issuer.to_json(); + if (!ignore_issuer && this._issuer !== d._issuer) { + return 'Non-XRP issuer differs: ' + d._issuer + '/' + this._issuer; } } }; diff --git a/src/core/constants.js b/src/core/constants.js new file mode 100644 index 00000000..3adbdbf9 --- /dev/null +++ b/src/core/constants.js @@ -0,0 +1,6 @@ +'use strict'; + +module.exports = { + ACCOUNT_ZERO: 'rrrrrrrrrrrrrrrrrrrrrhoLvTp', + ACCOUNT_ONE: 'rrrrrrrrrrrrrrrrrrrrBZbvji' +}; diff --git a/src/core/meta.js b/src/core/meta.js index c4f9b781..d1b026c3 100644 --- a/src/core/meta.js +++ b/src/core/meta.js @@ -1,7 +1,10 @@ -var extend = require('extend'); -var utils = require('./utils'); -var UInt160 = require('./uint160').UInt160; -var Amount = require('./amount').Amount; +'use strict'; +const extend = require('extend'); +const utils = require('./utils'); +const UInt160 = require('./uint160').UInt160; +const Amount = require('./amount').Amount; +const ACCOUNT_ZERO = require('./constants').ACCOUNT_ZERO; +const {isValidAddress} = require('ripple-address-codec'); /** * Meta data processing facility @@ -11,8 +14,6 @@ var Amount = require('./amount').Amount; */ function Meta(data) { - var self = this; - this.nodes = [ ]; if (typeof data !== 'object') { @@ -24,7 +25,7 @@ function Meta(data) { } data.AffectedNodes.forEach(this.addNode, this); -}; +} Meta.NODE_TYPES = [ 'CreatedNode', @@ -53,10 +54,10 @@ Meta.ACCOUNT_FIELDS = [ */ Meta.prototype.getNodeType = function(node) { - var result = null; + let result = null; - for (var i=0; i 254) { @@ -416,7 +417,8 @@ exports.Quality = new SerializedType({ value = new BigNumber(val); } - let hi = 0, lo = 0; + let hi = 0; + let lo = 0; const offset = value.e - 15; if (val !== 0) { @@ -483,7 +485,8 @@ const STAmount = exports.Amount = new SerializedType({ valueBytes[0] |= 0x40; } } else { - let hi = 0, lo = 0; + let hi = 0; + let lo = 0; // First bit: non-native hi |= 1 << 31; @@ -518,7 +521,7 @@ const STAmount = exports.Amount = new SerializedType({ STCurrency.serialize(so, currency, true); // Issuer (160-bit hash) - so.append(amount.issuer().to_bytes()); + so.append(UInt160.from_json(amount.issuer()).to_bytes()); } }, parse: function(so) { @@ -834,7 +837,7 @@ exports.STMemo = new SerializedType({ output.parsed_memo_data = convertHexToString(output.MemoData); } /* eslint-disable no-empty */ - } catch(e) { + } catch (e) { // empty // we'll fail in case the content does not match what the MemoFormat // described diff --git a/src/core/transaction.js b/src/core/transaction.js index 90e455fe..0a54b4cb 100644 --- a/src/core/transaction.js +++ b/src/core/transaction.js @@ -14,6 +14,7 @@ const SerializedObject = require('./serializedobject').SerializedObject; const RippleError = require('./rippleerror').RippleError; const hashprefixes = require('./hashprefixes'); const log = require('./log').internal.sub('transaction'); +const {isValidAddress} = require('ripple-address-codec'); /** * @constructor Transaction @@ -722,7 +723,7 @@ Transaction.prototype._setAmount = function(name, amount, options_) { if (!(isNative || parsedAmount.currency().is_valid())) { throw new Error(name + ' must have a valid currency'); } - if (!(isNative || parsedAmount.issuer().is_valid())) { + if (!(isNative || isValidAddress(parsedAmount.issuer()))) { throw new Error(name + ' must have a valid issuer'); } diff --git a/src/core/transactionmanager.js b/src/core/transactionmanager.js index 3406e30f..fb5c241d 100644 --- a/src/core/transactionmanager.js +++ b/src/core/transactionmanager.js @@ -21,7 +21,7 @@ function TransactionManager(account) { const self = this; this._account = account; - this._accountID = account._account_id; + this._accountID = account._address; this._remote = account._remote; this._nextSequence = undefined; this._maxFee = this._remote.max_fee;