anvil_zksync_core/formatter/transaction/
summary.rs1use std::fmt::Display;
7
8use anvil_zksync_common::utils::cost::{format_eth, format_gwei};
9use zksync_multivm::interface::VmExecutionResultAndLogs;
10use zksync_types::{Address, Transaction, H256, U256};
11
12use crate::utils::to_human_size;
13
14use super::{
15 balance_diff::{BalanceDiff, BalanceDiffRepr},
16 status::TransactionStatus,
17};
18
19struct TransactionContext {
24 l2_gas_price: u64,
26}
27
28struct GasDetails {
35 limit: U256,
36 used: U256,
37 refunded: u64,
38}
39
40pub struct TransactionSummary {
46 status: TransactionStatus,
48 tx_hash: H256,
50 initiator: Address,
52 payer: Address,
54 context: TransactionContext,
56 gas: GasDetails,
58 balance_diffs: Option<Vec<BalanceDiff>>,
60}
61
62impl TransactionSummary {
63 pub fn new(
71 l2_gas_price: u64,
72 tx: &Transaction,
73 tx_result: &VmExecutionResultAndLogs,
74 balance_diffs: Option<Vec<BalanceDiff>>,
75 ) -> Self {
76 let status: TransactionStatus = (&tx_result.result).into();
77 let tx_hash = tx.hash();
78 let initiator = tx.initiator_account();
79 let payer = tx.payer();
80
81 let used = tx.gas_limit() - tx_result.refunds.gas_refunded;
82 let limit = tx.gas_limit();
83 let refunded = tx_result.refunds.gas_refunded;
84
85 Self {
86 status,
87 tx_hash,
88 initiator,
89 payer,
90 context: TransactionContext { l2_gas_price },
91 gas: GasDetails {
92 limit,
93 used,
94 refunded,
95 },
96 balance_diffs,
97 }
98 }
99}
100
101impl Display for TransactionSummary {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 let Self {
104 status,
105 tx_hash,
106 initiator,
107 payer,
108 context: TransactionContext { l2_gas_price },
109 gas,
110 balance_diffs,
111 } = self;
112
113 let paid = U256::from(*l2_gas_price) * gas.used;
115 let refunded = U256::from(*l2_gas_price) * gas.refunded;
116
117 let gas_used = gas.used;
119 let gas_limit_human = to_human_size(gas.limit);
120 let gas_used_human = to_human_size(gas.used);
121 let gas_refunded_human = to_human_size(gas.refunded.into());
122 let emoji = self.status.emoji();
123 let l2_gas_price_human = format_gwei(self.context.l2_gas_price.into());
124
125 write!(
127 f,
128 r#"
129{emoji} [{status}] Hash: {tx_hash:?}
130Initiator: {initiator:?}
131Payer: {payer:?}
132Gas Limit: {gas_limit_human} | Used: {gas_used_human} | Refunded: {gas_refunded_human}
133Paid: {paid_in_eth} ({gas_used} gas * {l2_gas_price_human})
134Refunded: {refunded_in_eth}
135"#,
136 paid_in_eth = format_eth(paid),
137 refunded_in_eth = format_eth(refunded),
138 )?;
139
140 if let Some(balance_diffs) = balance_diffs {
141 if !balance_diffs.is_empty() {
142 let mut balance_diffs_formatted_table = tabled::Table::new(
143 balance_diffs
144 .iter()
145 .map(Into::<BalanceDiffRepr>::into)
146 .collect::<Vec<_>>(),
147 );
148 balance_diffs_formatted_table.with(tabled::settings::Style::modern());
149
150 write!(f, "\n{balance_diffs_formatted_table}")?;
151 }
152 }
153 Ok(())
154 }
155}