2024-06-24 08:02:17 +01:00
|
|
|
use crate::{keys, utils};
|
2024-06-24 16:43:17 +01:00
|
|
|
use bdk::bitcoin::psbt::PartiallySignedTransaction;
|
2024-06-24 17:20:52 +01:00
|
|
|
use bdk::bitcoin::Network;
|
2024-06-24 15:57:31 +01:00
|
|
|
use bdk::database::MemoryDatabase;
|
2024-06-24 18:41:55 +01:00
|
|
|
use bdk::keys::ExtendedKey;
|
2024-06-24 17:20:52 +01:00
|
|
|
use bdk::template::Bip84;
|
2024-06-24 15:57:31 +01:00
|
|
|
use bdk::wallet::AddressIndex::{self, New};
|
2024-06-24 16:31:03 +01:00
|
|
|
use bdk::wallet::AddressInfo;
|
2024-06-24 13:56:57 +01:00
|
|
|
use bdk::{blockchain::ElectrumBlockchain, electrum_client, SyncOptions};
|
2024-06-24 18:41:55 +01:00
|
|
|
use bdk::{FeeRate, KeychainKind, SignOptions, TransactionDetails, Wallet};
|
2024-06-21 18:18:52 +01:00
|
|
|
|
|
|
|
|
pub async fn run() -> Result<(), anyhow::Error> {
|
2024-06-24 08:02:17 +01:00
|
|
|
let dave = utils::home(&"dave".to_string());
|
2024-06-24 16:31:03 +01:00
|
|
|
let sammy = utils::home(&"sammy".to_string());
|
2024-06-24 18:41:55 +01:00
|
|
|
let dave_key = keys::bitcoin::load_from_file(&dave).unwrap();
|
|
|
|
|
let sammy_key = keys::bitcoin::load_from_file(&sammy).unwrap();
|
2024-06-24 17:20:52 +01:00
|
|
|
|
2024-06-24 18:41:55 +01:00
|
|
|
let dave_wallet = create_wallet(dave_key)?;
|
|
|
|
|
let sammy_wallet = create_wallet(sammy_key)?;
|
2024-06-24 08:02:17 +01:00
|
|
|
|
2024-06-24 16:31:03 +01:00
|
|
|
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);
|
2024-06-24 08:02:17 +01:00
|
|
|
|
2024-06-24 13:56:57 +01:00
|
|
|
let blockchain = ElectrumBlockchain::from(electrum_client::Client::new(
|
|
|
|
|
"ssl://electrum.blockstream.info:60002",
|
|
|
|
|
)?);
|
2024-06-24 08:02:17 +01:00
|
|
|
|
2024-06-24 13:56:57 +01:00
|
|
|
println!("Syncing...");
|
|
|
|
|
dave_wallet.sync(&blockchain, SyncOptions::default())?;
|
2024-06-24 15:57:31 +01:00
|
|
|
|
2024-06-24 16:31:03 +01:00
|
|
|
display_balance(&dave_wallet);
|
|
|
|
|
display_balance(&sammy_wallet);
|
2024-06-24 15:57:31 +01:00
|
|
|
|
2024-06-24 16:31:03 +01:00
|
|
|
let (mut psbt, details) =
|
|
|
|
|
build_sending_tx(&dave_wallet, sammy_wallet.get_address(New)?).expect("psbt build error");
|
2024-06-24 15:57:31 +01:00
|
|
|
|
2024-06-24 16:43:17 +01:00
|
|
|
println!("About to sign the transaction: {:?}", details);
|
2024-06-24 15:57:31 +01:00
|
|
|
|
2024-06-24 16:43:17 +01:00
|
|
|
dave_wallet.sign(&mut psbt, SignOptions::default())?;
|
2024-06-24 17:20:52 +01:00
|
|
|
let _signed_tx = psbt.extract_tx();
|
2024-06-24 15:57:31 +01:00
|
|
|
|
2024-06-24 17:20:52 +01:00
|
|
|
// println!("Broadcasting...");
|
|
|
|
|
// blockchain.broadcast(&signed_tx).expect("broadcast error");
|
|
|
|
|
// println!("Transaction ID: {:?}", signed_tx.txid());
|
2024-06-21 18:18:52 +01:00
|
|
|
Ok(())
|
|
|
|
|
}
|
2024-06-24 15:57:31 +01:00
|
|
|
|
2024-06-24 17:20:52 +01:00
|
|
|
/// Create a BDK wallet using BIP 84 descriptor ("m/84h/1h/0h/0" and "m/84h/1h/0h/1")
|
2024-06-24 18:41:55 +01:00
|
|
|
pub fn create_wallet(xkey: ExtendedKey) -> anyhow::Result<Wallet<MemoryDatabase>> {
|
|
|
|
|
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));
|
2024-06-24 17:20:52 +01:00
|
|
|
|
|
|
|
|
let wallet = Wallet::new(
|
|
|
|
|
external_descriptor,
|
|
|
|
|
internal_descriptor,
|
|
|
|
|
Network::Testnet,
|
|
|
|
|
MemoryDatabase::default(),
|
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
Ok(wallet)
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 16:31:03 +01:00
|
|
|
fn display_balance(wallet: &Wallet<MemoryDatabase>) {
|
|
|
|
|
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(),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 15:57:31 +01:00
|
|
|
fn build_sending_tx(
|
|
|
|
|
wallet: &Wallet<MemoryDatabase>,
|
2024-06-24 16:31:03 +01:00
|
|
|
recipient: AddressInfo,
|
2024-06-24 15:57:31 +01:00
|
|
|
) -> anyhow::Result<(PartiallySignedTransaction, TransactionDetails), anyhow::Error> {
|
|
|
|
|
let mut builder = wallet.build_tx();
|
|
|
|
|
builder
|
2024-06-24 16:31:03 +01:00
|
|
|
.add_recipient(recipient.script_pubkey(), 1000)
|
2024-06-24 15:57:31 +01:00
|
|
|
.enable_rbf()
|
|
|
|
|
.do_not_spend_change()
|
2024-06-24 16:31:03 +01:00
|
|
|
.fee_rate(FeeRate::from_sat_per_vb(7.0));
|
2024-06-24 15:57:31 +01:00
|
|
|
Ok(builder.finish()?)
|
|
|
|
|
}
|