Skip to content

Instantly share code, notes, and snippets.

@kobigurk
Created December 4, 2016 20:54
Show Gist options
  • Save kobigurk/40a7c90baee23699b493250518661cf2 to your computer and use it in GitHub Desktop.
Save kobigurk/40a7c90baee23699b493250518661cf2 to your computer and use it in GitHub Desktop.
var bip39 = require('bip39');
var bitcoin = require('bitcoinjs-lib');
var Wallet = {};
// FILL IN: REDEEM_SCRIPT, MNEMONIC1, PASSPHRASE, MNEMONIC2, TARGET_ADDRESS, TXID, VALUE
// build like here: https://github.com/blocktrail/blocktrail-sdk-nodejs/blob/ff4bde6983385f5adff3a89e10959ddc323e4160/lib/wallet_sweeper.js#L228
var redeemScript = new Buffer('REDEEM_SCRIPT', 'hex');
var primaryPrivateKeyMaster = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed('MNEMONIC1', 'PASSPHRASE'));
var backupPrivateKeyMaster = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed('MNEMONIC2'));
// change path: https://github.com/blocktrail/blocktrail-sdk-nodejs/blob/ff4bde6983385f5adff3a89e10959ddc323e4160/lib/wallet_sweeper.js#L252
var primaryPrivateKey = deriveByPath(primaryPrivateKeyMaster, 'M/0\'/0/0'.replace("M", "m"), "m");
var backupPrivateKey = deriveByPath(backupPrivateKeyMaster, 'M/0\'/0/0'.replace("M", "m").replace("'", ""), "m");
var keyPairs = [primaryPrivateKey.keyPair, backupPrivateKey.keyPair];
var pubKeys = keyPairs.map(function (x) { return x.getPublicKeyBuffer() });
console.log(pubKeys);
var txb = new bitcoin.TransactionBuilder();
var targetAddress = 'TARGET_ADDRESS';
var unspent = {
txId: 'TXID',
vout: 0,
value: VALUE
};
txb.addInput(unspent.txId, unspent.vout);
txb.addOutput(targetAddress, unspent.value-10000);
txb.sign(0, backupPrivateKey.keyPair, redeemScript);
txb.sign(0, primaryPrivateKey.keyPair, redeemScript);
var tx = txb.build();
console.log(tx.toHex());
function deriveByPath (hdKey, path, keyPath) {
keyPath = keyPath || (!!hdKey.privKey ? "m" : "M");
if (path[0].toLowerCase() !== "m" || keyPath[0].toLowerCase() !== "m") {
throw new blocktrail.KeyPathError("Wallet.deriveByPath only works with absolute paths. (" + path + ", " + keyPath + ")");
}
if (path[0] === "m" && keyPath[0] === "M") {
throw new blocktrail.KeyPathError("Wallet.deriveByPath can't derive private path from public parent. (" + path + ", " + keyPath + ")");
}
// if the desired path is public while the input is private
var toPublic = path[0] === "M" && keyPath[0] === "m";
if (toPublic) {
// derive the private path, convert to public when returning
path[0] = "m";
}
// keyPath should be the parent parent of path
if (path.toLowerCase().indexOf(keyPath.toLowerCase()) !== 0) {
throw new blocktrail.KeyPathError("Wallet.derivePath requires path (" + path + ") to be a child of keyPath (" + keyPath + ")");
}
// remove the part of the path we already have
path = path.substr(keyPath.length);
// iterate over the chunks and derive
var newKey = hdKey;
path.replace(/^\//, "").split("/").forEach(function(chunk) {
if (!chunk) {
return;
}
if (chunk.indexOf("'") !== -1) {
chunk = parseInt(chunk.replace("'", ""), 10) + bitcoin.HDNode.HIGHEST_BIT;
}
newKey = newKey.derive(chunk);
});
if (toPublic) {
return newKey.neutered();
} else {
return newKey;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment