From a39fc787d57e8e869642821b015f91dce288b414 Mon Sep 17 00:00:00 2001 From: Sudarsan Balaji Date: Fri, 25 Mar 2022 17:24:21 +0000 Subject: [PATCH] Add initial version of TxBuilder --- src/bdk.udl | 8 ++++++++ src/lib.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/bdk.udl b/src/bdk.udl index 7ee8e80..e6d99c7 100644 --- a/src/bdk.udl +++ b/src/bdk.udl @@ -142,6 +142,14 @@ interface PartiallySignedBitcoinTransaction { string serialize(); }; +interface TxBuilder { + constructor(); + TxBuilder add_recipient(string address, u64 amount); + TxBuilder fee_rate(float sat_per_vbyte); + [Throws=BdkError] + PartiallySignedBitcoinTransaction build([ByRef] Wallet wallet); +}; + dictionary ExtendedKeyInfo { string mnemonic; string xprv; diff --git a/src/lib.rs b/src/lib.rs index 2fd0015..f3868b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ use bdk::wallet::AddressIndex; use bdk::{BlockTime, Error, FeeRate, SignOptions, Wallet as BdkWallet}; use std::convert::TryFrom; use std::str::FromStr; -use std::sync::{Mutex, MutexGuard}; +use std::sync::{Arc, Mutex, MutexGuard}; uniffi_macros::include_scaffolding!("bdk"); @@ -303,4 +303,53 @@ fn restore_extended_key( }) } +struct TxBuilder { + recipients: Vec<(String, u64)>, + fee_rate: Option, +} + +impl TxBuilder { + fn new() -> Self { + TxBuilder { + recipients: Vec::new(), + fee_rate: None, + } + } + + fn add_recipient(&self, recipient: String, amount: u64) -> Arc { + let mut recipients = self.recipients.to_vec(); + recipients.append(&mut vec![(recipient, amount)]); + Arc::new(TxBuilder { + recipients, + fee_rate: self.fee_rate, + }) + } + + fn fee_rate(&self, sat_per_vb: f32) -> Arc { + Arc::new(TxBuilder { + recipients: self.recipients.to_vec(), + fee_rate: Some(sat_per_vb), + }) + } + + fn build(&self, wallet: &Wallet) -> Result, Error> { + let wallet = wallet.get_wallet(); + let mut tx_builder = wallet.build_tx(); + for (address, amount) in &self.recipients { + let address = Address::from_str(address).expect("recipient address parsing failed"); + tx_builder.add_recipient(address.script_pubkey(), *amount); + } + if let Some(sat_per_vb) = self.fee_rate { + tx_builder.fee_rate(FeeRate::from_sat_per_vb(sat_per_vb)); + } + tx_builder + .finish() + .map(|(psbt, _)| PartiallySignedBitcoinTransaction { + internal: Mutex::new(psbt), + }) + .map(Arc::new) + .map_err(|_| BdkError::Generic("Failed to build transaction".to_string())) + } +} + uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);