From 2952341e5245acef14623b482095526d55b64bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Thu, 18 May 2023 10:14:47 +0800 Subject: [PATCH] Update the `wallet_electrum` example --- example-crates/wallet_electrum/src/main.rs | 164 ++++++++++----------- 1 file changed, 76 insertions(+), 88 deletions(-) diff --git a/example-crates/wallet_electrum/src/main.rs b/example-crates/wallet_electrum/src/main.rs index 7eb88264..7f352bc1 100644 --- a/example-crates/wallet_electrum/src/main.rs +++ b/example-crates/wallet_electrum/src/main.rs @@ -1,105 +1,93 @@ -// use std::{io::Write, str::FromStr}; +const DB_MAGIC: &str = "bdk_wallet_electrum_example"; +const SEND_AMOUNT: u64 = 5000; +const STOP_GAP: usize = 50; +const BATCH_SIZE: usize = 5; -// use bdk::{ -// bitcoin::{Address, Network}, -// SignOptions, Wallet, -// }; -// use bdk_electrum::{ -// electrum_client::{self, ElectrumApi}, -// ElectrumExt, -// }; -// use bdk_file_store::KeychainStore; +use std::io::Write; +use std::str::FromStr; -// const SEND_AMOUNT: u64 = 5000; -// const STOP_GAP: usize = 50; -// const BATCH_SIZE: usize = 5; +use bdk::bitcoin::Address; +use bdk::SignOptions; +use bdk::{bitcoin::Network, Wallet}; +use bdk_electrum::electrum_client::{self, ElectrumApi}; +use bdk_electrum::v2::ElectrumExt; +use bdk_file_store::Store; fn main() -> Result<(), Box> { - todo!("update this example!"); - // println!("Hello, world!"); + let db_path = std::env::temp_dir().join("bdk-electrum-example"); + let db = Store::::new_from_path(DB_MAGIC.as_bytes(), db_path)?; + let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)"; + let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/1/*)"; - // let db_path = std::env::temp_dir().join("bdk-electrum-example"); - // let db = KeychainStore::new_from_path(db_path)?; - // let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)"; - // let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/1/*)"; + let mut wallet = Wallet::new( + external_descriptor, + Some(internal_descriptor), + db, + Network::Testnet, + )?; - // let mut wallet = Wallet::new( - // external_descriptor, - // Some(internal_descriptor), - // db, - // Network::Testnet, - // )?; + let address = wallet.get_address(bdk::wallet::AddressIndex::New); + println!("Generated Address: {}", address); - // let address = wallet.get_address(bdk::wallet::AddressIndex::New); - // println!("Generated Address: {}", address); + let balance = wallet.get_balance(); + println!("Wallet balance before syncing: {} sats", balance.total()); - // let balance = wallet.get_balance(); - // println!("Wallet balance before syncing: {} sats", balance.total()); + print!("Syncing..."); + let client = electrum_client::Client::new("ssl://electrum.blockstream.info:60002")?; - // print!("Syncing..."); - // // Scanning the chain... - // let electrum_url = "ssl://electrum.blockstream.info:60002"; - // let client = electrum_client::Client::new(electrum_url)?; - // let local_chain = wallet.checkpoints(); - // let spks = wallet - // .spks_of_all_keychains() - // .into_iter() - // .map(|(k, spks)| { - // let mut first = true; - // ( - // k, - // spks.inspect(move |(spk_i, _)| { - // if first { - // first = false; - // print!("\nScanning keychain [{:?}]:", k); - // } - // print!(" {}", spk_i); - // let _ = std::io::stdout().flush(); - // }), - // ) - // }) - // .collect(); - // let electrum_update = client - // .scan( - // local_chain, - // spks, - // core::iter::empty(), - // core::iter::empty(), - // STOP_GAP, - // BATCH_SIZE, - // )? - // .into_confirmation_time_update(&client)?; - // println!(); - // let new_txs = client.batch_transaction_get(electrum_update.missing_full_txs(&wallet))?; - // let update = electrum_update.into_keychain_scan(new_txs, &wallet)?; - // wallet.apply_update(update)?; - // wallet.commit()?; + let local_chain = wallet.checkpoints(); + let keychain_spks = wallet + .spks_of_all_keychains() + .into_iter() + .map(|(k, k_spks)| { + let mut once = Some(()); + let mut stdout = std::io::stdout(); + let k_spks = k_spks + .inspect(move |(spk_i, _)| match once.take() { + Some(_) => print!("\nScanning keychain [{:?}]", k), + None => print!(" {:<3}", spk_i), + }) + .inspect(move |_| stdout.flush().expect("must flush")); + (k, k_spks) + }) + .collect(); - // let balance = wallet.get_balance(); - // println!("Wallet balance after syncing: {} sats", balance.total()); + let electrum_update = + client.scan(local_chain, keychain_spks, None, None, STOP_GAP, BATCH_SIZE)?; - // if balance.total() < SEND_AMOUNT { - // println!( - // "Please send at least {} sats to the receiving address", - // SEND_AMOUNT - // ); - // std::process::exit(0); - // } + println!(); - // let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?; + let missing = electrum_update.missing_full_txs(wallet.as_ref()); + let update = electrum_update.finalize_as_confirmation_time(&client, None, missing)?; - // let mut tx_builder = wallet.build_tx(); - // tx_builder - // .add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT) - // .enable_rbf(); + wallet.apply_update(update)?; + wallet.commit()?; - // let (mut psbt, _) = tx_builder.finish()?; - // let finalized = wallet.sign(&mut psbt, SignOptions::default())?; - // assert!(finalized); + let balance = wallet.get_balance(); + println!("Wallet balance after syncing: {} sats", balance.total()); - // let tx = psbt.extract_tx(); - // client.transaction_broadcast(&tx)?; - // println!("Tx broadcasted! Txid: {}", tx.txid()); + if balance.total() < SEND_AMOUNT { + println!( + "Please send at least {} sats to the receiving address", + SEND_AMOUNT + ); + std::process::exit(0); + } - // Ok(()) + let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?; + + let mut tx_builder = wallet.build_tx(); + tx_builder + .add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT) + .enable_rbf(); + + let (mut psbt, _) = tx_builder.finish()?; + let finalized = wallet.sign(&mut psbt, SignOptions::default())?; + assert!(finalized); + + let tx = psbt.extract_tx(); + client.transaction_broadcast(&tx)?; + println!("Tx broadcasted! Txid: {}", tx.txid()); + + Ok(()) }