allow custom bip32 prefixes, and varying types of addresses returned get hdnode.getAddress
This commit is contained in:
parent
5b0ccb6f68
commit
f44e662dbe
5 changed files with 286 additions and 25 deletions
|
@ -1,6 +1,7 @@
|
||||||
var Buffer = require('safe-buffer').Buffer
|
var Buffer = require('safe-buffer').Buffer
|
||||||
var base58check = require('bs58check')
|
var base58check = require('bs58check')
|
||||||
var bcrypto = require('./crypto')
|
var bcrypto = require('./crypto')
|
||||||
|
var baddress = require('./address')
|
||||||
var createHmac = require('create-hmac')
|
var createHmac = require('create-hmac')
|
||||||
var typeforce = require('typeforce')
|
var typeforce = require('typeforce')
|
||||||
var types = require('./types')
|
var types = require('./types')
|
||||||
|
@ -9,12 +10,15 @@ var NETWORKS = require('./networks')
|
||||||
var BigInteger = require('bigi')
|
var BigInteger = require('bigi')
|
||||||
var ECPair = require('./ecpair')
|
var ECPair = require('./ecpair')
|
||||||
|
|
||||||
|
// var KeyToScript = require('./keytoscript')
|
||||||
var ecurve = require('ecurve')
|
var ecurve = require('ecurve')
|
||||||
var curve = ecurve.getCurveByName('secp256k1')
|
var curve = ecurve.getCurveByName('secp256k1')
|
||||||
|
|
||||||
function HDNode (keyPair, chainCode) {
|
function HDNode (keyPair, chainCode, prefix) {
|
||||||
typeforce(types.tuple('ECPair', types.Buffer256bit), arguments)
|
typeforce(types.tuple('ECPair', types.Buffer256bit), arguments)
|
||||||
|
if (!prefix) {
|
||||||
|
prefix = keyPair.network.bip32
|
||||||
|
}
|
||||||
if (!keyPair.compressed) throw new TypeError('BIP32 only allows compressed keyPairs')
|
if (!keyPair.compressed) throw new TypeError('BIP32 only allows compressed keyPairs')
|
||||||
|
|
||||||
this.keyPair = keyPair
|
this.keyPair = keyPair
|
||||||
|
@ -22,13 +26,14 @@ function HDNode (keyPair, chainCode) {
|
||||||
this.depth = 0
|
this.depth = 0
|
||||||
this.index = 0
|
this.index = 0
|
||||||
this.parentFingerprint = 0x00000000
|
this.parentFingerprint = 0x00000000
|
||||||
|
this.prefix = prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
HDNode.HIGHEST_BIT = 0x80000000
|
HDNode.HIGHEST_BIT = 0x80000000
|
||||||
HDNode.LENGTH = 78
|
HDNode.LENGTH = 78
|
||||||
HDNode.MASTER_SECRET = Buffer.from('Bitcoin seed', 'utf8')
|
HDNode.MASTER_SECRET = Buffer.from('Bitcoin seed', 'utf8')
|
||||||
|
|
||||||
HDNode.fromSeedBuffer = function (seed, network) {
|
HDNode.fromSeedBuffer = function (seed, network, prefix) {
|
||||||
typeforce(types.tuple(types.Buffer, types.maybe(types.Network)), arguments)
|
typeforce(types.tuple(types.Buffer, types.maybe(types.Network)), arguments)
|
||||||
|
|
||||||
if (seed.length < 16) throw new TypeError('Seed should be at least 128 bits')
|
if (seed.length < 16) throw new TypeError('Seed should be at least 128 bits')
|
||||||
|
@ -45,14 +50,21 @@ HDNode.fromSeedBuffer = function (seed, network) {
|
||||||
network: network
|
network: network
|
||||||
})
|
})
|
||||||
|
|
||||||
return new HDNode(keyPair, IR)
|
return new HDNode(keyPair, IR, prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
HDNode.fromSeedHex = function (hex, network) {
|
HDNode.fromSeedHex = function (hex, network, prefix) {
|
||||||
return HDNode.fromSeedBuffer(Buffer.from(hex, 'hex'), network)
|
return HDNode.fromSeedBuffer(Buffer.from(hex, 'hex'), network, prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
HDNode.fromBase58 = function (string, networks) {
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} string
|
||||||
|
* @param {Array<network>|network} networks
|
||||||
|
* @param {Array<prefix>} prefixes - only used if networks is object/undefined(so bitcoin).
|
||||||
|
* @returns {HDNode}
|
||||||
|
*/
|
||||||
|
HDNode.fromBase58 = function (string, networks, prefixes) {
|
||||||
var buffer = base58check.decode(string)
|
var buffer = base58check.decode(string)
|
||||||
if (buffer.length !== 78) throw new Error('Invalid buffer length')
|
if (buffer.length !== 78) throw new Error('Invalid buffer length')
|
||||||
|
|
||||||
|
@ -61,6 +73,7 @@ HDNode.fromBase58 = function (string, networks) {
|
||||||
var network
|
var network
|
||||||
|
|
||||||
// list of networks?
|
// list of networks?
|
||||||
|
var prefix
|
||||||
if (Array.isArray(networks)) {
|
if (Array.isArray(networks)) {
|
||||||
network = networks.filter(function (x) {
|
network = networks.filter(function (x) {
|
||||||
return version === x.bip32.private ||
|
return version === x.bip32.private ||
|
||||||
|
@ -69,13 +82,26 @@ HDNode.fromBase58 = function (string, networks) {
|
||||||
|
|
||||||
if (!network) throw new Error('Unknown network version')
|
if (!network) throw new Error('Unknown network version')
|
||||||
|
|
||||||
|
// we found a network by it's bip32 prefixes, use that
|
||||||
|
prefix = network.bip32
|
||||||
|
|
||||||
// otherwise, assume a network object (or default to bitcoin)
|
// otherwise, assume a network object (or default to bitcoin)
|
||||||
} else {
|
} else {
|
||||||
network = networks || NETWORKS.bitcoin
|
network = networks || NETWORKS.bitcoin
|
||||||
|
if (prefixes) {
|
||||||
|
prefix = prefixes.filter(function (x) {
|
||||||
|
return version === x.private ||
|
||||||
|
version === x.public
|
||||||
|
}).pop()
|
||||||
|
} else {
|
||||||
|
// no special prefixes to consider, use networks bip32 prefix
|
||||||
|
prefix = network.bip32
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version !== network.bip32.private &&
|
// sanity check the version against the prefix
|
||||||
version !== network.bip32.public) throw new Error('Invalid network version')
|
if (version !== prefix.private &&
|
||||||
|
version !== prefix.public) throw new Error('Invalid network version')
|
||||||
|
|
||||||
// 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ...
|
// 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ...
|
||||||
var depth = buffer[4]
|
var depth = buffer[4]
|
||||||
|
@ -114,7 +140,7 @@ HDNode.fromBase58 = function (string, networks) {
|
||||||
keyPair = new ECPair(null, Q, { network: network })
|
keyPair = new ECPair(null, Q, { network: network })
|
||||||
}
|
}
|
||||||
|
|
||||||
var hd = new HDNode(keyPair, chainCode)
|
var hd = new HDNode(keyPair, chainCode, prefix)
|
||||||
hd.depth = depth
|
hd.depth = depth
|
||||||
hd.index = index
|
hd.index = index
|
||||||
hd.parentFingerprint = parentFingerprint
|
hd.parentFingerprint = parentFingerprint
|
||||||
|
@ -123,7 +149,8 @@ HDNode.fromBase58 = function (string, networks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HDNode.prototype.getAddress = function () {
|
HDNode.prototype.getAddress = function () {
|
||||||
return this.keyPair.getAddress()
|
var data = this.prefix.scriptFactory.convert(this.keyPair)
|
||||||
|
return baddress.fromOutputScript(data.scriptPubKey, this.keyPair.network)
|
||||||
}
|
}
|
||||||
|
|
||||||
HDNode.prototype.getIdentifier = function () {
|
HDNode.prototype.getIdentifier = function () {
|
||||||
|
@ -147,7 +174,7 @@ HDNode.prototype.neutered = function () {
|
||||||
network: this.keyPair.network
|
network: this.keyPair.network
|
||||||
})
|
})
|
||||||
|
|
||||||
var neutered = new HDNode(neuteredKeyPair, this.chainCode)
|
var neutered = new HDNode(neuteredKeyPair, this.chainCode, this.prefix)
|
||||||
neutered.depth = this.depth
|
neutered.depth = this.depth
|
||||||
neutered.index = this.index
|
neutered.index = this.index
|
||||||
neutered.parentFingerprint = this.parentFingerprint
|
neutered.parentFingerprint = this.parentFingerprint
|
||||||
|
@ -167,8 +194,7 @@ HDNode.prototype.toBase58 = function (__isPrivate) {
|
||||||
if (__isPrivate !== undefined) throw new TypeError('Unsupported argument in 2.0.0')
|
if (__isPrivate !== undefined) throw new TypeError('Unsupported argument in 2.0.0')
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
var network = this.keyPair.network
|
var version = (!this.isNeutered()) ? this.prefix.private : this.prefix.public
|
||||||
var version = (!this.isNeutered()) ? network.bip32.private : network.bip32.public
|
|
||||||
var buffer = Buffer.allocUnsafe(78)
|
var buffer = Buffer.allocUnsafe(78)
|
||||||
|
|
||||||
// 4 bytes: version bytes
|
// 4 bytes: version bytes
|
||||||
|
@ -268,7 +294,7 @@ HDNode.prototype.derive = function (index) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var hd = new HDNode(derivedKeyPair, IR)
|
var hd = new HDNode(derivedKeyPair, IR, this.prefix)
|
||||||
hd.depth = this.depth + 1
|
hd.depth = this.depth + 1
|
||||||
hd.index = index
|
hd.index = index
|
||||||
hd.parentFingerprint = this.getFingerprint().readUInt32BE(0)
|
hd.parentFingerprint = this.getFingerprint().readUInt32BE(0)
|
||||||
|
|
124
src/keytoscript.js
Normal file
124
src/keytoscript.js
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
var bcrypto = require('./crypto')
|
||||||
|
var btemplates = require('./templates')
|
||||||
|
|
||||||
|
function checkAllowedP2sh (keyFactory) {
|
||||||
|
if (!(keyFactory instanceof P2pkhFactory ||
|
||||||
|
keyFactory instanceof P2wpkhFactory ||
|
||||||
|
keyFactory instanceof P2pkFactory
|
||||||
|
)) {
|
||||||
|
throw new Error('Unsupported script factory for P2SH')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAllowedP2wsh (keyFactory) {
|
||||||
|
if (!(keyFactory instanceof P2pkhFactory ||
|
||||||
|
keyFactory instanceof P2pkFactory
|
||||||
|
)) {
|
||||||
|
throw new Error('Unsupported script factory for P2SH')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var P2pkFactory = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {bitcoin.ECPair} key
|
||||||
|
*/
|
||||||
|
P2pkFactory.prototype.convert = function (key) {
|
||||||
|
return {
|
||||||
|
scriptPubKey: btemplates.pubKey.output.encode(key.getPublicKeyBuffer()),
|
||||||
|
signData: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var P2pkhFactory = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {bitcoin.ECPair} key
|
||||||
|
*/
|
||||||
|
P2pkhFactory.prototype.convert = function (key) {
|
||||||
|
var hash160 = bcrypto.hash160(key.getPublicKeyBuffer())
|
||||||
|
return {
|
||||||
|
scriptPubKey: btemplates.pubKeyHash.output.encode(hash160),
|
||||||
|
signData: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var P2wpkhFactory = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {bitcoin.ECPair} key
|
||||||
|
*/
|
||||||
|
P2wpkhFactory.prototype.convert = function (key) {
|
||||||
|
var hash160 = bcrypto.hash160(key.getPublicKeyBuffer())
|
||||||
|
return {
|
||||||
|
scriptPubKey: btemplates.witnessPubKeyHash.output.encode(hash160),
|
||||||
|
signData: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var P2shFactory = function (keyFactory) {
|
||||||
|
checkAllowedP2sh(keyFactory)
|
||||||
|
this.factory = keyFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
P2shFactory.prototype.convert = function (key) {
|
||||||
|
var detail = this.factory.convert(key)
|
||||||
|
var hash160 = bcrypto.hash160(detail.scriptPubKey)
|
||||||
|
return {
|
||||||
|
scriptPubKey: btemplates.scriptHash.output.encode(hash160),
|
||||||
|
signData: {
|
||||||
|
redeemScript: detail.scriptPubKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var P2wshFactory = function (keyFactory) {
|
||||||
|
checkAllowedP2wsh(keyFactory)
|
||||||
|
this.factory = keyFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
P2wshFactory.prototype.convert = function (key) {
|
||||||
|
var detail = this.factory.convert(key)
|
||||||
|
var hash160 = bcrypto.hash160(detail.scriptPubKey)
|
||||||
|
return {
|
||||||
|
scriptPubKey: btemplates.scriptHash.output.encode(hash160),
|
||||||
|
signData: {
|
||||||
|
redeemScript: detail.scriptPubKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var P2shP2wshFactory = function (keyFactory) {
|
||||||
|
checkAllowedP2wsh(keyFactory)
|
||||||
|
this.factory = keyFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
P2shP2wshFactory.prototype.convert = function (key) {
|
||||||
|
var detail = this.factory.convert(key)
|
||||||
|
var sha256 = bcrypto.sha256(detail.scriptPubKey)
|
||||||
|
var wp = btemplates.witnessScriptHash.output.encode(sha256)
|
||||||
|
var hash160 = bcrypto.hash160(wp)
|
||||||
|
var spk = btemplates.scriptHash.output.encode(hash160)
|
||||||
|
return {
|
||||||
|
scriptPubKey: spk,
|
||||||
|
signData: {
|
||||||
|
redeemScript: wp,
|
||||||
|
witnessScript: detail.scriptPubKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
P2pkhFactory: P2pkhFactory,
|
||||||
|
P2wpkhFactory: P2wpkhFactory,
|
||||||
|
P2pkFactory: P2pkFactory,
|
||||||
|
P2shFactory: P2shFactory,
|
||||||
|
P2wshFactory: P2wshFactory,
|
||||||
|
P2shP2wshFactory: P2shP2wshFactory
|
||||||
|
}
|
|
@ -1,13 +1,28 @@
|
||||||
|
var KeyToScript = require('./keytoscript')
|
||||||
// https://en.bitcoin.it/wiki/List_of_address_prefixes
|
// https://en.bitcoin.it/wiki/List_of_address_prefixes
|
||||||
// Dogecoin BIP32 is a proposed standard: https://bitcointalk.org/index.php?topic=409731
|
// Dogecoin BIP32 is a proposed standard: https://bitcointalk.org/index.php?topic=409731
|
||||||
|
|
||||||
|
var p2pkh = new KeyToScript.P2pkhFactory()
|
||||||
|
var p2wpkh = new KeyToScript.P2wpkhFactory()
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
bitcoin: {
|
bitcoin: {
|
||||||
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
||||||
bech32: 'bc',
|
bech32: 'bc',
|
||||||
bip32: {
|
bip32: {
|
||||||
public: 0x0488b21e,
|
public: 0x0488b21e,
|
||||||
private: 0x0488ade4
|
private: 0x0488ade4,
|
||||||
|
scriptFactory: p2pkh
|
||||||
|
},
|
||||||
|
bip49: {
|
||||||
|
private: 0x049d7878,
|
||||||
|
public: 0x049d7cb2,
|
||||||
|
scriptFactory: new KeyToScript.P2shFactory(p2wpkh)
|
||||||
|
},
|
||||||
|
bip84: {
|
||||||
|
private: 0x04b2430c,
|
||||||
|
public: 0x04b24746,
|
||||||
|
scriptFactory: p2wpkh
|
||||||
},
|
},
|
||||||
pubKeyHash: 0x00,
|
pubKeyHash: 0x00,
|
||||||
scriptHash: 0x05,
|
scriptHash: 0x05,
|
||||||
|
@ -18,7 +33,8 @@ module.exports = {
|
||||||
bech32: 'tb',
|
bech32: 'tb',
|
||||||
bip32: {
|
bip32: {
|
||||||
public: 0x043587cf,
|
public: 0x043587cf,
|
||||||
private: 0x04358394
|
private: 0x04358394,
|
||||||
|
scriptFactory: p2pkh
|
||||||
},
|
},
|
||||||
pubKeyHash: 0x6f,
|
pubKeyHash: 0x6f,
|
||||||
scriptHash: 0xc4,
|
scriptHash: 0xc4,
|
||||||
|
@ -28,7 +44,8 @@ module.exports = {
|
||||||
messagePrefix: '\x19Litecoin Signed Message:\n',
|
messagePrefix: '\x19Litecoin Signed Message:\n',
|
||||||
bip32: {
|
bip32: {
|
||||||
public: 0x019da462,
|
public: 0x019da462,
|
||||||
private: 0x019d9cfe
|
private: 0x019d9cfe,
|
||||||
|
scriptFactory: p2pkh
|
||||||
},
|
},
|
||||||
pubKeyHash: 0x30,
|
pubKeyHash: 0x30,
|
||||||
scriptHash: 0x32,
|
scriptHash: 0x32,
|
||||||
|
|
95
test/hdaddress.js
Normal file
95
test/hdaddress.js
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
/* global describe, it */
|
||||||
|
/* eslint-disable no-new */
|
||||||
|
|
||||||
|
var assert = require('assert')
|
||||||
|
var HDNode = require('../src/hdnode')
|
||||||
|
var bnetwork = require('../src/networks')
|
||||||
|
|
||||||
|
describe('bip44', function () {
|
||||||
|
it('works without a ScriptFactory', function () {
|
||||||
|
// mnemonic: abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
|
||||||
|
var seed = '5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4'
|
||||||
|
var network = bnetwork.bitcoin
|
||||||
|
|
||||||
|
var root = HDNode.fromSeedHex(seed, network)
|
||||||
|
assert.equal(
|
||||||
|
root.toBase58(),
|
||||||
|
'xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu'
|
||||||
|
)
|
||||||
|
|
||||||
|
var account = root.derivePath('44\'/0\'/0\'')
|
||||||
|
assert.equal(
|
||||||
|
account.toBase58(),
|
||||||
|
'xprv9xpXFhFpqdQK3TmytPBqXtGSwS3DLjojFhTGht8gwAAii8py5X6pxeBnQ6ehJiyJ6nDjWGJfZ95WxByFXVkDxHXrqu53WCRGypk2ttuqncb'
|
||||||
|
)
|
||||||
|
assert.equal(
|
||||||
|
'xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj',
|
||||||
|
account.neutered().toBase58()
|
||||||
|
)
|
||||||
|
|
||||||
|
var key = account.derivePath('0/0')
|
||||||
|
assert.equal('1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA', key.getAddress())
|
||||||
|
})
|
||||||
|
|
||||||
|
it('works with a prefix', function () {
|
||||||
|
// mnemonic: abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
|
||||||
|
var seed = '5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4'
|
||||||
|
var network = bnetwork.bitcoin
|
||||||
|
|
||||||
|
var root = HDNode.fromSeedHex(seed, network, network.bip32)
|
||||||
|
var account = root.derivePath('44\'/0\'/0\'')
|
||||||
|
assert.equal(
|
||||||
|
account.toBase58(),
|
||||||
|
'xprv9xpXFhFpqdQK3TmytPBqXtGSwS3DLjojFhTGht8gwAAii8py5X6pxeBnQ6ehJiyJ6nDjWGJfZ95WxByFXVkDxHXrqu53WCRGypk2ttuqncb'
|
||||||
|
)
|
||||||
|
assert.equal(
|
||||||
|
'xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj',
|
||||||
|
account.neutered().toBase58()
|
||||||
|
)
|
||||||
|
|
||||||
|
var key = account.derivePath('0/0')
|
||||||
|
assert.equal('1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA', key.getAddress())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('bip49', function () {
|
||||||
|
it('serialization and address', function () {
|
||||||
|
// mnemonic: abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
|
||||||
|
var seed = '5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4'
|
||||||
|
var network = bnetwork.bitcoin
|
||||||
|
var root = HDNode.fromSeedHex(seed, network, network.bip49)
|
||||||
|
var account = root.derivePath('49\'/0\'/0\'')
|
||||||
|
assert.equal(
|
||||||
|
account.toBase58(),
|
||||||
|
'yprvAHwhK6RbpuS3dgCYHM5jc2ZvEKd7Bi61u9FVhYMpgMSuZS613T1xxQeKTffhrHY79hZ5PsskBjcc6C2V7DrnsMsNaGDaWev3GLRQRgV7hxF'
|
||||||
|
)
|
||||||
|
assert.equal(
|
||||||
|
'ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP',
|
||||||
|
account.neutered().toBase58()
|
||||||
|
)
|
||||||
|
|
||||||
|
var key = account.derivePath('0/0')
|
||||||
|
assert.equal('37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf', key.getAddress())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('bip84', function () {
|
||||||
|
it('serialization and address', function () {
|
||||||
|
// mnemonic: abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
|
||||||
|
var seed = '5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4'
|
||||||
|
var network = bnetwork.bitcoin
|
||||||
|
var root = HDNode.fromSeedHex(seed, network, network.bip84)
|
||||||
|
var account = root.derivePath('84\'/0\'/0\'')
|
||||||
|
assert.equal(
|
||||||
|
account.toBase58(),
|
||||||
|
'zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE'
|
||||||
|
)
|
||||||
|
assert.equal(
|
||||||
|
'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs',
|
||||||
|
account.neutered().toBase58()
|
||||||
|
)
|
||||||
|
|
||||||
|
var key = account.derivePath('0/0')
|
||||||
|
assert.equal('bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu', key.getAddress())
|
||||||
|
})
|
||||||
|
})
|
|
@ -50,7 +50,6 @@ describe('HDNode', function () {
|
||||||
|
|
||||||
it('has a default depth/index of 0', function () {
|
it('has a default depth/index of 0', function () {
|
||||||
var hd = new HDNode(keyPair, chainCode)
|
var hd = new HDNode(keyPair, chainCode)
|
||||||
|
|
||||||
assert.strictEqual(hd.depth, 0)
|
assert.strictEqual(hd.depth, 0)
|
||||||
assert.strictEqual(hd.index, 0)
|
assert.strictEqual(hd.index, 0)
|
||||||
})
|
})
|
||||||
|
@ -124,12 +123,12 @@ describe('HDNode', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('getAddress', function () {
|
describe('getAddress', function () {
|
||||||
it('wraps keyPair.getAddress', setupTest(function () {
|
// it('wraps keyPair.getAddress', setupTest(function () {
|
||||||
this.mock(keyPair).expects('getAddress')
|
// this.mock(keyPair).expects('getAddress')
|
||||||
.once().withArgs().returns('foobar')
|
// .once().withArgs().returns('foobar')
|
||||||
|
//
|
||||||
assert.strictEqual(hd.getAddress(), 'foobar')
|
// assert.strictEqual(hd.getAddress(), 'foobar')
|
||||||
}))
|
// }))
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('getNetwork', function () {
|
describe('getNetwork', function () {
|
||||||
|
|
Loading…
Reference in a new issue