Comment on page

Creating PSBTs

PSBTs or partially signed Bitcoin transactions is a standard that allows unsigned or partially signed transactions to be transported for signing by multiple parties.
Here we will show examples of creating partially signed Bitcoin transactions using the light-weight and audited Bitcoin javascript library scure-btc-signer.

Creating a transaction with a wrapped-segwit (P2SH-P2WPHK) address

import * as btc from 'micro-btc-signer'
import { hex, base64 } from '@scure/base'
const bitcoinTestnet = {
bech32: 'tb',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
wif: 0xef,
}
// You can use any public Bitcoin API to retrieve unspent outputs
const output = {
"tx_hash": "f39d37ec885de70c598648a2f80f103e1cdf34f7021ddfcb22216b7076169226",
"block_height": 780179,
"tx_input_n": -1,
"tx_output_n": 1,
"value": 300000,
"ref_balance": 22681,
"spent": false,
"confirmations": 123,
"confirmed": "2023-03-10T10:02:21Z",
"double_spend": false
}
const publicKey = hex.encode("02818b7ff740a40f311d002123087053d5d9e0e1546674aedb10e15a5b57fd3985")
const p2wpkh = btc.p2wpkh(publicKey, bitcoinTestnet);
const p2sh = btc.p2sh(p2wpkh, bitcoinTestnet);
tx.addInput({
txid: output.tx_hash,
index: output.tx_output_n,
witnessUtxo: {
script: p2sh.script,
amount: BigInt(output.value),
},
redeemScript: p2sh.redeemScript,
})
// You can add more inputs here as necessary
// Add outputs
const recipient = "tb1pzwa68q3udj0f7g5xtdakgecvf45dvssu66ry7y3at22w7vus20vq3sgw62"
const changeAddress = "2NBfRKCUpafbatj5gV9T82uau3igdSf9BXJ"
tx.addOutputAddress(recipient, BigInt(200000), bitcoinTestnet)
tx.addOutputAddress(changeAddress, BigInt(80000), bitcoinTestnet)
// Generate the base64 encoded PSBT that can be
// passed to a compatible wallet for signing
const psbt = tx.toPSBT(0)
const psbtB64 = base64.encode(psbt0)

Creating a transaction with a Taproot (P2TR) address

const internalPubKey =
hex.decode("b9907521ddb85e0e6a37622b7c685efbdc8ae53a334928adbd12cf204ad4e717")
const p2tr = btc.p2tr(internalPubKey, undefined, bitcoinTestnet)
tx.addInput({
txid: output.tx_hash,
index: output.tx_output_n,
witnessUtxo: {
script: p2tr.script,
amount: BigInt(output.value),
},
tapInternalKey: internalPubKey,
sighashType: btc.SignatureHash.SINGLE|btc.SignatureHash.ANYONECANPAY
})
// You can add more inputs here as necessary
// Add outputs
const recipient = "tb1pzwa68q3udj0f7g5xtdakgecvf45dvssu66ry7y3at22w7vus20vq3sgw62"
const changeAddress = "2NBfRKCUpafbatj5gV9T82uau3igdSf9BXJ"
tx.addOutputAddress(recipient, BigInt(200000), bitcoinTestnet)
tx.addOutputAddress(changeAddress, BigInt(80000), bitcoinTestnet)
// Generate the base64 encoded PSBT that can be
// passed to a compatible wallet for signing
const psbt = tx.toPSBT(0)
const psbtB64 = base64.encode(psbt0)
Last modified 3mo ago