jitash_bdk/lib.rs
1// Bitcoin Dev Kit
2// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
3//
4// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
5//
6// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
7// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
9// You may not use this file except in accordance with one or both of these
10// licenses.
11
12// rustdoc will warn if there are missing docs
13#![warn(missing_docs)]
14// only enables the `doc_cfg` feature when
15// the `docsrs` configuration attribute is defined
16#![cfg_attr(docsrs, feature(doc_cfg))]
17#![cfg_attr(
18 docsrs,
19 doc(html_logo_url = "https://github.com/bitcoindevkit/bdk/raw/master/static/bdk.png")
20)]
21
22//! A modern, lightweight, descriptor-based wallet library written in Rust.
23//!
24//! # About
25//!
26//! The BDK library aims to be the core building block for Bitcoin wallets of any kind.
27//!
28//! * 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
29//! single-sig wallets, multisigs, timelocked contracts and more.
30//! * It supports multiple blockchain backends and databases, allowing developers to choose exactly what's right for their projects.
31//! * It is built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
32//! * 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.
33//!
34//! # A Tour of BDK
35//!
36//! BDK consists of a number of modules that provide a range of functionality
37//! essential for implementing descriptor based Bitcoin wallet applications in Rust. In this
38//! section, we will take a brief tour of BDK, summarizing the major APIs and
39//! their uses.
40//!
41//! The easiest way to get started is to add bdk to your dependencies with the default features.
42//! The default features include a simple key-value database ([`sled`](sled)) to cache
43//! blockchain data and an [electrum](https://docs.rs/electrum-client/) blockchain client to
44//! interact with the bitcoin P2P network.
45//!
46//! # Examples
47#![cfg_attr(
48 feature = "electrum",
49 doc = r##"
50## Sync the balance of a descriptor
51
52```no_run
53use jitash_bdk::{Wallet, SyncOptions};
54use jitash_bdk::database::MemoryDatabase;
55use jitash_bdk::blockchain::ElectrumBlockchain;
56use jitash_bdk::electrum_client::Client;
57
58fn main() -> Result<(), jitash_bdk::Error> {
59 let client = Client::new("ssl://electrum.blockstream.info:60002")?;
60 let blockchain = ElectrumBlockchain::from(client);
61 let wallet = Wallet::new(
62 "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
63 Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
64 bitcoin::Network::Testnet,
65 MemoryDatabase::default(),
66 )?;
67
68 wallet.sync(&blockchain, SyncOptions::default())?;
69
70 println!("Descriptor balance: {} SAT", wallet.get_balance()?);
71
72 Ok(())
73}
74```
75"##
76)]
77//!
78//! ## Generate a few addresses
79//!
80//! ### Example
81//! ```
82//! use jitash_bdk::{Wallet};
83//! use jitash_bdk::database::MemoryDatabase;
84//! use jitash_bdk::wallet::AddressIndex::New;
85//!
86//! fn main() -> Result<(), jitash_bdk::Error> {
87//! let wallet = Wallet::new(
88//! "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
89//! Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
90//! bitcoin::Network::Testnet,
91//! MemoryDatabase::default(),
92//! )?;
93//!
94//! println!("Address #0: {}", wallet.get_address(New)?);
95//! println!("Address #1: {}", wallet.get_address(New)?);
96//! println!("Address #2: {}", wallet.get_address(New)?);
97//!
98//! Ok(())
99//! }
100//! ```
101#![cfg_attr(
102 feature = "electrum",
103 doc = r##"
104## Create a transaction
105
106```no_run
107use jitash_bdk::{FeeRate, Wallet, SyncOptions};
108use jitash_bdk::database::MemoryDatabase;
109use jitash_bdk::blockchain::ElectrumBlockchain;
110use jitash_bdk::electrum_client::Client;
111
112use bitcoin::consensus::serialize;
113use jitash_bdk::wallet::AddressIndex::New;
114
115fn main() -> Result<(), jitash_bdk::Error> {
116 let client = Client::new("ssl://electrum.blockstream.info:60002")?;
117 let wallet = Wallet::new(
118 "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
119 Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
120 bitcoin::Network::Testnet,
121 MemoryDatabase::default(),
122 )?;
123 let blockchain = ElectrumBlockchain::from(client);
124
125 wallet.sync(&blockchain, SyncOptions::default())?;
126
127 let send_to = wallet.get_address(New)?;
128 let (psbt, details) = {
129 let mut builder = wallet.build_tx();
130 builder
131 .add_recipient(send_to.script_pubkey(), 50_000)
132 .enable_rbf()
133 .do_not_spend_change()
134 .fee_rate(FeeRate::from_sat_per_vb(5.0));
135 builder.finish()?
136 };
137
138 println!("Transaction details: {:#?}", details);
139 println!("Unsigned PSBT: {}", &psbt);
140
141 Ok(())
142}
143```
144"##
145)]
146//!
147//! ## Sign a transaction
148//!
149//! ```no_run
150//! use std::str::FromStr;
151//!
152//! use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
153//!
154//! use jitash_bdk::{Wallet, SignOptions};
155//! use jitash_bdk::database::MemoryDatabase;
156//!
157//! fn main() -> Result<(), jitash_bdk::Error> {
158//! let wallet = Wallet::new(
159//! "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
160//! Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
161//! bitcoin::Network::Testnet,
162//! MemoryDatabase::default(),
163//! )?;
164//!
165//! let psbt = "...";
166//! let mut psbt = Psbt::from_str(psbt)?;
167//!
168//! let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
169//!
170//! Ok(())
171//! }
172//! ```
173//!
174//! # Feature flags
175//!
176//! BDK uses a set of [feature flags](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section)
177//! to reduce the amount of compiled code by allowing projects to only enable the features they need.
178//! By default, BDK enables two internal features, `key-value-db` and `electrum`.
179//!
180//! If you are new to BDK we recommended that you use the default features which will enable
181//! basic descriptor wallet functionality. More advanced users can disable the `default` features
182//! (`--no-default-features`) and build the BDK library with only the features you need.
183
184//! Below is a list of the available feature flags and the additional functionality they provide.
185//!
186//! * `all-keys`: all features for working with bitcoin keys
187//! * `async-interface`: async functions in bdk traits
188//! * `keys-bip39`: [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonic codes for generating deterministic keys
189//!
190//! # Internal features
191//!
192//! These features do not expose any new API, but influence internal implementation aspects of
193//! BDK.
194//!
195//! * `compact_filters`: [`compact_filters`](crate::blockchain::compact_filters) client protocol for interacting with the bitcoin P2P network
196//! * `electrum`: [`electrum`](crate::blockchain::electrum) client protocol for interacting with electrum servers
197//! * `esplora`: [`esplora`](crate::blockchain::esplora) client protocol for interacting with blockstream [electrs](https://github.com/Blockstream/electrs) servers
198//! * `key-value-db`: key value [`database`](crate::database) based on [`sled`](crate::sled) for caching blockchain data
199
200pub extern crate bitcoin;
201extern crate log;
202pub extern crate miniscript;
203extern crate serde;
204#[macro_use]
205extern crate serde_json;
206#[cfg(feature = "hardware-signer")]
207pub extern crate hwi;
208
209#[cfg(all(feature = "reqwest", feature = "ureq"))]
210compile_error!("Features reqwest and ureq are mutually exclusive and cannot be enabled together");
211
212#[cfg(all(feature = "async-interface", feature = "electrum"))]
213compile_error!(
214 "Features async-interface and electrum are mutually exclusive and cannot be enabled together"
215);
216
217#[cfg(all(feature = "async-interface", feature = "ureq"))]
218compile_error!(
219 "Features async-interface and ureq are mutually exclusive and cannot be enabled together"
220);
221
222#[cfg(all(feature = "async-interface", feature = "compact_filters"))]
223compile_error!(
224 "Features async-interface and compact_filters are mutually exclusive and cannot be enabled together"
225);
226
227#[cfg(feature = "keys-bip39")]
228extern crate bip39;
229
230#[cfg(feature = "async-interface")]
231#[macro_use]
232extern crate async_trait;
233#[macro_use]
234extern crate bdk_macros;
235
236#[cfg(feature = "rpc")]
237pub extern crate bitcoincore_rpc;
238
239#[cfg(feature = "electrum")]
240pub extern crate electrum_client;
241
242#[cfg(feature = "esplora")]
243pub extern crate esplora_client;
244
245#[cfg(feature = "key-value-db")]
246pub extern crate sled;
247
248#[cfg(feature = "sqlite")]
249pub extern crate rusqlite;
250
251// We should consider putting this under a feature flag but we need the macro in doctests so we need
252// to wait until https://github.com/rust-lang/rust/issues/67295 is fixed.
253//
254// Stuff in here is too rough to document atm
255#[doc(hidden)]
256#[macro_use]
257pub mod testutils;
258
259#[cfg(test)]
260extern crate assert_matches;
261
262#[allow(unused_imports)]
263#[macro_use]
264pub(crate) mod error;
265pub mod blockchain;
266pub mod database;
267pub mod descriptor;
268#[cfg(feature = "test-md-docs")]
269mod doctest;
270pub mod keys;
271pub mod psbt;
272pub(crate) mod types;
273pub mod wallet;
274
275pub use descriptor::template;
276pub use descriptor::HdKeyPaths;
277pub use error::Error;
278pub use types::*;
279pub use wallet::signer;
280pub use wallet::signer::SignOptions;
281pub use wallet::tx_builder::TxBuilder;
282pub use wallet::SyncOptions;
283pub use wallet::Wallet;
284
285/// Get the version of BDK at runtime
286pub fn version() -> &'static str {
287 env!("CARGO_PKG_VERSION", "unknown")
288}