BDK-CLI

A Command-line Bitcoin Wallet App in pure rust using BDK

Crate Info MIT or Apache-2.0 Licensed CI Status API Docs Chat on Discord

Project Homepage | Documentation

## About **EXPERIMENTAL** This crate has been updated to use `bdk_wallet` 3.x. Only use for testing on test networks. This project provides a command-line Bitcoin wallet application using the latest [BDK Wallet APIs](https://docs.rs/bdk_wallet/1.0.0/bdk_wallet/index.html) and chain sources ([RPC](https://docs.rs/bdk_bitcoind_rpc/0.18.0/bdk_bitcoind_rpc/index.html), [Electrum](https://docs.rs/bdk_electrum/0.21.0/bdk_electrum/index.html), [Esplora](https://docs.rs/bdk_esplora/0.21.0/bdk_esplora/), [Kyoto](https://docs.rs/bdk_kyoto/0.9.0/bdk_kyoto/)). This might look tiny and innocent, but by harnessing the power of BDK it provides a powerful generic descriptor based command line wallet tool. And yes, it can do Taproot!! This crate can be used for the following purposes: - Instantly create a miniscript based wallet and connect to your backend of choice (Electrum, Esplora, Core RPC, Kyoto etc) and quickly play around with your own complex bitcoin scripting workflow. With one or many wallets, connected with one or many backends. - The `tests/integration.rs` module is used to document high level complex workflows between BDK and different Bitcoin infrastructure systems, like Core, Electrum and Lightning(soon TM). - Receive and send async Payjoins with session persistence. Sessions can be resumed if interrupted. - Creating (experimental) silent payment transactions and sending Bitcoin to silent payment addresses - (Planned) Expose the basic command handler via `wasm` to integrate `bdk-cli` functionality natively into the web platform. See also the [playground](https://bitcoindevkit.org/bdk-cli/playground/) page. If you are considering using BDK in your own wallet project bdk-cli is a nice playground to get started with. It allows easy testnet and regtest wallet operations, to try out what's possible with descriptors, miniscript, and BDK APIs. For more information on BDK refer to the [website](https://bitcoindevkit.org/) and the [rust docs](https://docs.rs/bdk_wallet/1.0.0/bdk_wallet/index.html) bdk-cli can be compiled with different features to suit your experimental needs. - Database Options - `sqlite` : Sets the wallet database to a `sqlite3` db. - Blockchain Client Options - `esplora` : Connects the wallet to an esplora server. - `electrum` : Connects the wallet to an electrum server. - `cbf`: BIP157/158 compact block filters (Kyoto light client) - `rpc`: Connects the wallet to Bitcoind server. - Extra Utility Tools - `repl` : use bdk-cli as a [REPL](https://codewith.mu/en/tutorials/1.0/repl) shell (useful for quick manual testing of wallet operations). - `compiler` : opens up bdk-cli policy compiler commands. - `message_signer`: BIP322 message signing/verification. - `silent-payments`: Experimental BIP-352 silent payment sending - `dns_payment`: BIP-353 DNS payment instructions The `default` feature set is `repl` and `sqlite`. With the `default` features, `bdk-cli` can be used as an **air-gapped** wallet, and can do everything that doesn't require a network connection. ## Install bdk-cli ### Prerequisites Building BDK requires `gcc`. If you do not have this installed run: ```shell sudo apt-get install build-essential ``` ### From source To install a dev version of `bdk-cli` from a local git repo with the `electrum` blockchain client enabled: ```shell cd cargo install --path . --features electrum bdk-cli help # to verify it worked ``` If no blockchain client feature is enabled online wallet commands `sync` and `broadcast` will be disabled. To enable these commands a blockchain client feature such as `electrum` or another blockchain client feature must be enabled. Below is an example of how to run the `bdk-cli` binary with the `electrum` blockchain client feature. ```shell RUST_LOG=debug cargo run --features electrum -- --network testnet4 wallet --wallet testnetwallet config --ext-descriptor "wpkh(tprv8ZgxMBicQKsPda2kR5xbHy1eVDWReS8CjQ9LaPL3UDubtA7ns1UcRbyaLMYy44YzBoBTgLCSKpMRXk1LcC5Wxm1r77QDsSJBqwejfftW3mY/84'/1'/0'/0/*)#t3xrg3ld" --client-type electrum --database-type sqlite --url "ssl://mempool.space:40002" RUST_LOG=debug cargo run --features electrum -- wallet -w testnetwallet full_scan RUST_LOG=debug cargo run --features electrum -- wallet -w testnetwallet balance ``` Available blockchain client features are: `electrum`, `esplora`, `cbf`, `rpc`. ### From crates.io You can install the binary for the latest tag of `bdk-cli` with online wallet features directly from [crates.io](https://crates.io/crates/bdk-cli) with a command as below: ```sh cargo install bdk-cli --features electrum ``` ### bdk-cli bin usage examples To get usage information for the `bdk-cli` binary use the below command which returns a list of available wallet options and commands: ```shell cargo run ``` To sync a wallet to the default electrum server: ```shell cargo run --features electrum -- --network testnet4 wallet --wallet sample_wallet config --ext-descriptor "wpkh(tprv8ZgxMBicQKsPda2kR5xbHy1eVDWReS8CjQ9LaPL3UDubtA7ns1UcRbyaLMYy44YzBoBTgLCSKpMRXk1LcC5Wxm1r77QDsSJBqwejfftW3mY/84'/1'/0'/0/*)#t3xrg3ld" --database-type sqlite --client-type electrum --url "ssl://mempool.space:40002" cargo run --features electrum -- wallet --wallet sample_wallet full_scan cargo run --features electrum -- wallet --wallet sample_wallet balance ``` To get a wallet balance with customized logging: ```shell RUST_LOG=debug,rusqlite=info,rustls=info cargo run --features electrum -- wallet --wallet sample_wallet balance ``` To generate a new extended master key, suitable for use in a descriptor: ```shell cargo run -- key generate ``` To start a Payjoin session as the receiver with regtest RPC and example OHTTP relays: ``` cargo run --features rpc -- --network regtest wallet --wallet payjoin_wallet1 config --ext-descriptor "wpkh(tprv8ZgxMBicQKsPd2PoUEcGNDHPZmVWgtPYERAwMG6qHheX6LN4oaazp3qZU7mykiaAZga1ZB2SJJR6Mriyq8MocMs7QTe7toaabSwTWu5fRFz/84h/1h/0h/0/*)#8guqp7rn" --client-type rpc --database-type sqlite --url "127.0.0.1:18443" cargo run --features rpc -- wallet --wallet payjoin_wallet1 sync cargo run --features rpc -- wallet --wallet payjoin_wallet1 balance cargo run --features rpc -- wallet --wallet payjoin_wallet1 receive_payjoin --amount 400000 --max_fee_rate 1000 --directory "https://payjo.in" --ohttp_relay "https://pj.bobspacebkk.com" --ohttp_relay "https://pj.benalleng.com" ``` To send a Payjoin with regtest RPC and example OHTTP relays: ``` cargo run --features rpc -- --network regtest wallet --wallet payjoin_wallet2 config --ext-descriptor "wpkh(tprv8ZgxMBicQKsPfBxswkATvZRQ9kDdRbJPtHYZaZCARL2myxcK7DqsqPhRo2G2rRVHFPbowq63BE6S4k2pUMYeF2fUMTT63Q7zhoXtKsM1FaS/84'/1'/0'/0/*)#qf5gnqrf" --client-type rpc --database-type sqlite --url "127.0.0.1:18443" cargo run --features rpc -- wallet --wallet payjoin_wallet2 sync cargo run --features rpc -- wallet --wallet payjoin_wallet2 balance cargo run --features rpc -- wallet --wallet payjoin_wallet2 send_payjoin --ohttp_relay "https://pj.bobspacebkk.com" --ohttp_relay "https://pj.benalleng.com" --fee_rate 1 --uri "" #### Silent payments > [!WARNING] > This tool does not support silent payment scanning, nor the `silent_payment_code` > command has any control on the public keys provided. If you don't have access > to a silent payment scanner with the keys you provided, you are not going to > be able to discover any funds, and if you do not control the private keys, > you are not going to be able to spend the funds. We do not recommend the use > of any of the silent payment features with real funds. To experiment with silent payments, you can get two public keys in compressed or uncompressed format, `A1` and `A2`, and produce a silent payment code by calling: ```shell cargo run --features silent-payments -- --network signet silent_payment_code --scan_key '' --spend_key '' ``` Once you have a silent payment code, `SP_CODE_1` and an amount `AMOUNT_1` to send, you can create a valid transaction locking funds to a silent payment code derived address with the following command: ```shell cargo run --features electrum,silent-payments -- --network testnet4 wallet --wallet sample_wallet --ext-descriptor "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)" --database-type sqlite --client-type electrum --url "ssl://mempool.space:40002" create_sp_tx --to-sp : ``` It's also possible to drain all balance to a silent payment wallet by using the `--send_all` flag: ```shell cargo run --features electrum,silent-payments -- --network testnet4 wallet --wallet sample_wallet --ext-descriptor "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)" --database-type sqlite --client-type electrum --url "ssl://mempool.space:40002" create_sp_tx --send_all --to-sp :0 ``` ### Payjoin #### Payjoin Session Persistence Payjoin sessions are automatically persisted to a SQLite database (`payjoin.sqlite`) in the data directory. This allows sessions to be resumed if interrupted. Old completed sessions and stale inactive sessions older than 30 days are pruned automatically when the payjoin database is accessed. ##### Resume Payjoin Sessions Resume all pending sessions: ``` cargo run --features rpc -- wallet --wallet resume_payjoin --directory "https://payjo.in" --ohttp_relay "https://pj.bobspacebkk.com" ``` Resume a specific session by ID: ``` cargo run --features rpc -- wallet --wallet resume_payjoin --directory "https://payjo.in" --ohttp_relay "https://pj.bobspacebkk.com" --session_id ``` Sessions are processed sequentially (not concurrently) due to BDK-CLI's architecture. Each session waits up to 30 seconds for updates before timing out. If no session ID is specified, the most recent active sessions are resumed first. ##### View Session History View all payjoin sessions (active and completed) and also see their status: ``` cargo run -- wallet --wallet payjoin_history ``` ## Justfile We have added the `just` command runner to help you with common commands (during development) and running regtest `bitcoind` if you are using the `rpc` feature. Visit the [just](https://just.systems/man/en/packages.html) page for setup instructions. The below are some of the commands included: ``` shell just # list all available recipes just test # test the project just build # build the project just pre-push # run full CI checks locally (tests, clippy, fmt) before pushing ``` ### Using `Justfile` to run `bitcoind` as a Client If you are testing `bdk-cli` in regtest mode and wants to use your `bitcoind` node as a blockchain client, the `Justfile` can help you to quickly do so. Below are the steps to use your `bitcoind` node in *regtest* mode with `bdk-cli`: Note: You can modify the `Justfile` to reflect your nodes' configuration values. These values are the default values used in `bdk-cli` > * default wallet: The set default wallet name is `regtest_default_wallet` > * default data directory: The set default data directory is `~/.bdk-bitcoin` > * RPC username: The set RPC username is `user` > * RPC password: The set RPC password is `password` #### Steps 1. Start bitcoind ```shell just start ``` 2. Create or load a bitcoind wallet with default wallet name ```shell just create ``` or ```shell just load ``` 3. Generate a bitcoind wallet address to send regtest bitcoins to. ```shell just address ``` 4. Mine 101 blocks on regtest to bitcoind wallet address ```shell just generate 101 $(just address) ``` 5. Check the bitcoind wallet balance ```shell just balance ``` 6. Setup your `bdk-cli` wallet config and connect it to your regtest node to perform a `sync` ```shell cargo run --features rpc -- -n regtest wallet -w regtest1 config -e "wpkh(tprv8ZgxMBicQKsPdMzWj9KHvoExKJDqfZFuT5D8o9XVZ3wfyUcnPNPJKncq5df8kpDWnMxoKbGrpS44VawHG17ZSwTkdhEtVRzSYXd14vDYXKw/0/*)" -i "wpkh(tprv8ZgxMBicQKsPdMzWj9KHvoExKJDqfZFuT5D8o9XVZ3wfyUcnPNPJKncq5df8kpDWnMxoKbGrpS44VawHG17ZSwTkdhEtVRzSYXd14vDYXKw/1/*)" -u "127.0.0.1:18443" -c rpc -d sqlite -a user:password cargo run --features rpc -- wallet -w regtest1 sync ``` 7. Generate an address from your `bdk-cli` wallet and fund it with 10 bitcoins from your bitcoind node's wallet ```shell export address=$(cargo run --features rpc -- wallet -w regtest1 new_address | jq '.address') just send 10 $address ``` 8. Mine 6 more blocks to the bitcoind wallet ```shell just generate 6 $(just address) ``` 9. You can `sync` your `bdk-cli` wallet now and the balance should reflect the regtest bitcoin you received ```shell cargo run --features rpc -- wallet -w regtest1 sync cargo run --features rpc -- wallet -w regtest1 balance ``` ## Shell Completions `bdk-cli` supports generating shell completions for Bash, Zsh, Fish, Elvish, and PowerShell. For setup instructions, run: ```shell bdk-cli completions --help ``` Completion files are generated from the currently installed binary. After upgrading `bdk-cli`, re-run the `completions` command to keep them in sync with the new version. ## Saving and using wallet configurations The `wallet config` sub-command allows you to save wallet settings to a `config.toml` file in the default directory (`~/.bdk-bitcoin/`) or custom directory specified with the `--datadir` flag. This eliminate the need to repeatedly specify descriptors, client types, and other parameters for each command. Once configured, you can use any wallet command by simply specifying the wallet name. All other parameters are automatically loaded from the saved configuration. To save a wallet settings: ```shell cargo run --features -- -n wallet --wallet config [ -f ] --ext-descriptor --int-descriptor --client-type --url [--database-type ] [--rpc-user ] [--rpc-password ] ``` For example, to initialize a wallet named `my_wallet` with `electrum` as the backend on `signet` network: ```shell cargo run --features electrum -- -n signet wallet -w my_wallet config -e "tr(tprv8Z.../0/*)#dtdqk3dx" -i "tr(tprv8Z.../1/*)#ulgptya7" -d sqlite -c electrum -u "ssl://mempool.space:60602" ``` To overwrite an existing wallet configuration, use the `--force` flag after the `config` sub-command. #### Using a Configured Wallet Once configured, use any wallet command with just the wallet name: ```shell cargo run --features electrum wallet -w my_wallet new_address cargo run --features electrum wallet -w my_wallet full_scan ``` Note that each wallet has its own configuration, allowing multiple wallets with different configurations. #### View all saved Wallet Configs To view all saved wallet configurations: ```shell cargo run wallets` ``` ## Adding new features/command This [guide](./NEW_FEATURE.md) explains how to add a new command/feature to bdk-cli's modular architecture.