Command Line introduction to Bitcoin Wallet Development using bdk-cli

By waterst0ne on 9/23/2022 - Tags: Bdk-cli, Basics, Novice


# Tutorial Goals

  • The goal for this tutorial is to introduce you to bdk-cli (opens new window), a powerful command-line program. You will be exposed to many of the basic skills that go into creating and managing bitcoin wallets.

  • If you've read most of the "Mastering Bitcoin" (opens new window) book, this tutorial could serve as a stepping stone into your Bitcoin wallet development journey.

  • This short tutorial will expose you to the bdk library (opens new window) and the practical knowledge needed for bitcoin wallet development. As a consequence you will deepen your technical understanding about bitcoin and the bdk library.

  • BDK also has language-bindings (opens new window) for Kotlin/Java, Swift, Python which enable the use of BDK's Rust library as an API. You can later use these similar steps to create your own bitcoin mobile, desktop or even WebApp by using the bdk-ffi language bindings.


# A few things before you begin:

  • Three things to look out for in each step of the tutorial:
      1. ▶️ / 🔶 - Commands for the Terminal or Shell
      1. 👍 - Preview of the command output. Note, not all commands will output code.
      1. Preview Video of the tutorial for reference of what things should look like in action.

# Outline of Tutorial and Installation notes:

# Brief Outline of Tutorial

  • Step 1: Creating a mnemonic word list + XPRV (Extended Private Key)
  • Step 2: Generate testnet Receive Address
  • Step 3: Send funds to newly generated address
  • Step 4: Sync Wallet
  • Step 5: Check Balance of Wallet
  • Step 6: Create a Transaction (PSBT)
  • Step 7: Sign the Transaction (PSBT)
  • Step 8: Broadcast Transaction

# Rust and Cargo installation:


# bdk-cli installation:

# Emoji Legend:

▶️ : Unix/Linux Commands to copied and pasted 🔶 : Windows Powershell Commands to copied and pasted 👍 : Output/ preview of code


# Step 0: Check Version of bdk-cli

▶️ / 🔶 bdk-cli -V 👍 The output below confirms the command was successful.

bdk-cli 0.6.0

# Preview of bdk-cli help menu

▶️ / 🔶 bdk-cli --help
👍 The output below confirms the command was successful.

The BDK Command Line Wallet App

bdk-cli is a light weight command line bitcoin wallet, powered by BDK. This app can be used as a playground as well as
testing environment to simulate various wallet testing situations. If you are planning to use BDK in your wallet, bdk-
cli is also a great intro tool to get familiar with the BDK API.

But this is not just any toy. bdk-cli is also a fully functioning bitcoin wallet with taproot support!

For more information checkout <https://bitcoindevkit.org/>

USAGE:
    bdk-cli [OPTIONS] <SUBCOMMAND>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -d, --datadir <DATADIR>    Sets the wallet data directory. Default value : "~/.bdk-bitcoin
    -n, --network <NETWORK>    Sets the network [default: testnet]  [possible values: bitcoin, testnet, signet, regtest]

SUBCOMMANDS:
    compile    Compile a miniscript policy to an output descriptor
    help       Prints this message or the help of the given subcommand(s)
    key        Subcommands for Key operations
    repl       Options to configure a SOCKS5 proxy for a blockchain client connection
    wallet     Wallet subcommands that can be issued without a blockchain backend

# Step 1: Seed Generate

# 1a: Mnemonic word-list + XPRV (Extended Private Key) 🔑

Linux/Terminal: ▶️ bdk-cli key generate | tee key.json

Windows Powershell: 🔶 bdk-cli key generate | Out-File -FilePath "key.json"

{
  "fingerprint": "42b15d2f",
  "mnemonic": "party salon worth satoshi envelope suggest garlic dry add pitch throw clap keen narrow antique oyster ketchup purchase gasp visual work venue fog crater",
  "xprv": "tprv8ZgxMBicQKsPdwpamtjqMFpYRTafnE1bN2SphLEybCtRKakk6S1TgQCsZgiBwJuJNWe3jYdgVCTsKf9weMxj6tW4zNNKWptykszJpS2L8wE"
}

# 1b: Save XPRV (Extended Private Key) into environment variable

Linux/Terminal: ▶️ export XPRV_00=$(cat key.json | jq -r .xprv)

Windows Powershell:

🔶 $json = Get-Content -Path .\key.json | ConvertFrom-Json

🔶 $mykeyValue = $json.xprv

🔶 [System.Environment]::SetEnvironmentVariable('XPRV',$mykeyValue, 'Process')


# 1c: Verify environment variable XPRV_00 is active

Linux/Terminal: ▶️ env | grep XPRV

Windows Powershell: 🔶 $env:XPRV


# 1d: Create Descriptor and Save into environment variable

Linux/Terminal: ▶️ export my_descriptor="wpkh($XPRV_00/84h/1h/0h/0/*)"

Windows Powershell: 🔶 [System.Environment]::SetEnvironmentVariable('my_descriptor', "wpkh($env:XPRV/84h/1h/0h/0/*)", 'Process')


# 1e: Verify environment variable my_descriptor is active

Linux/Terminal: ▶️ env | grep my_descriptor

Windows Powershell: 🔶 $env:my_descriptor


# Step 2: Generate Receive-Address

Linux/Terminal:

▶️ bdk-cli wallet --wallet wallet_name --descriptor $my_descriptor get_new_address

Windows Powershell: 🔶bdk-cli wallet --descriptor $env:my_descriptor get_new_address

👍 The output below confirms the command was successful.

{
  "address": "tb1qrh4sq5va0unqtxyfv8al9lz3sna3988cj59uya"
}

# Step 3: Send testnet bitcoin to the newly created receive-address

Use a faucet to send funds to your newly created address. Here is a link to one: Bitcoin Testnet Faucet (opens new window)


# Step 4: Sync the wallet

Linux/Terminal: ▶️ bdk-cli wallet --wallet wallet_name --descriptor $my_descriptor sync

Windows Powershell: 🔶 bdk-cli wallet --descriptor $env:my_descriptor sync

👍 The output below confirms the command was successful.

{}

# Step 5: Check the balance

Linux/Terminal: ▶️ bdk-cli wallet --wallet wallet_name --descriptor $my_descriptor get_balance

Windows Powershell: 🔶 bdk-cli wallet --descriptor $env:my_descriptor get_balance

TIP

Note: The balance will only show after the transaction has been confirmed in a block at least once.

👍 The output below confirms the command was successful:

{
  "satoshi": {
    "confirmed": 100000,
    "immature": 0,
    "trusted_pending": 0,
    "untrusted_pending": 0
  }
}

# Step 6: Create Transaction (PSBT)

To create a PSBT (partially-signed-bitcoin-transaction) run the command:

Linux/Terminal: ▶️ bdk-cli wallet --wallet wallet_name --descriptor $my_descriptor create_tx --to tb1qw2c3lxufxqe2x9s4rdzh65tpf4d7fssjgh8nv6:50000

Windows Powershell: 🔶 bdk-cli wallet --descriptor $env:my_descriptor create_tx --to tb1qjk6n943uwhqhdf7en600tnwxpslvwtr0udsehp:0 --send_all

👍 The output below confirms the command was successful.

{
  "details": {
    "confirmation_time": null,
    "fee": 113,
    "received": 0,
    "sent": 123000,
    "transaction": null,
    "txid": "029173d76253e3441f9dc26f91e6ef30dff486848e91a7941f0cacd0af25ee30"
  },
  "psbt": "cHNidP8BAFUBAAAAAak8uMR3UGkAGUKWsq8Mv45qg2fdD93JQRIsa2P0wFloAQAAAAD/////AQfgAQAAAAAAGXapFDRKD0jKFQ7CuQOBdmC5tosTpnAmiKwAAAAAAAEA3gIAAAAAAQFY9sVfEEbyjrHXSlxXDxL+71WOMnsPpVElwk+3E/J9vAAAAAAA/v///wIYZRIAAAAAABYAFBKYf7yF+ss6EFdw2rDZTfdLhep8eOABAAAAAAAWABQd6wBRnX8mBZiJYfvy/FGE+xKc+AJHMEQCIFSIkvEUI9yUgEw4JocRs1aiVsBlKKXrOQaQb3XFqR21AiBqiEVzCVVSRGjckyPDgAQBnOdSzBYR6Rw6KFcCP+E27wEhAwIlXdfM2WYnYa36Hp4MS6YkplBAgBsb1tYG9NiWFWTKzPYhAAEBH3jgAQAAAAAAFgAUHesAUZ1/JgWYiWH78vxRhPsSnPgiBgP80FpaWYQzGzCnNI9blXbei61YpAmtoezMRxpVvBJ6SxgTizKsVAAAgAEAAIAAAACAAAAAAAAAAAAAAA=="
}

# 6a: export PSBT to environment-variable

Linux/Terminal: ▶️ export PSBT="PASTE_PSBT_HERE"

Windows Powershell: 🔶[System.Environment]::SetEnvironmentVariable('PSBT',"PASTE_PSBT_HERE",'Process')


# Step 7: Sign Transaction (PSBT)

Linux/Terminal: ▶️ bdk-cli wallet --wallet wallet_name --descriptor $my_descriptor sign --psbt $PSBT

Windows Powershell: 🔶bdk-cli wallet --descriptor $env:my_descriptor sign --psbt $env:PSBT

  • DON'T FORGET to COPY the PSBT for the next step

👍 The output below confirms the command was successful.

{
  "is_finalized": true,
  "psbt": "cHNidP8BAFUBAAAAAak8uMR3UGkAGUKWsq8Mv45qg2fdD93JQRIsa2P0wFloAQAAAAD/////AQfgAQAAAAAAGXapFDRKD0jKFQ7CuQOBdmC5tosTpnAmiKwAAAAAAAEA3gIAAAAAAQFY9sVfEEbyjrHXSlxXDxL+71WOMnsPpVElwk+3E/J9vAAAAAAA/v///wIYZRIAAAAAABYAFBKYf7yF+ss6EFdw2rDZTfdLhep8eOABAAAAAAAWABQd6wBRnX8mBZiJYfvy/FGE+xKc+AJHMEQCIFSIkvEUI9yUgEw4JocRs1aiVsBlKKXrOQaQb3XFqR21AiBqiEVzCVVSRGjckyPDgAQBnOdSzBYR6Rw6KFcCP+E27wEhAwIlXdfM2WYnYa36Hp4MS6YkplBAgBsb1tYG9NiWFWTKzPYhAAEBH3jgAQAAAAAAFgAUHesAUZ1/JgWYiWH78vxRhPsSnPgiAgP80FpaWYQzGzCnNI9blXbei61YpAmtoezMRxpVvBJ6S0gwRQIhALWkBRSJzxuf0od4tPu3qFmEfJ2Y+/QBGtfjSFObWsPeAiA4QJx8Rk5pacrjHv5EOdw6RNHXcdtepFs+m0/Za/h0UQEiBgP80FpaWYQzGzCnNI9blXbei61YpAmtoezMRxpVvBJ6SxgTizKsVAAAgAEAAIAAAACAAAAAAAAAAAABBwABCGwCSDBFAiEAtaQFFInPG5/Sh3i0+7eoWYR8nZj79AEa1+NIU5taw94CIDhAnHxGTmlpyuMe/kQ53DpE0ddx216kWz6bT9lr+HRRASED/NBaWlmEMxswpzSPW5V23outWKQJraHszEcaVbwSeksAAA=="
}

# 7a: export signed psbt to environment variable

Linux/Terminal: ▶️ export SIGNED_PSBT="Paste_PSBT_HERE"

Windows Powershell: 🔶 $env:PSBTSIGNED = "STRINGHERE"


# Step 8: Broadcast Transaction

Linux/Terminal: ▶️ bdk-cli wallet --wallet wallet_name --descriptor $my_descriptor broadcast --psbt $SIGNED_PSBT

Windows Powershell: 🔶 bdk-cli wallet --descriptor $env:my_descriptor broadcast --psbt $env:PSBTSIGNED

👍 The output below confirms the command was successful.

{
  "txid": "a0877b7ce91ea6d141ba63277673f5bdf0edfdd45f91a39ba1a1ace15f839b52"
}

TIP

Run sync one more time and see that the balance has decreased.


# Resources