Simple Transaction (1 input, 1 output) - Legacy P2PKH

To follow along this tutorial

  • Clone the Github repository

  • cd code

  • npm install or yarn install

  • Execute the transaction code by typing node tx_filename.js

  • Alternatively you can enter the commands step-by-step by cd into ./code then type node in a terminal to open the Node.js REPL

  • Open the Bitcoin Core GUI console or use bitcoin-cli for the Bitcoin Core commands

  • Use bx aka Libbitcoin-explorer as a handy complement

Let’s create a legacy P2PKH transaction with 1 input and 1 output.

Create UTXO to spend from

First we need to create a previous transaction in order to have a UTXO at our disposal.

Import libraries, test wallets and set the network.
const bitcoin = require('bitcoinjs-lib')
const { alice, bob } = require('./wallets.json')
const network = bitcoin.networks.regtest
Send 1 BTC to alice_1 P2PKH address with Bitcoin Core CLI.
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.

Get the output index so that we have the outpoint (txid / vout).
gettransaction TX_ID
Find the output index (or vout) under details  vout

Creating the simple transaction

Now let’s spend the UTXO with BitcoinJS.

Create a bitcoinJS key pair object for alice_1, the spender of our new UTXO, and the only one capable of spending it.
const keyPairAlice1 = bitcoin.ECPair.fromWIF(alice[1].wif, network)
Create a key pair object and a P2PKH address for the recipient bob_1.
const keyPairBob1 = bitcoin.ECPair.fromWIF(bob[1].wif, network)
const p2pkhBob1 = bitcoin.payments.p2pkh({pubkey: keyPairBob1.publicKey, network})
Create a BitcoinJS transaction builder object.
const txb = new bitcoin.TransactionBuilder(network)
Add the input by filling it with the outpoint (previous values txId and vout).
txb.addInput('TX_ID', TX_VOUT)
Add the output with the bob_1 P2PKH recipient address and the amount of 0.999 btc.
txb.addOutput(p2pkhBob1.address, 999e5)

The miner fee is calculated by subtracting the outputs from the inputs.
100 000 000 - 99 900 000 = 100 000 100 000 satoshis equals 0,001 BTC, this is the miner fee.

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)
Finally we can build the transaction and get the raw hex serialization.
const tx = txb.build()
console.log('Transaction hexadecimal:')
console.log(tx.toHex())
Inspect the raw transaction with Bitcoin Core CLI, check that everything is correct.
decoderawtransaction TX_HEX

Broadcasting the transaction

It’s time to broadcast the transaction via Bitcoin Core CLI.
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.