solana_block_decoder/block/
confirmed_block.rs

1
2use {
3    crate::{
4        errors::{
5            decode_error::DecodeError,
6        },
7        decodable::Decodable,
8        transaction::{
9            versioned_transaction::VersionedTransactionWithStatusMeta,
10        },
11        block::{
12            encoded_block::EncodedTransactionWithStatusMeta,
13            ui_block::UiConfirmedBlock,
14        },
15        transaction::{
16            transaction::{Transaction},
17        }
18    },
19    solana_clock::{
20        Slot,
21        UnixTimestamp,
22    },
23    solana_transaction_status::{
24        BlockEncodingOptions,
25    },
26    solana_transaction_status_client_types::{
27        UiTransactionEncoding,
28        TransactionDetails,
29        Rewards,
30    },
31    serde_derive::{Serialize,Deserialize},
32};
33
34#[derive(Clone, Debug, PartialEq)]
35pub struct ConfirmedBlock {
36    pub previous_blockhash: String,
37    pub blockhash: String,
38    pub parent_slot: Slot,
39    pub transactions: Vec<TransactionWithStatusMeta>,
40    pub rewards: Rewards,
41    pub num_partitions: Option<u64>,
42    pub block_time: Option<UnixTimestamp>,
43    pub block_height: Option<u64>,
44}
45
46impl ConfirmedBlock {
47    pub fn decode_with_options(
48        ui_confirmed_block: UiConfirmedBlock,
49        encoding: UiTransactionEncoding,
50        options: BlockEncodingOptions,
51    ) -> Result<Self, DecodeError> {
52        let transactions = match options.transaction_details {
53            TransactionDetails::Full => {
54                let transactions = ui_confirmed_block
55                    .transactions
56                    .ok_or(DecodeError::InvalidEncoding)?
57                    .into_iter()
58                    .map(|encoded_tx_with_meta| {
59                        TransactionWithStatusMeta::decode(encoded_tx_with_meta, encoding)
60                    })
61                    .collect::<Result<Vec<_>, _>>()?;
62                transactions
63            }
64            TransactionDetails::Signatures => {
65                let _signatures = ui_confirmed_block
66                    .signatures
67                    .ok_or(DecodeError::InvalidEncoding)?;
68                // Implement a method or mechanism to retrieve transactions using signatures
69                return Err(DecodeError::NotImplemented);
70            }
71            TransactionDetails::None => Vec::new(),
72            TransactionDetails::Accounts => {
73                let transactions = ui_confirmed_block
74                    .transactions
75                    .ok_or(DecodeError::InvalidEncoding)?
76                    .into_iter()
77                    .map(|encoded_tx_with_meta| {
78                        TransactionWithStatusMeta::decode(encoded_tx_with_meta, encoding)
79                    })
80                    .collect::<Result<Vec<_>, _>>()?;
81                transactions
82            }
83        };
84
85        Ok(ConfirmedBlock {
86            previous_blockhash: ui_confirmed_block.previous_blockhash,
87            blockhash: ui_confirmed_block.blockhash,
88            parent_slot: ui_confirmed_block.parent_slot,
89            transactions,
90            rewards: ui_confirmed_block
91                .rewards
92                .unwrap_or_default(),
93            num_partitions: ui_confirmed_block.num_reward_partitions,
94            block_time: ui_confirmed_block.block_time,
95            block_height: ui_confirmed_block.block_height,
96        })
97    }
98}
99
100
101#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
102#[allow(clippy::large_enum_variant)]
103pub enum TransactionWithStatusMeta {
104    // Very old transactions may be missing metadata
105    MissingMetadata(Transaction),
106    // Versioned stored transaction always have metadata
107    Complete(VersionedTransactionWithStatusMeta),
108}
109
110impl TransactionWithStatusMeta {
111    pub fn decode(
112        encoded: EncodedTransactionWithStatusMeta,
113        encoding: UiTransactionEncoding,
114    ) -> Result<Self, DecodeError> {
115        match encoded.meta {
116            Some(_) => {
117                let complete = VersionedTransactionWithStatusMeta::decode(encoded, encoding /*, None*/)?;
118                Ok(Self::Complete(complete))
119            },
120            None => {
121                let transaction = Transaction::decode(&encoded.transaction)?;
122                Ok(Self::MissingMetadata(transaction))
123            }
124        }
125    }
126}