Merge pull request #705 from braydonf/ref/address-network
Address: Documentation and Network Refactor
This commit is contained in:
commit
b89f15bcf1
|
@ -4,6 +4,44 @@ Represents a bitcoin Address. Addresses became the most popular way to make
|
|||
bitcoin transactions. See [the official Bitcoin
|
||||
Wiki](https://en.bitcoin.it/wiki/Address) for more information.
|
||||
|
||||
|
||||
## Instantiate an Address
|
||||
|
||||
To be able to receive bitcoin an address is needed, here is how to create an
|
||||
address from a new private key. Please see the [`PrivateKey`](PrivateKey.md) docs
|
||||
for more information about exporting and saving a key.
|
||||
|
||||
```javascript
|
||||
|
||||
var PrivateKey = require('bitcore/lib/privatekey');
|
||||
var privateKey = new PrivateKey();
|
||||
var address = privateKey.toAddress();
|
||||
|
||||
```
|
||||
|
||||
You can also instantiate an address from a String or PublicKey.
|
||||
|
||||
```javascript
|
||||
|
||||
var Address = require('bitcore/lib/address');
|
||||
var PublicKey = require('bitcore/lib/publickey');
|
||||
var Networks = require('bitcore/lib/networks');
|
||||
|
||||
// from a string
|
||||
var address = Address.fromString('mwkXG8NnB2snbqWTcpNiK6qqGHm1LebHDc');
|
||||
|
||||
// a default network address from a public key
|
||||
var publicKey = PublicKey(privateKey);
|
||||
var address = Address.fromPublicKey(publicKey);
|
||||
|
||||
// a testnet address from a public key
|
||||
var publicKey = PublicKey(privateKey);
|
||||
var address = Address.fromPublicKey(publicKey, Networks.testnet);
|
||||
|
||||
```
|
||||
|
||||
## Validating an Address
|
||||
|
||||
The main use that we expect you'll have for the `Address` class in bitcore is
|
||||
validating that an address is a valid one, what type of address it is (you may
|
||||
be interested on knowning if the address is a simple "pay to public key hash"
|
||||
|
@ -13,18 +51,27 @@ belong to.
|
|||
The code to do these validations looks like this:
|
||||
|
||||
```javascript
|
||||
var address = new bitcore.Address('1BitcoinAddress...');
|
||||
assert(address.network === bitcore.network.livenet);
|
||||
// Detect the kind of the address...
|
||||
assert(address.scriptType === bitcore.Address.Pay2PubKeyHash);
|
||||
```
|
||||
|
||||
There are also static methods for this that work very similarly:
|
||||
// validate an address
|
||||
if (Address.isValid(input){
|
||||
...
|
||||
}
|
||||
|
||||
// validate that an input field is a valid testnet address
|
||||
if (Address.isValid(input, Networks.testnet){
|
||||
...
|
||||
}
|
||||
|
||||
// validate that an input field is a valid livenet pubkeyhash
|
||||
if (Address.isValid(input, Networks.livenet, Address.Pay2PubKeyHash){
|
||||
...
|
||||
}
|
||||
|
||||
// get the specific validation error that can occurred
|
||||
var error = Address.getValidationError(input, Networks.testnet);
|
||||
if (error) {
|
||||
// handle the error
|
||||
}
|
||||
}
|
||||
|
||||
```javascript
|
||||
var address = new bitcore.Address();
|
||||
assert(bitcore.Address.isValid('1BitcoinAddress...'));
|
||||
assert(bitcore.Address.network('1BitcoinAddress...') === bitcore.network.livenet);
|
||||
assert(bitcore.Address.scriptType('1BitcoinAddress...') !== bitcore.Address.Pay2ScriptHash);
|
||||
assert(bitcore.Address.scriptType('3MultisigP2SH...') === bitcore.Address.Pay2ScriptHash);
|
||||
```
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
var base58check = require('./encoding/base58check');
|
||||
var networks = require('./networks');
|
||||
var Networks = require('./networks');
|
||||
var Hash = require('./crypto/hash');
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from an address String or Buffer, a public key or script hash Buffer,
|
||||
* or an instance of PublicKey or Script.
|
||||
*
|
||||
|
@ -40,7 +39,7 @@ function Address(data, network, type) {
|
|||
throw new TypeError('First argument is required, please include address data.');
|
||||
}
|
||||
|
||||
if (network && !networks.get(network)) {
|
||||
if (network && !Networks.get(network)) {
|
||||
throw new TypeError('Second argument must be "livenet" or "testnet".');
|
||||
}
|
||||
|
||||
|
@ -68,7 +67,7 @@ function Address(data, network, type) {
|
|||
}
|
||||
|
||||
// set defaults if not set
|
||||
info.network = info.network || network || networks.defaultNetwork.name;
|
||||
info.network = info.network || Networks.get(network) || Networks.defaultNetwork;
|
||||
info.type = info.type || type || Address.PayToPublicKeyHash;
|
||||
|
||||
Object.defineProperty(this, 'hashBuffer', {
|
||||
|
@ -93,7 +92,6 @@ Address.PayToPublicKeyHash = 'pubkeyhash';
|
|||
Address.PayToScriptHash = 'scripthash';
|
||||
|
||||
/**
|
||||
*
|
||||
* Internal function to transform a hash buffer
|
||||
*
|
||||
* @param {Buffer} hash - An instance of a hash Buffer
|
||||
|
@ -113,7 +111,39 @@ Address._transformHash = function(hash){
|
|||
};
|
||||
|
||||
/**
|
||||
* Internal function to discover the network and type
|
||||
*
|
||||
* @param {Buffer} buffer - An instance of a hex encoded address Buffer
|
||||
* @returns {Object} An object with keys: network and type
|
||||
* @private
|
||||
*/
|
||||
Address._classifyFromVersion = function(buffer){
|
||||
var version = {};
|
||||
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;
|
||||
}
|
||||
return version;
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal function to transform a bitcoin address buffer
|
||||
*
|
||||
* @param {Buffer} buffer - An instance of a hex encoded address Buffer
|
||||
|
@ -131,47 +161,24 @@ Address._transformBuffer = function(buffer, network, type){
|
|||
throw new TypeError('Address buffers must be exactly 21 bytes.');
|
||||
}
|
||||
|
||||
var bufNetwork = false;
|
||||
var bufType = false;
|
||||
network = Networks.get(network);
|
||||
var bufferVersion = Address._classifyFromVersion(buffer);
|
||||
|
||||
switch(buffer[0]){ // the version byte
|
||||
case networks.livenet.pubkeyhash:
|
||||
bufNetwork = 'livenet';
|
||||
bufType = 'pubkeyhash';
|
||||
break;
|
||||
|
||||
case networks.livenet.scripthash:
|
||||
bufNetwork = 'livenet';
|
||||
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)) {
|
||||
if (!bufferVersion.network || (network && network !== bufferVersion.network)) {
|
||||
throw new TypeError('Address has mismatched network type.');
|
||||
}
|
||||
|
||||
if (!bufType || ( type && type !== bufType )) {
|
||||
if (!bufferVersion.type || ( type && type !== bufferVersion.type )) {
|
||||
throw new TypeError('Address has mismatched type.');
|
||||
}
|
||||
|
||||
info.hashBuffer = buffer.slice(1);
|
||||
info.network = bufNetwork;
|
||||
info.type = bufType;
|
||||
info.network = bufferVersion.network;
|
||||
info.type = bufferVersion.type;
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Internal function to transform a PublicKey
|
||||
*
|
||||
* @param {PublicKey} pubkey - An instance of PublicKey
|
||||
|
@ -189,7 +196,6 @@ Address._transformPublicKey = function(pubkey){
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Internal function to transform a Script
|
||||
*
|
||||
* @param {Script} script - An instance of Script
|
||||
|
@ -207,7 +213,6 @@ Address._transformScript = function(script){
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Internal function to transform a bitcoin address string
|
||||
*
|
||||
* @param {String} data - An instance of PublicKey
|
||||
|
@ -226,7 +231,6 @@ Address._transformString = function(data, network, type){
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from a PublicKey instance
|
||||
*
|
||||
* @param {PublicKey} data - An instance of PublicKey
|
||||
|
@ -235,12 +239,11 @@ Address._transformString = function(data, network, type){
|
|||
*/
|
||||
Address.fromPublicKey = function(data, network){
|
||||
var info = Address._transformPublicKey(data);
|
||||
network = network || networks.defaultNetwork.name;
|
||||
network = network || Networks.defaultNetwork;
|
||||
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
|
||||
|
@ -253,7 +256,6 @@ Address.fromPublicKeyHash = function(hash, network) {
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from a ripemd160 script hash
|
||||
*
|
||||
* @param {Buffer} hash - An instance of buffer of the hash
|
||||
|
@ -266,7 +268,6 @@ Address.fromScriptHash = function(hash, network) {
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from a Script
|
||||
*
|
||||
* @param {Script} script - An instance of Script
|
||||
|
@ -279,7 +280,6 @@ Address.fromScript = function(script, network) {
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from a buffer of the address
|
||||
*
|
||||
* @param {Buffer} buffer - An instance of buffer of the address
|
||||
|
@ -293,7 +293,6 @@ Address.fromBuffer = function(buffer, network, type) {
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Instantiate an address from an address string
|
||||
*
|
||||
* @param {String} str - An string of the bitcoin address
|
||||
|
@ -307,7 +306,6 @@ Address.fromString = function(str, network, type) {
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Will return a validation error if exists
|
||||
*
|
||||
* @example
|
||||
|
@ -331,7 +329,6 @@ Address.getValidationError = function(data, network, type) {
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Will return a boolean if an address is valid
|
||||
*
|
||||
* @example
|
||||
|
@ -365,19 +362,17 @@ Address.prototype.isPayToScriptHash = function() {
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Will return a buffer representation of the address
|
||||
*
|
||||
* @returns {Buffer} Bitcoin address buffer
|
||||
*/
|
||||
Address.prototype.toBuffer = function() {
|
||||
var version = new Buffer([networks[this.network][this.type]]);
|
||||
var version = new Buffer([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
|
||||
|
@ -387,7 +382,6 @@ Address.prototype.toString = function() {
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Will return a string formatted for the console
|
||||
*
|
||||
* @returns {String} Bitcoin address
|
||||
|
|
|
@ -9,6 +9,10 @@ var _ = require('lodash');
|
|||
*/
|
||||
function Network() {}
|
||||
|
||||
Network.prototype.toString = function toString() {
|
||||
return this.name;
|
||||
};
|
||||
|
||||
/**
|
||||
* @instance
|
||||
* @member Network#livenet
|
||||
|
|
|
@ -8,7 +8,7 @@ var bitcore = require('..');
|
|||
var PublicKey = bitcore.PublicKey;
|
||||
var Address = bitcore.Address;
|
||||
var Script = bitcore.Script;
|
||||
var networks = bitcore.Networks;
|
||||
var Networks = bitcore.Networks;
|
||||
|
||||
describe('Address', function() {
|
||||
|
||||
|
@ -205,6 +205,10 @@ describe('Address', function() {
|
|||
new Address(str).toString().should.equal(str);
|
||||
});
|
||||
|
||||
it('should make an address using a non-string network', function() {
|
||||
Address.fromString(str, Networks.livenet).toString().should.equal(str);
|
||||
});
|
||||
|
||||
it('should error because of unrecognized data format', function() {
|
||||
(function() {
|
||||
return new Address(new Error());
|
||||
|
@ -257,7 +261,7 @@ describe('Address', function() {
|
|||
var hash = pubkeyhash; //use the same hash
|
||||
Address.fromPublicKeyHash(hash).toString().should.equal(str);
|
||||
var b = Address.fromPublicKeyHash(hash, 'testnet');
|
||||
b.network.should.equal('testnet');
|
||||
b.network.should.equal(Networks.testnet);
|
||||
b.type.should.equal('pubkeyhash');
|
||||
new Address(hash).toString().should.equal(str);
|
||||
});
|
||||
|
@ -265,13 +269,13 @@ describe('Address', function() {
|
|||
it('should make an address using the default network', function() {
|
||||
var hash = pubkeyhash; //use the same hash
|
||||
var a = Address.fromPublicKeyHash(hash);
|
||||
a.network.should.equal('livenet');
|
||||
a.network.should.equal(Networks.livenet);
|
||||
// change the default
|
||||
networks.defaultNetwork = networks.testnet;
|
||||
Networks.defaultNetwork = Networks.testnet;
|
||||
var b = Address.fromPublicKeyHash(hash);
|
||||
b.network.should.equal('testnet');
|
||||
b.network.should.equal(Networks.testnet);
|
||||
// restore the default
|
||||
networks.defaultNetwork = networks.livenet;
|
||||
Networks.defaultNetwork = Networks.livenet;
|
||||
});
|
||||
|
||||
it('should throw an error for invalid length hashBuffer', function() {
|
||||
|
@ -325,7 +329,7 @@ describe('Address', function() {
|
|||
var a = new Address(PKHTestnet[0], 'testnet');
|
||||
var b = new Address(a.toString());
|
||||
b.toString().should.equal(PKHTestnet[0]);
|
||||
b.network.should.equal('testnet');
|
||||
b.network.should.equal(Networks.testnet);
|
||||
});
|
||||
|
||||
it('should derive from this known address string livenet scripthash', function() {
|
||||
|
|
14
test/uri.js
14
test/uri.js
|
@ -1,9 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
var chai = chai || require('chai');
|
||||
var should = chai.should();
|
||||
var expect = chai.expect;
|
||||
var bitcore = require('..');
|
||||
var expect = chai.expect;
|
||||
var Networks = bitcore.Networks;
|
||||
var should = chai.should();
|
||||
var URI = bitcore.URI;
|
||||
|
||||
describe('URI', function() {
|
||||
|
@ -62,11 +63,11 @@ describe('URI', function() {
|
|||
|
||||
uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
||||
uri.address.should.be.instanceof(bitcore.Address);
|
||||
uri.network.should.equal('livenet');
|
||||
uri.network.should.equal(Networks.livenet);
|
||||
|
||||
uri = new URI('bitcoin:mkYY5NRvikVBY1EPtaq9fAFgquesdjqECw');
|
||||
uri.address.should.be.instanceof(bitcore.Address);
|
||||
uri.network.should.equal('testnet');
|
||||
uri.network.should.equal(Networks.testnet);
|
||||
|
||||
uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&other=param');
|
||||
uri.address.should.be.instanceof(bitcore.Address);
|
||||
|
@ -92,14 +93,13 @@ describe('URI', function() {
|
|||
address: '1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj'
|
||||
});
|
||||
uri.address.should.be.instanceof(bitcore.Address);
|
||||
uri.network.should.equal('livenet');
|
||||
uri.network.should.equal(Networks.livenet);
|
||||
|
||||
uri = new URI({
|
||||
address: 'mkYY5NRvikVBY1EPtaq9fAFgquesdjqECw'
|
||||
});
|
||||
uri.address.should.be.instanceof(bitcore.Address);
|
||||
uri.network.should.equal('testnet');
|
||||
|
||||
uri.network.should.equal(Networks.testnet);
|
||||
|
||||
uri = new URI({
|
||||
address: '1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj',
|
||||
|
|
Loading…
Reference in New Issue