Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/cont_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ jobs:
run: |
cargo build --workspace --all-targets ${{ matrix.features }}
cargo test --workspace ${{ matrix.features }}
# cargo build --workspace --exclude 'example_*' --exclude 'bdk_wallet_fuzz' ${{ matrix.features }}
# cargo test --workspace --exclude 'example_*' --exclude 'bdk_wallet_fuzz' ${{ matrix.features }}

check-no-std:
name: Check no_std
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ Cargo.lock
*.db
*.sqlite*
examples/test_data

# fuzz testing related
fuzz/target
fuzz/corpus
fuzz/artifacts
fuzz/coverage
85 changes: 16 additions & 69 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,76 +1,23 @@
[package]
name = "bdk_wallet"
homepage = "https://bitcoindevkit.org"
version = "3.0.0-alpha.0"
repository = "https://github.com/bitcoindevkit/bdk_wallet"
documentation = "https://docs.rs/bdk_wallet"
description = "A modern, lightweight, descriptor-based wallet library"
keywords = ["bitcoin", "wallet", "descriptor", "psbt"]
readme = "README.md"
license = "MIT OR Apache-2.0"
[workspace]
resolver = "2"
members = [
"wallet",
"fuzz",
]

[workspace.package]
authors = ["Bitcoin Dev Kit Developers"]
edition = "2021"
rust-version = "1.85.0"
homepage = "https://bitcoindevkit.org"
repository = "https://github.com/bitcoindevkit/bdk_wallet"
license = "MIT OR Apache-2.0"

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[workspace.dependencies]
# Internal crates
bdk_wallet = { path = "./wallet", version = "3.0.0-alpha.0" }

[dependencies]
bdk_chain = { version = "0.23.1", features = ["miniscript", "serde"], default-features = false }
# External dependencies
bitcoin = { version = "0.32.7", features = ["serde", "base64"], default-features = false }
miniscript = { version = "12.3.1", features = ["serde"], default-features = false }
rand_core = { version = "0.6.0" }
serde_json = { version = "1" }
serde = { version = "1", features = ["derive"] }

# Optional dependencies
anyhow = { version = "1.0.98", optional = true }
bdk_file_store = { version = "0.21.1", optional = true }
bip39 = { version = "2.0", optional = true }
tempfile = { version = "3.20.0", optional = true }

[features]
default = ["std"]
std = ["bitcoin/std", "bitcoin/rand-std", "miniscript/std", "bdk_chain/std"]
compiler = ["miniscript/compiler"]
all-keys = ["keys-bip39"]
keys-bip39 = ["bip39"]
rusqlite = ["bdk_chain/rusqlite"]
file_store = ["bdk_file_store"]
test-utils = ["std", "anyhow", "tempfile"]

[dev-dependencies]
anyhow = "1"
assert_matches = "1.5.0"
bdk_bitcoind_rpc = { version = "0.21.0" }
bdk_electrum = { version = "0.23.1" }
bdk_esplora = { version = "0.22.1", features = ["async-https", "blocking-https", "tokio"] }
bdk_wallet = { path = ".", features = ["rusqlite", "file_store", "test-utils"] }
clap = { version = "4.5.17", features = ["derive", "env"] }
ctrlc = "3.4.6"
rand = "0.8"
tempfile = "3"
tokio = { version = "1.38.1", features = ["rt", "rt-multi-thread", "macros"] }

[[example]]
name = "mnemonic_to_descriptors"
path = "examples/mnemonic_to_descriptors.rs"
required-features = ["all-keys"]

[[example]]
name = "miniscriptc"
path = "examples/compiler.rs"
required-features = ["compiler"]

[[example]]
name = "electrum"

[[example]]
name = "esplora_async"

[[example]]
name = "esplora_blocking"

[[example]]
name = "bitcoind_rpc"
bdk_chain = { version = "0.23.1", features = ["miniscript", "serde"], default-features = false }
159 changes: 11 additions & 148 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,161 +1,24 @@
<div align="center">
<h1>BDK</h1>
# BDK Wallet Workspace

<img src="https://raw.githubusercontent.com/bitcoindevkit/bdk/master/static/bdk.png" width="220" />
This is a workspace containing the Bitcoin Development Kit wallet library and related tools.

<p>
<strong>A modern, lightweight, descriptor-based wallet library written in Rust!</strong>
</p>
## Workspace Members

<p>
<a href="https://crates.io/crates/bdk_wallet"><img alt="Crate Info" src="https://img.shields.io/crates/v/bdk_wallet.svg"/></a>
<a href="https://github.com/bitcoindevkit/bdk/blob/master/LICENSE"><img alt="MIT or Apache-2.0 Licensed" src="https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg"/></a>
<a href="https://github.com/bitcoindevkit/bdk/actions?query=workflow%3ACI"><img alt="CI Status" src="https://github.com/bitcoindevkit/bdk/workflows/CI/badge.svg"></a>
<a href="https://codecov.io/github/bitcoindevkit/bdk_wallet" ><img src="https://codecov.io/github/bitcoindevkit/bdk_wallet/graph/badge.svg"/></a>
<a href="https://docs.rs/bdk_wallet"><img alt="API Docs" src="https://img.shields.io/badge/docs.rs-bdk_wallet-green"/></a>
<a href="https://blog.rust-lang.org/2025/02/20/Rust-1.85.0/"><img alt="Rustc Version 1.85.0+" src="https://img.shields.io/badge/rustc-1.85.0%2B-lightgrey.svg"/></a>
<a href="https://discord.gg/d7NkDKm"><img alt="Chat on Discord" src="https://img.shields.io/discord/753336465005608961?logo=discord"></a>
</p>
- `wallet/` - The main BDK wallet library
- `fuzz/` - Fuzz testing infrastructure for the wallet

<h4>
<a href="https://bitcoindevkit.org">Project Homepage</a>
<span> | </span>
<a href="https://docs.rs/bdk_wallet">Documentation</a>
</h4>
</div>
## Building

## About

The `bdk_wallet` project provides a high level descriptor based wallet API for building Bitcoin applications.

## Architecture

[`bdk_wallet`] contains the central high level [`Wallet`] type that is built from the other low-level components.

Core BDK crates that `bdk_wallet` depends on are found in the [`bdk`] repository. This works by
leveraging the functionality in [`rust-bitcoin`] and [`rust-miniscript`].

# BDK Wallet

The `bdk_wallet` provides the [`Wallet`] type which is a simple, high-level
interface built from the low-level components of [`bdk_chain`]. `Wallet` is a good starting point
for many simple applications as well as a good demonstration of how to use the other mechanisms to
construct a wallet. It has two keychains (external and internal) that are defined by
[miniscript descriptors][`rust-miniscript`] and uses them to generate addresses. When you give it
chain data it also uses the descriptors to find transaction outputs owned by them. From there, you
can create and sign transactions.

For details about the API of `Wallet` see the [module-level documentation][`Wallet`].

## Blockchain data

In order to get blockchain data for `Wallet` to consume, you should configure a client from
an available chain source. Typically you make a request to the chain source and get a response
that the `Wallet` can use to update its view of the chain.

**Blockchain Data Sources**

* [`bdk_esplora`]: Gets blockchain data from Esplora for updating BDK structures.
* [`bdk_electrum`]: Gets blockchain data from Electrum for updating BDK structures.
* [`bdk_bitcoind_rpc`]: Gets blockchain data from Bitcoin Core for updating BDK structures.

**Examples**

* [`examples/esplora_async`](https://github.com/bitcoindevkit/bdk_wallet/blob/master/examples/esplora_async.rs)
* [`examples/esplora_blocking`](https://github.com/bitcoindevkit/bdk_wallet/blob/master/examples/esplora_blocking.rs)
* [`examples/electrum`](https://github.com/bitcoindevkit/bdk_wallet/blob/master/examples/electrum.rs)
* [`examples/bitcoind_rpc`](https://github.com/bitcoindevkit/bdk_wallet/blob/master/examples/bitcoind_rpc.rs)

## Persistence

To persist `Wallet` state use a data storage crate that reads and writes [`ChangeSet`].

**Implementations**

* [`bdk_file_store`]: Stores wallet changes in a simple flat file.
* `rusqlite`: Stores wallet changes in a SQLite database.

**Example**

```rust,no_run
use bdk_wallet::rusqlite;
use bdk_wallet::{KeychainKind, Wallet};

// Open or create a new SQLite database for wallet data.
let db_path = "my_wallet.sqlite";
let mut conn = rusqlite::Connection::open(db_path)?;

let network = bitcoin::Network::Testnet;
let descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
let change_descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/1/*)";

let mut wallet = match Wallet::load()
.descriptor(KeychainKind::External, Some(descriptor))
.descriptor(KeychainKind::Internal, Some(change_descriptor))
.extract_keys()
.check_network(network)
.load_wallet(&mut conn)?
{
Some(wallet) => wallet,
None => Wallet::create(descriptor, change_descriptor)
.network(network)
.create_wallet(&mut conn)?,
};

// Get a new address to receive bitcoin!
let address_info = wallet.reveal_next_address(KeychainKind::External);

// Persist new wallet state to database.
wallet.persist(&mut conn)?;

println!("Next receive address: {}", address_info.address);
Ok::<_, anyhow::Error>(())
```bash
cargo build --all
```

## Minimum Supported Rust Version (MSRV)

The libraries in this repository maintain a MSRV of 1.85.0.

To build with the MSRV of 1.85.0 you may need to pin dependencies by running the [`pin-msrv.sh`](./ci/pin-msrv.sh) script.

## Just

This project has a [`justfile`](/justfile) for easy command running. You must have [`just`](https://github.com/casey/just) installed.

To see a list of available recipes: `just -l`

## Testing

### Unit testing

```bash
just test
cargo test --all
```

# License

Licensed under either of

* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <https://www.apache.org/licenses/LICENSE-2.0>)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or <https://opensource.org/licenses/MIT>)

at your option.

# Contribution

Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.
## Fuzz Testing

[`Wallet`]: https://docs.rs/bdk_wallet/latest/bdk_wallet/struct.Wallet.html
[`ChangeSet`]: https://docs.rs/bdk_wallet/latest/bdk_wallet/struct.ChangeSet.html
[`bdk`]: https://github.com/bitcoindevkit/bdk
[`bdk_wallet`]: https://docs.rs/bdk_wallet/latest
[`bdk_chain`]: https://docs.rs/bdk_chain/latest
[`bdk_file_store`]: https://docs.rs/bdk_file_store/latest
[`bdk_electrum`]: https://docs.rs/bdk_electrum/latest
[`bdk_esplora`]: https://docs.rs/bdk_esplora/latest
[`bdk_bitcoind_rpc`]: https://docs.rs/bdk_bitcoind_rpc/latest
[`rust-bitcoin`]: https://docs.rs/bitcoin/latest/bitcoin/
[`rust-miniscript`]: https://docs.rs/miniscript/latest/miniscript/index.html
See the [fuzz/README.md](fuzz/README.md) for fuzz testing instructions.
34 changes: 34 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[package]
name = "bdk_wallet_fuzz"
homepage = "https://bitcoindevkit.org"
version = "0.0.1-alpha.0"
repository = "https://github.com/bitcoindevkit/bdk_wallet"
description = "A fuzz testing library for the Bitcoin Development Kit Wallet"
keywords = ["fuzz", "testing", "fuzzing", "bitcoin", "wallet"]
publish = false
readme = "README.md"
license = "MIT OR Apache-2.0"
authors = ["Bitcoin Dev Kit Developers"]
edition = "2021"

[package.metadata]
cargo-fuzz = true

[dependencies]
libfuzzer-sys = "0.4"
arbitrary = { version = "1.4", features = ["derive"] }
bdk_wallet = { path = "../wallet", features = ["rusqlite"] }

[[bin]]
name = "bdk_wallet"
path = "fuzz_targets/bdk_wallet.rs"
test = false
doc = false
bench = false

[[bin]]
name = "bdk_wallet_optimized"
path = "fuzz_targets/bdk_wallet_optimized.rs"
test = false
doc = false
bench = false
Loading
Loading