solana_block_decoder/message/
message_v0.rs1use {
2 crate::{
3 address::{
4 address_table_lookup::MessageAddressTableLookup,
5 },
6 errors::{
7 decode_error::DecodeError,
8 },
9 instruction::{
10 CompiledInstruction,
11 },
12 decodable::{
13 DecodableWithMeta,
14 },
15 },
16 serde_derive::{Deserialize, Serialize},
17 solana_short_vec as short_vec,
18 solana_hash::{
19 Hash,
20 },
21 solana_message::{
22 v0::Message as SolanaMessageV0,
23 MessageHeader,
24 },
25 solana_pubkey::Pubkey,
26 solana_transaction::{
27 versioned::TransactionVersion,
28 },
29 solana_transaction_status_client_types::{
30 UiMessage,
31 UiTransactionEncoding,
32 },
33};
34
35#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone)]
36#[serde(rename_all = "camelCase")]
37pub struct Message {
38 pub header: MessageHeader,
42
43 #[serde(with = "short_vec")]
45 pub account_keys: Vec<Pubkey>,
46
47 pub recent_blockhash: Hash,
49
50 #[serde(with = "short_vec")]
64 pub instructions: Vec<CompiledInstruction>,
65
66 #[serde(with = "short_vec")]
69 pub address_table_lookups: Vec<MessageAddressTableLookup>,
70}
71
72impl DecodableWithMeta for Message {
73 type Encoded = UiMessage;
74 type Decoded = Message;
75
76 fn decode_with_meta(
77 encoded: Self::Encoded,
78 decoding: UiTransactionEncoding,
79 version: Option<TransactionVersion>
80 ) -> Result<Self::Decoded, DecodeError> {
81 match decoding {
82 UiTransactionEncoding::Json => match encoded {
83 UiMessage::Raw(_) => Self::json_decode(encoded, version),
84 UiMessage::Parsed(_) => Err(DecodeError::UnsupportedEncoding),
85 },
86 _ => Err(DecodeError::UnsupportedEncoding),
87 }
88 }
89
90 fn json_decode(encoded: Self::Encoded, _version: Option<TransactionVersion>) -> Result<Self::Decoded, DecodeError> {
91 if let UiMessage::Raw(raw_msg) = encoded {
92 let header = raw_msg.header;
93 let account_keys = raw_msg.account_keys
94 .iter()
95 .map(|s| s.parse::<Pubkey>())
96 .collect::<Result<Vec<_>, _>>()
97 .map_err(|_| DecodeError::InvalidAccountKey)?;
98 let recent_blockhash = raw_msg.recent_blockhash.parse::<Hash>()
99 .map_err(|_| DecodeError::InvalidBlockhash)?;
100 let instructions = raw_msg.instructions
101 .iter()
102 .map(|i| CompiledInstruction::from(i.clone()))
103 .collect::<Vec<_>>();
104 let address_table_lookups = match raw_msg.address_table_lookups {
105 Some(lookups) => lookups
106 .iter()
107 .map(|lookup| MessageAddressTableLookup::try_from(lookup).unwrap())
108 .collect(),
109 None => vec![],
110 };
111
112 Ok(Self {
113 header,
114 account_keys,
115 recent_blockhash,
116 instructions,
117 address_table_lookups,
118 })
119 } else {
120 Err(DecodeError::UnsupportedEncoding)
121 }
122 }
123}
124
125
126impl From<Message> for SolanaMessageV0 {
127 fn from(msg: Message) -> Self {
128 Self {
129 header: msg.header,
130 account_keys: msg.account_keys,
131 recent_blockhash: msg.recent_blockhash,
132 instructions: msg.instructions.into_iter().map(Into::into).collect(),
133 address_table_lookups: msg.address_table_lookups.into_iter().map(Into::into).collect(),
134 }
135 }
136}