|
1 | | -// use std::{io::Write, str::FromStr}; |
2 | | - |
3 | | -// use bdk::{ |
4 | | -// bitcoin::{Address, Network}, |
5 | | -// SignOptions, Wallet, |
6 | | -// }; |
7 | | -// use bdk_electrum::{ |
8 | | -// electrum_client::{self, ElectrumApi}, |
9 | | -// ElectrumExt, |
10 | | -// }; |
11 | | -// use bdk_file_store::KeychainStore; |
12 | | - |
13 | | -// const SEND_AMOUNT: u64 = 5000; |
14 | | -// const STOP_GAP: usize = 50; |
15 | | -// const BATCH_SIZE: usize = 5; |
| 1 | +const DB_MAGIC: &str = "bdk_wallet_electrum_example"; |
| 2 | +const SEND_AMOUNT: u64 = 5000; |
| 3 | +const STOP_GAP: usize = 50; |
| 4 | +const BATCH_SIZE: usize = 5; |
| 5 | + |
| 6 | +use std::io::Write; |
| 7 | +use std::str::FromStr; |
| 8 | + |
| 9 | +use bdk::bitcoin::Address; |
| 10 | +use bdk::SignOptions; |
| 11 | +use bdk::{bitcoin::Network, Wallet}; |
| 12 | +use bdk_electrum::electrum_client::{self, ElectrumApi}; |
| 13 | +use bdk_electrum::v2::ElectrumExt; |
| 14 | +use bdk_file_store::Store; |
16 | 15 |
|
17 | 16 | fn main() -> Result<(), Box<dyn std::error::Error>> { |
18 | | - todo!("update this example!"); |
19 | | - // println!("Hello, world!"); |
20 | | - |
21 | | - // let db_path = std::env::temp_dir().join("bdk-electrum-example"); |
22 | | - // let db = KeychainStore::new_from_path(db_path)?; |
23 | | - // let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)"; |
24 | | - // let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/1/*)"; |
25 | | - |
26 | | - // let mut wallet = Wallet::new( |
27 | | - // external_descriptor, |
28 | | - // Some(internal_descriptor), |
29 | | - // db, |
30 | | - // Network::Testnet, |
31 | | - // )?; |
32 | | - |
33 | | - // let address = wallet.get_address(bdk::wallet::AddressIndex::New); |
34 | | - // println!("Generated Address: {}", address); |
35 | | - |
36 | | - // let balance = wallet.get_balance(); |
37 | | - // println!("Wallet balance before syncing: {} sats", balance.total()); |
38 | | - |
39 | | - // print!("Syncing..."); |
40 | | - // // Scanning the chain... |
41 | | - // let electrum_url = "ssl://electrum.blockstream.info:60002"; |
42 | | - // let client = electrum_client::Client::new(electrum_url)?; |
43 | | - // let local_chain = wallet.checkpoints(); |
44 | | - // let spks = wallet |
45 | | - // .spks_of_all_keychains() |
46 | | - // .into_iter() |
47 | | - // .map(|(k, spks)| { |
48 | | - // let mut first = true; |
49 | | - // ( |
50 | | - // k, |
51 | | - // spks.inspect(move |(spk_i, _)| { |
52 | | - // if first { |
53 | | - // first = false; |
54 | | - // print!("\nScanning keychain [{:?}]:", k); |
55 | | - // } |
56 | | - // print!(" {}", spk_i); |
57 | | - // let _ = std::io::stdout().flush(); |
58 | | - // }), |
59 | | - // ) |
60 | | - // }) |
61 | | - // .collect(); |
62 | | - // let electrum_update = client |
63 | | - // .scan( |
64 | | - // local_chain, |
65 | | - // spks, |
66 | | - // core::iter::empty(), |
67 | | - // core::iter::empty(), |
68 | | - // STOP_GAP, |
69 | | - // BATCH_SIZE, |
70 | | - // )? |
71 | | - // .into_confirmation_time_update(&client)?; |
72 | | - // println!(); |
73 | | - // let new_txs = client.batch_transaction_get(electrum_update.missing_full_txs(&wallet))?; |
74 | | - // let update = electrum_update.into_keychain_scan(new_txs, &wallet)?; |
75 | | - // wallet.apply_update(update)?; |
76 | | - // wallet.commit()?; |
77 | | - |
78 | | - // let balance = wallet.get_balance(); |
79 | | - // println!("Wallet balance after syncing: {} sats", balance.total()); |
80 | | - |
81 | | - // if balance.total() < SEND_AMOUNT { |
82 | | - // println!( |
83 | | - // "Please send at least {} sats to the receiving address", |
84 | | - // SEND_AMOUNT |
85 | | - // ); |
86 | | - // std::process::exit(0); |
87 | | - // } |
88 | | - |
89 | | - // let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?; |
90 | | - |
91 | | - // let mut tx_builder = wallet.build_tx(); |
92 | | - // tx_builder |
93 | | - // .add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT) |
94 | | - // .enable_rbf(); |
95 | | - |
96 | | - // let (mut psbt, _) = tx_builder.finish()?; |
97 | | - // let finalized = wallet.sign(&mut psbt, SignOptions::default())?; |
98 | | - // assert!(finalized); |
99 | | - |
100 | | - // let tx = psbt.extract_tx(); |
101 | | - // client.transaction_broadcast(&tx)?; |
102 | | - // println!("Tx broadcasted! Txid: {}", tx.txid()); |
103 | | - |
104 | | - // Ok(()) |
| 17 | + let db_path = std::env::temp_dir().join("bdk-electrum-example"); |
| 18 | + let db = Store::<bdk::wallet::ChangeSet>::new_from_path(DB_MAGIC.as_bytes(), db_path)?; |
| 19 | + let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)"; |
| 20 | + let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/1/*)"; |
| 21 | + |
| 22 | + let mut wallet = Wallet::new( |
| 23 | + external_descriptor, |
| 24 | + Some(internal_descriptor), |
| 25 | + db, |
| 26 | + Network::Testnet, |
| 27 | + )?; |
| 28 | + |
| 29 | + let address = wallet.get_address(bdk::wallet::AddressIndex::New); |
| 30 | + println!("Generated Address: {}", address); |
| 31 | + |
| 32 | + let balance = wallet.get_balance(); |
| 33 | + println!("Wallet balance before syncing: {} sats", balance.total()); |
| 34 | + |
| 35 | + print!("Syncing..."); |
| 36 | + let client = electrum_client::Client::new("ssl://electrum.blockstream.info:60002")?; |
| 37 | + |
| 38 | + let local_chain = wallet.checkpoints(); |
| 39 | + let keychain_spks = wallet |
| 40 | + .spks_of_all_keychains() |
| 41 | + .into_iter() |
| 42 | + .map(|(k, k_spks)| { |
| 43 | + let mut once = Some(()); |
| 44 | + let mut stdout = std::io::stdout(); |
| 45 | + let k_spks = k_spks |
| 46 | + .inspect(move |(spk_i, _)| match once.take() { |
| 47 | + Some(_) => print!("\nScanning keychain [{:?}]", k), |
| 48 | + None => print!(" {:<3}", spk_i), |
| 49 | + }) |
| 50 | + .inspect(move |_| stdout.flush().expect("must flush")); |
| 51 | + (k, k_spks) |
| 52 | + }) |
| 53 | + .collect(); |
| 54 | + |
| 55 | + let electrum_update = |
| 56 | + client.scan(local_chain, keychain_spks, None, None, STOP_GAP, BATCH_SIZE)?; |
| 57 | + |
| 58 | + println!(); |
| 59 | + |
| 60 | + let missing = electrum_update.missing_full_txs(wallet.as_ref()); |
| 61 | + let update = electrum_update.finalize_as_confirmation_time(&client, None, missing)?; |
| 62 | + |
| 63 | + wallet.apply_update(update)?; |
| 64 | + wallet.commit()?; |
| 65 | + |
| 66 | + let balance = wallet.get_balance(); |
| 67 | + println!("Wallet balance after syncing: {} sats", balance.total()); |
| 68 | + |
| 69 | + if balance.total() < SEND_AMOUNT { |
| 70 | + println!( |
| 71 | + "Please send at least {} sats to the receiving address", |
| 72 | + SEND_AMOUNT |
| 73 | + ); |
| 74 | + std::process::exit(0); |
| 75 | + } |
| 76 | + |
| 77 | + let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?; |
| 78 | + |
| 79 | + let mut tx_builder = wallet.build_tx(); |
| 80 | + tx_builder |
| 81 | + .add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT) |
| 82 | + .enable_rbf(); |
| 83 | + |
| 84 | + let (mut psbt, _) = tx_builder.finish()?; |
| 85 | + let finalized = wallet.sign(&mut psbt, SignOptions::default())?; |
| 86 | + assert!(finalized); |
| 87 | + |
| 88 | + let tx = psbt.extract_tx(); |
| 89 | + client.transaction_broadcast(&tx)?; |
| 90 | + println!("Tx broadcasted! Txid: {}", tx.txid()); |
| 91 | + |
| 92 | + Ok(()) |
105 | 93 | } |
0 commit comments