Skip to content

Commit 252bcaa

Browse files
feat: add bumpfeetxbuilder
1 parent 643d254 commit 252bcaa

File tree

4 files changed

+101
-96
lines changed

4 files changed

+101
-96
lines changed

bdk-ffi/src/bdk.udl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,19 @@ interface TxBuilder {
150150
PartiallySignedTransaction finish([ByRef] Wallet wallet);
151151
};
152152

153+
interface BumpFeeTxBuilder {
154+
constructor(string txid, f32 fee_rate);
155+
156+
BumpFeeTxBuilder allow_shrinking(Script script_pubkey);
157+
158+
BumpFeeTxBuilder enable_rbf();
159+
160+
BumpFeeTxBuilder enable_rbf_with_sequence(u32 nsequence);
161+
162+
[Throws=BdkError]
163+
PartiallySignedTransaction finish([ByRef] Wallet wallet);
164+
};
165+
153166
// ------------------------------------------------------------------------
154167
// bdk crate - descriptor module
155168
// ------------------------------------------------------------------------

bdk-ffi/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::types::AddressInfo;
2323
use crate::types::Balance;
2424
use crate::types::LocalUtxo;
2525
use crate::types::ScriptAmount;
26+
use crate::wallet::BumpFeeTxBuilder;
2627
use crate::wallet::SentAndReceivedValues;
2728
use crate::wallet::TxBuilder;
2829
use crate::wallet::Update;

bdk-ffi/src/types.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,3 @@ impl From<BdkLocalUtxo> for LocalUtxo {
146146
}
147147
}
148148
}
149-
150-
#[derive(Clone, Debug)]
151-
pub enum RbfValue {
152-
Default,
153-
Value(u32),
154-
}

bdk-ffi/src/wallet.rs

Lines changed: 87 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
use crate::bitcoin::{OutPoint, PartiallySignedTransaction, Transaction};
22
use crate::descriptor::Descriptor;
3+
use crate::types::Balance;
34
use crate::types::ScriptAmount;
4-
use crate::types::{Balance, RbfValue};
55
use crate::Script;
66
use crate::{AddressIndex, AddressInfo, Network};
77

88
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
9-
use bdk::bitcoin::{OutPoint as BdkOutPoint, Sequence};
9+
use bdk::bitcoin::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
10+
use bdk::bitcoin::{OutPoint as BdkOutPoint, Sequence, Txid};
1011
use bdk::wallet::tx_builder::ChangeSpendPolicy;
1112
use bdk::wallet::Update as BdkUpdate;
1213
use bdk::{Error as BdkError, FeeRate};
1314
use bdk::{SignOptions, Wallet as BdkWallet};
1415

1516
use std::collections::HashSet;
17+
use std::str::FromStr;
1618
use std::sync::{Arc, Mutex, MutexGuard};
1719

1820
#[derive(Debug)]
@@ -530,102 +532,97 @@ impl TxBuilder {
530532
// tx_builder.add_data(self.data.as_slice());
531533
// }
532534

533-
// tx_builder.finish().map(|psbt| psbt.serialize_hex())
534-
// tx_builder.finish().into()
535535
let psbt = tx_builder.finish()?;
536536

537537
Ok(Arc::new(psbt.into()))
538538
}
539539
}
540540

541541
// /// The BumpFeeTxBuilder is used to bump the fee on a transaction that has been broadcast and has its RBF flag set to true.
542-
// #[derive(Clone)]
543-
// pub(crate) struct BumpFeeTxBuilder {
544-
// pub(crate) txid: String,
545-
// pub(crate) fee_rate: f32,
546-
// pub(crate) allow_shrinking: Option<String>,
547-
// pub(crate) rbf: Option<RbfValue>,
548-
// }
549-
//
550-
// impl BumpFeeTxBuilder {
551-
// pub(crate) fn new(txid: String, fee_rate: f32) -> Self {
552-
// Self {
553-
// txid,
554-
// fee_rate,
555-
// allow_shrinking: None,
556-
// rbf: None,
557-
// }
558-
// }
559-
//
560-
// /// Explicitly tells the wallet that it is allowed to reduce the amount of the output matching this script_pubkey
561-
// /// in order to bump the transaction fee. Without specifying this the wallet will attempt to find a change output to
562-
// /// shrink instead. Note that the output may shrink to below the dust limit and therefore be removed. If it is preserved
563-
// /// then it is currently not guaranteed to be in the same position as it was originally. Returns an error if script_pubkey
564-
// /// can’t be found among the recipients of the transaction we are bumping.
565-
// pub(crate) fn allow_shrinking(&self, address: String) -> Arc<Self> {
566-
// Arc::new(Self {
567-
// allow_shrinking: Some(address),
568-
// ..self.clone()
569-
// })
570-
// }
571-
//
572-
// /// Enable signaling RBF. This will use the default `nsequence` value of `0xFFFFFFFD`.
573-
// pub(crate) fn enable_rbf(&self) -> Arc<Self> {
574-
// Arc::new(Self {
575-
// rbf: Some(RbfValue::Default),
576-
// ..self.clone()
577-
// })
578-
// }
579-
//
580-
// /// Enable signaling RBF with a specific nSequence value. This can cause conflicts if the wallet's descriptors contain an
581-
// /// "older" (OP_CSV) operator and the given `nsequence` is lower than the CSV value. If the `nsequence` is higher than `0xFFFFFFFD`
582-
// /// an error will be thrown, since it would not be a valid nSequence to signal RBF.
583-
// pub(crate) fn enable_rbf_with_sequence(&self, nsequence: u32) -> Arc<Self> {
584-
// Arc::new(Self {
585-
// rbf: Some(RbfValue::Value(nsequence)),
586-
// ..self.clone()
587-
// })
588-
// }
589-
//
590-
// /// Finish building the transaction. Returns the BIP174 PSBT.
591-
// pub(crate) fn finish(
592-
// &self,
593-
// wallet: &Wallet,
594-
// ) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
595-
// let wallet = wallet.get_wallet();
596-
// let txid = Txid::from_str(self.txid.as_str())?;
597-
// let mut tx_builder = wallet.build_fee_bump(txid)?;
598-
// tx_builder.fee_rate(FeeRate::from_sat_per_vb(self.fee_rate));
599-
// if let Some(allow_shrinking) = &self.allow_shrinking {
600-
// let address = BdkAddress::from_str(allow_shrinking)
601-
// .map_err(|e| BdkError::Generic(e.to_string()))?;
602-
// let script = address.script_pubkey();
603-
// tx_builder.allow_shrinking(script)?;
604-
// }
605-
// if let Some(rbf) = &self.rbf {
606-
// match *rbf {
607-
// RbfValue::Default => {
608-
// tx_builder.enable_rbf();
609-
// }
610-
// RbfValue::Value(nsequence) => {
611-
// tx_builder.enable_rbf_with_sequence(Sequence(nsequence));
612-
// }
613-
// }
614-
// }
615-
// tx_builder
616-
// .finish()
617-
// .map(|(psbt, _)| PartiallySignedTransaction {
618-
// inner: Mutex::new(psbt),
619-
// })
620-
// .map(Arc::new)
621-
// }
622-
// }
542+
#[derive(Clone)]
543+
pub(crate) struct BumpFeeTxBuilder {
544+
pub(crate) txid: String,
545+
pub(crate) fee_rate: f32,
546+
pub(crate) allow_shrinking: Option<Arc<Script>>,
547+
pub(crate) rbf: Option<RbfValue>,
548+
}
623549

624-
// #[derive(Clone, Debug)]
625-
// enum RbfValue {
626-
// Default,
627-
// Value(u32),
628-
// }
550+
impl BumpFeeTxBuilder {
551+
pub(crate) fn new(txid: String, fee_rate: f32) -> Self {
552+
Self {
553+
txid,
554+
fee_rate,
555+
allow_shrinking: None,
556+
rbf: None,
557+
}
558+
}
559+
560+
/// Explicitly tells the wallet that it is allowed to reduce the amount of the output matching this script_pubkey
561+
/// in order to bump the transaction fee. Without specifying this the wallet will attempt to find a change output to
562+
/// shrink instead. Note that the output may shrink to below the dust limit and therefore be removed. If it is preserved
563+
/// then it is currently not guaranteed to be in the same position as it was originally. Returns an error if script_pubkey
564+
/// can’t be found among the recipients of the transaction we are bumping.
565+
pub(crate) fn allow_shrinking(&self, script_pubkey: Arc<Script>) -> Arc<Self> {
566+
Arc::new(Self {
567+
allow_shrinking: Some(script_pubkey),
568+
..self.clone()
569+
})
570+
}
571+
572+
/// Enable signaling RBF. This will use the default `nsequence` value of `0xFFFFFFFD`.
573+
pub(crate) fn enable_rbf(&self) -> Arc<Self> {
574+
Arc::new(Self {
575+
rbf: Some(RbfValue::Default),
576+
..self.clone()
577+
})
578+
}
579+
580+
/// Enable signaling RBF with a specific nSequence value. This can cause conflicts if the wallet's descriptors contain an
581+
/// "older" (OP_CSV) operator and the given `nsequence` is lower than the CSV value. If the `nsequence` is higher than `0xFFFFFFFD`
582+
/// an error will be thrown, since it would not be a valid nSequence to signal RBF.
583+
pub(crate) fn enable_rbf_with_sequence(&self, nsequence: u32) -> Arc<Self> {
584+
Arc::new(Self {
585+
rbf: Some(RbfValue::Value(nsequence)),
586+
..self.clone()
587+
})
588+
}
589+
590+
/// Finish building the transaction. Returns the BIP174 PSBT.
591+
pub(crate) fn finish(
592+
&self,
593+
wallet: &Wallet,
594+
) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
595+
let txid =
596+
Txid::from_str(self.txid.as_str()).map_err(|e| BdkError::Generic(e.to_string()))?;
597+
let mut wallet = wallet.get_wallet();
598+
let mut tx_builder = wallet.build_fee_bump(txid)?;
599+
tx_builder.fee_rate(FeeRate::from_sat_per_vb(self.fee_rate));
600+
if let Some(allow_shrinking) = &self.allow_shrinking {
601+
tx_builder.allow_shrinking(allow_shrinking.0.clone())?;
602+
}
603+
if let Some(rbf) = &self.rbf {
604+
match *rbf {
605+
RbfValue::Default => {
606+
tx_builder.enable_rbf();
607+
}
608+
RbfValue::Value(nsequence) => {
609+
tx_builder.enable_rbf_with_sequence(Sequence(nsequence));
610+
}
611+
}
612+
}
613+
let psbt: BdkPartiallySignedTransaction = tx_builder
614+
.finish()
615+
.map_err(|e| BdkError::Generic(e.to_string()))?;
616+
617+
Ok(Arc::new(psbt.into()))
618+
}
619+
}
620+
621+
#[derive(Clone, Debug)]
622+
pub enum RbfValue {
623+
Default,
624+
Value(u32),
625+
}
629626

630627
// // The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
631628
// // These tests should not be used to verify `bdk` behavior that is already tested in the `bdk`

0 commit comments

Comments
 (0)