breez_sdk_liquid/payjoin/
network_fee.rs1pub const MIN_FEE_RATE: f64 = 0.1;
2
3pub const WEIGHT_FIXED: usize = 222;
4pub const WEIGHT_VIN_SINGLE_SIG_NATIVE: usize = 275;
5pub const WEIGHT_VIN_SINGLE_SIG_NESTED: usize = 367;
6pub const WEIGHT_VOUT_NESTED: usize = 270;
7
8pub fn weight_to_vsize(weight: usize) -> usize {
9 (weight + 3) / 4
10}
11
12pub fn vsize_to_fee(vsize: usize, fee_rate: f64) -> u64 {
13 (vsize as f64 * fee_rate).ceil() as u64
14}
15
16pub fn weight_to_fee(weight: usize, fee_rate: f64) -> u64 {
17 vsize_to_fee(weight_to_vsize(weight), fee_rate)
18}
19
20#[derive(Copy, Clone, Default)]
21pub struct TxFee {
22 pub server_inputs: usize,
23 pub user_inputs: usize,
24 pub outputs: usize,
25}
26
27impl TxFee {
28 pub fn tx_weight(&self) -> usize {
29 let TxFee {
30 server_inputs,
31 user_inputs,
32 outputs,
33 } = self;
34 WEIGHT_FIXED
35 + WEIGHT_VIN_SINGLE_SIG_NATIVE * server_inputs
36 + WEIGHT_VIN_SINGLE_SIG_NESTED * user_inputs
37 + WEIGHT_VOUT_NESTED * outputs
38 }
39
40 pub fn fee(&self) -> u64 {
41 weight_to_fee(self.tx_weight(), MIN_FEE_RATE)
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[cfg(all(target_family = "wasm", target_os = "unknown"))]
50 wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
51
52 #[sdk_macros::test_all]
53 fn test_weight_to_vsize() {
54 assert_eq!(weight_to_vsize(4), 1);
55 assert_eq!(weight_to_vsize(5), 2);
56 assert_eq!(weight_to_vsize(7), 2);
57 assert_eq!(weight_to_vsize(8), 2);
58 assert_eq!(weight_to_vsize(9), 3);
59 assert_eq!(weight_to_vsize(1000), 250);
60 }
61
62 #[sdk_macros::test_all]
63 fn test_vsize_to_fee() {
64 assert_eq!(vsize_to_fee(100, 1.0), 100);
65 assert_eq!(vsize_to_fee(100, 0.5), 50);
66 assert_eq!(vsize_to_fee(100, 0.1), 10);
67 assert_eq!(vsize_to_fee(100, 0.11), 11);
68 assert_eq!(vsize_to_fee(100, 0.15), 15);
69 assert_eq!(vsize_to_fee(100, 0.151), 16);
70 }
71
72 #[sdk_macros::test_all]
73 fn test_weight_to_fee() {
74 assert_eq!(weight_to_fee(400, 1.0), 100);
75 assert_eq!(weight_to_fee(400, 0.5), 50);
76 assert_eq!(weight_to_fee(401, 1.0), 101);
77 assert_eq!(weight_to_fee(399, 1.0), 100);
78 }
79
80 #[sdk_macros::test_all]
81 fn test_tx_fee_calculation() {
82 let fee = TxFee {
83 server_inputs: 1,
84 user_inputs: 1,
85 outputs: 2,
86 };
87
88 assert_eq!(
89 fee.tx_weight(),
90 WEIGHT_FIXED
91 + WEIGHT_VIN_SINGLE_SIG_NATIVE
92 + WEIGHT_VIN_SINGLE_SIG_NESTED
93 + 2 * WEIGHT_VOUT_NESTED
94 );
95
96 let empty_fee = TxFee::default();
97 assert_eq!(empty_fee.tx_weight(), WEIGHT_FIXED);
98 assert_eq!(empty_fee.fee(), weight_to_fee(WEIGHT_FIXED, MIN_FEE_RATE));
99
100 let complex_fee = TxFee {
101 server_inputs: 3,
102 user_inputs: 2,
103 outputs: 4,
104 };
105 assert_eq!(
106 complex_fee.tx_weight(),
107 WEIGHT_FIXED
108 + 3 * WEIGHT_VIN_SINGLE_SIG_NATIVE
109 + 2 * WEIGHT_VIN_SINGLE_SIG_NESTED
110 + 4 * WEIGHT_VOUT_NESTED
111 );
112 }
113}