Skip to content

Commit 8cd0550

Browse files
committed
Merge branch 'master' into feature/more-getters
2 parents 1b90148 + 9c0141b commit 8cd0550

File tree

6 files changed

+290
-27
lines changed

6 files changed

+290
-27
lines changed

.github/workflows/cont_integration.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
- async-interface
2929
- use-esplora-reqwest
3030
- sqlite
31+
- sqlite-bundled
3132
steps:
3233
- name: checkout
3334
uses: actions/checkout@v2
@@ -114,7 +115,7 @@ jobs:
114115
override: true
115116
- name: Test
116117
run: cargo test --no-default-features --features ${{ matrix.blockchain.features }} ${{ matrix.blockchain.name }}::bdk_blockchain_tests
117-
118+
118119
check-wasm:
119120
name: Check WASM
120121
runs-on: ubuntu-20.04

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9-
9+
- Add `sqlite-bundled` feature for deployments that need a bundled version of sqlite, ie. for mobile platforms.
1010
- Added `Wallet::get_signers()`, `Wallet::descriptor_checksum()` and `Wallet::get_address_validators()`, exposed the `AsDerived` trait.
1111

1212
## [v0.17.0] - [v0.16.1]
@@ -440,4 +440,4 @@ final transaction is created by calling `finish` on the builder.
440440
[v0.16.0]: https://github.com/bitcoindevkit/bdk/compare/v0.15.0...v0.16.0
441441
[v0.16.1]: https://github.com/bitcoindevkit/bdk/compare/v0.16.0...v0.16.1
442442
[v0.17.0]: https://github.com/bitcoindevkit/bdk/compare/v0.16.1...v0.17.0
443-
[unreleased]: https://github.com/bitcoindevkit/bdk/compare/v0.17.0...HEAD
443+
[unreleased]: https://github.com/bitcoindevkit/bdk/compare/v0.17.0...HEAD

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ compiler = ["miniscript/compiler"]
5555
verify = ["bitcoinconsensus"]
5656
default = ["key-value-db", "electrum"]
5757
sqlite = ["rusqlite", "ahash"]
58+
sqlite-bundled = ["sqlite", "rusqlite/bundled"]
5859
compact_filters = ["rocksdb", "socks", "lazy_static", "cc"]
5960
key-value-db = ["sled"]
6061
all-keys = ["keys-bip39"]
@@ -109,6 +110,11 @@ name = "miniscriptc"
109110
path = "examples/compiler.rs"
110111
required-features = ["compiler"]
111112

113+
[[example]]
114+
name = "rpcwallet"
115+
path = "examples/rpcwallet.rs"
116+
required-features = ["keys-bip39", "key-value-db", "rpc"]
117+
112118
[workspace]
113119
members = ["macros"]
114120
[package.metadata.docs.rs]

examples/rpcwallet.rs

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
2+
//
3+
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
4+
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
6+
// You may not use this file except in accordance with one or both of these
7+
// licenses.
8+
9+
use bdk::bitcoin::secp256k1::Secp256k1;
10+
use bdk::bitcoin::util::bip32::ExtendedPrivKey;
11+
use bdk::bitcoin::Amount;
12+
use bdk::bitcoin::Network;
13+
use bdk::bitcoincore_rpc::RpcApi;
14+
15+
use bdk::blockchain::rpc::{Auth, RpcBlockchain, RpcConfig};
16+
use bdk::blockchain::ConfigurableBlockchain;
17+
18+
use bdk::keys::bip39::{Language, Mnemonic, WordCount};
19+
use bdk::keys::{DerivableKey, ExtendedKey, GeneratableKey, GeneratedKey};
20+
21+
use bdk::miniscript::miniscript::Segwitv0;
22+
23+
use bdk::sled;
24+
use bdk::template::Bip84;
25+
use bdk::wallet::{signer::SignOptions, wallet_name_from_descriptor, AddressIndex, SyncOptions};
26+
use bdk::KeychainKind;
27+
use bdk::Wallet;
28+
29+
use bdk::blockchain::Blockchain;
30+
31+
use electrsd;
32+
33+
use std::error::Error;
34+
use std::path::PathBuf;
35+
use std::str::FromStr;
36+
37+
/// This example demonstrates a typical way to create a wallet and work with bdk.
38+
///
39+
/// This example bdk wallet is connected to a bitcoin core rpc regtest node,
40+
/// and will attempt to receive, create and broadcast transactions.
41+
///
42+
/// To start a bitcoind regtest node programmatically, this example uses
43+
/// `electrsd` library, which is also a bdk dev-dependency.
44+
///
45+
/// But you can start your own bitcoind backend, and the rest of the example should work fine.
46+
47+
fn main() -> Result<(), Box<dyn Error>> {
48+
// -- Setting up background bitcoind process
49+
50+
println!(">> Setting up bitcoind");
51+
52+
// Start the bitcoind process
53+
let bitcoind_conf = electrsd::bitcoind::Conf::default();
54+
55+
// electrsd will automatically download the bitcoin core binaries
56+
let bitcoind_exe =
57+
electrsd::bitcoind::downloaded_exe_path().expect("We should always have downloaded path");
58+
59+
// Launch bitcoind and gather authentication access
60+
let bitcoind = electrsd::bitcoind::BitcoinD::with_conf(bitcoind_exe, &bitcoind_conf).unwrap();
61+
let bitcoind_auth = Auth::Cookie {
62+
file: bitcoind.params.cookie_file.clone(),
63+
};
64+
65+
// Get a new core address
66+
let core_address = bitcoind.client.get_new_address(None, None)?;
67+
68+
// Generate 101 blocks and use the above address as coinbase
69+
bitcoind.client.generate_to_address(101, &core_address)?;
70+
71+
println!(">> bitcoind setup complete");
72+
println!(
73+
"Available coins in Core wallet : {}",
74+
bitcoind.client.get_balance(None, None)?
75+
);
76+
77+
// -- Setting up the Wallet
78+
79+
println!("\n>> Setting up BDK wallet");
80+
81+
// Get a random private key
82+
let xprv = generate_random_ext_privkey()?;
83+
84+
// Use the derived descriptors from the privatekey to
85+
// create unique wallet name.
86+
// This is a special utility function exposed via `bdk::wallet_name_from_descriptor()`
87+
let wallet_name = wallet_name_from_descriptor(
88+
Bip84(xprv, KeychainKind::External),
89+
Some(Bip84(xprv, KeychainKind::Internal)),
90+
Network::Regtest,
91+
&Secp256k1::new(),
92+
)?;
93+
94+
// Create a database (using default sled type) to store wallet data
95+
let mut datadir = PathBuf::from_str("/tmp/")?;
96+
datadir.push(".bdk-example");
97+
let database = sled::open(datadir)?;
98+
let database = database.open_tree(wallet_name.clone())?;
99+
100+
// Create a RPC configuration of the running bitcoind backend we created in last step
101+
// Note: If you are using custom regtest node, use the appropriate url and auth
102+
let rpc_config = RpcConfig {
103+
url: bitcoind.params.rpc_socket.to_string(),
104+
auth: bitcoind_auth,
105+
network: Network::Regtest,
106+
wallet_name,
107+
skip_blocks: None,
108+
};
109+
110+
// Use the above configuration to create a RPC blockchain backend
111+
let blockchain = RpcBlockchain::from_config(&rpc_config)?;
112+
113+
// Combine Database + Descriptor to create the final wallet
114+
let wallet = Wallet::new(
115+
Bip84(xprv, KeychainKind::External),
116+
Some(Bip84(xprv, KeychainKind::Internal)),
117+
Network::Regtest,
118+
database,
119+
)?;
120+
121+
// The `wallet` and the `blockchain` are independent structs.
122+
// The wallet will be used to do all wallet level actions
123+
// The blockchain can be used to do all blockchain level actions.
124+
// For certain actions (like sync) the wallet will ask for a blockchain.
125+
126+
// Sync the wallet
127+
// The first sync is important as this will instantiate the
128+
// wallet files.
129+
wallet.sync(&blockchain, SyncOptions::default())?;
130+
131+
println!(">> BDK wallet setup complete.");
132+
println!(
133+
"Available initial coins in BDK wallet : {} sats",
134+
wallet.get_balance()?
135+
);
136+
137+
// -- Wallet transaction demonstration
138+
139+
println!("\n>> Sending coins: Core --> BDK, 10 BTC");
140+
// Get a new address to receive coins
141+
let bdk_new_addr = wallet.get_address(AddressIndex::New)?.address;
142+
143+
// Send 10 BTC from core wallet to bdk wallet
144+
bitcoind.client.send_to_address(
145+
&bdk_new_addr,
146+
Amount::from_btc(10.0)?,
147+
None,
148+
None,
149+
None,
150+
None,
151+
None,
152+
None,
153+
)?;
154+
155+
// Confirm transaction by generating 1 block
156+
bitcoind.client.generate_to_address(1, &core_address)?;
157+
158+
// Sync the BDK wallet
159+
// This time the sync will fetch the new transaction and update it in
160+
// wallet database
161+
wallet.sync(&blockchain, SyncOptions::default())?;
162+
163+
println!(">> Received coins in BDK wallet");
164+
println!(
165+
"Available balance in BDK wallet: {} sats",
166+
wallet.get_balance()?
167+
);
168+
169+
println!("\n>> Sending coins: BDK --> Core, 5 BTC");
170+
// Attempt to send back 5.0 BTC to core address by creating a transaction
171+
//
172+
// Transactions are created using a `TxBuilder`.
173+
// This helps us to systematically build a transaction with all
174+
// required customization.
175+
// A full list of APIs offered by `TxBuilder` can be found at
176+
// https://docs.rs/bdk/latest/bdk/wallet/tx_builder/struct.TxBuilder.html
177+
let mut tx_builder = wallet.build_tx();
178+
179+
// For a regular transaction, just set the recipient and amount
180+
tx_builder.set_recipients(vec![(core_address.script_pubkey(), 500000000)]);
181+
182+
// Finalize the transaction and extract the PSBT
183+
let (mut psbt, _) = tx_builder.finish()?;
184+
185+
// Set signing option
186+
let signopt = SignOptions {
187+
assume_height: None,
188+
..Default::default()
189+
};
190+
191+
// Sign the psbt
192+
wallet.sign(&mut psbt, signopt)?;
193+
194+
// Extract the signed transaction
195+
let tx = psbt.extract_tx();
196+
197+
// Broadcast the transaction
198+
blockchain.broadcast(&tx)?;
199+
200+
// Confirm transaction by generating some blocks
201+
bitcoind.client.generate_to_address(1, &core_address)?;
202+
203+
// Sync the BDK wallet
204+
wallet.sync(&blockchain, SyncOptions::default())?;
205+
206+
println!(">> Coins sent to Core wallet");
207+
println!(
208+
"Remaining BDK wallet balance: {} sats",
209+
wallet.get_balance()?
210+
);
211+
println!("\nCongrats!! you made your first test transaction with bdk and bitcoin core.");
212+
213+
Ok(())
214+
}
215+
216+
// Helper function demonstrating privatekey extraction using bip39 mnemonic
217+
// The mnemonic can be shown to user to safekeeping and the same wallet
218+
// private descriptors can be recreated from it.
219+
fn generate_random_ext_privkey() -> Result<ExtendedPrivKey, Box<dyn Error>> {
220+
// a Bip39 passphrase can be set optionally
221+
let password = Some("random password".to_string());
222+
223+
// Generate a random mnemonic, and use that to create an Extended PrivateKey
224+
let mnemonic: GeneratedKey<_, Segwitv0> =
225+
Mnemonic::generate((WordCount::Words12, Language::English))
226+
.map_err(|e| e.expect("Unknown Error"))?;
227+
let mnemonic = mnemonic.into_key();
228+
let xkey: ExtendedKey = (mnemonic, password).into_extended_key()?;
229+
let xprv = xkey
230+
.into_xprv(Network::Regtest)
231+
.expect("Expected Private Key");
232+
Ok(xprv)
233+
}

src/lib.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,13 @@
4646
//! ```toml
4747
//! bdk = "0.17.0"
4848
//! ```
49+
//!
50+
//! # Examples
4951
#![cfg_attr(
5052
feature = "electrum",
5153
doc = r##"
5254
## Sync the balance of a descriptor
5355
54-
### Example
5556
```no_run
5657
use bdk::{Wallet, SyncOptions};
5758
use bdk::database::MemoryDatabase;
@@ -80,7 +81,6 @@ fn main() -> Result<(), bdk::Error> {
8081
//!
8182
//! ## Generate a few addresses
8283
//!
83-
//! ### Example
8484
//! ```
8585
//! use bdk::{Wallet};
8686
//! use bdk::database::MemoryDatabase;
@@ -106,7 +106,6 @@ fn main() -> Result<(), bdk::Error> {
106106
doc = r##"
107107
## Create a transaction
108108
109-
### Example
110109
```no_run
111110
use bdk::{FeeRate, Wallet, SyncOptions};
112111
use bdk::database::MemoryDatabase;
@@ -150,7 +149,6 @@ fn main() -> Result<(), bdk::Error> {
150149
//!
151150
//! ## Sign a transaction
152151
//!
153-
//! ### Example
154152
//! ```no_run
155153
//! use std::str::FromStr;
156154
//!
@@ -192,7 +190,7 @@ fn main() -> Result<(), bdk::Error> {
192190
//! * `async-interface`: async functions in bdk traits
193191
//! * `keys-bip39`: [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonic codes for generating deterministic keys
194192
//!
195-
//! ## Internal features
193+
//! # Internal features
196194
//!
197195
//! These features do not expose any new API, but influence internal implementation aspects of
198196
//! BDK.

0 commit comments

Comments
 (0)