solana_block_decoder/message/
message.rs

1use {
2    crate::{
3        errors::{
4            decode_error::DecodeError,
5        },
6        instruction::{
7            CompiledInstruction,
8        },
9        decodable::{
10            Decodable,
11        },
12    },
13    serde_derive::{Deserialize, Serialize},
14    solana_program::short_vec,
15    solana_sdk::{
16        hash::Hash,
17        message::{
18            Message as SolanaMessage,
19            MessageHeader,
20        },
21        pubkey::Pubkey,
22    },
23    solana_transaction_status::UiMessage,
24    std::{
25        str::FromStr,
26    },
27};
28
29#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone)]
30#[serde(rename_all = "camelCase")]
31pub struct Message {
32    /// The message header, identifying signed and read-only `account_keys`.
33    // NOTE: Serialization-related changes must be paired with the direct read at sigverify.
34    pub header: MessageHeader,
35
36    /// All the account keys used by this transaction.
37    #[serde(with = "short_vec")]
38    pub account_keys: Vec<Pubkey>,
39
40    /// The id of a recent ledger entry.
41    pub recent_blockhash: Hash,
42
43    /// Programs that will be executed in sequence and committed in one atomic transaction if all
44    /// succeed.
45    #[serde(with = "short_vec")]
46    pub instructions: Vec<CompiledInstruction>,
47}
48
49impl Decodable for Message {
50    type Encoded = UiMessage;
51    type Decoded = Message;
52
53    fn decode(encoded: &Self::Encoded) -> Result<Self::Decoded, DecodeError> {
54        match encoded {
55            UiMessage::Raw(raw_message) => {
56                let header = raw_message.header;
57                let account_keys: Result<Vec<Pubkey>, _> = raw_message
58                    .account_keys
59                    .iter()
60                    .map(|key_str| key_str.parse())
61                    .collect();
62                let account_keys = account_keys?;
63                let recent_blockhash = Hash::from_str(&raw_message.recent_blockhash)
64                    .map_err(|err| DecodeError::ParseHashFailed(err))?;
65                let instructions: Vec<CompiledInstruction> = raw_message
66                    .instructions
67                    .iter()
68                    // .map(|ui_instruction| (*ui_instruction).into() )
69                    .map(|ui_instruction| ui_instruction.clone().into() )
70                    .collect();
71
72                Ok(Message {
73                    header,
74                    account_keys,
75                    recent_blockhash,
76                    instructions,
77                })
78            }
79            UiMessage::Parsed(_) => {
80                Err(DecodeError::UnsupportedEncoding)
81            }
82        }
83    }
84}
85
86
87impl From<Message> for SolanaMessage {
88    fn from(msg: Message) -> Self {
89        Self {
90            header: msg.header,
91            account_keys: msg.account_keys,
92            recent_blockhash: msg.recent_blockhash,
93            instructions: msg.instructions.into_iter().map(Into::into).collect(),
94        }
95    }
96}