Browse Source

Refactor: Cleaner way how HD wallet addresses are created

map
Pavel Ševčík 6 years ago
parent
commit
708a8541f6
  1. 52
      class/hd-legacy-p2pkh-wallet.js
  2. 117
      class/hd-segwit-p2sh-wallet.js

52
class/hd-legacy-p2pkh-wallet.js

@ -1,4 +1,3 @@
import { LegacyWallet } from './';
import { AbstractHDWallet } from './abstract-hd-wallet';
const bitcoin = require('bitcoinjs-lib');
const bip39 = require('bip39');
@ -53,51 +52,30 @@ export class HDLegacyP2PKHWallet extends AbstractHDWallet {
return child.keyPair.toWIF();
}
_getExternalAddressByIndex(index) {
_getExternalAddressByIndex (index) {
index = index * 1; // cast to int
if (this.external_addresses_cache[index]) return this.external_addresses_cache[index]; // cache hit
if (!this._xpub) {
let mnemonic = this.secret;
let seed = bip39.mnemonicToSeed(mnemonic);
let root = bitcoin.HDNode.fromSeedBuffer(seed);
let path = "m/44'/0'/0'/0/" + index;
let child = root.derivePath(path);
let w = new LegacyWallet();
w.setSecret(child.keyPair.toWIF());
return (this.external_addresses_cache[index] = w.getAddress());
} else {
let node = bitcoin.HDNode.fromBase58(this._xpub);
let address = node
.derive(0)
.derive(index)
.getAddress();
return (this.external_addresses_cache[index] = address);
}
const node = bitcoin.HDNode.fromBase58(this.getXpub());
const address = node
.derive(0)
.derive(index)
.getAddress();
return (this.external_addresses_cache[index] = address);
}
_getInternalAddressByIndex(index) {
_getInternalAddressByIndex (index) {
index = index * 1; // cast to int
if (this.internal_addresses_cache[index]) return this.internal_addresses_cache[index]; // cache hit
if (!this._xpub) {
let mnemonic = this.secret;
let seed = bip39.mnemonicToSeed(mnemonic);
let root = bitcoin.HDNode.fromSeedBuffer(seed);
let path = "m/44'/0'/0'/1/" + index;
let child = root.derivePath(path);
const node = bitcoin.HDNode.fromBase58(this.getXpub());
const address = node
.derive(1)
.derive(index)
.getAddress();
let w = new LegacyWallet();
w.setSecret(child.keyPair.toWIF());
return (this.internal_addresses_cache[index] = w.getAddress());
} else {
let node = bitcoin.HDNode.fromBase58(this._xpub);
let address = node
.derive(1)
.derive(index)
.getAddress();
return (this.internal_addresses_cache[index] = address);
}
return (this.internal_addresses_cache[index] = address);
}
createTx(utxos, amount, fee, address) {

117
class/hd-segwit-p2sh-wallet.js

@ -8,6 +8,32 @@ const BigNumber = require('bignumber.js');
const b58 = require('bs58check');
const signer = require('../models/signer');
/**
* Converts ypub to xpub
* @param {String} ypub - wallet ypub
* @returns {*}
*/
function ypubToXpub (ypub) {
let data = b58.decode(ypub);
data = data.slice(4);
data = Buffer.concat([Buffer.from("0488b21e", "hex"), data]);
return b58.encode(data);
}
/**
* Creates Segwit P2SH Bitcoin address
* @param hdNode
* @returns {String}
*/
function nodeToP2shSegwitAddress (hdNode) {
const pubkeyBuf = hdNode.keyPair.getPublicKeyBuffer();
const hash = bitcoin.crypto.hash160(pubkeyBuf);
const redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(hash);
const hash2 = bitcoin.crypto.hash160(redeemScript);
const scriptPubkey = bitcoin.script.scriptHash.output.encode(hash2);
return bitcoin.address.fromOutputScript(scriptPubkey);
}
/**
* HD Wallet (BIP39).
* In particular, BIP49 (P2SH Segwit)
@ -64,89 +90,26 @@ export class HDSegwitP2SHWallet extends AbstractHDWallet {
return child.keyPair.toWIF();
}
_getExternalAddressByIndex(index) {
_getExternalAddressByIndex (index) {
index = index * 1; // cast to int
if (this.external_addresses_cache[index]) return this.external_addresses_cache[index]; // cache hit
if (!this._xpub) {
let mnemonic = this.secret;
let seed = bip39.mnemonicToSeed(mnemonic);
let root = bitcoin.HDNode.fromSeedBuffer(seed);
let path = "m/49'/0'/0'/0/" + index;
let child = root.derivePath(path);
let keyhash = bitcoin.crypto.hash160(child.getPublicKeyBuffer());
let scriptSig = bitcoin.script.witnessPubKeyHash.output.encode(keyhash);
let addressBytes = bitcoin.crypto.hash160(scriptSig);
let outputScript = bitcoin.script.scriptHash.output.encode(addressBytes);
let address = bitcoin.address.fromOutputScript(outputScript, bitcoin.networks.bitcoin);
this._address_to_wif_cache[address] = child.keyPair.toWIF();
return (this.external_addresses_cache[index] = address);
} else {
let b58 = require('bs58check');
// eslint-disable-next-line
function ypubToXpub(ypub) {
var data = b58.decode(ypub);
data = data.slice(4);
data = Buffer.concat([Buffer.from('0488b21e', 'hex'), data]);
return b58.encode(data);
}
// eslint-disable-next-line
function nodeToP2shSegwitAddress(hdNode) {
let pubkeyBuf = hdNode.keyPair.getPublicKeyBuffer();
let hash = bitcoin.crypto.hash160(pubkeyBuf);
let redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(hash);
let hash2 = bitcoin.crypto.hash160(redeemScript);
let scriptPubkey = bitcoin.script.scriptHash.output.encode(hash2);
return bitcoin.address.fromOutputScript(scriptPubkey);
}
let xpub = ypubToXpub(this._xpub);
let hdNode = bitcoin.HDNode.fromBase58(xpub);
let address = nodeToP2shSegwitAddress(hdNode.derive(0).derive(index));
return (this.external_addresses_cache[index] = address);
}
let xpub = ypubToXpub(this.getXpub());
let hdNode = bitcoin.HDNode.fromBase58(xpub);
let address = nodeToP2shSegwitAddress(hdNode.derive(0).derive(index));
return (this.external_addresses_cache[index] = address);
}
_getInternalAddressByIndex(index) {
_getInternalAddressByIndex (index) {
index = index * 1; // cast to int
if (this.internal_addresses_cache[index]) return this.internal_addresses_cache[index]; // cache hit
if (!this._xpub) {
let mnemonic = this.secret;
let seed = bip39.mnemonicToSeed(mnemonic);
let root = bitcoin.HDNode.fromSeedBuffer(seed);
let path = "m/49'/0'/0'/1/" + index;
let child = root.derivePath(path);
let keyhash = bitcoin.crypto.hash160(child.getPublicKeyBuffer());
let scriptSig = bitcoin.script.witnessPubKeyHash.output.encode(keyhash);
let addressBytes = bitcoin.crypto.hash160(scriptSig);
let outputScript = bitcoin.script.scriptHash.output.encode(addressBytes);
let address = bitcoin.address.fromOutputScript(outputScript, bitcoin.networks.bitcoin);
this._address_to_wif_cache[address] = child.keyPair.toWIF();
return (this.internal_addresses_cache[index] = address);
} else {
let b58 = require('bs58check');
// eslint-disable-next-line
function ypubToXpub(ypub) {
var data = b58.decode(ypub);
data = data.slice(4);
data = Buffer.concat([Buffer.from('0488b21e', 'hex'), data]);
return b58.encode(data);
}
// eslint-disable-next-line
function nodeToP2shSegwitAddress(hdNode) {
let pubkeyBuf = hdNode.keyPair.getPublicKeyBuffer();
let hash = bitcoin.crypto.hash160(pubkeyBuf);
let redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(hash);
let hash2 = bitcoin.crypto.hash160(redeemScript);
let scriptPubkey = bitcoin.script.scriptHash.output.encode(hash2);
return bitcoin.address.fromOutputScript(scriptPubkey);
}
let xpub = ypubToXpub(this._xpub);
let hdNode = bitcoin.HDNode.fromBase58(xpub);
let address = nodeToP2shSegwitAddress(hdNode.derive(1).derive(index));
return (this.internal_addresses_cache[index] = address);
}
let xpub = ypubToXpub(this.getXpub());
let hdNode = bitcoin.HDNode.fromBase58(xpub);
let address = nodeToP2shSegwitAddress(hdNode.derive(1).derive(index));
return (this.internal_addresses_cache[index] = address);
}
/**

Loading…
Cancel
Save