1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
pub mod thread;
pub mod explorer;
use std::fmt::{Debug, Display, Formatter};
use anchor_lang::{prelude::Pubkey, prelude::*, AnchorDeserialize};
use base64;
#[derive(AnchorDeserialize, AnchorSerialize, Clone, Debug)]
pub struct CrateInfo {
pub spec: String,
pub blob: String,
}
impl Display for CrateInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "spec:{} blob:{}", self.spec, self.blob)
}
}
pub trait ProgramLogsDeserializable {
fn try_from_program_logs(
program_logs: Vec<String>,
program_id: &Pubkey,
) -> std::result::Result<Self, ErrorCode>
where
Self: Sized;
}
impl<T> ProgramLogsDeserializable for T
where
T: AnchorDeserialize,
{
fn try_from_program_logs(
program_logs: Vec<String>,
program_id: &Pubkey,
) -> std::result::Result<T, ErrorCode> {
let preimage = format!("Program return: {} ", program_id.to_string());
let get_return_data_base64 = program_logs
.iter()
.find(|&s| s.starts_with(&preimage))
.ok_or(ErrorCode::AccountDidNotDeserialize)?
.strip_prefix(&preimage)
.ok_or(ErrorCode::AccountDidNotDeserialize)?;
let decoded = base64::decode(get_return_data_base64)
.map_err(|_err| ErrorCode::AccountDidNotDeserialize)?;
T::try_from_slice(&decoded).map_err(|_err| ErrorCode::AccountDidNotDeserialize)
}
}