testsvm_core/
tx_result.rs1use std::error::Error;
19use std::fmt::Display;
20
21use colored::Colorize;
22use litesvm::types::{FailedTransactionMetadata, TransactionMetadata};
23use solana_sdk::transaction::Transaction;
24
25use solana_address_book::AddressBook;
26
27#[derive(Debug)]
32pub struct TXError {
33 pub transaction: Transaction,
35 pub metadata: FailedTransactionMetadata,
37}
38
39impl Error for TXError {}
40
41impl Display for TXError {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 write!(f, "Transaction failed: {}", self.metadata.err)
44 }
45}
46
47impl TXError {
48 pub fn print_error(&self, address_book: &AddressBook) {
50 println!(
51 "\n{} {}",
52 "❌".red(),
53 "Transaction failed with error:".red().bold()
54 );
55 println!(" {}", format!("{:?}", self.metadata.err).bright_red());
56
57 println!(
58 "\n{} {}",
59 "📜".yellow(),
60 "Transaction Logs:".yellow().bold()
61 );
62 println!(
63 "{}",
64 address_book.replace_addresses_in_text(&self.metadata.meta.pretty_logs())
65 );
66
67 println!(
69 "\n{} {}",
70 "📋".blue(),
71 "Instructions in failed transaction:".blue().bold()
72 );
73 for (i, ix) in self.transaction.message.instructions.iter().enumerate() {
74 let program_id = self.transaction.message.account_keys[ix.program_id_index as usize];
75 println!(
76 " {} {}: {}",
77 "Instruction".dimmed(),
78 i.to_string().bold(),
79 address_book.format_address(&program_id)
80 );
81 println!(
82 " {} {}",
83 "Accounts:".dimmed(),
84 format!("{} total", ix.accounts.len()).cyan()
85 );
86
87 for (j, account_index) in ix.accounts.iter().enumerate() {
89 let account_key = self.transaction.message.account_keys[*account_index as usize];
90 let is_signer = self.transaction.message.is_signer(*account_index as usize);
91 let is_writable = self
92 .transaction
93 .message
94 .is_maybe_writable(*account_index as usize, None);
95
96 let mut flags = Vec::new();
97 if is_signer {
98 flags.push("signer".green().to_string());
99 }
100 if is_writable {
101 flags.push("writable".yellow().to_string());
102 }
103
104 let flags_str = if !flags.is_empty() {
105 format!(" [{}]", flags.join(", "))
106 } else {
107 String::new()
108 };
109
110 println!(
111 " {} {}: {}{}",
112 "Account".dimmed(),
113 j.to_string().bold(),
114 address_book.format_address(&account_key),
115 flags_str
116 );
117 }
118 }
119
120 }
122}
123
124pub type TXResult = Result<TransactionMetadata, Box<TXError>>;