Merge pull request #567 from braydonf/address-interface
Address: Modified interface so that any instance of Address is valid
This commit is contained in:
commit
183d401992
407
lib/address.js
407
lib/address.js
|
@ -4,117 +4,350 @@ var base58check = require('./encoding/base58check');
|
|||
var networks = require('./networks');
|
||||
var Hash = require('./crypto/hash');
|
||||
|
||||
function Address(buf) {
|
||||
if (!(this instanceof Address))
|
||||
return new Address(buf);
|
||||
if (Buffer.isBuffer(buf)) {
|
||||
this.fromBuffer(buf);
|
||||
} else if (typeof buf === 'string') {
|
||||
var str = buf;
|
||||
this.fromString(str);
|
||||
} else if (buf) {
|
||||
var obj = buf;
|
||||
this.set(obj);
|
||||
/**
|
||||
*
|
||||
* Bitcore Address
|
||||
*
|
||||
* Instantiate an address from an address String or Buffer, a public key or script hash Buffer,
|
||||
* or an instance of Pubkey or Script.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var address = new Address(keypair.pubkey, 'testnet').toString();
|
||||
*
|
||||
* @param {String} data - The encoded data in various formats
|
||||
* @param {String} [network] - The network: 'mainnet' or 'testnet'
|
||||
* @param {String} [type] - The type of address: 'script' or 'pubkey'
|
||||
* @returns {Address} A new valid and frozen instance of an Address
|
||||
*/
|
||||
function Address(data, network, type) {
|
||||
|
||||
if (!(this instanceof Address)) {
|
||||
return new Address(data, network, type);
|
||||
}
|
||||
}
|
||||
|
||||
Address.prototype.set = function(obj) {
|
||||
this.hashbuf = obj.hashbuf || this.hashbuf || null;
|
||||
this.networkstr = obj.networkstr || this.networkstr || 'mainnet';
|
||||
this.typestr = obj.typestr || this.typestr || 'pubkeyhash';
|
||||
return this;
|
||||
};
|
||||
if (!data) {
|
||||
throw new TypeError('First argument is required, please include address data.');
|
||||
}
|
||||
|
||||
Address.prototype.fromBuffer = function(buf) {
|
||||
if (buf.length !== 1 + 20)
|
||||
throw new Error('Address buffers must be exactly 21 bytes');
|
||||
var version = buf[0];
|
||||
if (version === networks['mainnet']['pubkeyhash']) {
|
||||
this.networkstr = 'mainnet';
|
||||
this.typestr = 'pubkeyhash';
|
||||
} else if (version === networks['mainnet']['scripthash']) {
|
||||
this.networkstr = 'mainnet';
|
||||
this.typestr = 'scripthash';
|
||||
} else if (version === networks['testnet']['pubkeyhash']) {
|
||||
this.networkstr = 'testnet';
|
||||
this.typestr = 'pubkeyhash';
|
||||
} else if (version === networks['testnet']['scripthash']) {
|
||||
this.networkstr = 'testnet';
|
||||
this.typestr = 'scripthash';
|
||||
if (network && (network !== 'mainnet' && network !== 'testnet')) {
|
||||
throw new TypeError('Second argument must be "mainnet" or "testnet".');
|
||||
}
|
||||
|
||||
if (type && (type !== 'pubkeyhash' && type !== 'scripthash')) {
|
||||
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 === 'Pubkey')) {
|
||||
info = Address._transformPubkey(data);
|
||||
} else if (data.constructor && (data.constructor.name && data.constructor.name === 'Script')) {
|
||||
info = Address._transformScript(data);
|
||||
} else if (typeof(data) === 'string') {
|
||||
info = Address._transformString(data, network, type);
|
||||
} else {
|
||||
this.networkstr = 'unknown';
|
||||
this.typestr = 'unknown';
|
||||
throw new TypeError('First argument is an unrecognized data format.');
|
||||
}
|
||||
|
||||
this.hashbuf = buf.slice(1);
|
||||
// set defaults if not set
|
||||
info.network = info.network || network || 'mainnet';
|
||||
info.type = info.type || type || 'pubkeyhash';
|
||||
|
||||
// set the validated values
|
||||
this.hashBuffer = info.hashBuffer;
|
||||
this.network = info.network;
|
||||
this.type = info.type;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Address.prototype.fromHashbuf = function(hashbuf, networkstr, typestr) {
|
||||
if (hashbuf.length !== 20)
|
||||
throw new Error('hashbuf must be exactly 20 bytes');
|
||||
this.hashbuf = hashbuf;
|
||||
this.networkstr = networkstr || 'mainnet';
|
||||
this.typestr = typestr || 'pubkeyhash';
|
||||
return this;
|
||||
};
|
||||
|
||||
Address.prototype.fromPubkey = function(pubkey, networkstr) {
|
||||
this.hashbuf = Hash.sha256ripemd160(pubkey.toBuffer());
|
||||
this.networkstr = networkstr || 'mainnet';
|
||||
this.typestr = 'pubkeyhash';
|
||||
return this;
|
||||
};
|
||||
|
||||
Address.prototype.fromScript = function(script, networkstr) {
|
||||
this.hashbuf = Hash.sha256ripemd160(script.toBuffer());
|
||||
this.networkstr = networkstr || 'mainnet';
|
||||
this.typestr = 'scripthash';
|
||||
return this;
|
||||
};
|
||||
|
||||
Address.prototype.fromString = function(str) {
|
||||
var buf = base58check.decode(str);
|
||||
return this.fromBuffer(buf);
|
||||
}
|
||||
|
||||
Address.isValid = function(addrstr) {
|
||||
try {
|
||||
var address = new Address().fromString(addrstr);
|
||||
} catch (e) {
|
||||
return false;
|
||||
/**
|
||||
*
|
||||
* Internal function to transform a hash buffer
|
||||
*
|
||||
* @param {Buffer} hash - An instance of a hash Buffer
|
||||
* @returns {Object} An object with keys: hashBuffer
|
||||
*/
|
||||
Address._transformHash = function(hash){
|
||||
var info = {};
|
||||
if (!(hash instanceof Buffer) && !(hash instanceof Uint8Array)) {
|
||||
throw new TypeError('Address supplied is not a buffer.');
|
||||
}
|
||||
return address.isValid();
|
||||
if (hash.length !== 20) {
|
||||
throw new TypeError('Address hashbuffers must be exactly 20 bytes.');
|
||||
}
|
||||
info.hashBuffer = hash;
|
||||
return info;
|
||||
};
|
||||
|
||||
Address.prototype.isValid = function() {
|
||||
try {
|
||||
this.validate();
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
/**
|
||||
*
|
||||
* Internal function to transform a bitcoin address buffer
|
||||
*
|
||||
* @param {Buffer} buffer - An instance of a hex encoded address Buffer
|
||||
* @param {String} [network] - The network: 'mainnet' or 'testnet'
|
||||
* @param {String} [type] - The type: 'pubkeyhash' or 'scripthash'
|
||||
* @returns {Object} An object with keys: hashBuffer, network and type
|
||||
*/
|
||||
Address._transformBuffer = function(buffer, network, type){
|
||||
var info = {};
|
||||
if (!(buffer instanceof Buffer) && !(buffer instanceof Uint8Array)) {
|
||||
throw new TypeError('Address supplied is not a buffer.');
|
||||
}
|
||||
if (buffer.length !== 1 + 20) {
|
||||
throw new TypeError('Address buffers must be exactly 21 bytes.');
|
||||
}
|
||||
|
||||
var bufNetwork = false;
|
||||
var bufType = false;
|
||||
|
||||
switch(buffer[0]){ // the version byte
|
||||
case networks.mainnet.pubkeyhash:
|
||||
bufNetwork = 'mainnet';
|
||||
bufType = 'pubkeyhash';
|
||||
break;
|
||||
|
||||
case networks.mainnet.scripthash:
|
||||
bufNetwork = 'mainnet';
|
||||
bufType = 'scripthash';
|
||||
break;
|
||||
|
||||
case networks.testnet.pubkeyhash:
|
||||
bufNetwork = 'testnet';
|
||||
bufType = 'pubkeyhash';
|
||||
break;
|
||||
|
||||
case networks.testnet.scripthash:
|
||||
bufNetwork = 'testnet';
|
||||
bufType = 'scripthash';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bufNetwork || (network && network !== bufNetwork)) {
|
||||
throw new TypeError('Address has mismatched network type.');
|
||||
}
|
||||
|
||||
if (!bufType || ( type && type !== bufType )) {
|
||||
throw new TypeError('Address has mismatched type.');
|
||||
}
|
||||
|
||||
info.hashBuffer = buffer.slice(1);
|
||||
info.network = bufNetwork;
|
||||
info.type = bufType;
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Internal function to transform a Pubkey
|
||||
*
|
||||
* @param {Pubkey} pubkey - An instance of Pubkey
|
||||
* @returns {Object} An object with keys: hashBuffer, type
|
||||
*/
|
||||
Address._transformPubkey = function(pubkey){
|
||||
var info = {};
|
||||
if (!pubkey.constructor || (pubkey.constructor.name && pubkey.constructor.name !== 'Pubkey')) {
|
||||
throw new TypeError('Address must be an instance of Pubkey.');
|
||||
}
|
||||
info.hashBuffer = Hash.sha256ripemd160(pubkey.toBuffer());
|
||||
info.type = 'pubkeyhash';
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Internal function to transform a Script
|
||||
*
|
||||
* @param {Script} script - An instance of Script
|
||||
* @returns {Object} An object with keys: hashBuffer, type
|
||||
*/
|
||||
Address._transformScript = function(script){
|
||||
var info = {};
|
||||
if (!script.constructor || (script.constructor.name && script.constructor.name !== 'Script')) {
|
||||
throw new TypeError('Address must be an instance of Script.');
|
||||
}
|
||||
info.hashBuffer = Hash.sha256ripemd160(script.toBuffer());
|
||||
info.type = 'scripthash';
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Internal function to transform a bitcoin address string
|
||||
*
|
||||
* @param {String} data - An instance of Pubkey
|
||||
* @param {String} [network] - The network: 'mainnet' or 'testnet'
|
||||
* @param {String} [type] - The type: 'pubkeyhash' or 'scripthash'
|
||||
* @returns {Object} An object with keys: hashBuffer, network and type
|
||||
*/
|
||||
Address._transformString = function(data, network, type){
|
||||
if( typeof(data) !== 'string' ) {
|
||||
throw new TypeError('Address supplied is not a string.');
|
||||
}
|
||||
var addressBuffer = base58check.decode(data);
|
||||
var info = Address._transformBuffer(addressBuffer, network, type);
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from a Pubkey instance
|
||||
*
|
||||
* @param {String} data - An instance of Pubkey
|
||||
* @param {String} network - The network: 'mainnet' or 'testnet'
|
||||
* @returns {Address} A new valid and frozen instance of an Address
|
||||
*/
|
||||
Address.fromPubkey = function(data, network){
|
||||
var info = Address._transformPubkey(data);
|
||||
return new Address(info.hashBuffer, network, info.type);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from a ripemd160 public key hash
|
||||
*
|
||||
* @param {Buffer} hash - An instance of buffer of the hash
|
||||
* @param {String} network - The network: 'mainnet' or 'testnet'
|
||||
* @returns {Address} A new valid and frozen instance of an Address
|
||||
*/
|
||||
Address.fromPubkeyHash = function(hash, network) {
|
||||
var info = Address._transformHash(hash);
|
||||
return new Address(info.hashBuffer, network, 'pubkeyhash');
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from a ripemd160 script hash
|
||||
*
|
||||
* @param {Buffer} hash - An instance of buffer of the hash
|
||||
* @param {String} network - The network: 'mainnet' or 'testnet'
|
||||
* @returns {Address} A new valid and frozen instance of an Address
|
||||
*/
|
||||
Address.fromScriptHash = function(hash, network) {
|
||||
var info = Address._transformHash(hash);
|
||||
return new Address(info.hashBuffer, network, 'scripthash');
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from a Script
|
||||
*
|
||||
* @param {Script} script - An instance of Script
|
||||
* @param {String} network - The network: 'mainnet' or 'testnet'
|
||||
* @returns {Address} A new valid and frozen instance of an Address
|
||||
*/
|
||||
Address.fromScript = function(script, network) {
|
||||
var info = Address._transformScript(script);
|
||||
return new Address(info.hashBuffer, network, info.type);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from a buffer of the address
|
||||
*
|
||||
* @param {Buffer} buffer - An instance of buffer of the address
|
||||
* @param {String} [network] - The network: 'mainnet' or 'testnet'
|
||||
* @param {String} [type] - The type of address: 'script' or 'pubkey'
|
||||
* @returns {Address} A new valid and frozen instance of an Address
|
||||
*/
|
||||
Address.fromBuffer = function(buffer, network, type) {
|
||||
var info = Address._transformBuffer(buffer, network, type);
|
||||
return new Address(info.hashBuffer, info.network, info.type);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from an address string
|
||||
*
|
||||
* @param {String} str - An string of the bitcoin address
|
||||
* @param {String} [network] - The network: 'mainnet' or 'testnet'
|
||||
* @param {String} [type] - The type of address: 'script' or 'pubkey'
|
||||
* @returns {Address} A new valid and frozen instance of an Address
|
||||
*/
|
||||
Address.fromString = function(str, network, type) {
|
||||
var info = Address._transformString(str, network, type);
|
||||
return new Address(info.hashBuffer, info.network, info.type);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Will return a validation error if exists
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var error = Address.getValidationError('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'testnet');
|
||||
* // a network mismatch error
|
||||
*
|
||||
* @param {String} data - The encoded data
|
||||
* @param {String} network - The network: 'mainnet' 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 {
|
||||
new Address(data, network, type);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
return error;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Will return a boolean if an address is valid
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var valid = Address.isValid('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'mainnet');
|
||||
* // true
|
||||
*
|
||||
* @param {String} data - The encoded data
|
||||
* @param {String} network - The network: 'mainnet' or 'testnet'
|
||||
* @param {String} type - The type of address: 'script' or 'pubkey'
|
||||
* @returns {null|Error} The corresponding error message
|
||||
*/
|
||||
Address.isValid = function(data, network, type) {
|
||||
return !Address.getValidationError(data, network, type);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Will return a buffer representation of the address
|
||||
*
|
||||
* @returns {Buffer} Bitcoin address buffer
|
||||
*/
|
||||
Address.prototype.toBuffer = function() {
|
||||
var version = new Buffer([networks[this.networkstr][this.typestr]]);
|
||||
var buf = Buffer.concat([version, this.hashbuf]);
|
||||
var version = new Buffer([networks[this.network][this.type]]);
|
||||
var buf = Buffer.concat([version, this.hashBuffer]);
|
||||
return buf;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Will return a the string representation of the address
|
||||
*
|
||||
* @returns {String} Bitcoin address
|
||||
*/
|
||||
Address.prototype.toString = function() {
|
||||
return base58check.encode(this.toBuffer());
|
||||
};
|
||||
|
||||
Address.prototype.validate = function() {
|
||||
if (!Buffer.isBuffer(this.hashbuf) || this.hashbuf.length !== 20)
|
||||
throw new Error('hash must be a buffer of 20 bytes');
|
||||
if (this.networkstr !== 'mainnet' && this.networkstr !== 'testnet')
|
||||
throw new Error('networkstr must be "mainnet" or "testnet"');
|
||||
if (this.typestr !== 'pubkeyhash' && this.typestr !== 'scripthash')
|
||||
throw new Error('typestr must be "pubkeyhash" or "scripthash"');
|
||||
return this;
|
||||
};
|
||||
/**
|
||||
*
|
||||
* Will return a string formatted for the console
|
||||
*
|
||||
* @returns {String} Bitcoin address
|
||||
*/
|
||||
Address.prototype.inspect = function() {
|
||||
return '<Address: ' + this.toString() + ', type: '+this.type+', network: '+this.network+'>';
|
||||
}
|
||||
|
||||
module.exports = Address;
|
||||
|
|
425
test/address.js
425
test/address.js
|
@ -8,149 +8,329 @@ var Address = bitcore.Address;
|
|||
var Script = bitcore.Script;
|
||||
|
||||
describe('Address', function() {
|
||||
|
||||
var pubkeyhash = new Buffer('3c3fa3d4adcaf8f52d5b1843975e122548269937', 'hex');
|
||||
var buf = Buffer.concat([new Buffer([0]), pubkeyhash]);
|
||||
var str = '16VZnHwRhwrExfeHFHGjwrgEMq8VcYPs9r';
|
||||
var strTest = 'n28S35tqEMbt6vNad7A5K3mZ7vdn8dZ86X';
|
||||
|
||||
it('should create a new address object', function() {
|
||||
var address = new Address();
|
||||
should.exist(address);
|
||||
address = new Address(buf);
|
||||
should.exist(address);
|
||||
address = new Address(str);
|
||||
should.exist(address);
|
||||
it('should throw an error because of missing data', function() {
|
||||
(function() {
|
||||
var a = new Address();
|
||||
}).should.throw('First argument is required, please include address data.');
|
||||
});
|
||||
|
||||
describe('@isValid', function() {
|
||||
it('should throw an error because of bad network param', function() {
|
||||
(function(){
|
||||
var a = new Address(validAddresses[0], 'main', 'pubkeyhash');
|
||||
}).should.throw('Second argument must be "mainnet" or "testnet".');
|
||||
});
|
||||
|
||||
it('should validate this valid address string', function() {
|
||||
Address.isValid(str).should.equal(true);
|
||||
it('should throw an error because of bad type param', function() {
|
||||
(function() {
|
||||
var a = new Address(validAddresses[0], 'mainnet', 'pubkey');
|
||||
}).should.throw('Third argument must be "pubkeyhash" or "scripthash"');
|
||||
});
|
||||
|
||||
|
||||
// mainnet valid
|
||||
var validAddresses = [
|
||||
'15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2',
|
||||
'1A6ut1tWnUq1SEQLMr4ttDh24wcbJ5o9TT',
|
||||
'1BpbpfLdY7oBS9gK7aDXgvMgr1DPvNhEB2',
|
||||
'1Jz2yCRd5ST1p2gUqFB5wsSQfdm3jaFfg7'
|
||||
];
|
||||
|
||||
// mainnet p2sh
|
||||
var validp2shAddresses = [
|
||||
'342ftSRCvFHfCeFFBuz4xwbeqnDw6BGUey',
|
||||
'33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk',
|
||||
'37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3',
|
||||
'3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy'
|
||||
];
|
||||
|
||||
// testnet p2sh
|
||||
var testValidp2shAddresses = [
|
||||
'2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C',
|
||||
'2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda',
|
||||
'2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN',
|
||||
'2NB72XtkjpnATMggui83aEtPawyyKvnbX2o'
|
||||
];
|
||||
|
||||
//mainnet bad checksums
|
||||
var badChecksums = [
|
||||
'15vkcKf7gB23wLAnZLmbVuMiiVDc3nq4a2',
|
||||
'1A6ut1tWnUq1SEQLMr4ttDh24wcbj4w2TT',
|
||||
'1BpbpfLdY7oBS9gK7aDXgvMgr1DpvNH3B2',
|
||||
'1Jz2yCRd5ST1p2gUqFB5wsSQfdmEJaffg7'
|
||||
];
|
||||
|
||||
//mainnet non-base58
|
||||
var nonBase58 = [
|
||||
'15vkcKf7g#23wLAnZLmb$uMiiVDc3nq4a2',
|
||||
'1A601ttWnUq1SEQLMr4ttDh24wcbj4w2TT',
|
||||
'1BpbpfLdY7oBS9gK7aIXgvMgr1DpvNH3B2',
|
||||
'1Jz2yCRdOST1p2gUqFB5wsSQfdmEJaffg7'
|
||||
];
|
||||
|
||||
//testnet valid
|
||||
var testValidAddresses = [
|
||||
'n28S35tqEMbt6vNad7A5K3mZ7vdn8dZ86X',
|
||||
'n45x3R2w2jaSC62BMa9MeJCd3TXxgvDEmm',
|
||||
'mursDVxqNQmmwWHACpM9VHwVVSfTddGsEM',
|
||||
'mtX8nPZZdJ8d3QNLRJ1oJTiEi26Sj6LQXS'
|
||||
];
|
||||
|
||||
describe('validation', function() {
|
||||
|
||||
it('should describe this mainnet address as an invalid testnet address', function() {
|
||||
var error = Address.getValidationError('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo', 'testnet');
|
||||
should.exist(error);
|
||||
});
|
||||
|
||||
it('should invalidate this valid address string', function() {
|
||||
Address.isValid(str.substr(1)).should.equal(false);
|
||||
it('should should return a true boolean', function(){
|
||||
var valid = Address.isValid('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo', 'mainnet');
|
||||
valid.should.equal(true);
|
||||
});
|
||||
|
||||
it('should should return a false boolean', function(){
|
||||
var valid = Address.isValid('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo', 'testnet');
|
||||
valid.should.equal(false);
|
||||
});
|
||||
|
||||
it('should validate addresses', function() {
|
||||
for(var i=0;i<validAddresses.length;i++){
|
||||
var error = Address.getValidationError(validAddresses[i]);
|
||||
should.not.exist(error);
|
||||
}
|
||||
});
|
||||
|
||||
it('should validate p2sh addresses', function() {
|
||||
for(var i=0;i<validp2shAddresses.length;i++){
|
||||
var error = Address.getValidationError(validp2shAddresses[i]);
|
||||
should.not.exist(error);
|
||||
}
|
||||
});
|
||||
|
||||
it('should validate testnet p2sh addresses', function() {
|
||||
for(var i=0;i<testValidp2shAddresses.length;i++){
|
||||
var error = Address.getValidationError(testValidp2shAddresses[i], 'testnet');
|
||||
should.not.exist(error);
|
||||
}
|
||||
});
|
||||
|
||||
it('should not validate addresses with params', function() {
|
||||
for(var i=0;i<validAddresses.length;i++){
|
||||
var error = Address.getValidationError(validAddresses[i], 'testnet');
|
||||
should.exist(error);
|
||||
}
|
||||
});
|
||||
|
||||
it('should validate addresses with params', function() {
|
||||
for(var i=0;i<validAddresses.length;i++){
|
||||
var error = Address.getValidationError(validAddresses[i], 'mainnet');
|
||||
should.not.exist(error);
|
||||
}
|
||||
});
|
||||
|
||||
it('should not validate because of an invalid checksum', function() {
|
||||
for(var i=0;i<badChecksums.length;i++){
|
||||
var error = Address.getValidationError(badChecksums[i], 'mainnet', 'pubkeyhash');
|
||||
should.exist(error);
|
||||
error.message.should.equal('Checksum mismatch');
|
||||
}
|
||||
});
|
||||
|
||||
it('should not validate because of mismatched network', function() {
|
||||
for(var i=0;i<validAddresses.length;i++){
|
||||
var error = Address.getValidationError(validAddresses[i], 'testnet', 'pubkeyhash');
|
||||
should.exist(error);
|
||||
error.message.should.equal('Address has mismatched network type.');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
it('should not validate because of a mismatched type', function() {
|
||||
for(var i=0;i<validAddresses.length;i++){
|
||||
var error = Address.getValidationError(validAddresses[i], 'mainnet', 'scripthash');
|
||||
should.exist(error);
|
||||
error.message.should.equal('Address has mismatched type.');
|
||||
}
|
||||
});
|
||||
|
||||
it('should not validate because of non-base58 characters', function() {
|
||||
for(var i=0;i<nonBase58.length;i++){
|
||||
var error = Address.getValidationError(nonBase58[i], 'mainnet', 'pubkeyhash');
|
||||
should.exist(error);
|
||||
error.message.should.equal('Non-base58 character');
|
||||
}
|
||||
});
|
||||
|
||||
it('should not validate addresses', function() {
|
||||
for(var i=0;i<badChecksums.length;i++){
|
||||
var error = Address.getValidationError(badChecksums[i]);
|
||||
should.exist(error);
|
||||
}
|
||||
});
|
||||
|
||||
it('should validate testnet addresses', function() {
|
||||
for(var i=0;i<testValidAddresses.length;i++){
|
||||
var error = Address.getValidationError(testValidAddresses[i], 'testnet');
|
||||
should.not.exist(error);
|
||||
}
|
||||
});
|
||||
|
||||
it('should not validate testnet addresses because of mismatched network', function() {
|
||||
for(var i=0;i<testValidAddresses.length;i++){
|
||||
var error = Address.getValidationError(testValidAddresses[i], 'mainnet', 'pubkeyhash');
|
||||
should.exist(error);
|
||||
error.message.should.equal('Address has mismatched network type.');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#fromBuffer', function() {
|
||||
|
||||
describe('encodings', function() {
|
||||
|
||||
it('should make an address from a buffer', function() {
|
||||
Address().fromBuffer(buf).toString().should.equal(str);
|
||||
var a = Address.fromBuffer(buf).toString().should.equal(str);
|
||||
var b = new Address(buf).toString().should.equal(str);
|
||||
var c = Address(buf).toString().should.equal(str);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#fromHashbuf', function() {
|
||||
|
||||
it('should make an address from a hashbuf', function() {
|
||||
Address().fromHashbuf(pubkeyhash).toString().should.equal(str);
|
||||
var a = Address().fromHashbuf(pubkeyhash, 'testnet', 'scripthash');
|
||||
a.networkstr.should.equal('testnet');
|
||||
a.typestr.should.equal('scripthash');
|
||||
it('should make an address from a string', function() {
|
||||
var a = Address.fromString(str).toString().should.equal(str);
|
||||
var b = new Address(str).toString().should.equal(str);
|
||||
});
|
||||
|
||||
it('should throw an error for invalid length hashbuf', function() {
|
||||
it('should error because of unrecognized data format', function() {
|
||||
(function() {
|
||||
Address().fromHashbuf(buf);
|
||||
}).should.throw('hashbuf must be exactly 20 bytes');
|
||||
var a = new Address(new Error());
|
||||
}).should.throw('First argument is an unrecognized data format.');
|
||||
});
|
||||
|
||||
});
|
||||
it('should error because of incorrect format for pubkey hash', function() {
|
||||
(function() {
|
||||
var a = new Address.fromPubkeyHash('notahash');
|
||||
}).should.throw('Address supplied is not a buffer.');
|
||||
});
|
||||
|
||||
describe('#fromPubkey', function() {
|
||||
it('should error because of incorrect format for script hash', function() {
|
||||
(function() {
|
||||
var a = new Address.fromScriptHash('notascript');
|
||||
}).should.throw('Address supplied is not a buffer.');
|
||||
});
|
||||
|
||||
it('should make this address from a compressed pubkey', function() {
|
||||
it('should error because of incorrect type for transform buffer', function() {
|
||||
(function() {
|
||||
var info = Address._transformBuffer('notabuffer');
|
||||
}).should.throw('Address supplied is not a buffer.');
|
||||
});
|
||||
|
||||
it('should error because of incorrect length buffer for transform buffer', function() {
|
||||
(function() {
|
||||
var info = Address._transformBuffer(new Buffer(20));
|
||||
}).should.throw('Address buffers must be exactly 21 bytes.');
|
||||
});
|
||||
|
||||
it('should error because of incorrect type for pubkey transform', function() {
|
||||
(function() {
|
||||
var info = Address._transformPubkey(new Buffer(20));
|
||||
}).should.throw('Address must be an instance of Pubkey.');
|
||||
});
|
||||
|
||||
it('should error because of incorrect type for script transform', function() {
|
||||
(function() {
|
||||
var info = Address._transformScript(new Buffer(20));
|
||||
}).should.throw('Address must be an instance of Script.');
|
||||
});
|
||||
|
||||
it('should error because of incorrect type for string transform', function() {
|
||||
(function() {
|
||||
var info = Address._transformString(new Buffer(20));
|
||||
}).should.throw('Address supplied is not a string.');
|
||||
});
|
||||
|
||||
it('should make an address from a pubkey hash buffer', function() {
|
||||
var hash = pubkeyhash; //use the same hash
|
||||
var a = Address.fromPubkeyHash(hash).toString().should.equal(str);
|
||||
var b = Address.fromPubkeyHash(hash, 'testnet');
|
||||
b.network.should.equal('testnet');
|
||||
b.type.should.equal('pubkeyhash');
|
||||
var c = new Address(hash).toString().should.equal(str);
|
||||
});
|
||||
|
||||
it('should throw an error for invalid length hashBuffer', function() {
|
||||
(function() {
|
||||
var a = Address.fromPubkeyHash(buf);
|
||||
}).should.throw('Address hashbuffers must be exactly 20 bytes.');
|
||||
});
|
||||
|
||||
it('should make this address from a compressed pubkey object', function() {
|
||||
var pubkey = new Pubkey();
|
||||
pubkey.fromDER(new Buffer('0285e9737a74c30a873f74df05124f2aa6f53042c2fc0a130d6cbd7d16b944b004', 'hex'));
|
||||
var address = new Address();
|
||||
address.fromPubkey(pubkey);
|
||||
address.toString().should.equal('19gH5uhqY6DKrtkU66PsZPUZdzTd11Y7ke');
|
||||
pubkey.fromDER(new Buffer('0285e9737a74c30a873f74df05124f2aa6f53042c2fc0a130d6cbd7d16b944b004',
|
||||
'hex'));
|
||||
var a = Address.fromPubkey(pubkey);
|
||||
a.toString().should.equal('19gH5uhqY6DKrtkU66PsZPUZdzTd11Y7ke');
|
||||
var b = new Address(pubkey);
|
||||
b.toString().should.equal('19gH5uhqY6DKrtkU66PsZPUZdzTd11Y7ke');
|
||||
});
|
||||
|
||||
it('should make this address from an uncompressed pubkey', function() {
|
||||
var pubkey = new Pubkey();
|
||||
pubkey.fromDER(new Buffer('0285e9737a74c30a873f74df05124f2aa6f53042c2fc0a130d6cbd7d16b944b004', 'hex'));
|
||||
var address = new Address();
|
||||
pubkey.fromDER(new Buffer('0285e9737a74c30a873f74df05124f2aa6f53042c2fc0a130d6cbd7d16b944b004',
|
||||
'hex'));
|
||||
pubkey.compressed = false;
|
||||
address.fromPubkey(pubkey, 'mainnet');
|
||||
address.toString().should.equal('16JXnhxjJUhxfyx4y6H4sFcxrgt8kQ8ewX');
|
||||
var a = Address.fromPubkey(pubkey, 'mainnet', 'pubkeyhash');
|
||||
a.toString().should.equal('16JXnhxjJUhxfyx4y6H4sFcxrgt8kQ8ewX');
|
||||
var b = new Address(pubkey, 'mainnet', 'pubkeyhash');
|
||||
b.toString().should.equal('16JXnhxjJUhxfyx4y6H4sFcxrgt8kQ8ewX');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#fromScript', function() {
|
||||
|
||||
it('should make this address from a script', function() {
|
||||
var script = Script().fromString("OP_CHECKMULTISIG");
|
||||
var address = Address().fromScript(script);
|
||||
address.toString().should.equal('3BYmEwgV2vANrmfRymr1mFnHXgLjD6gAWm');
|
||||
var s = Script().fromString("OP_CHECKMULTISIG");
|
||||
var buf = s.toBuffer();
|
||||
var a = Address.fromScript(s);
|
||||
a.toString().should.equal('3BYmEwgV2vANrmfRymr1mFnHXgLjD6gAWm');
|
||||
var b = new Address(s);
|
||||
b.toString().should.equal('3BYmEwgV2vANrmfRymr1mFnHXgLjD6gAWm');
|
||||
var c = Address.fromScriptHash(bitcore.crypto.Hash.sha256ripemd160(buf));
|
||||
c.toString().should.equal('3BYmEwgV2vANrmfRymr1mFnHXgLjD6gAWm');
|
||||
});
|
||||
|
||||
it('should make this address from other script', function() {
|
||||
var script = Script().fromString("OP_CHECKSIG OP_HASH160");
|
||||
var address = Address().fromScript(script);
|
||||
address.toString().should.equal('347iRqVwks5r493N1rsLN4k9J7Ljg488W7');
|
||||
var s = Script().fromString("OP_CHECKSIG OP_HASH160");
|
||||
var a = Address.fromScript(s);
|
||||
a.toString().should.equal('347iRqVwks5r493N1rsLN4k9J7Ljg488W7');
|
||||
var b = new Address(s);
|
||||
b.toString().should.equal('347iRqVwks5r493N1rsLN4k9J7Ljg488W7');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#fromString', function() {
|
||||
|
||||
it('should derive from this known address string mainnet', function() {
|
||||
var address = new Address();
|
||||
address.fromString(str);
|
||||
address.toBuffer().slice(1).toString('hex').should.equal(pubkeyhash.toString('hex'));
|
||||
var address = new Address(str);
|
||||
var buffer = address.toBuffer();
|
||||
var slice = buffer.slice(1);
|
||||
var sliceString = slice.toString('hex')
|
||||
sliceString.should.equal(pubkeyhash.toString('hex'));
|
||||
});
|
||||
|
||||
it('should derive from this known address string testnet', function() {
|
||||
var address = new Address();
|
||||
address.fromString(str);
|
||||
address.networkstr = 'testnet';
|
||||
address.fromString(address.toString());
|
||||
address.toString().should.equal('mm1X5M2QWyHVjn7txrF7mmtZDpjCXzoa98');
|
||||
var a = new Address(testValidAddresses[0], 'testnet');
|
||||
var b = new Address(a.toString());
|
||||
b.toString().should.equal(testValidAddresses[0]);
|
||||
b.network.should.equal('testnet');
|
||||
});
|
||||
|
||||
it('should derive from this known address string mainnet scripthash', function() {
|
||||
var address = new Address();
|
||||
address.fromString(str);
|
||||
address.networkstr = 'mainnet';
|
||||
address.typestr = 'scripthash';
|
||||
address.fromString(address.toString());
|
||||
address.toString().should.equal('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo');
|
||||
var a = new Address(validp2shAddresses[0], 'mainnet', 'scripthash');
|
||||
var b = new Address(a.toString());
|
||||
b.toString().should.equal(validp2shAddresses[0]);
|
||||
});
|
||||
|
||||
it('should derive from this known address string testnet scripthash', function() {
|
||||
var address = new Address();
|
||||
address.fromString(str);
|
||||
address.networkstr = 'testnet';
|
||||
address.typestr = 'scripthash';
|
||||
address.fromString(address.toString());
|
||||
address.toString().should.equal('2MxjnmaMtsJfyFcyG3WZCzS2RihdNuWqeX4');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#isValid', function() {
|
||||
|
||||
it('should describe this valid address as valid', function() {
|
||||
var address = new Address();
|
||||
address.fromString('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo');
|
||||
address.isValid().should.equal(true);
|
||||
});
|
||||
|
||||
it('should describe this address with unknown network as invalid', function() {
|
||||
var address = new Address();
|
||||
address.fromString('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo');
|
||||
address.networkstr = 'unknown';
|
||||
address.isValid().should.equal(false);
|
||||
});
|
||||
|
||||
it('should describe this address with unknown type as invalid', function() {
|
||||
var address = new Address();
|
||||
address.fromString('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo');
|
||||
address.typestr = 'unknown';
|
||||
address.isValid().should.equal(false);
|
||||
var address = new Address(testValidp2shAddresses[0], 'testnet', 'scripthash');
|
||||
address = new Address(address.toString());
|
||||
address.toString().should.equal(testValidp2shAddresses[0]);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -158,47 +338,42 @@ describe('Address', function() {
|
|||
describe('#toBuffer', function() {
|
||||
|
||||
it('should output this known hash', function() {
|
||||
var address = new Address();
|
||||
address.fromString(str);
|
||||
var address = new Address(str);
|
||||
address.toBuffer().slice(1).toString('hex').should.equal(pubkeyhash.toString('hex'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#toString', function() {
|
||||
|
||||
it('should output the same thing that was input', function() {
|
||||
var address = new Address();
|
||||
address.fromString(str);
|
||||
|
||||
it('should output a mainnet pubkeyhash address', function() {
|
||||
var address = new Address(str);
|
||||
address.toString().should.equal(str);
|
||||
});
|
||||
|
||||
it('should output a scripthash address', function() {
|
||||
var address = new Address(validp2shAddresses[0]);
|
||||
address.toString().should.equal(validp2shAddresses[0]);
|
||||
});
|
||||
|
||||
it('should output a testnet scripthash address', function() {
|
||||
var address = new Address(testValidp2shAddresses[0]);
|
||||
address.toString().should.equal(testValidp2shAddresses[0]);
|
||||
});
|
||||
|
||||
it('should output a testnet pubkeyhash address', function() {
|
||||
var address = new Address(testValidAddresses[0]);
|
||||
address.toString().should.equal(testValidAddresses[0]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#validate', function() {
|
||||
|
||||
it('should not throw an error on this valid address', function() {
|
||||
var address = new Address();
|
||||
address.fromString(str);
|
||||
should.exist(address.validate());
|
||||
});
|
||||
describe('#inspect', function() {
|
||||
|
||||
it('should throw an error on this invalid network', function() {
|
||||
var address = new Address();
|
||||
address.fromString(str);
|
||||
address.networkstr = 'unknown';
|
||||
(function() {
|
||||
address.validate();
|
||||
}).should.throw('networkstr must be "mainnet" or "testnet"');
|
||||
});
|
||||
|
||||
it('should throw an error on this invalid type', function() {
|
||||
var address = new Address();
|
||||
address.fromString(str);
|
||||
address.typestr = 'unknown';
|
||||
(function() {
|
||||
address.validate();
|
||||
}).should.throw('typestr must be "pubkeyhash" or "scripthash"');
|
||||
it('should output formatted output correctly', function() {
|
||||
var address = new Address(str);
|
||||
var output = '<Address: 16VZnHwRhwrExfeHFHGjwrgEMq8VcYPs9r, type: pubkeyhash, network: mainnet>';
|
||||
address.inspect().should.equal(output);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue