]> Untitled Git - bdk/commitdiff
add `electrum_backend` example.
authorw0xlt <woltx@protonmail.com>
Wed, 3 Aug 2022 16:11:46 +0000 (13:11 -0300)
committerw0xlt <woltx@protonmail.com>
Tue, 1 Nov 2022 22:59:46 +0000 (19:59 -0300)
Cargo.toml
examples/electrum_backend.rs [new file with mode: 0644]
examples/utils/mod.rs [new file with mode: 0644]

index 1bb9b983c11198f9c45c2af0633b956b4a6841f0..a01e2148a56f479fecebda09b4bbd0ae666ce9bb 100644 (file)
@@ -138,6 +138,11 @@ name = "hardware_signer"
 path = "examples/hardware_signer.rs"
 required-features = ["electrum", "hardware-signer"]
 
+[[example]]
+name = "electrum_backend"
+path = "examples/electrum_backend.rs"
+required-features = ["electrum"]
+
 [workspace]
 members = ["macros"]
 [package.metadata.docs.rs]
diff --git a/examples/electrum_backend.rs b/examples/electrum_backend.rs
new file mode 100644 (file)
index 0000000..5259865
--- /dev/null
@@ -0,0 +1,87 @@
+use std::str::FromStr;
+
+use bdk::bitcoin::util::bip32::ExtendedPrivKey;
+use bdk::bitcoin::Network;
+use bdk::blockchain::{Blockchain, ElectrumBlockchain};
+use bdk::database::MemoryDatabase;
+use bdk::template::Bip84;
+use bdk::wallet::export::FullyNodedExport;
+use bdk::{KeychainKind, SyncOptions, Wallet};
+
+use bdk::electrum_client::Client;
+use bdk::wallet::AddressIndex;
+use bitcoin::util::bip32;
+
+pub mod utils;
+
+use crate::utils::tx::build_signed_tx;
+
+/// This will create a wallet from an xpriv and get the balance by connecting to an Electrum server.
+/// If enough amount is available, this will send a transaction to an address.
+/// Otherwise, this will display a wallet address to receive funds.
+///
+/// This can be run with `cargo run --example electrum_backend` in the root folder.
+fn main() {
+    let network = Network::Testnet;
+
+    let xpriv = "tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy";
+
+    let electrum_url = "ssl://electrum.blockstream.info:60002";
+
+    run(&network, electrum_url, xpriv);
+}
+
+fn create_wallet(network: &Network, xpriv: &ExtendedPrivKey) -> Wallet<MemoryDatabase> {
+    Wallet::new(
+        Bip84(*xpriv, KeychainKind::External),
+        Some(Bip84(*xpriv, KeychainKind::Internal)),
+        *network,
+        MemoryDatabase::default(),
+    )
+    .unwrap()
+}
+
+fn run(network: &Network, electrum_url: &str, xpriv: &str) {
+    let xpriv = bip32::ExtendedPrivKey::from_str(xpriv).unwrap();
+
+    // Apparently it works only with Electrs (not EletrumX)
+    let blockchain = ElectrumBlockchain::from(Client::new(electrum_url).unwrap());
+
+    let wallet = create_wallet(network, &xpriv);
+
+    wallet.sync(&blockchain, SyncOptions::default()).unwrap();
+
+    let address = wallet.get_address(AddressIndex::New).unwrap().address;
+
+    println!("address: {}", address);
+
+    let balance = wallet.get_balance().unwrap();
+
+    println!("Available coins in BDK wallet : {} sats", balance);
+
+    if balance.confirmed > 6500 {
+        // the wallet sends the amount to itself.
+        let recipient_address = wallet
+            .get_address(AddressIndex::New)
+            .unwrap()
+            .address
+            .to_string();
+
+        let amount = 5359;
+
+        let tx = build_signed_tx(&wallet, &recipient_address, amount);
+
+        blockchain.broadcast(&tx).unwrap();
+
+        println!("tx id: {}", tx.txid());
+    } else {
+        println!("Insufficient Funds. Fund the wallet with the address above");
+    }
+
+    let export = FullyNodedExport::export_wallet(&wallet, "exported wallet", true)
+        .map_err(ToString::to_string)
+        .map_err(bdk::Error::Generic)
+        .unwrap();
+
+    println!("------\nWallet Backup: {}", export.to_string());
+}
diff --git a/examples/utils/mod.rs b/examples/utils/mod.rs
new file mode 100644 (file)
index 0000000..25249fa
--- /dev/null
@@ -0,0 +1,30 @@
+pub(crate) mod tx {
+
+    use std::str::FromStr;
+
+    use bdk::{database::BatchDatabase, SignOptions, Wallet};
+    use bitcoin::{Address, Transaction};
+
+    pub fn build_signed_tx<D: BatchDatabase>(
+        wallet: &Wallet<D>,
+        recipient_address: &str,
+        amount: u64,
+    ) -> Transaction {
+        // Create a transaction builder
+        let mut tx_builder = wallet.build_tx();
+
+        let to_address = Address::from_str(recipient_address).unwrap();
+
+        // Set recipient of the transaction
+        tx_builder.set_recipients(vec![(to_address.script_pubkey(), amount)]);
+
+        // Finalise the transaction and extract PSBT
+        let (mut psbt, _) = tx_builder.finish().unwrap();
+
+        // Sign the above psbt with signing option
+        wallet.sign(&mut psbt, SignOptions::default()).unwrap();
+
+        // Extract the final transaction
+        psbt.extract_tx()
+    }
+}