Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9e49c24
feat!: extract anti-fee-sniping from create_psbt
claude May 7, 2026
f3852e2
refactor: AFS becomes pre-construction Selection mutation
claude May 11, 2026
2310e41
refactor: drop AntiFeeSnipingError::TipBelowExistingLocktime
claude May 11, 2026
cee5fff
refactor: move sequence override into Plan variant; validate set_sequ…
claude May 11, 2026
e90cd3c
refactor: skip relative-timelocked inputs at AFS selection instead of…
claude May 11, 2026
4add2b6
refactor: auto-bump tx version to V2 in AFS instead of erroring
claude May 11, 2026
78b7b21
feat!: flip PsbtParams::fallback_sequence default to ENABLE_RBF_NO_LO…
claude May 11, 2026
7ef9103
refactor: don't bump tx version in AFS; force locktime branch at v1 i…
claude May 11, 2026
e9bc616
refactor: force sequence branch when effective lock_time is time-based
claude May 11, 2026
3258276
refactor(example): drop dead clone of selection.inputs
claude May 11, 2026
809033e
refactor(example): collapse PsbtParams literal to ::default()
claude May 11, 2026
f8f862e
refactor: Selection::apply_anti_fee_sniping consumes and returns self
claude May 11, 2026
f87f88c
refactor(example): chain apply_anti_fee_sniping into create_psbt
claude May 11, 2026
418823c
Revert "refactor(example): chain apply_anti_fee_sniping into create_p…
claude May 11, 2026
f71a2f0
refactor(example): chain apply_anti_fee_sniping into create_psbt
claude May 11, 2026
cdc1b86
refactor: rename AntiFeeSnipingError::TimeBasedLocktime → NoApplicabl…
claude May 11, 2026
d788278
feat!: validate locktime-unit consistency in Selector::new
claude May 11, 2026
a96287d
feat!: rename PsbtParams::fallback_locktime → min_locktime
claude May 11, 2026
e358edd
feat!: rename PsbtParams::version → min_version with opportunistic bu…
claude May 11, 2026
459dc87
feat!: replace PsbtParams::sighash_type with per-input Input::set_sig…
claude May 11, 2026
3220da7
feat!: introduce TxTemplate as intermediary between Selection and Psbt
claude May 11, 2026
10247ea
feat: TxTemplate::shuffle_inputs and shuffle_outputs
claude May 11, 2026
b3fe0b5
feat!: redesign Finalizer API around populate_finalizer
claude May 11, 2026
0073930
feat!: make Selection and TxTemplate fields pub(crate)
claude May 11, 2026
546e37e
feat: TxTemplate::set_input_sequence and set_input_sighash
claude May 11, 2026
4528a32
feat!: rename Finalizer → PsbtFinalizer; create_psbt returns (Psbt, P…
claude May 12, 2026
46c5085
refactor: rename src/template.rs → src/tx_template.rs; TemplateParams…
claude May 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }
miniscript = { version = "12.3.5", default-features = false }
bdk_coin_select = "0.4.0"
rand_core = { version = "0.6.4", default-features = false }
rand = { version = "0.8", optional = true }

[dev-dependencies]
anyhow = "1"
Expand All @@ -26,10 +25,11 @@ bitcoin = { version = "0.32", default-features = false, features = ["rand-std"]
bdk_testenv = "0.13.0"
bdk_bitcoind_rpc = "0.20.0"
bdk_chain = { version = "0.23.0" }
rand = "0.8"

[features]
default = ["std"]
std = ["miniscript/std", "rand/std"]
std = ["miniscript/std"]

[[example]]
name = "synopsis"
Expand Down
21 changes: 8 additions & 13 deletions examples/anti_fee_sniping.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#![allow(dead_code)]
use bdk_testenv::{bitcoincore_rpc::RpcApi, TestEnv};
use bdk_tx::{
filter_unspendable, group_by_spk, selection_algorithm_lowest_fee_bnb, Output, PsbtParams,
SelectorParams,
filter_unspendable, group_by_spk, selection_algorithm_lowest_fee_bnb, Output, PsbtBuildParams,
SelectorParams, TxTemplateParams,
};
use bitcoin::{absolute::LockTime, key::Secp256k1, Amount, FeeRate, Sequence};
use bitcoin::{absolute::LockTime, key::Secp256k1, Amount, FeeRate};
use miniscript::Descriptor;

mod common;
Expand Down Expand Up @@ -88,16 +88,11 @@ fn main() -> anyhow::Result<()> {
},
)?;

let fallback_locktime: LockTime = LockTime::from_consensus(tip_height.to_consensus_u32());

let selection_inputs = selection.inputs.clone();

let psbt = selection.create_psbt(PsbtParams {
enable_anti_fee_sniping: true,
fallback_locktime,
fallback_sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
..Default::default()
})?;
let selection_inputs = selection.inputs().to_vec();
let (psbt, _) = selection
.into_template(TxTemplateParams::default())
.apply_anti_fee_sniping(tip_height, &mut rand::thread_rng())?
.create_psbt(PsbtBuildParams::default())?;

let tx = psbt.unsigned_tx;

Expand Down
25 changes: 10 additions & 15 deletions examples/synopsis.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use bdk_testenv::{bitcoincore_rpc::RpcApi, TestEnv};
use bdk_tx::{
filter_unspendable, group_by_spk, selection_algorithm_lowest_fee_bnb, Output, PsbtParams,
SelectorParams, Signer,
filter_unspendable, group_by_spk, selection_algorithm_lowest_fee_bnb, Output, PsbtBuildParams,
SelectorParams, Signer, TxTemplateParams,
};
use bitcoin::{key::Secp256k1, Amount, FeeRate, Sequence};
use bitcoin::{key::Secp256k1, Amount, FeeRate};
use miniscript::Descriptor;

mod common;
Expand Down Expand Up @@ -68,11 +68,9 @@ fn main() -> anyhow::Result<()> {
},
)?;

let mut psbt = selection.create_psbt(PsbtParams {
fallback_sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
..Default::default()
})?;
let finalizer = selection.into_finalizer();
let (mut psbt, finalizer) = selection
.into_template(TxTemplateParams::default())
.create_psbt(PsbtBuildParams::default())?;

let _ = psbt.sign(&signer, &secp);
let res = finalizer.finalize(&mut psbt);
Expand Down Expand Up @@ -149,21 +147,18 @@ fn main() -> anyhow::Result<()> {
},
)?;

let mut psbt = selection.create_psbt(PsbtParams {
// Not strictly necessary, but it may help us replace the tx faster.
fallback_sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
..Default::default()
})?;
println!(
"selected inputs: {:?}",
selection
.inputs
.inputs()
.iter()
.map(|input| input.prev_outpoint())
.collect::<Vec<_>>()
);

let finalizer = selection.into_finalizer();
let (mut psbt, finalizer) = selection
.into_template(TxTemplateParams::default())
.create_psbt(PsbtBuildParams::default())?;
psbt.sign(&signer, &secp).expect("failed to sign");
assert!(
finalizer.finalize(&mut psbt).is_finalized(),
Expand Down
Loading