[][src]Crate bdk

A modern, lightweight, descriptor-based wallet library written in Rust.

About

The BDK library aims to be the core building block for Bitcoin wallets of any kind.

  • It uses Miniscript to support descriptors with generalized conditions. This exact same library can be used to build single-sig wallets, multisigs, timelocked contracts and more.
  • It supports multiple blockchain backends and databases, allowing developers to choose exactly what's right for their projects.
  • It is built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
  • It is very easy to extend: developers can implement customized logic for blockchain backends, databases, signers, coin selection, and more, without having to fork and modify this library.

A Tour of BDK

BDK consists of a number of modules that provide a range of functionality essential for implementing descriptor based Bitcoin wallet applications in Rust. In this section, we will take a brief tour of BDK, summarizing the major APIs and their uses.

The easiest way to get started is to add bdk to your dependencies with the default features. The default features include a simple key-value database (sled) to cache blockchain data and an electrum blockchain client to interact with the bitcoin P2P network.

bdk = "0.2.0"

Sync the balance of a descriptor

Example

This example is not tested
use bdk::Wallet;
use bdk::database::MemoryDatabase;
use bdk::blockchain::{noop_progress, ElectrumBlockchain};

use bdk::electrum_client::Client;

fn main() -> Result<(), bdk::Error> {
    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    let wallet = Wallet::new(
        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
        bitcoin::Network::Testnet,
        MemoryDatabase::default(),
        ElectrumBlockchain::from(client)
    )?;

    wallet.sync(noop_progress(), None)?;

    println!("Descriptor balance: {} SAT", wallet.get_balance()?);

    Ok(())
}

Generate a few addresses

Example

use bdk::{Wallet, OfflineWallet};
use bdk::database::MemoryDatabase;

fn main() -> Result<(), bdk::Error> {
    let wallet: OfflineWallet<_> = Wallet::new_offline(
        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
        bitcoin::Network::Testnet,
        MemoryDatabase::default(),
    )?;

    println!("Address #0: {}", wallet.get_new_address()?);
    println!("Address #1: {}", wallet.get_new_address()?);
    println!("Address #2: {}", wallet.get_new_address()?);

    Ok(())
}

Create a transaction

Example

This example is not tested
use base64::decode;
use bdk::{FeeRate, TxBuilder, Wallet};
use bdk::database::MemoryDatabase;
use bdk::blockchain::{noop_progress, ElectrumBlockchain};

use bdk::electrum_client::Client;

use bitcoin::consensus::serialize;

fn main() -> Result<(), bdk::Error> {
    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    let wallet = Wallet::new(
        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
        bitcoin::Network::Testnet,
        MemoryDatabase::default(),
        ElectrumBlockchain::from(client)
    )?;

    wallet.sync(noop_progress(), None)?;

    let send_to = wallet.get_new_address()?;
    let (psbt, details) = wallet.create_tx(
        TxBuilder::with_recipients(vec![(send_to.script_pubkey(), 50_000)])
            .enable_rbf()
            .do_not_spend_change()
            .fee_rate(FeeRate::from_sat_per_vb(5.0))
    )?;

    println!("Transaction details: {:#?}", details);
    println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));

    Ok(())
}

Sign a transaction

Example

This example is not tested
use base64::decode;
use bdk::{Wallet, OfflineWallet};
use bdk::database::MemoryDatabase;

use bitcoin::consensus::deserialize;

fn main() -> Result<(), bdk::Error> {
    let wallet: OfflineWallet<_> = Wallet::new_offline(
        "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
        Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
        bitcoin::Network::Testnet,
        MemoryDatabase::default(),
    )?;

    let psbt = "...";
    let psbt = deserialize(&base64::decode(psbt).unwrap())?;

    let (signed_psbt, finalized) = wallet.sign(psbt, None)?;

    Ok(())
}

Feature flags

BDK uses a set of feature flags to reduce the amount of compiled code by allowing projects to only enable the features they need. By default, BDK enables two internal features, key-value-db and electrum.

If you are new to BDK we recommended that you use the default features which will enable basic descriptor wallet functionality. More advanced users can disable the default features (--no-default-features) and build the BDK library with only the features you need. Below is a list of the available feature flags and the additional functionality they provide.

  • all-keys: all features for working with bitcoin keys
  • async-interface: async functions in bdk traits
  • cli-utils: utilities for creating a command line interface wallet
  • keys-bip39: BIP-39 mnemonic codes for generating deterministic keys

Internal features

These features do not expose any new API, but influence internal implementation aspects of BDK.

  • compact_filters: compact_filters client protocol for interacting with the bitcoin P2P network
  • electrum: electrum client protocol for interacting with electrum servers
  • esplora: esplora client protocol for interacting with blockstream electrs servers
  • key-value-db: key value database based on sled for caching blockchain data

Re-exports

pub extern crate bitcoin;
pub extern crate miniscript;
pub extern crate electrum_client;
pub extern crate reqwest;
pub extern crate sled;
pub use descriptor::template;
pub use descriptor::HDKeyPaths;
pub use wallet::address_validator;
pub use wallet::signer;
pub use wallet::tx_builder::TxBuilder;
pub use wallet::OfflineWallet;
pub use wallet::Wallet;

Modules

blockchain

Blockchain backends

database

Database types

descriptor

Descriptors

keys

Key formats

wallet

Wallet

Macros

descriptor

Macro to write full descriptors with code

fragment

Macro to write descriptor fragments with code

Structs

FeeRate

Fee rate

TransactionDetails

A wallet transaction

UTXO

A wallet unspent output

Enums

Error

Errors that can be thrown by the Wallet

KeychainKind

Types of keychains