btc: classify.
This commit is contained in:
parent
51e3341252
commit
32b81f0d95
@ -10,348 +10,353 @@ const assert = require('assert');
|
||||
const fixed = require('../utils/fixed');
|
||||
|
||||
/**
|
||||
* Amount
|
||||
* Represents a bitcoin amount (satoshis internally).
|
||||
* @alias module:btc.Amount
|
||||
* @constructor
|
||||
* @param {(String|Number)?} value
|
||||
* @param {String?} unit
|
||||
* @property {Amount} value
|
||||
*/
|
||||
|
||||
function Amount(value, unit) {
|
||||
if (!(this instanceof Amount))
|
||||
return new Amount(value, unit);
|
||||
class Amount {
|
||||
/**
|
||||
* Create an amount.
|
||||
* @constructor
|
||||
* @param {(String|Number)?} value
|
||||
* @param {String?} unit
|
||||
*/
|
||||
|
||||
this.value = 0;
|
||||
constructor(value, unit) {
|
||||
this.value = 0;
|
||||
|
||||
if (value != null)
|
||||
this.fromOptions(value, unit);
|
||||
}
|
||||
if (value != null)
|
||||
this.fromOptions(value, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject properties from options.
|
||||
* @private
|
||||
* @param {(String|Number)?} value
|
||||
* @param {String?} unit
|
||||
* @returns {Amount}
|
||||
*/
|
||||
/**
|
||||
* Inject properties from options.
|
||||
* @private
|
||||
* @param {(String|Number)?} value
|
||||
* @param {String?} unit
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.fromOptions = function fromOptions(value, unit) {
|
||||
if (typeof unit === 'string')
|
||||
return this.from(unit, value);
|
||||
fromOptions(value, unit) {
|
||||
if (typeof unit === 'string')
|
||||
return this.from(unit, value);
|
||||
|
||||
if (typeof value === 'number')
|
||||
return this.fromValue(value);
|
||||
if (typeof value === 'number')
|
||||
return this.fromValue(value);
|
||||
|
||||
return this.fromBTC(value);
|
||||
};
|
||||
return this.fromBTC(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get satoshi value.
|
||||
* @returns {Amount}
|
||||
*/
|
||||
/**
|
||||
* Get satoshi value.
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.toValue = function toValue() {
|
||||
return this.value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get satoshi string or value.
|
||||
* @param {Boolean?} num
|
||||
* @returns {String|Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.toSatoshis = function toSatoshis(num) {
|
||||
if (num)
|
||||
toValue() {
|
||||
return this.value;
|
||||
|
||||
return this.value.toString(10);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get bits string or value.
|
||||
* @param {Boolean?} num
|
||||
* @returns {String|Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.toBits = function toBits(num) {
|
||||
return Amount.encode(this.value, 2, num);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get mbtc string or value.
|
||||
* @param {Boolean?} num
|
||||
* @returns {String|Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.toMBTC = function toMBTC(num) {
|
||||
return Amount.encode(this.value, 5, num);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get btc string or value.
|
||||
* @param {Boolean?} num
|
||||
* @returns {String|Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.toBTC = function toBTC(num) {
|
||||
return Amount.encode(this.value, 8, num);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get unit string or value.
|
||||
* @param {String} unit - Can be `sat`,
|
||||
* `ubtc`, `bits`, `mbtc`, or `btc`.
|
||||
* @param {Boolean?} num
|
||||
* @returns {String|Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.to = function to(unit, num) {
|
||||
switch (unit) {
|
||||
case 'sat':
|
||||
return this.toSatoshis(num);
|
||||
case 'ubtc':
|
||||
case 'bits':
|
||||
return this.toBits(num);
|
||||
case 'mbtc':
|
||||
return this.toMBTC(num);
|
||||
case 'btc':
|
||||
return this.toBTC(num);
|
||||
}
|
||||
throw new Error(`Unknown unit "${unit}".`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert amount to bitcoin string.
|
||||
* @returns {String}
|
||||
*/
|
||||
/**
|
||||
* Get satoshi string or value.
|
||||
* @param {Boolean?} num
|
||||
* @returns {String|Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.toString = function toString() {
|
||||
return this.toBTC();
|
||||
};
|
||||
toSatoshis(num) {
|
||||
if (num)
|
||||
return this.value;
|
||||
|
||||
/**
|
||||
* Inject properties from value.
|
||||
* @private
|
||||
* @param {Amount} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.fromValue = function fromValue(value) {
|
||||
assert(Number.isSafeInteger(value) && value >= 0, 'Value must be an int64.');
|
||||
this.value = value;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from satoshis.
|
||||
* @private
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.fromSatoshis = function fromSatoshis(value) {
|
||||
this.value = Amount.decode(value, 0);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from bits.
|
||||
* @private
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.fromBits = function fromBits(value) {
|
||||
this.value = Amount.decode(value, 2);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from mbtc.
|
||||
* @private
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.fromMBTC = function fromMBTC(value) {
|
||||
this.value = Amount.decode(value, 5);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from btc.
|
||||
* @private
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.fromBTC = function fromBTC(value) {
|
||||
this.value = Amount.decode(value, 8);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from unit.
|
||||
* @private
|
||||
* @param {String} unit
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.from = function from(unit, value) {
|
||||
switch (unit) {
|
||||
case 'sat':
|
||||
return this.fromSatoshis(value);
|
||||
case 'ubtc':
|
||||
case 'bits':
|
||||
return this.fromBits(value);
|
||||
case 'mbtc':
|
||||
return this.fromMBTC(value);
|
||||
case 'btc':
|
||||
return this.fromBTC(value);
|
||||
return this.value.toString(10);
|
||||
}
|
||||
throw new Error(`Unknown unit "${unit}".`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate amount from options.
|
||||
* @param {(String|Number)?} value
|
||||
* @param {String?} unit
|
||||
* @returns {Amount}
|
||||
*/
|
||||
/**
|
||||
* Get bits string or value.
|
||||
* @param {Boolean?} num
|
||||
* @returns {String|Amount}
|
||||
*/
|
||||
|
||||
Amount.fromOptions = function fromOptions(value, unit) {
|
||||
return new Amount().fromOptions(value, unit);
|
||||
};
|
||||
toBits(num) {
|
||||
return Amount.encode(this.value, 2, num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from value.
|
||||
* @private
|
||||
* @param {Amount} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
/**
|
||||
* Get mbtc string or value.
|
||||
* @param {Boolean?} num
|
||||
* @returns {String|Amount}
|
||||
*/
|
||||
|
||||
Amount.fromValue = function fromValue(value) {
|
||||
return new Amount().fromValue(value);
|
||||
};
|
||||
toMBTC(num) {
|
||||
return Amount.encode(this.value, 5, num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from satoshis.
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
/**
|
||||
* Get btc string or value.
|
||||
* @param {Boolean?} num
|
||||
* @returns {String|Amount}
|
||||
*/
|
||||
|
||||
Amount.fromSatoshis = function fromSatoshis(value) {
|
||||
return new Amount().fromSatoshis(value);
|
||||
};
|
||||
toBTC(num) {
|
||||
return Amount.encode(this.value, 8, num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from bits.
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
/**
|
||||
* Get unit string or value.
|
||||
* @param {String} unit - Can be `sat`,
|
||||
* `ubtc`, `bits`, `mbtc`, or `btc`.
|
||||
* @param {Boolean?} num
|
||||
* @returns {String|Amount}
|
||||
*/
|
||||
|
||||
Amount.fromBits = function fromBits(value) {
|
||||
return new Amount().fromBits(value);
|
||||
};
|
||||
to(unit, num) {
|
||||
switch (unit) {
|
||||
case 'sat':
|
||||
return this.toSatoshis(num);
|
||||
case 'ubtc':
|
||||
case 'bits':
|
||||
return this.toBits(num);
|
||||
case 'mbtc':
|
||||
return this.toMBTC(num);
|
||||
case 'btc':
|
||||
return this.toBTC(num);
|
||||
}
|
||||
throw new Error(`Unknown unit "${unit}".`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from mbtc.
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
/**
|
||||
* Convert amount to bitcoin string.
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
Amount.fromMBTC = function fromMBTC(value) {
|
||||
return new Amount().fromMBTC(value);
|
||||
};
|
||||
toString() {
|
||||
return this.toBTC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from btc.
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
/**
|
||||
* Inject properties from value.
|
||||
* @private
|
||||
* @param {Amount} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.fromBTC = function fromBTC(value) {
|
||||
return new Amount().fromBTC(value);
|
||||
};
|
||||
fromValue(value) {
|
||||
assert(Number.isSafeInteger(value) && value >= 0,
|
||||
'Value must be an int64.');
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from unit.
|
||||
* @param {String} unit
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
/**
|
||||
* Inject properties from satoshis.
|
||||
* @private
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.from = function from(unit, value) {
|
||||
return new Amount().from(unit, value);
|
||||
};
|
||||
fromSatoshis(value) {
|
||||
this.value = Amount.decode(value, 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspect amount.
|
||||
* @returns {String}
|
||||
*/
|
||||
/**
|
||||
* Inject properties from bits.
|
||||
* @private
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.prototype.inspect = function inspect() {
|
||||
return `<Amount: ${this.toString()}>`;
|
||||
};
|
||||
fromBits(value) {
|
||||
this.value = Amount.decode(value, 2);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely convert satoshis to a BTC string.
|
||||
* This function explicitly avoids any
|
||||
* floating point arithmetic.
|
||||
* @param {Amount} value - Satoshis.
|
||||
* @returns {String} BTC string.
|
||||
*/
|
||||
/**
|
||||
* Inject properties from mbtc.
|
||||
* @private
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.btc = function btc(value, num) {
|
||||
if (typeof value === 'string')
|
||||
return value;
|
||||
fromMBTC(value) {
|
||||
this.value = Amount.decode(value, 5);
|
||||
return this;
|
||||
}
|
||||
|
||||
return Amount.encode(value, 8, num);
|
||||
};
|
||||
/**
|
||||
* Inject properties from btc.
|
||||
* @private
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Safely convert a BTC string to satoshis.
|
||||
* @param {String} str - BTC
|
||||
* @returns {Amount} Satoshis.
|
||||
* @throws on parse error
|
||||
*/
|
||||
fromBTC(value) {
|
||||
this.value = Amount.decode(value, 8);
|
||||
return this;
|
||||
}
|
||||
|
||||
Amount.value = function value(str) {
|
||||
if (typeof str === 'number')
|
||||
return str;
|
||||
/**
|
||||
* Inject properties from unit.
|
||||
* @private
|
||||
* @param {String} unit
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
return Amount.decode(str, 8);
|
||||
};
|
||||
from(unit, value) {
|
||||
switch (unit) {
|
||||
case 'sat':
|
||||
return this.fromSatoshis(value);
|
||||
case 'ubtc':
|
||||
case 'bits':
|
||||
return this.fromBits(value);
|
||||
case 'mbtc':
|
||||
return this.fromMBTC(value);
|
||||
case 'btc':
|
||||
return this.fromBTC(value);
|
||||
}
|
||||
throw new Error(`Unknown unit "${unit}".`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely convert satoshis to a BTC string.
|
||||
* @param {Amount} value
|
||||
* @param {Number} exp - Exponent.
|
||||
* @param {Boolean} num - Return a number.
|
||||
* @returns {String|Number}
|
||||
*/
|
||||
/**
|
||||
* Instantiate amount from options.
|
||||
* @param {(String|Number)?} value
|
||||
* @param {String?} unit
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.encode = function encode(value, exp, num) {
|
||||
if (num)
|
||||
return fixed.toFloat(value, exp);
|
||||
return fixed.encode(value, exp);
|
||||
};
|
||||
static fromOptions(value, unit) {
|
||||
return new this().fromOptions(value, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely convert a BTC string to satoshis.
|
||||
* @param {String|Number} value - BTC
|
||||
* @param {Number} exp - Exponent.
|
||||
* @returns {Amount} Satoshis.
|
||||
* @throws on parse error
|
||||
*/
|
||||
/**
|
||||
* Instantiate amount from value.
|
||||
* @private
|
||||
* @param {Amount} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Amount.decode = function decode(value, exp) {
|
||||
if (typeof value === 'number')
|
||||
return fixed.fromFloat(value, exp);
|
||||
return fixed.decode(value, exp);
|
||||
};
|
||||
static fromValue(value) {
|
||||
return new this().fromValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from satoshis.
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
static fromSatoshis(value) {
|
||||
return new this().fromSatoshis(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from bits.
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
static fromBits(value) {
|
||||
return new this().fromBits(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from mbtc.
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
static fromMBTC(value) {
|
||||
return new this().fromMBTC(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from btc.
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
static fromBTC(value) {
|
||||
return new this().fromBTC(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate amount from unit.
|
||||
* @param {String} unit
|
||||
* @param {Number|String} value
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
static from(unit, value) {
|
||||
return new this().from(unit, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspect amount.
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
inspect() {
|
||||
return `<Amount: ${this.toString()}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely convert satoshis to a BTC string.
|
||||
* This function explicitly avoids any
|
||||
* floating point arithmetic.
|
||||
* @param {Amount} value - Satoshis.
|
||||
* @returns {String} BTC string.
|
||||
*/
|
||||
|
||||
static btc(value, num) {
|
||||
if (typeof value === 'string')
|
||||
return value;
|
||||
|
||||
return Amount.encode(value, 8, num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely convert a BTC string to satoshis.
|
||||
* @param {String} str - BTC
|
||||
* @returns {Amount} Satoshis.
|
||||
* @throws on parse error
|
||||
*/
|
||||
|
||||
static value(str) {
|
||||
if (typeof str === 'number')
|
||||
return str;
|
||||
|
||||
return Amount.decode(str, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely convert satoshis to a BTC string.
|
||||
* @param {Amount} value
|
||||
* @param {Number} exp - Exponent.
|
||||
* @param {Boolean} num - Return a number.
|
||||
* @returns {String|Number}
|
||||
*/
|
||||
|
||||
static encode(value, exp, num) {
|
||||
if (num)
|
||||
return fixed.toFloat(value, exp);
|
||||
return fixed.encode(value, exp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely convert a BTC string to satoshis.
|
||||
* @param {String|Number} value - BTC
|
||||
* @param {Number} exp - Exponent.
|
||||
* @returns {Amount} Satoshis.
|
||||
* @throws on parse error
|
||||
*/
|
||||
|
||||
static decode(value, exp) {
|
||||
if (typeof value === 'number')
|
||||
return fixed.fromFloat(value, exp);
|
||||
return fixed.decode(value, exp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose
|
||||
|
||||
290
lib/btc/uri.js
290
lib/btc/uri.js
@ -11,10 +11,9 @@ const Address = require('../primitives/address');
|
||||
const Amount = require('./amount');
|
||||
|
||||
/**
|
||||
* URI
|
||||
* Represents a bitcoin URI.
|
||||
* @alias module:btc.URI
|
||||
* @constructor
|
||||
* @param {Object|String} options
|
||||
* @property {Address} address
|
||||
* @property {Amount} amount
|
||||
* @property {String|null} label
|
||||
@ -22,185 +21,194 @@ const Amount = require('./amount');
|
||||
* @property {String|null} request
|
||||
*/
|
||||
|
||||
function URI(options) {
|
||||
if (!(this instanceof URI))
|
||||
return new URI(options);
|
||||
class URI {
|
||||
/**
|
||||
* Create a bitcoin URI.
|
||||
* @alias module:btc.URI
|
||||
* @constructor
|
||||
* @param {Object|String} options
|
||||
*/
|
||||
|
||||
this.address = new Address();
|
||||
this.amount = -1;
|
||||
this.label = null;
|
||||
this.message = null;
|
||||
this.request = null;
|
||||
constructor(options) {
|
||||
this.address = new Address();
|
||||
this.amount = -1;
|
||||
this.label = null;
|
||||
this.message = null;
|
||||
this.request = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject properties from options object.
|
||||
* @private
|
||||
* @param {Object|String} options
|
||||
* @returns {URI}
|
||||
*/
|
||||
|
||||
URI.prototype.fromOptions = function fromOptions(options) {
|
||||
if (typeof options === 'string')
|
||||
return this.fromString(options);
|
||||
|
||||
if (options.address)
|
||||
this.address.fromOptions(options.address);
|
||||
|
||||
if (options.amount != null) {
|
||||
assert(Number.isSafeInteger(options.amount) && options.amount >= 0,
|
||||
'Amount must be a uint64.');
|
||||
this.amount = options.amount;
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
if (options.label) {
|
||||
assert(typeof options.label === 'string', 'Label must be a string.');
|
||||
this.label = options.label;
|
||||
}
|
||||
/**
|
||||
* Inject properties from options object.
|
||||
* @private
|
||||
* @param {Object|String} options
|
||||
* @returns {URI}
|
||||
*/
|
||||
|
||||
if (options.message) {
|
||||
assert(typeof options.message === 'string', 'Message must be a string.');
|
||||
this.message = options.message;
|
||||
}
|
||||
fromOptions(options) {
|
||||
if (typeof options === 'string')
|
||||
return this.fromString(options);
|
||||
|
||||
if (options.request) {
|
||||
assert(typeof options.request === 'string', 'Request must be a string.');
|
||||
this.request = options.request;
|
||||
}
|
||||
if (options.address)
|
||||
this.address.fromOptions(options.address);
|
||||
|
||||
return this;
|
||||
};
|
||||
if (options.amount != null) {
|
||||
assert(Number.isSafeInteger(options.amount) && options.amount >= 0,
|
||||
'Amount must be a uint64.');
|
||||
this.amount = options.amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate URI from options.
|
||||
* @param {Object|String} options
|
||||
* @returns {URI}
|
||||
*/
|
||||
if (options.label) {
|
||||
assert(typeof options.label === 'string', 'Label must be a string.');
|
||||
this.label = options.label;
|
||||
}
|
||||
|
||||
URI.fromOptions = function fromOptions(options) {
|
||||
return new URI().fromOptions(options);
|
||||
};
|
||||
if (options.message) {
|
||||
assert(typeof options.message === 'string', 'Message must be a string.');
|
||||
this.message = options.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and inject properties from string.
|
||||
* @private
|
||||
* @param {String} str
|
||||
* @param {Network?} network
|
||||
* @returns {URI}
|
||||
*/
|
||||
if (options.request) {
|
||||
assert(typeof options.request === 'string', 'Request must be a string.');
|
||||
this.request = options.request;
|
||||
}
|
||||
|
||||
URI.prototype.fromString = function fromString(str, network) {
|
||||
assert(typeof str === 'string');
|
||||
assert(str.length > 8, 'Not a bitcoin URI.');
|
||||
|
||||
const prefix = str.substring(0, 8);
|
||||
|
||||
assert(prefix === 'bitcoin:', 'Not a bitcoin URI.');
|
||||
|
||||
str = str.substring(8);
|
||||
|
||||
const index = str.indexOf('?');
|
||||
|
||||
let addr, qs;
|
||||
if (index === -1) {
|
||||
addr = str;
|
||||
} else {
|
||||
addr = str.substring(0, index);
|
||||
qs = str.substring(index + 1);
|
||||
}
|
||||
|
||||
this.address.fromString(addr, network);
|
||||
|
||||
if (!qs)
|
||||
return this;
|
||||
|
||||
const query = parsePairs(qs);
|
||||
|
||||
if (query.amount) {
|
||||
assert(query.amount.length > 0, 'Value is empty.');
|
||||
assert(query.amount[0] !== '-', 'Value is negative.');
|
||||
this.amount = Amount.value(query.amount);
|
||||
}
|
||||
|
||||
if (query.label)
|
||||
this.label = query.label;
|
||||
/**
|
||||
* Instantiate URI from options.
|
||||
* @param {Object|String} options
|
||||
* @returns {URI}
|
||||
*/
|
||||
|
||||
if (query.message)
|
||||
this.message = query.message;
|
||||
static fromOptions(options) {
|
||||
return new this().fromOptions(options);
|
||||
}
|
||||
|
||||
if (query.r)
|
||||
this.request = query.r;
|
||||
/**
|
||||
* Parse and inject properties from string.
|
||||
* @private
|
||||
* @param {String} str
|
||||
* @param {Network?} network
|
||||
* @returns {URI}
|
||||
*/
|
||||
|
||||
return this;
|
||||
};
|
||||
fromString(str, network) {
|
||||
assert(typeof str === 'string');
|
||||
assert(str.length > 8, 'Not a bitcoin URI.');
|
||||
|
||||
/**
|
||||
* Instantiate uri from string.
|
||||
* @param {String} str
|
||||
* @param {Network?} network
|
||||
* @returns {URI}
|
||||
*/
|
||||
const prefix = str.substring(0, 8);
|
||||
|
||||
URI.fromString = function fromString(str, network) {
|
||||
return new URI().fromString(str, network);
|
||||
};
|
||||
assert(prefix === 'bitcoin:', 'Not a bitcoin URI.');
|
||||
|
||||
/**
|
||||
* Serialize uri to a string.
|
||||
* @returns {String}
|
||||
*/
|
||||
str = str.substring(8);
|
||||
|
||||
URI.prototype.toString = function toString() {
|
||||
let str = 'bitcoin:';
|
||||
const index = str.indexOf('?');
|
||||
|
||||
str += this.address.toString();
|
||||
let addr, qs;
|
||||
if (index === -1) {
|
||||
addr = str;
|
||||
} else {
|
||||
addr = str.substring(0, index);
|
||||
qs = str.substring(index + 1);
|
||||
}
|
||||
|
||||
const query = [];
|
||||
this.address.fromString(addr, network);
|
||||
|
||||
if (this.amount !== -1)
|
||||
query.push(`amount=${Amount.btc(this.amount)}`);
|
||||
if (!qs)
|
||||
return this;
|
||||
|
||||
if (this.label)
|
||||
query.push(`label=${escape(this.label)}`);
|
||||
const query = parsePairs(qs);
|
||||
|
||||
if (this.message)
|
||||
query.push(`message=${escape(this.message)}`);
|
||||
if (query.amount) {
|
||||
assert(query.amount.length > 0, 'Value is empty.');
|
||||
assert(query.amount[0] !== '-', 'Value is negative.');
|
||||
this.amount = Amount.value(query.amount);
|
||||
}
|
||||
|
||||
if (this.request)
|
||||
query.push(`r=${escape(this.request)}`);
|
||||
if (query.label)
|
||||
this.label = query.label;
|
||||
|
||||
if (query.length > 0)
|
||||
str += '?' + query.join('&');
|
||||
if (query.message)
|
||||
this.message = query.message;
|
||||
|
||||
return str;
|
||||
};
|
||||
if (query.r)
|
||||
this.request = query.r;
|
||||
|
||||
/**
|
||||
* Inspect bitcoin uri.
|
||||
* @returns {String}
|
||||
*/
|
||||
return this;
|
||||
}
|
||||
|
||||
URI.prototype.inspect = function inspect() {
|
||||
return `<URI: ${this.toString()}>`;
|
||||
};
|
||||
/**
|
||||
* Instantiate uri from string.
|
||||
* @param {String} str
|
||||
* @param {Network?} network
|
||||
* @returns {URI}
|
||||
*/
|
||||
|
||||
static fromString(str, network) {
|
||||
return new this().fromString(str, network);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize uri to a string.
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
toString() {
|
||||
let str = 'bitcoin:';
|
||||
|
||||
str += this.address.toString();
|
||||
|
||||
const query = [];
|
||||
|
||||
if (this.amount !== -1)
|
||||
query.push(`amount=${Amount.btc(this.amount)}`);
|
||||
|
||||
if (this.label)
|
||||
query.push(`label=${escape(this.label)}`);
|
||||
|
||||
if (this.message)
|
||||
query.push(`message=${escape(this.message)}`);
|
||||
|
||||
if (this.request)
|
||||
query.push(`r=${escape(this.request)}`);
|
||||
|
||||
if (query.length > 0)
|
||||
str += '?' + query.join('&');
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspect bitcoin uri.
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
inspect() {
|
||||
return `<URI: ${this.toString()}>`;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function BitcoinQuery() {
|
||||
this.amount = null;
|
||||
this.label = null;
|
||||
this.message = null;
|
||||
this.r = null;
|
||||
class BitcoinQuery {
|
||||
constructor() {
|
||||
this.amount = null;
|
||||
this.label = null;
|
||||
this.message = null;
|
||||
this.r = null;
|
||||
}
|
||||
}
|
||||
|
||||
function parsePairs(str) {
|
||||
const parts = str.split('&');
|
||||
const data = new BitcoinQuery();
|
||||
|
||||
let size = 0;
|
||||
|
||||
for (const pair of parts) {
|
||||
@ -244,7 +252,7 @@ function parsePairs(str) {
|
||||
break;
|
||||
}
|
||||
|
||||
size++;
|
||||
size += 1;
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user