1use monero_oxide::transaction::{Input, Transaction};
4
5pub fn tx_fee(tx: &Transaction) -> u64 {
11 let mut fee = 0_u64;
12
13 match &tx {
14 Transaction::V1 { prefix, .. } => {
15 for input in &prefix.inputs {
16 match input {
17 Input::Gen(_) => return 0,
18 Input::ToKey { amount, .. } => {
19 fee = fee.checked_add(amount.unwrap_or(0)).unwrap();
20 }
21 }
22 }
23
24 for output in &prefix.outputs {
25 fee = fee.checked_sub(output.amount.unwrap_or(0)).unwrap();
26 }
27 }
28 Transaction::V2 { proofs, .. } => {
29 fee = proofs.as_ref().unwrap().base.fee;
30 }
31 }
32
33 fee
34}
35
36#[cfg(test)]
37mod test {
38 use monero_oxide::{
39 io::CompressedPoint,
40 transaction::{NotPruned, Output, Timelock, TransactionPrefix},
41 };
42
43 use super::*;
44
45 #[test]
46 #[should_panic(expected = "called `Option::unwrap()` on a `None` value")]
47 fn tx_fee_panic() {
48 let input = Input::ToKey {
49 amount: Some(u64::MAX),
50 key_offsets: vec![],
51 key_image: CompressedPoint([0; 32]),
52 };
53
54 let output = Output {
55 amount: Some(u64::MAX),
56 key: CompressedPoint([0; 32]),
57 view_tag: None,
58 };
59
60 let tx = Transaction::<NotPruned>::V1 {
61 prefix: TransactionPrefix {
62 additional_timelock: Timelock::None,
63 inputs: vec![input; 2],
64 outputs: vec![output],
65 extra: vec![],
66 },
67 signatures: vec![],
68 };
69
70 tx_fee(&tx);
71 }
72}