From e03182367f408d0e1c37c1215ea8041705b9ffc3 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 11 Aug 2017 04:35:36 -0700 Subject: [PATCH] amount: allow overloading for num vs. str by default. --- lib/btc/amount.js | 103 ++++++++++++++++------------------------- lib/node/config.js | 2 +- lib/utils/util.js | 5 +- lib/utils/validator.js | 2 +- test/script-test.js | 2 +- 5 files changed, 43 insertions(+), 71 deletions(-) diff --git a/lib/btc/amount.js b/lib/btc/amount.js index 45984699..6b69d0c1 100644 --- a/lib/btc/amount.js +++ b/lib/btc/amount.js @@ -15,18 +15,17 @@ const util = require('../utils/util'); * @constructor * @param {(String|Number)?} value * @param {String?} unit - * @param {Boolean?} num * @property {Amount} value */ -function Amount(value, unit, num) { +function Amount(value, unit) { if (!(this instanceof Amount)) - return new Amount(value, unit, num); + return new Amount(value, unit); this.value = 0; if (value != null) - this.fromOptions(value, unit, num); + this.fromOptions(value, unit); } /** @@ -34,13 +33,12 @@ function Amount(value, unit, num) { * @private * @param {(String|Number)?} value * @param {String?} unit - * @param {Boolean?} num * @returns {Amount} */ -Amount.prototype.fromOptions = function fromOptions(value, unit, num) { +Amount.prototype.fromOptions = function fromOptions(value, unit) { if (typeof unit === 'string') - return this.from(unit, value, num); + return this.from(unit, value); if (typeof value === 'number') return this.fromValue(value); @@ -149,12 +147,11 @@ Amount.prototype.fromValue = function fromValue(value) { * Inject properties from satoshis. * @private * @param {Number|String} value - * @param {Bolean?} num * @returns {Amount} */ -Amount.prototype.fromSatoshis = function fromSatoshis(value, num) { - this.value = Amount.decode(value, 0, num); +Amount.prototype.fromSatoshis = function fromSatoshis(value) { + this.value = Amount.decode(value, 0); return this; }; @@ -162,12 +159,11 @@ Amount.prototype.fromSatoshis = function fromSatoshis(value, num) { * Inject properties from bits. * @private * @param {Number|String} value - * @param {Bolean?} num * @returns {Amount} */ -Amount.prototype.fromBits = function fromBits(value, num) { - this.value = Amount.decode(value, 2, num); +Amount.prototype.fromBits = function fromBits(value) { + this.value = Amount.decode(value, 2); return this; }; @@ -175,12 +171,11 @@ Amount.prototype.fromBits = function fromBits(value, num) { * Inject properties from mbtc. * @private * @param {Number|String} value - * @param {Bolean?} num * @returns {Amount} */ -Amount.prototype.fromMBTC = function fromMBTC(value, num) { - this.value = Amount.decode(value, 5, num); +Amount.prototype.fromMBTC = function fromMBTC(value) { + this.value = Amount.decode(value, 5); return this; }; @@ -188,12 +183,11 @@ Amount.prototype.fromMBTC = function fromMBTC(value, num) { * Inject properties from btc. * @private * @param {Number|String} value - * @param {Bolean?} num * @returns {Amount} */ -Amount.prototype.fromBTC = function fromBTC(value, num) { - this.value = Amount.decode(value, 8, num); +Amount.prototype.fromBTC = function fromBTC(value) { + this.value = Amount.decode(value, 8); return this; }; @@ -202,21 +196,20 @@ Amount.prototype.fromBTC = function fromBTC(value, num) { * @private * @param {String} unit * @param {Number|String} value - * @param {Bolean?} num * @returns {Amount} */ -Amount.prototype.from = function from(unit, value, num) { +Amount.prototype.from = function from(unit, value) { switch (unit) { case 'sat': - return this.fromSatoshis(value, num); + return this.fromSatoshis(value); case 'ubtc': case 'bits': - return this.fromBits(value, num); + return this.fromBits(value); case 'mbtc': - return this.fromMBTC(value, num); + return this.fromMBTC(value); case 'btc': - return this.fromBTC(value, num); + return this.fromBTC(value); } throw new Error(`Unknown unit "${unit}".`); }; @@ -225,12 +218,11 @@ Amount.prototype.from = function from(unit, value, num) { * Instantiate amount from options. * @param {(String|Number)?} value * @param {String?} unit - * @param {Boolean?} num * @returns {Amount} */ -Amount.fromOptions = function fromOptions(value, unit, num) { - return new Amount().fromOptions(value); +Amount.fromOptions = function fromOptions(value, unit) { + return new Amount().fromOptions(value, unit); }; /** @@ -247,57 +239,52 @@ Amount.fromValue = function fromValue(value) { /** * Instantiate amount from satoshis. * @param {Number|String} value - * @param {Bolean?} num * @returns {Amount} */ -Amount.fromSatoshis = function fromSatoshis(value, num) { - return new Amount().fromSatoshis(value, num); +Amount.fromSatoshis = function fromSatoshis(value) { + return new Amount().fromSatoshis(value); }; /** * Instantiate amount from bits. * @param {Number|String} value - * @param {Bolean?} num * @returns {Amount} */ -Amount.fromBits = function fromBits(value, num) { - return new Amount().fromBits(value, num); +Amount.fromBits = function fromBits(value) { + return new Amount().fromBits(value); }; /** * Instantiate amount from mbtc. * @param {Number|String} value - * @param {Bolean?} num * @returns {Amount} */ -Amount.fromMBTC = function fromMBTC(value, num) { - return new Amount().fromMBTC(value, num); +Amount.fromMBTC = function fromMBTC(value) { + return new Amount().fromMBTC(value); }; /** * Instantiate amount from btc. * @param {Number|String} value - * @param {Bolean?} num * @returns {Amount} */ -Amount.fromBTC = function fromBTC(value, num) { - return new Amount().fromBTC(value, num); +Amount.fromBTC = function fromBTC(value) { + return new Amount().fromBTC(value); }; /** * Instantiate amount from unit. * @param {String} unit * @param {Number|String} value - * @param {Bolean?} num * @returns {Amount} */ -Amount.from = function from(unit, value, num) { - return new Amount().from(unit, value, num); +Amount.from = function from(unit, value) { + return new Amount().from(unit, value); }; /** @@ -331,50 +318,38 @@ Amount.btc = function btc(value, num) { * @throws on parse error */ -Amount.value = function value(str, num) { +Amount.value = function value(str) { if (typeof str === 'number') return str; - return Amount.decode(str, 8, num); + return Amount.decode(str, 8); }; /** * Safely convert satoshis to a BTC string. - * This function explicitly avoids any - * floating point arithmetic. * @param {Amount} value * @param {Number} exp - Exponent. * @param {Boolean} num - Return a number. - * @returns {String} + * @returns {String|Number} */ Amount.encode = function encode(value, exp, num) { const str = util.toFixed(value, exp); - - if (num) - return Number(str); - - return str; + return num ? Number(str) : str; }; /** * Safely convert a BTC string to satoshis. - * This function explicitly avoids any - * floating point arithmetic. It also does - * extra validation to ensure the resulting - * Number will be 53 bits or less. - * @param {String} str - BTC + * @param {String|Number} value - BTC * @param {Number} exp - Exponent. - * @param {Boolean} num - Allow numbers. * @returns {Amount} Satoshis. * @throws on parse error */ -Amount.decode = function decode(str, exp, num) { - if (num && typeof str === 'number') - str = str.toString(10); - - return util.fromFixed(str, exp); +Amount.decode = function decode(value, exp) { + if (typeof value === 'number') + return util.fromFloat(value, exp); + return util.fromFixed(value, exp); }; /* diff --git a/lib/node/config.js b/lib/node/config.js index 88cda889..8500bbf9 100644 --- a/lib/node/config.js +++ b/lib/node/config.js @@ -416,7 +416,7 @@ Config.prototype.fixed = function fixed(key, exp, fallback) { return fallback; try { - return util.fromDouble(value, exp || 0); + return util.fromFloat(value, exp || 0); } catch (e) { throw new Error(`${fmt(key)} must be a fixed number.`); } diff --git a/lib/utils/util.js b/lib/utils/util.js index ae295dd9..90e7cdbf 100644 --- a/lib/utils/util.js +++ b/lib/utils/util.js @@ -855,9 +855,6 @@ util.toFixed = function toFixed(num, exp) { assert(lo.length <= exp, 'Invalid integer value.'); if (lo.length === 0) - lo = '0'; - - if (exp === 0) return `${sign}${hi}`; return `${sign}${hi}.${lo}`; @@ -871,7 +868,7 @@ util.toFixed = function toFixed(num, exp) { * @returns {Number} */ -util.fromDouble = function fromDouble(num, exp) { +util.fromFloat = function fromFloat(num, exp) { assert(typeof num === 'number' && isFinite(num)); assert(Number.isSafeInteger(exp)); return util.fromFixed(num.toFixed(exp), exp); diff --git a/lib/utils/validator.js b/lib/utils/validator.js index 9f0afa99..15985143 100644 --- a/lib/utils/validator.js +++ b/lib/utils/validator.js @@ -273,7 +273,7 @@ Validator.prototype.fixed = function fixed(key, exp, fallback) { return fallback; try { - return util.fromDouble(value, exp || 0); + return util.fromFloat(value, exp || 0); } catch (e) { throw new ValidationError(key, 'fixed number'); } diff --git a/test/script-test.js b/test/script-test.js index 636664f8..74c9eaa3 100644 --- a/test/script-test.js +++ b/test/script-test.js @@ -39,7 +39,7 @@ function parseScriptTest(data) { let value = 0; if (witArr.length > 0) - value = util.fromDouble(witArr.pop(), 8); + value = util.fromFloat(witArr.pop(), 8); const witness = Witness.fromString(witArr); const input = Script.fromString(inpHex);