1use std::str::FromStr;
2
3use base64::{prelude::BASE64_STANDARD, Engine};
4use solana_pubkey::Pubkey;
5
6use crate::{
7 raw_log::{
8 RawCuLog, RawDataLog, RawFailedLog, RawInvokeLog, RawLog, RawOtherLog, RawProgramLog,
9 RawReturnLog, RawSuccessLog,
10 },
11 Result,
12};
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum ParsedLog {
16 Invoke(ParsedInvokeLog),
17 Success(ParsedSuccessLog),
18 Failed(ParsedFailedLog),
19 Log(ParsedProgramLog),
20 Data(ParsedDataLog),
21 Return(ParsedReturnLog),
22 Cu(ParsedCuLog),
23 Other(ParsedOtherLog),
24}
25
26impl ParsedLog {
27 pub fn from_raw(raw: &RawLog) -> Result<Self> {
28 match raw {
29 RawLog::Invoke(log) => ParsedInvokeLog::from_raw(log).map(ParsedLog::from),
30 RawLog::Success(log) => ParsedSuccessLog::from_raw(log).map(ParsedLog::from),
31 RawLog::Failed(log) => ParsedFailedLog::from_raw(log).map(ParsedLog::from),
32 RawLog::Log(log) => ParsedProgramLog::from_raw(log).map(ParsedLog::from),
33 RawLog::Data(log) => ParsedDataLog::from_raw(log).map(ParsedLog::from),
34 RawLog::Return(log) => ParsedReturnLog::from_raw(log).map(ParsedLog::from),
35 RawLog::Cu(log) => ParsedCuLog::from_raw(log).map(ParsedLog::from),
36 RawLog::Other(log) => ParsedOtherLog::from_raw(log).map(ParsedLog::from),
37 }
38 }
39}
40
41impl From<ParsedInvokeLog> for ParsedLog {
42 fn from(value: ParsedInvokeLog) -> Self {
43 ParsedLog::Invoke(value)
44 }
45}
46
47impl From<ParsedSuccessLog> for ParsedLog {
48 fn from(value: ParsedSuccessLog) -> Self {
49 ParsedLog::Success(value)
50 }
51}
52impl From<ParsedFailedLog> for ParsedLog {
53 fn from(value: ParsedFailedLog) -> Self {
54 ParsedLog::Failed(value)
55 }
56}
57impl From<ParsedProgramLog> for ParsedLog {
58 fn from(value: ParsedProgramLog) -> Self {
59 ParsedLog::Log(value)
60 }
61}
62impl From<ParsedDataLog> for ParsedLog {
63 fn from(value: ParsedDataLog) -> Self {
64 ParsedLog::Data(value)
65 }
66}
67impl From<ParsedReturnLog> for ParsedLog {
68 fn from(value: ParsedReturnLog) -> Self {
69 ParsedLog::Return(value)
70 }
71}
72impl From<ParsedCuLog> for ParsedLog {
73 fn from(value: ParsedCuLog) -> Self {
74 ParsedLog::Cu(value)
75 }
76}
77
78impl From<ParsedOtherLog> for ParsedLog {
79 fn from(value: ParsedOtherLog) -> Self {
80 ParsedLog::Other(value)
81 }
82}
83#[derive(Debug, Clone, PartialEq, Eq)]
87pub struct ParsedInvokeLog {
88 pub raw: String,
89 pub program_id: Pubkey,
90 pub depth: u8,
91}
92
93impl ParsedInvokeLog {
94 pub fn from_raw(log: &RawInvokeLog) -> Result<Self> {
95 Ok(ParsedInvokeLog {
96 raw: log.raw.to_string(),
97 program_id: Pubkey::from_str(log.program_id)?,
98 depth: log.depth,
99 })
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq)]
107pub struct ParsedSuccessLog {
108 pub raw: String,
109 pub program_id: Pubkey,
110}
111
112impl ParsedSuccessLog {
113 pub fn from_raw(log: &RawSuccessLog) -> Result<Self> {
114 Ok(ParsedSuccessLog {
115 raw: log.raw.to_string(),
116 program_id: Pubkey::from_str(log.program_id)?,
117 })
118 }
119}
120
121#[derive(Debug, Clone, PartialEq, Eq)]
125pub struct ParsedFailedLog {
126 pub raw: String,
127 pub program_id: Pubkey,
128 pub err: String,
129}
130
131impl ParsedFailedLog {
132 pub fn from_raw(log: &RawFailedLog) -> Result<Self> {
133 Ok(ParsedFailedLog {
134 raw: log.raw.to_string(),
135 program_id: Pubkey::from_str(log.program_id)?,
136 err: log.err.to_string(),
137 })
138 }
139}
140
141#[derive(Debug, Clone, PartialEq, Eq)]
145pub struct ParsedProgramLog {
146 pub raw: String,
147 pub msg: String,
148}
149
150impl ParsedProgramLog {
151 pub fn from_raw(log: &RawProgramLog) -> Result<Self> {
152 Ok(ParsedProgramLog {
153 raw: log.raw.to_string(),
154 msg: log.msg.to_string(),
155 })
156 }
157}
158
159#[derive(Debug, Clone, PartialEq, Eq)]
163pub struct ParsedDataLog {
164 pub raw: String,
165 pub data: Vec<u8>,
166}
167
168impl ParsedDataLog {
169 pub fn from_raw(log: &RawDataLog) -> Result<Self> {
170 Ok(ParsedDataLog {
171 raw: log.raw.to_string(),
172 data: BASE64_STANDARD.decode(log.data)?,
173 })
174 }
175}
176
177#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct ParsedReturnLog {
182 pub raw: String,
183 pub program_id: Pubkey,
184 pub data: Vec<u8>,
185}
186
187impl ParsedReturnLog {
188 pub fn from_raw(log: &RawReturnLog) -> Result<Self> {
189 Ok(ParsedReturnLog {
190 raw: log.raw.to_string(),
191 program_id: Pubkey::from_str(log.program_id)?,
192 data: BASE64_STANDARD.decode(log.data)?,
193 })
194 }
195}
196
197#[derive(Debug, Clone, PartialEq, Eq)]
201pub struct ParsedCuLog {
202 pub raw: String,
203 pub program_id: Pubkey,
204 pub consumed: u64,
205 pub budget: u64,
206}
207
208impl ParsedCuLog {
209 pub fn from_raw(log: &RawCuLog) -> Result<Self> {
210 Ok(ParsedCuLog {
211 raw: log.raw.to_string(),
212 program_id: Pubkey::from_str(log.program_id)?,
213 consumed: log.consumed,
214 budget: log.budget,
215 })
216 }
217}
218
219#[derive(Debug, Clone, PartialEq, Eq)]
220pub struct ParsedOtherLog {
221 pub raw: String,
222}
223
224impl ParsedOtherLog {
225 pub fn from_raw(log: &RawOtherLog) -> Result<Self> {
226 Ok(ParsedOtherLog {
227 raw: log.raw.to_string(),
228 })
229 }
230}
231
232mod helper_code {
237 use solana_pubkey::Pubkey;
238
239 use crate::structured_log::{
240 ComputeUnitsLog, FailedLog, InvokeLog, Log, ReturnLog, SuccessLog,
241 };
242
243 use super::{
244 ParsedCuLog, ParsedDataLog, ParsedFailedLog, ParsedInvokeLog, ParsedOtherLog,
245 ParsedProgramLog, ParsedReturnLog, ParsedSuccessLog,
246 };
247
248 impl Log for ParsedInvokeLog {
249 type RawLog = String;
250
251 fn raw_log(&self) -> Self::RawLog {
252 self.raw.clone()
253 }
254 }
255
256 impl Log for ParsedSuccessLog {
257 type RawLog = String;
258
259 fn raw_log(&self) -> Self::RawLog {
260 self.raw.clone()
261 }
262 }
263
264 impl Log for ParsedFailedLog {
265 type RawLog = String;
266
267 fn raw_log(&self) -> Self::RawLog {
268 self.raw.clone()
269 }
270 }
271
272 impl Log for ParsedProgramLog {
273 type RawLog = String;
274
275 fn raw_log(&self) -> Self::RawLog {
276 self.raw.clone()
277 }
278 }
279
280 impl Log for ParsedDataLog {
281 type RawLog = String;
282
283 fn raw_log(&self) -> Self::RawLog {
284 self.raw.clone()
285 }
286 }
287
288 impl Log for ParsedReturnLog {
289 type RawLog = String;
290
291 fn raw_log(&self) -> Self::RawLog {
292 self.raw.clone()
293 }
294 }
295
296 impl Log for ParsedCuLog {
297 type RawLog = String;
298
299 fn raw_log(&self) -> Self::RawLog {
300 self.raw.clone()
301 }
302 }
303
304 impl Log for ParsedOtherLog {
305 type RawLog = String;
306
307 fn raw_log(&self) -> Self::RawLog {
308 self.raw.clone()
309 }
310 }
311
312 impl InvokeLog for ParsedInvokeLog {
313 type ProgramId = Pubkey;
314
315 fn program_id(&self) -> Self::ProgramId {
316 self.program_id
317 }
318
319 fn depth(&self) -> u8 {
320 self.depth
321 }
322 }
323
324 impl SuccessLog for ParsedSuccessLog {
325 type ProgramId = Pubkey;
326
327 fn program_id(&self) -> Self::ProgramId {
328 self.program_id
329 }
330 }
331
332 impl FailedLog for ParsedFailedLog {
333 type ProgramId = Pubkey;
334 type Err = String;
335
336 fn program_id(&self) -> Self::ProgramId {
337 self.program_id
338 }
339
340 fn err(&self) -> Self::Err {
341 self.err.clone()
342 }
343 }
344
345 impl ReturnLog for ParsedReturnLog {
346 type ProgramId = Pubkey;
347 type Data = Vec<u8>;
348
349 fn program_id(&self) -> Self::ProgramId {
350 self.program_id
351 }
352
353 fn data(&self) -> Self::Data {
354 self.data.clone()
355 }
356 }
357
358 impl ComputeUnitsLog for ParsedCuLog {
359 type ProgramId = Pubkey;
360
361 fn program_id(&self) -> Self::ProgramId {
362 self.program_id
363 }
364 }
365}