1use base64::Engine;
2use solana_primitives::types::VersionedTransaction;
3
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 let tx = "ATU3t4TX00FNb4aqeojTYpIOZFQFED4pdoviPCBxUsEXwKHRbHBmmgsyEsDyjXREHGYAWlq13q4WzF5JDOvsBwKAAQAICwzd9xRZ1DCfrYBfTdgj38msCBn1maih1JKu7vCovzzacU2yFtM8/6xky5bNOdOL9vYNQWxOAtjDd8qJeKlPPJIXZyoBm/f1Y2xMsGa3gRLrL4a5Ba4vtFtLcOU1pWTT4wVKU1qZKSEGTSTocWDaOHx8NbXdvJK7geQfqEBBBUSNAwZGb+UhFzL/7K26csOb57yM5bvF9xJrLEObOkAAAAAGxoMMVxwvPwb8Y6KPKojQO9MxPeq3HTSRmeyRYk5jPwlU276eyWDJinopP+ITNpZv4YDRUa5LgXlWH4mFSlP2fhcCyQN7oqc4HZ+5zm3xXQ/FTXS7cxGfivEvGQwOFb4pA2InHkw7ace1KQX3P6I/rhhBsIayFI80eInx/pUv4R7U/fA1on6uX4cAPWh+6q5kflQbDzfTC/LJrf1AdS22d3DH2Q4dNNF2yrr6HjJmXJlYvanqTxxULDNngUZsJSq7g2zxeB7onMepv2C8TaiFnhOPYyeceZ5GEIyJx6r0FAYDADExNzQ2NzAxMDg2MTA0fDMzODYzMjQ4M3wxNzQ2NzAxMDg2MTEzfDMzODYzMjQ4M3xwBAAFApZUAgAEAAkDUMMAAAAAAAAFAgEAGFj16I5t+vX/F0jWAAAAAAAjixxoAAAAAAYMCwIABwgJCgwNDg8QDu7hX57jZwjCAQEBAQAABgwLAgAHCAkKDA0ODxBcPD8yewzFPL4CAAAAAQEAAACE1xcAAAAABAExPRcAAAABAAADAAEtixxoAAAAAAAAAAAAAAEBAQA0kqIPAAAAAPJZLkAXAAAAAQAAAwABLYscaAAAAAAAAAAAAAAB3E42Kl7pkP+vCgX6bK+0TFMtWHz2EUnYgJSxOMI1cDcABoNbXAMFAQ==";
7
8 let tx_bytes = base64::engine::general_purpose::STANDARD.decode(tx)?;
10
11 println!("Transaction bytes length: {}", tx_bytes.len());
13 println!("First byte (signature count): 0x{:02x}", tx_bytes[0]);
14
15 match VersionedTransaction::deserialize_with_version(&tx_bytes) {
17 Ok(decoded_tx) => {
18 println!("✅ Successfully decoded transaction from wire format");
19 print_versioned_transaction(&decoded_tx);
20 }
21 Err(e) => {
22 println!("❌ Failed to decode transaction: {e}");
23 }
24 }
25
26 Ok(())
27}
28
29fn print_versioned_transaction(tx: &VersionedTransaction) {
30 match tx {
31 VersionedTransaction::Legacy {
32 signatures,
33 message,
34 } => {
35 println!("Transaction Type: Legacy");
36 println!("Number of signatures: {}", signatures.len());
37 for (i, sig) in signatures.iter().enumerate() {
38 println!("Signature {}: {}", i + 1, sig.to_base58());
39 }
40
41 println!("\nMessage header:");
42 println!(
43 " Required signatures: {}",
44 message.header.num_required_signatures
45 );
46 println!(
47 " Readonly signed accounts: {}",
48 message.header.num_readonly_signed_accounts
49 );
50 println!(
51 " Readonly unsigned accounts: {}",
52 message.header.num_readonly_unsigned_accounts
53 );
54
55 println!("\nAccount keys: {}", message.account_keys.len());
56 for (i, key) in message.account_keys.iter().enumerate() {
57 println!(" Account {}: {}", i, key.to_base58());
58 }
59
60 println!(
61 "\nRecent blockhash: {}",
62 bs58::encode(&message.recent_blockhash).into_string()
63 );
64
65 println!("\nInstructions: {}", message.instructions.len());
66 for (i, instruction) in message.instructions.iter().enumerate() {
67 println!("\nInstruction {}:", i + 1);
68 println!(" Program ID Index: {}", instruction.program_id_index);
69 println!(" Account Indices: {:?}", instruction.accounts);
70 println!(
71 " Data (bs58): {}",
72 bs58::encode(&instruction.data).into_string()
73 );
74 println!(
75 " Data (utf8): {}",
76 String::from_utf8_lossy(&instruction.data)
77 );
78 }
79 }
80 VersionedTransaction::V0 {
81 signatures,
82 message,
83 } => {
84 println!("Transaction Type: V0");
85 println!("Number of signatures: {}", signatures.len());
86 for (i, sig) in signatures.iter().enumerate() {
87 println!("Signature {}: {}", i + 1, sig.to_base58());
88 }
89
90 println!("\nMessage header:");
91 println!(
92 " Required signatures: {}",
93 message.header.num_required_signatures
94 );
95 println!(
96 " Readonly signed accounts: {}",
97 message.header.num_readonly_signed_accounts
98 );
99 println!(
100 " Readonly unsigned accounts: {}",
101 message.header.num_readonly_unsigned_accounts
102 );
103
104 println!("\nAccount keys: {}", message.account_keys.len());
105 for (i, key) in message.account_keys.iter().enumerate() {
106 println!(" Account {}: {}", i, key.to_base58());
107 }
108
109 println!(
110 "\nRecent blockhash: {}",
111 bs58::encode(&message.recent_blockhash).into_string()
112 );
113
114 println!("\nInstructions: {}", message.instructions.len());
115 for (i, instruction) in message.instructions.iter().enumerate() {
116 println!("\nInstruction {}:", i + 1);
117 println!(" Program ID Index: {}", instruction.program_id_index);
118 println!(" Account Indices: {:?}", instruction.accounts);
119 println!(
120 " Data (bs58): {}",
121 bs58::encode(&instruction.data).into_string()
122 );
123 println!(
124 " Data (utf8): {}",
125 String::from_utf8_lossy(&instruction.data)
126 );
127 }
128
129 if !message.address_table_lookups.is_empty() {
130 println!(
131 "\nAddress Table Lookups: {}",
132 message.address_table_lookups.len()
133 );
134 for (i, lookup) in message.address_table_lookups.iter().enumerate() {
135 println!("\nLookup Table {}:", i + 1);
136 println!(" Table Key: {}", lookup.account_key.to_base58());
137 println!(" Writable Indexes: {:?}", lookup.writable_indexes);
138 println!(" Readonly Indexes: {:?}", lookup.readonly_indexes);
139 }
140 }
141 }
142 }
143}