use crate::{keys, utils}; use bdk::bitcoin::base64; use bdk::bitcoin::psbt::{PartiallySignedTransaction, Psbt}; use bdk::blockchain::{Blockchain, Progress}; use bdk::database::MemoryDatabase; use bdk::wallet::AddressIndex::{self, New}; use bdk::wallet::AddressInfo; use bdk::{blockchain::ElectrumBlockchain, electrum_client, SyncOptions}; use bdk::{FeeRate, SignOptions, TransactionDetails, Wallet}; use toml::to_string; use tracing::field::display; #[derive(Debug)] pub struct CustomProgress; impl Progress for CustomProgress { fn update(&self, progress: f32, message: Option) -> Result<(), bdk::Error> { println!("Progress: {} - {:?}", progress, message); Ok(()) } } pub async fn run() -> Result<(), anyhow::Error> { let dave = utils::home(&"dave".to_string()); let sammy = utils::home(&"sammy".to_string()); let dave_wallet = keys::bitcoin::load_from_file(&dave).unwrap(); let sammy_wallet = keys::bitcoin::load_from_file(&sammy).unwrap(); // Verify explicitly that the address is derived as expected let dave_expected_address = "tb1q88e45m4akrg2y00n4077vn90q8qw0svz7dss6k"; let derived_address = dave_wallet.get_address(AddressIndex::Peek(0))?.to_string(); assert_eq!(dave_expected_address, derived_address); let dave_address = dave_wallet.get_address(AddressIndex::Peek(0))?.to_string(); let sammy_address = sammy_wallet.get_address(AddressIndex::Peek(0))?.to_string(); println!("Dave's address: {}", dave_address); println!("Sammy's address: {}", sammy_address); let blockchain = ElectrumBlockchain::from(electrum_client::Client::new( "ssl://electrum.blockstream.info:60002", )?); println!("Syncing..."); dave_wallet.sync(&blockchain, SyncOptions::default())?; display_balance(&dave_wallet); display_balance(&sammy_wallet); let (mut psbt, details) = build_sending_tx(&dave_wallet, sammy_wallet.get_address(New)?).expect("psbt build error"); println!("Transaction details: {:#?}", details); println!("Unsigned PSBT: {}", base64::encode(psbt.serialize())); let finalized = dave_wallet.sign(&mut psbt, SignOptions::default())?; println!("Finalized: {}", finalized); let tx_id = blockchain .broadcast(&psbt.extract_tx()) .expect("broadcast error"); println!("Transaction ID: {:?}", tx_id); Ok(()) } fn display_balance(wallet: &Wallet) { println!( "Wallet balance for {} after syncing: {:?} sats on network {}", wallet .get_address(bdk::wallet::AddressIndex::Peek(0)) .expect("couldn't get address"), wallet.get_balance().expect("couldn't show balance"), wallet.network(), ); } fn build_sending_tx( wallet: &Wallet, recipient: AddressInfo, ) -> anyhow::Result<(PartiallySignedTransaction, TransactionDetails), anyhow::Error> { let mut builder = wallet.build_tx(); builder .add_recipient(recipient.script_pubkey(), 1000) .enable_rbf() .do_not_spend_change() .fee_rate(FeeRate::from_sat_per_vb(7.0)); Ok(builder.finish()?) }