Crate bdk[][src]

Expand description

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.9.0"

Sync the balance of a descriptor

Example

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};
use bdk::database::MemoryDatabase;
use bdk::wallet::AddressIndex::New;

fn main() -> Result<(), bdk::Error> {
let wallet = 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_address(New)?);
    println!("Address #1: {}", wallet.get_address(New)?);
    println!("Address #2: {}", wallet.get_address(New)?);

    Ok(())
}

Create a transaction

Example

use bdk::{FeeRate, Wallet};
use bdk::database::MemoryDatabase;
use bdk::blockchain::{noop_progress, ElectrumBlockchain};
use bdk::electrum_client::Client;

use bitcoin::consensus::serialize;
use bdk::wallet::AddressIndex::New;

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_address(New)?;
    let (psbt, details) = {
        let mut builder =  wallet.build_tx();
        builder
            .add_recipient(send_to.script_pubkey(), 50_000)
            .enable_rbf()
            .do_not_spend_change()
            .fee_rate(FeeRate::from_sat_per_vb(5.0));
        builder.finish()?
    };

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

    Ok(())
}

Sign a transaction

Example

use std::str::FromStr;

use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;

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

fn main() -> Result<(), bdk::Error> {
    let wallet = 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 mut psbt = Psbt::from_str(psbt)?;

    let finalized = wallet.sign(&mut psbt, SignOptions::default())?;

    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
  • 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 electrum_client;
pub extern crate miniscript;
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::signer::SignOptions;
pub use wallet::tx_builder::TxBuilder;
pub use wallet::Wallet;

Modules

Blockchain backends

Database types

Descriptors

Key formats

Wallet

Macros

Macro to write full descriptors with code

Macro to write descriptor fragments with code

Structs

Block height and timestamp of the block containing the confirmed transaction

Fee rate

An unspent output owned by a Wallet.

A wallet transaction

A Utxo with its satisfaction_weight.

Enums

Errors that can be thrown by the Wallet

Types of keychains

An unspent transaction output (UTXO).

Functions

Get the version of BDK at runtime