solana_block_decoder/instruction/
compiled_instruction.rs1use {
2 serde_derive::{Deserialize, Serialize},
3 solana_short_vec as short_vec,
4 solana_transaction_status_client_types::{
5 UiCompiledInstruction,
6 }
7};
8
9#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
17#[serde(rename_all = "camelCase")]
18pub struct CompiledInstruction {
19 pub program_id_index: u8,
21 #[serde(with = "short_vec")]
23 pub accounts: Vec<u8>,
24 #[serde(with = "short_vec")]
26 pub data: Vec<u8>,
27}
28
29impl From<UiCompiledInstruction> for CompiledInstruction {
30 fn from(ui_compiled_instruction: UiCompiledInstruction) -> Self {
31 Self {
32 program_id_index: ui_compiled_instruction.program_id_index,
33 accounts: ui_compiled_instruction.accounts,
34 data: bs58::decode(ui_compiled_instruction.data).into_vec().unwrap(),
35 }
36 }
37}
38
39impl From<CompiledInstruction> for solana_message::compiled_instruction::CompiledInstruction {
40 fn from(instr: CompiledInstruction) -> Self {
41 Self {
42 program_id_index: instr.program_id_index,
43 accounts: instr.accounts,
44 data: instr.data,
45 }
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52 use serde_json;
53 use solana_transaction_status_client_types::UiCompiledInstruction;
54 use solana_message::compiled_instruction::CompiledInstruction as SolanaCompiledInstruction;
55 use bs58;
56
57 #[test]
58 fn test_serialization_deserialization() {
59 let instr = CompiledInstruction {
60 program_id_index: 1,
61 accounts: vec![0, 1, 2],
62 data: vec![10, 20, 30],
63 };
64
65 let json = serde_json::to_string(&instr).unwrap();
66 let deserialized: CompiledInstruction = serde_json::from_str(&json).unwrap();
67
68 assert_eq!(instr, deserialized);
69 }
70
71 #[test]
72 fn test_from_ui_compiled_instruction_valid() {
73 let ui_instr = UiCompiledInstruction {
74 program_id_index: 2,
75 accounts: vec![3, 4, 5],
76 data: bs58::encode(vec![100, 101, 102]).into_string(),
77 stack_height: None,
78 };
79
80 let compiled_instr: CompiledInstruction = ui_instr.clone().into();
81
82 assert_eq!(compiled_instr.program_id_index, ui_instr.program_id_index);
83 assert_eq!(compiled_instr.accounts, ui_instr.accounts);
84 assert_eq!(compiled_instr.data, vec![100, 101, 102]);
85 }
86
87 #[test]
88 fn test_from_ui_compiled_instruction_invalid_base58() {
89 let ui_instr = UiCompiledInstruction {
90 program_id_index: 0,
91 accounts: vec![0],
92 data: "invalid_base58".to_string(),
93 stack_height: None,
94 };
95
96 let result = std::panic::catch_unwind(|| {
97 let _compiled_instr: CompiledInstruction = ui_instr.into();
98 });
99
100 assert!(result.is_err());
101 }
102
103 #[test]
104 fn test_from_compiled_instruction_to_solana_compiled_instruction() {
105 let instr = CompiledInstruction {
106 program_id_index: 3,
107 accounts: vec![6, 7, 8],
108 data: vec![9, 10, 11],
109 };
110
111 let solana_instr: SolanaCompiledInstruction = instr.clone().into();
112
113 assert_eq!(solana_instr.program_id_index, instr.program_id_index);
114 assert_eq!(solana_instr.accounts, instr.accounts);
115 assert_eq!(solana_instr.data, instr.data);
116 }
117}