Address: Modified interface so that any instance of Address can be assumed to be valid.

This commit is contained in:
Braydon Fuller 2014-11-18 21:18:07 -05:00
parent a70cafdf89
commit 90341f2ab6
2 changed files with 539 additions and 212 deletions

View File

@ -4,117 +4,341 @@ 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 (!data) {
throw Error('Please include address data');
}
}
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 (network && (network !== 'mainnet' && network !== 'testnet')) {
throw new Error('Network must be "mainnet" or "testnet"');
}
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 (type && (type !== 'pubkeyhash' && type !== 'scripthash')) {
throw new Error('Type must be "pubkeyhash" or "scripthash"');
}
var info;
// transform and validate input data
if (data instanceof Buffer && data.length === 20) {
info = Address._transformHash(data);
} else if (data instanceof Buffer && 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 Error('Unrecognized data format');
}
this.hashbuf = buf.slice(1);
// set defaults is 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) {
throw new Error('Address supplied is not a buffer');
}
return address.isValid();
if (hash.length !== 20) {
throw new Error('Address hashbuffers must be exactly a 20 bytes');
}
info.hashBuffer = hash;
return info;
}
/**
*
* 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) {
throw new Error('Address supplied is not a buffer');
}
if (buffer.length !== 1 + 20) {
throw new Error('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 Error('Address has mismatched network type');
}
if (!bufType || ( type && type !== bufType )) {
throw new Error('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 Error('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 Error('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 Error('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);
};
Address.prototype.isValid = function() {
/**
*
* 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 {
this.validate();
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) {
var error = Address.getValidationError(data, network, type);
if (error) {
return false;
} else {
return true;
} catch (e) {
return false;
}
};
/**
*
* 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;
};
module.exports = Address;

View File

@ -8,149 +8,267 @@ 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('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('Network 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('Type 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 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);
});
});
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 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() {
Address().fromHashbuf(buf);
}).should.throw('hashbuf must be exactly 20 bytes');
var a = Address.fromPubkeyHash(buf);
}).should.throw('Address hashbuffers must be exactly a 20 bytes');
});
});
describe('#fromPubkey', function() {
it('should make this address from a compressed pubkey', function() {
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 a = Address.fromScript(s);
a.toString().should.equal('3BYmEwgV2vANrmfRymr1mFnHXgLjD6gAWm');
var b = new Address(s);
b.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 +276,32 @@ 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);
});
});
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());
it('should output a scripthash address', function() {
var address = new Address(validp2shAddresses[0]);
address.toString().should.equal(validp2shAddresses[0]);
});
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 output a testnet scripthash address', function() {
var address = new Address(testValidp2shAddresses[0]);
address.toString().should.equal(testValidp2shAddresses[0]);
});
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 a testnet pubkeyhash address', function() {
var address = new Address(testValidAddresses[0]);
address.toString().should.equal(testValidAddresses[0]);
});
});