Created
May 17, 2020 10:38
-
-
Save lukechilds/3c374d6c5d85229a6c0d30f1b26630e6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const bitcoin = require('bitcoinjs-lib') | |
const regcli = require('regtest-client') | |
const bs58 = require('bs58check') | |
const APIURL = process.env['APIURL'] || 'http://127.0.0.1:8080/1'; | |
const APIPASS = process.env['APIPASS'] || 'satoshi'; | |
const regtestUtils = new regcli.RegtestUtils({ APIURL, APIPASS }) | |
const network = bitcoin.networks.regtest | |
const rootNode = bitcoin.bip32.fromBase58('tprv8ZgxMBicQKsPfBD2PErVQNAqcjwLBg8fWZSX8qwx1cRyFsDrgvRDLqaT5Rf2N4VEXZDAkpWeJ9vXXREbAUY67RtoZorrfxqgDMxsb6FiBFH', network) | |
async function main() { | |
const amount = 69420 | |
const alice = createPayment('p2wpkh', [rootNode]); | |
const inputData = await getInputData( | |
amount, | |
alice.payment, | |
true, | |
'noredeem', | |
); | |
const psbt = new bitcoin.Psbt({ network }) | |
.addInput(inputData) | |
.addOutput({ | |
address: alice.payment.address, | |
value: amount - 1000, | |
}) | |
.signInput(0, rootNode) | |
// delete psbt.data.inputs[0].witnessUtxo | |
console.log(psbt.toBase64()) | |
psbt.finalizeAllInputs() | |
console.log(psbt.toBase64()) | |
} | |
main().then(() => { | |
process.exit(0) | |
}) | |
.catch(err => { | |
console.error(err); | |
process.exit(1) | |
}) | |
// psbt.updateInput(0, { | |
// bip32Derivation: [ | |
// { | |
// path: "m/0", | |
// masterFingerprint: rootNode.fingerprint, | |
// pubkey: rootNode.publicKey, | |
// } | |
// ] | |
// }) | |
// psbt.updateGlobal({ | |
// globalXpub: [ | |
// { | |
// extendedPubkey: bs58.decode(rootNode.derivePath("m/44'/0'/0'").neutered().toBase58()), | |
// masterFingerprint: rootNode.fingerprint, | |
// path: "m/44'/0'/0'", | |
// } | |
// ] | |
// }) | |
function createPayment(_type, myKeys) { | |
const splitType = _type.split('-').reverse(); | |
const isMultisig = splitType[0].slice(0, 4) === 'p2ms'; | |
const keys = myKeys || []; | |
let m; | |
if (isMultisig) { | |
const match = splitType[0].match(/^p2ms\((\d+) of (\d+)\)$/); | |
m = parseInt(match[1], 10); | |
let n = parseInt(match[2], 10); | |
if (keys.length > 0 && keys.length !== n) { | |
throw new Error('Need n keys for multisig'); | |
} | |
while (!myKeys && n > 1) { | |
keys.push(bitcoin.ECPair.makeRandom({ network })); | |
n--; | |
} | |
} | |
if (!myKeys) keys.push(bitcoin.ECPair.makeRandom({ network })); | |
let payment; | |
splitType.forEach(type => { | |
if (type.slice(0, 4) === 'p2ms') { | |
payment = bitcoin.payments.p2ms({ | |
m, | |
pubkeys: keys.map(key => key.publicKey).sort(), | |
network, | |
}); | |
} else if (['p2sh', 'p2wsh'].indexOf(type) > -1) { | |
payment = bitcoin.payments[type]({ | |
redeem: payment, | |
network, | |
}); | |
} else { | |
payment = bitcoin.payments[type]({ | |
pubkey: keys[0].publicKey, | |
network, | |
}); | |
} | |
}); | |
return { | |
payment, | |
keys, | |
}; | |
} | |
function getWitnessUtxo(out) { | |
delete out.address; | |
out.script = Buffer.from(out.script, 'hex'); | |
return out; | |
} | |
async function getInputData( | |
amount, | |
payment, | |
isSegwit, | |
redeemType, | |
) { | |
const unspent = await regtestUtils.faucetComplex(payment.output, amount); | |
const utx = await regtestUtils.fetch(unspent.txId); | |
// for non segwit inputs, you must pass the full transaction buffer | |
const nonWitnessUtxo = Buffer.from(utx.txHex, 'hex'); | |
// for segwit inputs, you only need the output script and value as an object. | |
const witnessUtxo = getWitnessUtxo(utx.outs[unspent.vout]); | |
const mixin = isSegwit ? { witnessUtxo } : { nonWitnessUtxo }; | |
const mixin2 = {}; | |
switch (redeemType) { | |
case 'p2sh': | |
mixin2.redeemScript = payment.redeem.output; | |
break; | |
case 'p2wsh': | |
mixin2.witnessScript = payment.redeem.output; | |
break; | |
case 'p2sh-p2wsh': | |
mixin2.witnessScript = payment.redeem.redeem.output; | |
mixin2.redeemScript = payment.redeem.output; | |
break; | |
} | |
return { | |
hash: unspent.txId, | |
index: unspent.vout, | |
...mixin, | |
...mixin2, | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment