2020-09-07 11:16:41 +02:00
< div align = "center" >
2020-09-14 14:30:00 +02:00
< h1 > BDK< / h1 >
2020-01-22 23:13:11 +01:00
2021-12-10 13:01:21 +01:00
< img src = "./static/bdk.png" width = "220" / >
2020-05-06 17:27:40 +02:00
2020-09-07 11:16:41 +02:00
< p >
< strong > A modern, lightweight, descriptor-based wallet library written in Rust!< / strong >
< / p >
2020-05-06 17:27:40 +02:00
2020-09-07 11:16:41 +02:00
< p >
2020-12-21 09:35:39 -08:00
< a href = "https://crates.io/crates/bdk" > < img alt = "Crate Info" src = "https://img.shields.io/crates/v/bdk.svg" / > < / a >
2021-03-05 16:48:57 -08:00
< 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 >
2020-11-16 15:37:26 -08:00
< 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 >
2022-08-29 14:48:19 +05:30
< a href = "https://coveralls.io/github/bitcoindevkit/bdk?branch=master" > < img src = "https://coveralls.io/repos/github/bitcoindevkit/bdk/badge.svg?branch=master" / > < / a >
2020-12-21 09:35:39 -08:00
< a href = "https://docs.rs/bdk" > < img alt = "API Docs" src = "https://img.shields.io/badge/docs.rs-bdk-green" / > < / a >
2023-01-24 13:28:42 -06:00
< a href = "https://blog.rust-lang.org/2021/12/02/Rust-1.57.0.html" > < img alt = "Rustc Version 1.57.0+" src = "https://img.shields.io/badge/rustc-1.57.0%2B-lightgrey.svg" / > < / a >
2020-10-07 10:00:06 +02:00
< a href = "https://discord.gg/d7NkDKm" > < img alt = "Chat on Discord" src = "https://img.shields.io/discord/753336465005608961?logo=discord" > < / a >
2020-09-07 11:16:41 +02:00
< / p >
< h4 >
2020-09-14 14:30:00 +02:00
< a href = "https://bitcoindevkit.org" > Project Homepage< / a >
2020-09-07 11:16:41 +02:00
< span > | < / span >
2020-12-21 09:35:39 -08:00
< a href = "https://docs.rs/bdk" > Documentation< / a >
2020-09-07 11:16:41 +02:00
< / h4 >
< / div >
## About
2020-09-14 14:30:00 +02:00
The `bdk` library aims to be the core building block for Bitcoin wallets of any kind.
2020-09-07 11:16:41 +02:00
* It uses [Miniscript ](https://github.com/rust-bitcoin/rust-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's built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
* It's 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.
## Examples
### Sync the balance of a descriptor
2020-09-21 15:32:38 +01:00
```rust,no_run
2020-09-14 14:25:38 +02:00
use bdk::Wallet;
2022-01-27 16:52:53 +11:00
use bdk::blockchain::ElectrumBlockchain;
use bdk::SyncOptions;
2020-09-14 14:25:38 +02:00
use bdk::electrum_client::Client;
2022-05-06 09:03:35 -07:00
use bdk::bitcoin::Network;
2020-09-07 11:16:41 +02:00
2020-09-14 14:25:38 +02:00
fn main() -> Result< (), bdk::Error> {
2022-01-27 16:52:53 +11:00
let blockchain = ElectrumBlockchain::from(Client::new("ssl://electrum.blockstream.info:60002")?);
2020-09-07 11:16:41 +02:00
let wallet = Wallet::new(
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
2022-05-06 09:03:35 -07:00
Network::Testnet,
2020-09-07 11:16:41 +02:00
)?;
2022-01-27 16:52:53 +11:00
wallet.sync(& blockchain, SyncOptions::default())?;
2020-09-07 11:16:41 +02:00
println!("Descriptor balance: {} SAT", wallet.get_balance()?);
Ok(())
}
```
### Generate a few addresses
2020-09-21 15:32:38 +01:00
```rust
2023-02-21 12:38:16 +11:00
use bdk::Wallet;
2021-03-08 16:17:10 -08:00
use bdk::wallet::AddressIndex::New;
2022-12-11 13:54:33 -05:00
use bdk::bitcoin::Network;
2020-09-07 11:16:41 +02:00
2020-09-14 14:25:38 +02:00
fn main() -> Result< (), bdk::Error> {
2023-02-21 12:38:16 +11:00
let wallet = Wallet::new_no_persist(
2020-09-07 11:16:41 +02:00
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
2022-12-11 13:54:33 -05:00
Network::Testnet,
2020-09-07 11:16:41 +02:00
)?;
2022-11-03 15:59:38 +08:00
println!("Address #0: {}", wallet.get_address(New));
println!("Address #1: {}", wallet.get_address(New));
println!("Address #2: {}", wallet.get_address(New));
2020-09-07 11:16:41 +02:00
Ok(())
}
```
### Create a transaction
2020-09-21 15:32:38 +01:00
```rust,no_run
2022-01-27 16:52:53 +11:00
use bdk::{FeeRate, Wallet, SyncOptions};
use bdk::blockchain::ElectrumBlockchain;
2020-09-07 11:16:41 +02:00
2020-09-14 14:25:38 +02:00
use bdk::electrum_client::Client;
2021-03-08 16:17:10 -08:00
use bdk::wallet::AddressIndex::New;
2020-09-07 11:16:41 +02:00
2022-10-25 11:15:43 +02:00
use base64;
2022-12-11 13:54:33 -05:00
use bdk::bitcoin::consensus::serialize;
use bdk::bitcoin::Network;
2020-09-07 11:16:41 +02:00
2020-09-14 14:25:38 +02:00
fn main() -> Result< (), bdk::Error> {
2022-01-27 16:52:53 +11:00
let blockchain = ElectrumBlockchain::from(Client::new("ssl://electrum.blockstream.info:60002")?);
2023-02-21 12:38:16 +11:00
let wallet = Wallet::new_no_persist(
2020-09-07 11:16:41 +02:00
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
2022-12-11 13:54:33 -05:00
Network::Testnet,
2020-09-07 11:16:41 +02:00
)?;
2022-01-27 16:52:53 +11:00
wallet.sync(& blockchain, SyncOptions::default())?;
2020-09-07 11:16:41 +02:00
2022-11-03 15:59:38 +08:00
let send_to = wallet.get_address(New);
2021-01-30 13:05:23 +11:00
let (psbt, details) = {
2021-01-11 14:14:14 +11:00
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()?
};
2020-09-07 11:16:41 +02:00
println!("Transaction details: {:#?}", details);
println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));
Ok(())
}
```
### Sign a transaction
2020-09-21 15:32:38 +01:00
```rust,no_run
2023-02-21 12:38:16 +11:00
use bdk::{Wallet, SignOptions};
2020-09-07 11:16:41 +02:00
2022-10-25 11:15:43 +02:00
use base64;
2022-12-11 13:54:33 -05:00
use bdk::bitcoin::consensus::deserialize;
use bdk::bitcoin::Network;
2020-09-07 11:16:41 +02:00
2020-09-14 14:25:38 +02:00
fn main() -> Result< (), bdk::Error> {
2023-02-21 12:38:16 +11:00
let wallet = Wallet::new_no_persist(
2020-09-07 11:16:41 +02:00
"wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
2022-12-11 13:54:33 -05:00
Network::Testnet,
2020-09-07 11:16:41 +02:00
)?;
let psbt = "...";
2021-04-28 09:53:03 +10:00
let mut psbt = deserialize(&base64::decode(psbt).unwrap())?;
2020-09-07 11:16:41 +02:00
2022-12-11 13:54:33 -05:00
let _finalized = wallet.sign(& mut psbt, SignOptions::default())?;
2020-09-07 11:16:41 +02:00
Ok(())
}
```
2021-03-03 13:22:05 -08:00
2021-06-28 15:04:17 +02:00
## Testing
### Unit testing
2022-07-08 15:08:22 +02:00
```bash
2021-06-28 15:04:17 +02:00
cargo test
```
### Integration testing
Integration testing require testing features, for example:
2022-07-08 15:08:22 +02:00
```bash
2021-06-28 15:04:17 +02:00
cargo test --features test-electrum
```
2022-06-07 13:14:52 +02:00
The other options are `test-esplora` , `test-rpc` or `test-rpc-legacy` which runs against an older version of Bitcoin Core.
2021-06-29 11:30:45 +02:00
Note that `electrs` and `bitcoind` binaries are automatically downloaded (on mac and linux), to specify you already have installed binaries you must use `--no-default-features` and provide `BITCOIND_EXE` and `ELECTRS_EXE` as environment variables.
2021-06-28 15:04:17 +02:00
2022-10-24 12:01:56 +02:00
## Running under WASM
If you want to run this library under WASM you will probably have to add the following lines to you `Cargo.toml` :
```toml
[dependencies]
getrandom = { version = "0.2", features = ["js"] }
```
This enables the `rand` crate to work in environments where JavaScript is available. See [this link ](https://docs.rs/getrandom/0.2.8/getrandom/#webassembly-support ) to learn more.
2021-03-03 13:22:05 -08:00
## License
Licensed under either of
* Apache License, Version 2.0
([LICENSE-APACHE ](LICENSE-APACHE ) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license
([LICENSE-MIT ](LICENSE-MIT ) or http://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
2021-04-28 09:53:03 +10:00
dual licensed as above, without any additional terms or conditions.