make address more consistent with rest of lib
This commit is contained in:
parent
cd6c2b2410
commit
3871e43dd8
114
lib/address.js
114
lib/address.js
|
@ -1,78 +1,64 @@
|
||||||
var base58check = require('./base58check');
|
var base58check = require('./base58check');
|
||||||
var constants = require('./constants');
|
var constants = require('./constants');
|
||||||
|
|
||||||
function Address(str) {
|
function Address(hash, network, type) {
|
||||||
if (!str) {
|
this.hash = hash;
|
||||||
this.buf = undefined;
|
this.network = network;
|
||||||
return;
|
this.type = type;
|
||||||
}
|
|
||||||
if (typeof str !== 'string')
|
|
||||||
throw new Error('address: Input must be a string, or undefined');
|
|
||||||
this.fromString(str);
|
|
||||||
};
|
|
||||||
|
|
||||||
Address.prototype.getNetwork = function() {
|
|
||||||
if (this.buf[0] === constants.mainnet.pubkeyHash || this.buf[0] === constants.mainnet.p2sh)
|
|
||||||
return 'mainnet';
|
|
||||||
else if (this.buf[0] === constants.testnet.pubkeyHash || this.buf[0] === constants.testnet.p2sh)
|
|
||||||
return 'testnet';
|
|
||||||
else
|
|
||||||
return 'unknown';
|
|
||||||
};
|
|
||||||
|
|
||||||
Address.prototype.getHash = function() {
|
|
||||||
var pubkeyHash = this.buf.slice(1);
|
|
||||||
if (pubkeyHash.length === 20)
|
|
||||||
return pubkeyHash;
|
|
||||||
else
|
|
||||||
throw new Error('address: Hash must be exactly 20 bytes');
|
|
||||||
};
|
|
||||||
|
|
||||||
Address.prototype.getType = function() {
|
|
||||||
if (this.buf[0] === constants.mainnet.pubkeyHash || this.buf[0] === constants.testnet.pubkeyHash)
|
|
||||||
return 'pubkeyHash';
|
|
||||||
else if (this.buf[0] === constants.mainnet.p2sh || this.buf[0] === constants.testnet.p2sh)
|
|
||||||
return 'p2sh';
|
|
||||||
else
|
|
||||||
return 'unknown';
|
|
||||||
};
|
|
||||||
|
|
||||||
Address.prototype.isValid = function() {
|
|
||||||
if (Buffer.isBuffer(this.buf) && this.buf.length === 1 + 20)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
Address.prototype.setBuf = function(buf, network, type) {
|
|
||||||
var version;
|
|
||||||
if (!Buffer.isBuffer(buf))
|
|
||||||
throw new Error('address: buf must be a buffer');
|
|
||||||
if (buf.length !== 20)
|
|
||||||
throw new Error('address: buf must be 20 bytes');
|
|
||||||
if (typeof network === 'undefined')
|
|
||||||
throw new Error('address: Must specify network ("mainnet" or "testnet")');
|
|
||||||
if (typeof type === 'undefined')
|
|
||||||
throw new Error('address: Must specify type ("pubkeyHash" or "p2sh")');
|
|
||||||
if (network !== 'mainnet' && network !== 'testnet')
|
|
||||||
throw new Error('address: Unknown network');
|
|
||||||
if (type !== 'pubkeyHash' && type !== 'p2sh')
|
|
||||||
throw new Error('address: Unknown type');
|
|
||||||
|
|
||||||
version = new Buffer([constants[network][type]]);
|
|
||||||
|
|
||||||
this.buf = Buffer.concat([version, buf]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.fromString = function(str) {
|
Address.prototype.fromString = function(str) {
|
||||||
var buf = base58check.decode(str);
|
var buf = base58check.decode(str);
|
||||||
if (buf.length !== 1 + 20)
|
if (buf.length !== 1 + 20)
|
||||||
throw new Error('address: Addresses must be exactly 21 bytes');
|
throw new Error('address: Address buffers must be exactly 21 bytes');
|
||||||
this.buf = buf;
|
var version = buf[0];
|
||||||
|
if (version === constants['mainnet']['pubkeyhash']) {
|
||||||
|
this.network = 'mainnet';
|
||||||
|
this.type = 'pubkeyhash';
|
||||||
|
} else if (version === constants['mainnet']['p2sh']) {
|
||||||
|
this.network = 'mainnet';
|
||||||
|
this.type = 'p2sh';
|
||||||
|
} else if (version === constants['testnet']['pubkeyhash']) {
|
||||||
|
this.network = 'testnet';
|
||||||
|
this.type = 'pubkeyhash';
|
||||||
|
} else if (version === constants['testnet']['p2sh']) {
|
||||||
|
this.network = 'testnet';
|
||||||
|
this.type = 'p2sh';
|
||||||
|
} else {
|
||||||
|
this.network = 'unknown';
|
||||||
|
this.type = 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hash = buf.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Address.prototype.isValid = function() {
|
||||||
|
try {
|
||||||
|
this.validate();
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Address.prototype.toBuffer = function() {
|
||||||
|
version = new Buffer([constants[this.network][this.type]]);
|
||||||
|
var buf = Buffer.concat([version, this.hash]);
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
|
||||||
Address.prototype.toString = function() {
|
Address.prototype.toString = function() {
|
||||||
return base58check.encode(this.buf);
|
return base58check.encode(this.toBuffer());
|
||||||
|
};
|
||||||
|
|
||||||
|
Address.prototype.validate = function() {
|
||||||
|
if (!Buffer.isBuffer(this.hash) || this.hash.length !== 20)
|
||||||
|
throw new Error('address: hash must be a buffer of 20 bytes');
|
||||||
|
if (this.network !== 'mainnet' && this.network !== 'testnet')
|
||||||
|
throw new Error('address: network must be "mainnet" or "testnet"');
|
||||||
|
if (this.type !== 'pubkeyhash' && this.type !== 'p2sh')
|
||||||
|
throw new Error('address: type must be "pubkeyhash" or "p2sh"');
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Address;
|
module.exports = Address;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
exports.mainnet = {
|
exports.mainnet = {
|
||||||
pubkeyHash: 0x00,
|
pubkeyhash: 0x00,
|
||||||
privkey: 0x80,
|
privkey: 0x80,
|
||||||
p2sh: 0x05,
|
p2sh: 0x05,
|
||||||
bip32pubkey: 0x0488b21e,
|
bip32pubkey: 0x0488b21e,
|
||||||
|
@ -7,7 +7,7 @@ exports.mainnet = {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testnet = {
|
exports.testnet = {
|
||||||
pubkeyHash: 0x6f,
|
pubkeyhash: 0x6f,
|
||||||
privkey: 0xef,
|
privkey: 0xef,
|
||||||
p2sh: 0xc4,
|
p2sh: 0xc4,
|
||||||
bip32pubkey: 0x043587cf,
|
bip32pubkey: 0x043587cf,
|
||||||
|
|
|
@ -4,147 +4,117 @@ var Address = require('../lib/address');
|
||||||
|
|
||||||
describe('address', function() {
|
describe('address', function() {
|
||||||
var pubkeyhash = new Buffer('3c3fa3d4adcaf8f52d5b1843975e122548269937', 'hex');
|
var pubkeyhash = new Buffer('3c3fa3d4adcaf8f52d5b1843975e122548269937', 'hex');
|
||||||
var str = '1Cs8a3b7R5n4G9c8Cgbp9iW8BXbhv3SFt6';
|
var str = '16VZnHwRhwrExfeHFHGjwrgEMq8VcYPs9r';
|
||||||
|
|
||||||
it('should create a new address object', function() {
|
it('should create a new address object', function() {
|
||||||
var address = new Address();
|
var address = new Address();
|
||||||
should.exist(address);
|
should.exist(address);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when input is not a string', function() {
|
describe('#fromString', function() {
|
||||||
(function() {
|
|
||||||
var address = new Address(5);
|
|
||||||
}).should.throw('address: Input must be a string, or undefined');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#getNetwork', function() {
|
it('should derive from this known address string mainnet', function() {
|
||||||
|
|
||||||
it('should return mainnet for pubkeyhash', function() {
|
|
||||||
var address = new Address();
|
var address = new Address();
|
||||||
address.buf = Buffer.concat([new Buffer([constants.mainnet.pubkeyHash]), pubkeyhash]);
|
address.fromString(str);
|
||||||
address.getNetwork().should.equal('mainnet');
|
address.toBuffer().slice(1).toString('hex').should.equal(pubkeyhash.toString('hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return mainnet for p2sh', function() {
|
it('should derive from this known address string testnet', function() {
|
||||||
var address = new Address();
|
var address = new Address();
|
||||||
address.buf = Buffer.concat([new Buffer([constants.mainnet.p2sh]), pubkeyhash]);
|
address.fromString(str);
|
||||||
address.getNetwork().should.equal('mainnet');
|
address.network = 'testnet';
|
||||||
});
|
address.fromString(address.toString());
|
||||||
|
|
||||||
it('should return testnet for pubkeyhash', function() {
|
|
||||||
var address = new Address();
|
|
||||||
address.buf = Buffer.concat([new Buffer([constants.testnet.pubkeyHash]), pubkeyhash]);
|
|
||||||
address.getNetwork().should.equal('testnet');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return testnet for p2sh', function() {
|
|
||||||
var address = new Address();
|
|
||||||
address.buf = Buffer.concat([new Buffer([constants.testnet.p2sh]), pubkeyhash]);
|
|
||||||
address.getNetwork().should.equal('testnet');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return unknown', function() {
|
|
||||||
var address = new Address();
|
|
||||||
address.buf = Buffer.concat([new Buffer([0x55]), pubkeyhash]);
|
|
||||||
address.getNetwork().should.equal('unknown');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error if there is no buffer', function() {
|
|
||||||
var address = new Address();
|
|
||||||
(function() {
|
|
||||||
address.getNetwork();
|
|
||||||
}).should.throw();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#getHash', function() {
|
|
||||||
|
|
||||||
it('should return the hash', function() {
|
|
||||||
var address = new Address();
|
|
||||||
address.buf = Buffer.concat([new Buffer([0x00]), pubkeyhash]);
|
|
||||||
address.getHash().toString('hex').should.equal(pubkeyhash.toString('hex'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error if the buffer is an invalid length', function() {
|
|
||||||
var address = new Address();
|
|
||||||
address.buf = Buffer.concat([new Buffer([0x00]), pubkeyhash.slice(-1)]);
|
|
||||||
(function() {
|
|
||||||
address.getHash();
|
|
||||||
}).should.throw('address: Hash must be exactly 20 bytes');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#getType', function() {
|
|
||||||
|
|
||||||
it('should get the type of 2MxjnmaMtsJfyFcyG3WZCzS2RihdNuWqeX4 correctly', function() {
|
|
||||||
var addr = new Address();
|
|
||||||
addr.fromString('2MxjnmaMtsJfyFcyG3WZCzS2RihdNuWqeX4');
|
|
||||||
addr.getNetwork().should.equal('testnet');
|
|
||||||
addr.getType().should.equal('p2sh');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#setBuf', function() {
|
|
||||||
|
|
||||||
it('should convert this pubkeyhash on mainnet and type pubkeyHash to known address', function() {
|
|
||||||
var address = new Address();
|
|
||||||
address.setBuf(pubkeyhash, 'mainnet', 'pubkeyHash');
|
|
||||||
address.toString().should.equal('16VZnHwRhwrExfeHFHGjwrgEMq8VcYPs9r');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should convert this pubkeyhash on mainnet and type p2sh to known address', function() {
|
|
||||||
var address = new Address();
|
|
||||||
address.setBuf(pubkeyhash, 'mainnet', 'p2sh');
|
|
||||||
address.toString().should.equal('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should convert this pubkeyhash on testnet and type pubkeyHash to known address', function() {
|
|
||||||
var address = new Address();
|
|
||||||
address.setBuf(pubkeyhash, 'testnet', 'pubkeyHash');
|
|
||||||
address.toString().should.equal('mm1X5M2QWyHVjn7txrF7mmtZDpjCXzoa98');
|
address.toString().should.equal('mm1X5M2QWyHVjn7txrF7mmtZDpjCXzoa98');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should convert this pubkeyhash on testnet and type p2sh to known address', function() {
|
it('should derive from this known address string mainnet p2sh', function() {
|
||||||
var address = new Address();
|
var address = new Address();
|
||||||
address.setBuf(pubkeyhash, 'testnet', 'p2sh');
|
address.fromString(str);
|
||||||
|
address.network = 'mainnet';
|
||||||
|
address.type = 'p2sh';
|
||||||
|
address.fromString(address.toString());
|
||||||
|
address.toString().should.equal('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should derive from this known address string testnet p2sh', function() {
|
||||||
|
var address = new Address();
|
||||||
|
address.fromString(str);
|
||||||
|
address.network = 'testnet';
|
||||||
|
address.type = 'p2sh';
|
||||||
|
address.fromString(address.toString());
|
||||||
address.toString().should.equal('2MxjnmaMtsJfyFcyG3WZCzS2RihdNuWqeX4');
|
address.toString().should.equal('2MxjnmaMtsJfyFcyG3WZCzS2RihdNuWqeX4');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error for an unknown type', function() {
|
});
|
||||||
|
|
||||||
|
describe('#isValid', function() {
|
||||||
|
|
||||||
|
it('should describe this valid address as valid', function() {
|
||||||
var address = new Address();
|
var address = new Address();
|
||||||
(function() {
|
address.fromString('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo');
|
||||||
address.setBuf(pubkeyhash, 'testnet', 'p2sh2');
|
address.isValid().should.equal(true);
|
||||||
}).should.throw();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error for an unknown network', function() {
|
it('should describe this address with unknown network as invalid', function() {
|
||||||
var address = new Address();
|
var address = new Address();
|
||||||
(function() {
|
address.fromString('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo');
|
||||||
address.setBuf(pubkeyhash, 'testnet2', 'p2sh');
|
address.network = 'unknown';
|
||||||
}).should.throw();
|
address.isValid().should.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should describe this address with unknown type as invalid', function() {
|
||||||
|
var address = new Address();
|
||||||
|
address.fromString('37BahqRsFrAd3qLiNNwLNV3AWMRD7itxTo');
|
||||||
|
address.type = 'unknown';
|
||||||
|
address.isValid().should.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#fromString', function() {
|
describe('#toBuffer', function() {
|
||||||
|
|
||||||
it('should decode 1Cs8a3b7R5n4G9c8Cgbp9iW8BXbhv3SFt6 correctly', function() {
|
it('should output this known hash', function() {
|
||||||
var addr = new Address();
|
var address = new Address();
|
||||||
addr.fromString('1Cs8a3b7R5n4G9c8Cgbp9iW8BXbhv3SFt6');
|
address.fromString(str);
|
||||||
addr.getHash().toString('hex').should.equal('82248027cfb0fe085b750f359fd1e43234e46c7f');
|
address.toBuffer().slice(1).toString('hex').should.equal(pubkeyhash.toString('hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#toString', function() {
|
describe('#toString', function() {
|
||||||
|
|
||||||
it('should return 1Cs8a3b7R5n4G9c8Cgbp9iW8BXbhv3SFt6', function() {
|
it('should output the same thing that was input', function() {
|
||||||
var addr = new Address();
|
var address = new Address();
|
||||||
addr.fromString('1Cs8a3b7R5n4G9c8Cgbp9iW8BXbhv3SFt6');
|
address.fromString(str);
|
||||||
addr.toString().should.equal('1Cs8a3b7R5n4G9c8Cgbp9iW8BXbhv3SFt6');
|
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 throw an error on this invalid network', function() {
|
||||||
|
var address = new Address();
|
||||||
|
address.fromString(str);
|
||||||
|
address.network = 'unknown';
|
||||||
|
(function() {
|
||||||
|
address.validate();
|
||||||
|
}).should.throw('address: network must be "mainnet" or "testnet"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error on this invalid type', function() {
|
||||||
|
var address = new Address();
|
||||||
|
address.fromString(str);
|
||||||
|
address.type = 'unknown';
|
||||||
|
(function() {
|
||||||
|
address.validate();
|
||||||
|
}).should.throw('address: type must be "pubkeyhash" or "p2sh"');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue