diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index 41a57919..053bf8a6 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -1711,6 +1711,28 @@ impl Wallet { pub fn staged(&self) -> &ChangeSet { self.persist.staged() } + + /// Get a reference to the inner [`TxGraph`](bdk_chain::tx_graph::TxGraph). + pub fn as_graph(&self) -> &bdk_chain::tx_graph::TxGraph { + self.keychain_tracker.graph() + } + + /// Get a reference to the inner [`ChainGraph`](bdk_chain::chain_graph::ChainGraph). + pub fn as_chain_graph(&self) -> &bdk_chain::chain_graph::ChainGraph { + self.keychain_tracker.chain_graph() + } +} + +impl AsRef for Wallet { + fn as_ref(&self) -> &bdk_chain::tx_graph::TxGraph { + self.keychain_tracker.graph() + } +} + +impl AsRef> for Wallet { + fn as_ref(&self) -> &bdk_chain::chain_graph::ChainGraph { + self.keychain_tracker.chain_graph() + } } /// Deterministically generate a unique name given the descriptors defining the wallet diff --git a/example-crates/wallet_electrum/Cargo.toml b/example-crates/wallet_electrum/Cargo.toml index 0415d227..da84e85f 100644 --- a/example-crates/wallet_electrum/Cargo.toml +++ b/example-crates/wallet_electrum/Cargo.toml @@ -5,3 +5,5 @@ edition = "2021" [dependencies] bdk = { path = "../../crates/bdk" } +bdk_electrum = { path = "../../crates/electrum" } +bdk_file_store = { path = "../../crates/file_store" } diff --git a/example-crates/wallet_electrum/src/main.rs b/example-crates/wallet_electrum/src/main.rs index e7a11a96..dabd66da 100644 --- a/example-crates/wallet_electrum/src/main.rs +++ b/example-crates/wallet_electrum/src/main.rs @@ -1,3 +1,83 @@ -fn main() { +use std::str::FromStr; + +use bdk::{ + bitcoin::{Address, Network}, + SignOptions, Wallet, +}; +use bdk_electrum::{ + electrum_client::{self, ElectrumApi}, + ElectrumExt, +}; +use bdk_file_store::KeychainStore; + +const SEND_AMOUNT: u64 = 5000; +const STOP_GAP: usize = 50; +const BATCH_SIZE: usize = 5; + +fn main() -> Result<(), Box> { println!("Hello, world!"); + + 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 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()); + + println!("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(); + let electrum_update = client + .scan( + local_chain, + spks, + core::iter::empty(), + core::iter::empty(), + STOP_GAP, + BATCH_SIZE, + )? + .into_confirmation_time_update(&client)?; + 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 balance = wallet.get_balance(); + println!("Wallet balance after syncing: {} sats", balance.total()); + + if balance.total() == 0 { + println!("Please send some coins to the receiving address"); + std::process::exit(0); + } + + 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(()) }