pub const DUST_THRESHOLD_P2PKH: u64 = 546;
pub const DUST_THRESHOLD_P2WPKH: u64 = 294;
pub mod input_vsize {
pub const P2PKH: usize = 148;
pub const P2WPKH: usize = 68;
pub const P2TR: usize = 58;
}
pub mod output_size {
pub const P2PKH: usize = 34;
pub const P2WPKH: usize = 31;
pub const P2TR: usize = 43;
}
pub const TX_OVERHEAD: usize = 10;
pub const SEGWIT_OVERHEAD: usize = 2;
pub fn estimate_vsize(
num_p2pkh_inputs: usize,
num_p2wpkh_inputs: usize,
num_outputs: usize,
) -> usize {
let input_size = num_p2pkh_inputs * input_vsize::P2PKH
+ num_p2wpkh_inputs * input_vsize::P2WPKH;
let output_size = num_outputs * output_size::P2PKH;
let has_segwit = num_p2wpkh_inputs > 0;
let overhead = TX_OVERHEAD + if has_segwit { SEGWIT_OVERHEAD } else { 0 };
overhead + input_size + output_size
}
pub fn calculate_fee(vsize: usize, sat_per_vb: u64) -> u64 {
(vsize as u64) * sat_per_vb
}
pub fn estimate_fee(num_inputs: usize, num_outputs: usize, sat_per_vb: u64) -> u64 {
let vsize = estimate_vsize(0, num_inputs, num_outputs);
calculate_fee(vsize, sat_per_vb)
}
pub fn is_dust(value: u64, is_segwit: bool) -> bool {
let threshold = if is_segwit {
DUST_THRESHOLD_P2WPKH
} else {
DUST_THRESHOLD_P2PKH
};
value < threshold
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_estimate_vsize() {
let vsize = estimate_vsize(0, 1, 2);
assert!(vsize > 0);
assert!(vsize < 200);
}
#[test]
fn test_calculate_fee() {
let fee = calculate_fee(100, 10);
assert_eq!(fee, 1000);
}
#[test]
fn test_is_dust() {
assert!(is_dust(100, false));
assert!(!is_dust(1000, false));
assert!(is_dust(100, true));
assert!(!is_dust(500, true));
}
}