use crate::{bitcoin, utils}; use bdk::bitcoin::psbt::PartiallySignedTransaction; use bdk::bitcoin::Network; use bdk::database::MemoryDatabase; use bdk::keys::ExtendedKey; use bdk::template::Bip84; use bdk::wallet::AddressIndex::{self, New}; use bdk::wallet::AddressInfo; use bdk::{blockchain::ElectrumBlockchain, electrum_client, SyncOptions}; use bdk::{FeeRate, KeychainKind, SignOptions, TransactionDetails, Wallet}; /// Run the Bitcoin wallet example /// /// This is a bdk example that uses the Electrum client to interact with the Bitcoin network. /// Electrum is a light client that connects to a server to get information about the Bitcoin network. /// The BDK itself does not have the ability to connect to e.g. esplora servers. As the Blockstream Electrum Signet /// server does not appear to be picking up transactions properly at the moment, I've shifted over to using /// the (more complex) `bdk_wallet` crate and the esplora client there (see the other RPC client). /// /// Note:the types below are all completely different than the types in `bdk_wallet`. pub async fn run() -> Result<(), anyhow::Error> { let dave = utils::home(&"dave".to_string()); let sammy = utils::home(&"sammy".to_string()); let dave_key = bitcoin::keys::load_from_file(&dave).unwrap(); let sammy_key = bitcoin::keys::load_from_file(&sammy).unwrap(); let dave_wallet = create_wallet(dave_key)?; let sammy_wallet = create_wallet(sammy_key)?; 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!("About to sign the transaction: {:?}", details); dave_wallet.sign(&mut psbt, SignOptions::default())?; let _signed_tx = psbt.extract_tx(); // println!("Broadcasting..."); // blockchain.broadcast(&signed_tx).expect("broadcast error"); // println!("Transaction ID: {:?}", signed_tx.txid()); Ok(()) } /// Create a BDK wallet using BIP 84 descriptor ("m/84h/1h/0h/0" and "m/84h/1h/0h/1") pub fn create_wallet(xkey: ExtendedKey) -> anyhow::Result> { let xprv = xkey .into_xprv(Network::Testnet) .expect("couldn't turn xkey into xprv"); let external_descriptor = Bip84(xprv, KeychainKind::External); let internal_descriptor = Some(Bip84(xprv, KeychainKind::Internal)); let wallet = Wallet::new( external_descriptor, internal_descriptor, Network::Testnet, MemoryDatabase::default(), )?; Ok(wallet) } 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()?) }