// Bitcoin Dev Kit // Written in 2020 by Alekos Filini // // Copyright (c) 2020-2021 Bitcoin Dev Kit Developers // // This file is licensed under the Apache License, Version 2.0 or the MIT license // , at your option. // You may not use this file except in accordance with one or both of these // licenses. // rustdoc will warn if there are missing docs #![warn(missing_docs)] // only enables the `doc_cfg` feature when // the `docsrs` configuration attribute is defined #![cfg_attr(docsrs, feature(doc_cfg))] //! 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](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 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`](sled)) to cache //! blockchain data and an [electrum](https://docs.rs/electrum-client/) blockchain client to //! interact with the bitcoin P2P network. //! //! ```toml //! bdk = "0.11.0" //! ``` #![cfg_attr( feature = "electrum", doc = r##" ## Sync the balance of a descriptor ### Example ```no_run 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(()) //! } //! ``` #![cfg_attr( feature = "electrum", doc = r##" ## Create a transaction ### Example ```no_run 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 //! ```no_run //! 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](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section) //! 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](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) 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`](crate::blockchain::compact_filters) client protocol for interacting with the bitcoin P2P network //! * `electrum`: [`electrum`](crate::blockchain::electrum) client protocol for interacting with electrum servers //! * `esplora`: [`esplora`](crate::blockchain::esplora) client protocol for interacting with blockstream [electrs](https://github.com/Blockstream/electrs) servers //! * `key-value-db`: key value [`database`](crate::database) based on [`sled`](crate::sled) for caching blockchain data pub extern crate bitcoin; extern crate log; pub extern crate miniscript; extern crate serde; #[macro_use] extern crate serde_json; #[cfg(all(feature = "reqwest", feature = "ureq"))] compile_error!("Features reqwest and ureq are mutually exclusive and cannot be enabled together"); #[cfg(all(feature = "async-interface", feature = "electrum"))] compile_error!( "Features async-interface and electrum are mutually exclusive and cannot be enabled together" ); #[cfg(all(feature = "async-interface", feature = "ureq"))] compile_error!( "Features async-interface and ureq are mutually exclusive and cannot be enabled together" ); #[cfg(all(feature = "async-interface", feature = "compact_filters"))] compile_error!( "Features async-interface and compact_filters are mutually exclusive and cannot be enabled together" ); #[cfg(feature = "keys-bip39")] extern crate bip39; #[cfg(any(target_arch = "wasm32", feature = "async-interface"))] #[macro_use] extern crate async_trait; #[macro_use] extern crate bdk_macros; #[cfg(feature = "compact_filters")] extern crate lazy_static; #[cfg(feature = "rpc")] pub extern crate core_rpc; #[cfg(feature = "electrum")] pub extern crate electrum_client; #[cfg(feature = "key-value-db")] pub extern crate sled; #[allow(unused_imports)] #[macro_use] pub(crate) mod error; pub mod blockchain; pub mod database; pub mod descriptor; #[cfg(feature = "test-md-docs")] mod doctest; pub mod keys; pub(crate) mod psbt; pub(crate) mod types; pub mod wallet; pub use descriptor::template; pub use descriptor::HdKeyPaths; pub use error::Error; pub use types::*; pub use wallet::address_validator; pub use wallet::signer; pub use wallet::signer::SignOptions; pub use wallet::tx_builder::TxBuilder; pub use wallet::Wallet; /// Get the version of BDK at runtime pub fn version() -> &'static str { env!("CARGO_PKG_VERSION", "unknown") } // We should consider putting this under a feature flag but we need the macro in doctets so we need // to wait until https://github.com/rust-lang/rust/issues/67295 is fixed. // // Stuff in here is too rough to document atm #[doc(hidden)] pub mod testutils;