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