|
1 | 1 | use crate::bitcoin::{OutPoint, PartiallySignedTransaction, Transaction}; |
2 | 2 | use crate::descriptor::Descriptor; |
| 3 | +use crate::types::Balance; |
3 | 4 | use crate::types::ScriptAmount; |
4 | | -use crate::types::{Balance, RbfValue}; |
5 | 5 | use crate::Script; |
6 | 6 | use crate::{AddressIndex, AddressInfo, Network}; |
7 | 7 |
|
8 | 8 | 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}; |
10 | 11 | use bdk::wallet::tx_builder::ChangeSpendPolicy; |
11 | 12 | use bdk::wallet::Update as BdkUpdate; |
12 | 13 | use bdk::{Error as BdkError, FeeRate}; |
13 | 14 | use bdk::{SignOptions, Wallet as BdkWallet}; |
14 | 15 |
|
15 | 16 | use std::collections::HashSet; |
| 17 | +use std::str::FromStr; |
16 | 18 | use std::sync::{Arc, Mutex, MutexGuard}; |
17 | 19 |
|
18 | 20 | #[derive(Debug)] |
@@ -530,102 +532,97 @@ impl TxBuilder { |
530 | 532 | // tx_builder.add_data(self.data.as_slice()); |
531 | 533 | // } |
532 | 534 |
|
533 | | - // tx_builder.finish().map(|psbt| psbt.serialize_hex()) |
534 | | - // tx_builder.finish().into() |
535 | 535 | let psbt = tx_builder.finish()?; |
536 | 536 |
|
537 | 537 | Ok(Arc::new(psbt.into())) |
538 | 538 | } |
539 | 539 | } |
540 | 540 |
|
541 | 541 | // /// 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 | +} |
623 | 549 |
|
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 | +} |
629 | 626 |
|
630 | 627 | // // The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs. |
631 | 628 | // // These tests should not be used to verify `bdk` behavior that is already tested in the `bdk` |
|
0 commit comments