|
|
@ -17,6 +17,8 @@ var JSUtil = require('./util/js'); |
|
|
|
* An address has two key properties: `network` and `type`. The type is either |
|
|
|
* `Address.PayToPublicKeyHash` (value is the `'pubkeyhash'` string) |
|
|
|
* or `Address.PayToScriptHash` (the string `'scripthash'`). The network is an instance of {@link Network}. |
|
|
|
* You can quickly check whether an address is of a given kind by using the methods |
|
|
|
* `isPayToPublicKeyHash` and `isPayToScriptHash` |
|
|
|
* |
|
|
|
* @example |
|
|
|
* ```javascript
|
|
|
@ -40,6 +42,8 @@ var JSUtil = require('./util/js'); |
|
|
|
* @constructor |
|
|
|
*/ |
|
|
|
function Address(data, network, type) { |
|
|
|
/* jshint maxcomplexity: 12 */ |
|
|
|
/* jshint maxstatements: 20 */ |
|
|
|
|
|
|
|
if (!(this instanceof Address)) { |
|
|
|
return new Address(data, network, type); |
|
|
@ -49,6 +53,11 @@ function Address(data, network, type) { |
|
|
|
return Address.createMultisig(data, network, type); |
|
|
|
} |
|
|
|
|
|
|
|
if (data instanceof Address) { |
|
|
|
// Immutable instance
|
|
|
|
return data; |
|
|
|
} |
|
|
|
|
|
|
|
if (!data) { |
|
|
|
throw new TypeError('First argument is required, please include address data.'); |
|
|
|
} |
|
|
@ -61,24 +70,7 @@ function Address(data, network, type) { |
|
|
|
throw new TypeError('Third argument must be "pubkeyhash" or "scripthash".'); |
|
|
|
} |
|
|
|
|
|
|
|
var info; |
|
|
|
|
|
|
|
// transform and validate input data
|
|
|
|
if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 20) { |
|
|
|
info = Address._transformHash(data); |
|
|
|
} else if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 21) { |
|
|
|
info = Address._transformBuffer(data, network, type); |
|
|
|
} else if (data.constructor && (data.constructor.name && data.constructor.name === 'PublicKey')) { |
|
|
|
info = Address._transformPublicKey(data); |
|
|
|
} else if (data.constructor && (data.constructor.name && data.constructor.name === 'Script')) { |
|
|
|
info = Address._transformScript(data, network); |
|
|
|
} else if (data instanceof Address) { |
|
|
|
return data; |
|
|
|
} else if (typeof(data) === 'string') { |
|
|
|
info = Address._transformString(data, network, type); |
|
|
|
} else { |
|
|
|
throw new TypeError('First argument is an unrecognized data format.'); |
|
|
|
} |
|
|
|
var info = this._classifyArguments(data, network, type); |
|
|
|
|
|
|
|
// set defaults if not set
|
|
|
|
info.network = info.network || Networks.get(network) || Networks.defaultNetwork; |
|
|
@ -102,17 +94,37 @@ function Address(data, network, type) { |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
/** @static */ |
|
|
|
Address.PayToPublicKeyHash = 'pubkeyhash'; |
|
|
|
/** |
|
|
|
* @static |
|
|
|
* @value 'scripthash' |
|
|
|
* Internal function used to split different kinds of arguments of the constructor |
|
|
|
* @param {*} data - The encoded data in various formats |
|
|
|
* @param {Network|String|number} [network] - The network: 'livenet' or 'testnet' |
|
|
|
* @param {String} [type] - The type of address: 'script' or 'pubkey' |
|
|
|
* @returns {Object} An "info" object with "type", "network", and "hashBuffer" |
|
|
|
*/ |
|
|
|
Address.prototype._classifyArguments = function(data, network, type) { |
|
|
|
/* jshint maxcomplexity: 10 */ |
|
|
|
// transform and validate input data
|
|
|
|
if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 20) { |
|
|
|
return Address._transformHash(data); |
|
|
|
} else if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 21) { |
|
|
|
return Address._transformBuffer(data, network, type); |
|
|
|
} else if (data.constructor && (data.constructor.name && data.constructor.name === 'PublicKey')) { |
|
|
|
return Address._transformPublicKey(data); |
|
|
|
} else if (data.constructor && (data.constructor.name && data.constructor.name === 'Script')) { |
|
|
|
return Address._transformScript(data, network); |
|
|
|
} else if (typeof(data) === 'string') { |
|
|
|
return Address._transformString(data, network, type); |
|
|
|
} else { |
|
|
|
throw new TypeError('First argument is an unrecognized data format.'); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** @static */ |
|
|
|
Address.PayToPublicKeyHash = 'pubkeyhash'; |
|
|
|
/** @static */ |
|
|
|
Address.PayToScriptHash = 'scripthash'; |
|
|
|
|
|
|
|
/** |
|
|
|
* Internal function to transform a hash buffer |
|
|
|
* |
|
|
|
* @param {Buffer} hash - An instance of a hash Buffer |
|
|
|
* @returns {Object} An object with keys: hashBuffer |
|
|
|
* @private |
|
|
@ -130,7 +142,7 @@ Address._transformHash = function(hash){ |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Internal function to discover the network and type |
|
|
|
* Internal function to discover the network and type based on the first data byte |
|
|
|
* |
|
|
|
* @param {Buffer} buffer - An instance of a hex encoded address Buffer |
|
|
|
* @returns {Object} An object with keys: network and type |
|
|
@ -138,24 +150,21 @@ Address._transformHash = function(hash){ |
|
|
|
*/ |
|
|
|
Address._classifyFromVersion = function(buffer){ |
|
|
|
var version = {}; |
|
|
|
switch(buffer[0]){ // the version byte
|
|
|
|
version.network = Networks.get(buffer[0]); |
|
|
|
switch (buffer[0]) { // the version byte
|
|
|
|
case Networks.livenet.pubkeyhash: |
|
|
|
version.network = Networks.livenet; |
|
|
|
version.type = Address.PayToPublicKeyHash; |
|
|
|
break; |
|
|
|
|
|
|
|
case Networks.livenet.scripthash: |
|
|
|
version.network = Networks.livenet; |
|
|
|
version.type = Address.PayToScriptHash; |
|
|
|
break; |
|
|
|
|
|
|
|
case Networks.testnet.pubkeyhash: |
|
|
|
version.network = Networks.testnet; |
|
|
|
version.type = Address.PayToPublicKeyHash; |
|
|
|
break; |
|
|
|
|
|
|
|
case Networks.testnet.scripthash: |
|
|
|
version.network = Networks.testnet; |
|
|
|
version.type = Address.PayToScriptHash; |
|
|
|
break; |
|
|
|
} |
|
|
@ -172,6 +181,7 @@ Address._classifyFromVersion = function(buffer){ |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
Address._transformBuffer = function(buffer, network, type){ |
|
|
|
/* jshint maxcomplexity: 9 */ |
|
|
|
var info = {}; |
|
|
|
if (!(buffer instanceof Buffer) && !(buffer instanceof Uint8Array)) { |
|
|
|
throw new TypeError('Address supplied is not a buffer.'); |
|
|
@ -198,7 +208,7 @@ Address._transformBuffer = function(buffer, network, type){ |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Internal function to transform a PublicKey |
|
|
|
* Internal function to transform a {@link PublicKey} |
|
|
|
* |
|
|
|
* @param {PublicKey} pubkey - An instance of PublicKey |
|
|
|
* @returns {Object} An object with keys: hashBuffer, type |
|
|
@ -215,7 +225,7 @@ Address._transformPublicKey = function(pubkey){ |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Internal function to transform a Script |
|
|
|
* Internal function to transform a {@link Script} into a `info` object. |
|
|
|
* |
|
|
|
* @param {Script} script - An instance of Script |
|
|
|
* @returns {Object} An object with keys: hashBuffer, type |
|
|
@ -235,9 +245,13 @@ Address._transformScript = function(script, network){ |
|
|
|
/** |
|
|
|
* Creates a P2SH address from a set of public keys and a threshold. |
|
|
|
* |
|
|
|
* @param {Array} publicKeys |
|
|
|
* @param {number} threshold |
|
|
|
* @param {Network} network |
|
|
|
* The addresses will be sorted lexicographically, as that is the trend in bitcoin. |
|
|
|
* To create an address from unsorted public keys, use the {@link Script#buildMultisigOut} |
|
|
|
* interface. |
|
|
|
* |
|
|
|
* @param {Array} publicKeys - a set of public keys to create an address |
|
|
|
* @param {number} threshold - the number of signatures needed to release the funds |
|
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' |
|
|
|
* @return {Address} |
|
|
|
*/ |
|
|
|
Address.createMultisig = function(publicKeys, threshold, network) { |
|
|
@ -248,8 +262,8 @@ Address.createMultisig = function(publicKeys, threshold, network) { |
|
|
|
/** |
|
|
|
* Internal function to transform a bitcoin address string |
|
|
|
* |
|
|
|
* @param {String} data - An instance of PublicKey |
|
|
|
* @param {String} [network] - The network: 'livenet' or 'testnet' |
|
|
|
* @param {String} data |
|
|
|
* @param {String|Network} [network] - either a Network instance, 'livenet', or 'testnet' |
|
|
|
* @param {String} [type] - The type: 'pubkeyhash' or 'scripthash' |
|
|
|
* @returns {Object} An object with keys: hashBuffer, network and type |
|
|
|
* @private |
|
|
@ -266,8 +280,8 @@ Address._transformString = function(data, network, type){ |
|
|
|
/** |
|
|
|
* Instantiate an address from a PublicKey instance |
|
|
|
* |
|
|
|
* @param {PublicKey} data - An instance of PublicKey |
|
|
|
* @param {String} network - The network: 'livenet' or 'testnet' |
|
|
|
* @param {PublicKey} data |
|
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' |
|
|
|
* @returns {Address} A new valid and frozen instance of an Address |
|
|
|
*/ |
|
|
|
Address.fromPublicKey = function(data, network){ |
|
|
@ -280,7 +294,7 @@ Address.fromPublicKey = function(data, network){ |
|
|
|
* Instantiate an address from a ripemd160 public key hash |
|
|
|
* |
|
|
|
* @param {Buffer} hash - An instance of buffer of the hash |
|
|
|
* @param {String} network - The network: 'livenet' or 'testnet' |
|
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' |
|
|
|
* @returns {Address} A new valid and frozen instance of an Address |
|
|
|
*/ |
|
|
|
Address.fromPublicKeyHash = function(hash, network) { |
|
|
@ -292,7 +306,7 @@ Address.fromPublicKeyHash = function(hash, network) { |
|
|
|
* Instantiate an address from a ripemd160 script hash |
|
|
|
* |
|
|
|
* @param {Buffer} hash - An instance of buffer of the hash |
|
|
|
* @param {String} network - The network: 'livenet' or 'testnet' |
|
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' |
|
|
|
* @returns {Address} A new valid and frozen instance of an Address |
|
|
|
*/ |
|
|
|
Address.fromScriptHash = function(hash, network) { |
|
|
@ -304,7 +318,7 @@ Address.fromScriptHash = function(hash, network) { |
|
|
|
* Instantiate an address from a Script |
|
|
|
* |
|
|
|
* @param {Script} script - An instance of Script |
|
|
|
* @param {String} network - The network: 'livenet' or 'testnet' |
|
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' |
|
|
|
* @returns {Address} A new valid and frozen instance of an Address |
|
|
|
*/ |
|
|
|
Address.fromScript = function(script, network) { |
|
|
@ -316,7 +330,7 @@ Address.fromScript = function(script, network) { |
|
|
|
* Instantiate an address from a buffer of the address |
|
|
|
* |
|
|
|
* @param {Buffer} buffer - An instance of buffer of the address |
|
|
|
* @param {String} [network] - The network: 'livenet' or 'testnet' |
|
|
|
* @param {String|Network} [network] - either a Network instance, 'livenet', or 'testnet' |
|
|
|
* @param {String} [type] - The type of address: 'script' or 'pubkey' |
|
|
|
* @returns {Address} A new valid and frozen instance of an Address |
|
|
|
*/ |
|
|
@ -329,7 +343,7 @@ Address.fromBuffer = function(buffer, network, type) { |
|
|
|
* Instantiate an address from an address string |
|
|
|
* |
|
|
|
* @param {String} str - An string of the bitcoin address |
|
|
|
* @param {String} [network] - The network: 'livenet' or 'testnet' |
|
|
|
* @param {String|Network} [network] - either a Network instance, 'livenet', or 'testnet' |
|
|
|
* @param {String} [type] - The type of address: 'script' or 'pubkey' |
|
|
|
* @returns {Address} A new valid and frozen instance of an Address |
|
|
|
*/ |
|
|
@ -361,19 +375,19 @@ Address.fromJSON = function fromJSON(json) { |
|
|
|
* |
|
|
|
* @example |
|
|
|
* ```javascript
|
|
|
|
* |
|
|
|
* var error = Address.getValidationError('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'testnet'); |
|
|
|
* // a network mismatch error
|
|
|
|
* var error = Address.getValidationError('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'testnet'); |
|
|
|
* ``` |
|
|
|
* |
|
|
|
* @param {String} data - The encoded data |
|
|
|
* @param {String} network - The network: 'livenet' or 'testnet' |
|
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' |
|
|
|
* @param {String} type - The type of address: 'script' or 'pubkey' |
|
|
|
* @returns {null|Error} The corresponding error message |
|
|
|
*/ |
|
|
|
Address.getValidationError = function(data, network, type) { |
|
|
|
var error; |
|
|
|
try { |
|
|
|
/* jshint nonew: false */ |
|
|
|
new Address(data, network, type); |
|
|
|
} catch (e) { |
|
|
|
error = e; |
|
|
@ -386,13 +400,11 @@ Address.getValidationError = function(data, network, type) { |
|
|
|
* |
|
|
|
* @example |
|
|
|
* ```javascript
|
|
|
|
* |
|
|
|
* var valid = Address.isValid('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'livenet'); |
|
|
|
* // true
|
|
|
|
* assert(Address.isValid('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'livenet')); |
|
|
|
* ``` |
|
|
|
* |
|
|
|
* @param {String} data - The encoded data |
|
|
|
* @param {String} network - The network: 'livenet' or 'testnet' |
|
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' |
|
|
|
* @param {String} type - The type of address: 'script' or 'pubkey' |
|
|
|
* @returns {boolean} The corresponding error message |
|
|
|
*/ |
|
|
@ -428,7 +440,7 @@ Address.prototype.toBuffer = function() { |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* @returns {Object} An object of the address |
|
|
|
* @returns {Object} A plain object with the address information |
|
|
|
*/ |
|
|
|
Address.prototype.toObject = function toObject() { |
|
|
|
return { |
|
|
@ -439,7 +451,7 @@ Address.prototype.toObject = function toObject() { |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* @returns {Object} An object of the address |
|
|
|
* @returns {String} A JSON representation of a plain object with the address information |
|
|
|
*/ |
|
|
|
Address.prototype.toJSON = function toJSON() { |
|
|
|
return JSON.stringify(this.toObject()); |
|
|
|