• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bitcoindevkit / bdk / 5834188079

pending completion
5834188079

Pull #1071

github

web-flow
Merge 68b42331c into 0ba6bbe11
Pull Request #1071: Update rust bitcoin (BDK 0.28)

563 of 563 new or added lines in 28 files covered. (100.0%)

14625 of 18342 relevant lines covered (79.74%)

9267.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/examples/rpcwallet.rs
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::Amount;
11
use bdk::bitcoin::Network;
12
use bdk::bitcoincore_rpc::RpcApi;
13

14
use bdk::blockchain::rpc::{Auth, RpcBlockchain, RpcConfig};
15
use bdk::blockchain::ConfigurableBlockchain;
16

17
use bdk::keys::bip39::{Language, Mnemonic, WordCount};
18
use bdk::keys::{DerivableKey, GeneratableKey, GeneratedKey};
19

20
use bdk::miniscript::miniscript::Segwitv0;
21

22
use bdk::sled;
23
use bdk::template::Bip84;
24
use bdk::wallet::{signer::SignOptions, wallet_name_from_descriptor, AddressIndex, SyncOptions};
25
use bdk::KeychainKind;
26
use bdk::Wallet;
27

28
use bdk::blockchain::Blockchain;
29

30
use electrsd;
31

32
use std::error::Error;
33
use std::path::PathBuf;
34
use std::str::FromStr;
35

36
/// This example demonstrates a typical way to create a wallet and work with bdk.
37
///
38
/// This example bdk wallet is connected to a bitcoin core rpc regtest node,
39
/// and will attempt to receive, create and broadcast transactions.
40
///
41
/// To start a bitcoind regtest node programmatically, this example uses
42
/// `electrsd` library, which is also a bdk dev-dependency.
43
///
44
/// But you can start your own bitcoind backend, and the rest of the example should work fine.
45

46
fn main() -> Result<(), Box<dyn Error>> {
×
47
    // -- Setting up background bitcoind process
×
48

×
49
    println!(">> Setting up bitcoind");
×
50

×
51
    // Start the bitcoind process
×
52
    let bitcoind_conf = electrsd::bitcoind::Conf::default();
×
53

×
54
    // electrsd will automatically download the bitcoin core binaries
×
55
    let bitcoind_exe =
×
56
        electrsd::bitcoind::downloaded_exe_path().expect("We should always have downloaded path");
×
57

×
58
    // Launch bitcoind and gather authentication access
×
59
    let bitcoind = electrsd::bitcoind::BitcoinD::with_conf(bitcoind_exe, &bitcoind_conf).unwrap();
×
60
    let bitcoind_auth = Auth::Cookie {
×
61
        file: bitcoind.params.cookie_file.clone(),
×
62
    };
×
63

64
    // Get a new core address
65
    let core_address = bitcoind
×
66
        .client
×
67
        .get_new_address(None, None)?
×
68
        .require_network(Network::Regtest)?;
×
69

70
    // Generate 101 blocks and use the above address as coinbase
71
    bitcoind.client.generate_to_address(101, &core_address)?;
×
72

73
    println!(">> bitcoind setup complete");
×
74
    println!(
×
75
        "Available coins in Core wallet : {}",
×
76
        bitcoind.client.get_balance(None, None)?
×
77
    );
78

79
    // -- Setting up the Wallet
80

81
    println!("\n>> Setting up BDK wallet");
×
82

83
    // Get a random private key
84
    let xprv = generate_random_ext_privkey()?;
×
85

86
    // Use the derived descriptors from the privatekey to
87
    // create unique wallet name.
88
    // This is a special utility function exposed via `bdk::wallet_name_from_descriptor()`
89
    let wallet_name = wallet_name_from_descriptor(
×
90
        Bip84(xprv.clone(), KeychainKind::External),
×
91
        Some(Bip84(xprv.clone(), KeychainKind::Internal)),
×
92
        Network::Regtest,
×
93
        &Secp256k1::new(),
×
94
    )?;
×
95

96
    // Create a database (using default sled type) to store wallet data
97
    let mut datadir = PathBuf::from_str("/tmp/")?;
×
98
    datadir.push(".bdk-example");
×
99
    let database = sled::open(datadir)?;
×
100
    let database = database.open_tree(wallet_name.clone())?;
×
101

102
    // Create a RPC configuration of the running bitcoind backend we created in last step
103
    // Note: If you are using custom regtest node, use the appropriate url and auth
104
    let rpc_config = RpcConfig {
×
105
        url: bitcoind.params.rpc_socket.to_string(),
×
106
        auth: bitcoind_auth,
×
107
        network: Network::Regtest,
×
108
        wallet_name,
×
109
        sync_params: None,
×
110
    };
×
111

112
    // Use the above configuration to create a RPC blockchain backend
113
    let blockchain = RpcBlockchain::from_config(&rpc_config)?;
×
114

115
    // Combine Database + Descriptor to create the final wallet
116
    let wallet = Wallet::new(
×
117
        Bip84(xprv.clone(), KeychainKind::External),
×
118
        Some(Bip84(xprv.clone(), KeychainKind::Internal)),
×
119
        Network::Regtest,
×
120
        database,
×
121
    )?;
×
122

123
    // The `wallet` and the `blockchain` are independent structs.
124
    // The wallet will be used to do all wallet level actions
125
    // The blockchain can be used to do all blockchain level actions.
126
    // For certain actions (like sync) the wallet will ask for a blockchain.
127

128
    // Sync the wallet
129
    // The first sync is important as this will instantiate the
130
    // wallet files.
131
    wallet.sync(&blockchain, SyncOptions::default())?;
×
132

133
    println!(">> BDK wallet setup complete.");
×
134
    println!(
×
135
        "Available initial coins in BDK wallet : {} sats",
×
136
        wallet.get_balance()?
×
137
    );
138

139
    // -- Wallet transaction demonstration
140

141
    println!("\n>> Sending coins: Core --> BDK, 10 BTC");
×
142
    // Get a new address to receive coins
143
    let bdk_new_addr = wallet.get_address(AddressIndex::New)?.address;
×
144

145
    // Send 10 BTC from core wallet to bdk wallet
146
    bitcoind.client.send_to_address(
×
147
        &bdk_new_addr,
×
148
        Amount::from_btc(10.0)?,
×
149
        None,
×
150
        None,
×
151
        None,
×
152
        None,
×
153
        None,
×
154
        None,
×
155
    )?;
×
156

157
    // Confirm transaction by generating 1 block
158
    bitcoind.client.generate_to_address(1, &core_address)?;
×
159

160
    // Sync the BDK wallet
161
    // This time the sync will fetch the new transaction and update it in
162
    // wallet database
163
    wallet.sync(&blockchain, SyncOptions::default())?;
×
164

165
    println!(">> Received coins in BDK wallet");
×
166
    println!(
×
167
        "Available balance in BDK wallet: {} sats",
×
168
        wallet.get_balance()?
×
169
    );
170

171
    println!("\n>> Sending coins: BDK --> Core, 5 BTC");
×
172
    // Attempt to send back 5.0 BTC to core address by creating a transaction
×
173
    //
×
174
    // Transactions are created using a `TxBuilder`.
×
175
    // This helps us to systematically build a transaction with all
×
176
    // required customization.
×
177
    // A full list of APIs offered by `TxBuilder` can be found at
×
178
    // https://docs.rs/bdk/latest/bdk/wallet/tx_builder/struct.TxBuilder.html
×
179
    let mut tx_builder = wallet.build_tx();
×
180

×
181
    // For a regular transaction, just set the recipient and amount
×
182
    tx_builder.set_recipients(vec![(core_address.script_pubkey(), 500000000)]);
×
183

184
    // Finalize the transaction and extract the PSBT
185
    let (mut psbt, _) = tx_builder.finish()?;
×
186

187
    // Set signing option
188
    let signopt = SignOptions {
×
189
        assume_height: None,
×
190
        ..Default::default()
×
191
    };
×
192

×
193
    // Sign the psbt
×
194
    wallet.sign(&mut psbt, signopt)?;
×
195

196
    // Extract the signed transaction
197
    let tx = psbt.extract_tx();
×
198

×
199
    // Broadcast the transaction
×
200
    blockchain.broadcast(&tx)?;
×
201

202
    // Confirm transaction by generating some blocks
203
    bitcoind.client.generate_to_address(1, &core_address)?;
×
204

205
    // Sync the BDK wallet
206
    wallet.sync(&blockchain, SyncOptions::default())?;
×
207

208
    println!(">> Coins sent to Core wallet");
×
209
    println!(
×
210
        "Remaining BDK wallet balance: {} sats",
×
211
        wallet.get_balance()?
×
212
    );
213
    println!("\nCongrats!! you made your first test transaction with bdk and bitcoin core.");
×
214

×
215
    Ok(())
×
216
}
×
217

218
// Helper function demonstrating privatekey extraction using bip39 mnemonic
219
// The mnemonic can be shown to user to safekeeping and the same wallet
220
// private descriptors can be recreated from it.
221
fn generate_random_ext_privkey() -> Result<impl DerivableKey<Segwitv0> + Clone, Box<dyn Error>> {
×
222
    // a Bip39 passphrase can be set optionally
×
223
    let password = Some("random password".to_string());
×
224

225
    // Generate a random mnemonic, and use that to create a "DerivableKey"
226
    let mnemonic: GeneratedKey<_, _> = Mnemonic::generate((WordCount::Words12, Language::English))
×
227
        .map_err(|e| e.expect("Unknown Error"))?;
×
228

229
    // `Ok(mnemonic)` would also work if there's no passphrase and it would
230
    // yield the same result as this construct with `password` = `None`.
231
    Ok((mnemonic, password))
×
232
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc