Skip to content
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e2a788c
feat(btc-client): implement Largest-First UTXO selection
romanornr Dec 28, 2025
b6a22d7
refactor(btc-client): optimize select_utxos function
romanornr Dec 30, 2025
91f0103
fix(via_btc_client): add btc inscription output safety floors
romanornr Mar 24, 2026
2bc96f7
fix(via_btc_client): stop reusing unconfirmed change outputs
romanornr Mar 24, 2026
7019c70
feat(via_btc_sender): add config-backed spendability guardrails
romanornr Mar 24, 2026
526fc71
fix(via_btc_client): repair config-backed inscriber build
romanornr Mar 24, 2026
403f38a
feat(via_btc_sender): add adaptive fee policy scaffolding
romanornr Mar 24, 2026
8311aee
feat(via_btc_sender): add stuck inscription rebroadcast path
romanornr Mar 24, 2026
10ed39a
fix(via_btc_sender): address review feedback on policy and retries
romanornr Mar 24, 2026
293e6bc
refactor(via_btc_sender): align policy plumbing with review feedback
romanornr Mar 24, 2026
a351a10
fix(via_btc_client): fall back to full utxo set when needed
romanornr Mar 24, 2026
93ed235
fix(via_btc_sender): address latest copilot feedback
romanornr Mar 24, 2026
459f28c
fix(via_btc_client): tighten policy validation and tests
romanornr Mar 24, 2026
13530a5
refactor(via_btc_client): simplify latest review fixes
romanornr Mar 25, 2026
73bf931
test(via_btc_client): fix truncated utxo fallback coverage
romanornr Mar 25, 2026
6327233
test(via_btc_client): make fallback selection test robust
romanornr Mar 25, 2026
372ea0a
feat(via_btc_sender): add sender chain guardrails
romanornr Mar 25, 2026
560c30f
fix(via_btc_client): tighten selection target and chain guards
romanornr Mar 25, 2026
d819d6e
refactor(via_btc_client): reuse policy constants in defaults
romanornr Mar 25, 2026
6a45737
refactor(via_btc_client): simplify fee candidate calculation
romanornr Mar 25, 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
93 changes: 93 additions & 0 deletions core/lib/config/src/configs/via_btc_sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,36 @@ pub struct ViaBtcSenderConfig {

/// The required time (seconds) to wait before create a proof inscription.
pub block_time_to_proof: Option<u32>,

/// Minimum inscription output value to stay comfortably above dust-like policy floors.
pub min_inscription_output_sats: Option<u64>,

/// Minimum reusable change output value.
pub min_change_output_sats: Option<u64>,

/// Whether unconfirmed reveal-change outputs from the in-memory inscriber context may be reused.
pub allow_unconfirmed_change_reuse: Option<bool>,

/// Minimum feerate for normal inscription construction.
pub min_feerate_sat_vb: Option<u64>,

/// Minimum feerate when the sender is already operating on a pending chain.
pub min_feerate_chained_sat_vb: Option<u64>,

/// Maximum feerate cap to avoid runaway overpay behavior.
pub max_feerate_sat_vb: Option<u64>,

/// Additional sat/vB step applied as pending chain depth grows.
pub escalation_step_sat_vb: Option<u64>,

/// Minimum age before attempting a replacement / re-broadcast for a stuck inscription.
pub escalation_interval_sec: Option<u64>,

/// Max number of pending inscriptions in context before pausing new sends.
pub max_pending_chain_depth: Option<u32>,

/// Do not send new inscriptions when trusted (confirmed) balance goes below this threshold.
pub min_spendable_balance_sats: Option<u64>,
}

impl ViaBtcSenderConfig {
Expand All @@ -60,6 +90,46 @@ impl ViaBtcSenderConfig {
pub fn stuck_inscription_block_number(&self) -> u32 {
self.stuck_inscription_block_number.unwrap_or(6)
}

pub fn min_inscription_output_sats(&self) -> u64 {
self.min_inscription_output_sats.unwrap_or(600)
}

pub fn min_change_output_sats(&self) -> u64 {
self.min_change_output_sats.unwrap_or(1_000)
}

pub fn allow_unconfirmed_change_reuse(&self) -> bool {
self.allow_unconfirmed_change_reuse.unwrap_or(false)
}

pub fn min_feerate_sat_vb(&self) -> u64 {
self.min_feerate_sat_vb.unwrap_or(8)
}

pub fn min_feerate_chained_sat_vb(&self) -> u64 {
self.min_feerate_chained_sat_vb.unwrap_or(20)
}

pub fn max_feerate_sat_vb(&self) -> u64 {
self.max_feerate_sat_vb.unwrap_or(80)
}

pub fn escalation_step_sat_vb(&self) -> u64 {
self.escalation_step_sat_vb.unwrap_or(5)
}

pub fn escalation_interval_sec(&self) -> u64 {
self.escalation_interval_sec.unwrap_or(900)
}

pub fn max_pending_chain_depth(&self) -> u32 {
self.max_pending_chain_depth.unwrap_or(3)
}

pub fn min_spendable_balance_sats(&self) -> u64 {
self.min_spendable_balance_sats.unwrap_or(2_000)
}
}

impl ViaBtcSenderConfig {
Expand All @@ -76,6 +146,29 @@ impl ViaBtcSenderConfig {
block_time_to_commit: None,
block_time_to_proof: None,
stuck_inscription_block_number: None,
min_inscription_output_sats: None,
min_change_output_sats: None,
allow_unconfirmed_change_reuse: None,
min_feerate_sat_vb: None,
min_feerate_chained_sat_vb: None,
max_feerate_sat_vb: None,
escalation_step_sat_vb: None,
escalation_interval_sec: None,
max_pending_chain_depth: None,
min_spendable_balance_sats: None,
}
}
}

#[cfg(test)]
mod tests {
use super::ViaBtcSenderConfig;

#[test]
fn test_guardrail_defaults() {
let config = ViaBtcSenderConfig::for_tests();

assert_eq!(config.max_pending_chain_depth(), 3);
assert_eq!(config.min_spendable_balance_sats(), 2_000);
}
}
2 changes: 2 additions & 0 deletions core/lib/via_btc_client/src/inscriber/internal_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub struct CommitTxInputRes {
pub unlocked_value: Amount,
pub inputs_count: u32,
pub utxo_amounts: Vec<Amount>,
pub fee_rate: u64,
}

#[derive(Debug)]
Expand All @@ -22,6 +23,7 @@ pub struct RevealTxInputRes {
pub prev_outs: Vec<TxOut>,
pub unlock_value: Amount,
pub control_block: ControlBlock,
pub fee_rate: u64,
}

#[derive(Debug)]
Expand Down
Loading
Loading