Typical Transaction (1 input, 2 outputs) - Legacy P2PKH
To follow along this tutorial
|
Let’s create a legacy P2PKH transaction with 1 input and 2 outputs. This is a more realistic example that illustrates the notion of change. The second output is actually our change.
Spending a UTXO is like spending a bank note or a coin, you can’t split it. You spend it and you get back the change. |
Create UTXO to spend from
First we need to create a previous transaction in order to have a UTXO at our disposal.
const bitcoin = require('bitcoinjs-lib')
const { alice, bob } = require('./wallets.json')
const network = bitcoin.networks.regtest
sendtoaddress n4SvybJicv79X1Uc4o3fYXWGwXadA53FSq 1
We have now an UTXO locked with alice_1 public key hash. In order to spend it, we refer to it with the transaction id (txid) and the output index (vout), also called outpoint. Fortunately, sendtoaddress
returns the id of the transaction.
gettransaction TX_ID
Find the output index (or vout) under | .
Creating the typical transaction
Now let’s spend the UTXO with BitcoinJS.
const keyPairAlice1 = bitcoin.ECPair.fromWIF(alice[1].wif, network)
const keyPairAlice2 = bitcoin.ECPair.fromWIF(alice[2].wif, network)
const p2pkhAlice2 = bitcoin.payments.p2pkh({pubkey: keyPairAlice2.publicKey, network})
const keyPairBob1 = bitcoin.ECPair.fromWIF(bob[1].wif, network)
const p2pkhBob1 = bitcoin.payments.p2pkh({pubkey: keyPairBob1.publicKey, network})
Create a BitcoinJS transaction builder object. Add the input by providing the outpoint. Add the output #1 with the bob_1 P2PKH recipient address and the amount of 0.5 BTC. Add the output #2 with alice’s change address (here alice_2) and the amount of 0.499 BTC.
const txb = new bitcoin.TransactionBuilder(network)
txb.addInput('TX_ID', TX_VOUT)
txb.addOutput(p2pkhBob1.address, 5e7) (1)
txb.addOutput(p2pkhAlice2.address, 499e5) (2)
1 | the actual "spend" |
2 | Alice’s change |
The miner fee is calculated by subtracting the outputs from the inputs. |
The UTXO is locked with alice_1’s public key hash. If she wants to spend it, she needs to prove her ownership of the private key that is linked to the public key, which hash is written in the UTXO.
To do so, alice_1 will sign this transaction that we just built with her private key. BitcoinJS will automatically place the signature into the scriptSig
field of the input 0.
txb.sign(0, keyPairAlice1)
const tx = txb.build()
console.log('Transaction hexadecimal:')
console.log(tx.toHex())
decoderawtransaction TX_HEX
Broadcasting the transaction
sendrawtransaction TX_HEX
sendrawtransaction
returns the transaction ID, with which you can inspect your transaction again.
getrawtransaction TX_ID true
Don’t forget the second argument. If false, it returns the hex string, otherwise it returns a detailed json object. |