solana_block_decoder/block/
versioned_block.rs1
2use {
3 crate::{
4 block::{
5 confirmed_block::{
6 ConfirmedBlock,
7 TransactionWithStatusMeta
8 },
9 },
10 transaction::{
11 versioned_transaction::{VersionedTransactionWithStatusMeta, VersionedTransaction},
12 tx_status_meta::TransactionStatusMeta,
13 },
14 message::{
15 versioned_message::VersionedMessage,
16 },
17 address::{
18 loaded_addresses::LoadedAddresses,
19 },
20 },
21 solana_clock::{
22 Slot,
23 UnixTimestamp,
24 },
25 solana_transaction_status_client_types::{
26 Rewards,
27 },
28 thiserror::Error,
29};
30
31
32#[derive(Clone, Debug, PartialEq)]
35pub struct VersionedConfirmedBlock {
36 pub previous_blockhash: String,
37 pub blockhash: String,
38 pub parent_slot: Slot,
39 pub transactions: Vec<VersionedTransactionWithStatusMeta>,
40 pub rewards: Rewards,
41 pub num_partitions: Option<u64>,
42 pub block_time: Option<UnixTimestamp>,
43 pub block_height: Option<u64>,
44}
45
46
47impl TryFrom<ConfirmedBlock> for VersionedConfirmedBlock {
48 type Error = ConvertBlockError;
49
50 fn try_from(block: ConfirmedBlock) -> Result<Self, Self::Error> {
51 let expected_transaction_count = block.transactions.len();
52
53 let add_empty_tx_metadata_if_missing = crate::add_empty_tx_metadata_if_missing();
54
55 let txs: Vec<_> = block
56 .transactions
57 .into_iter()
58 .filter_map(|tx| {
59 match tx {
60 TransactionWithStatusMeta::MissingMetadata(transaction) => {
61 if add_empty_tx_metadata_if_missing {
62 let versioned_transaction = VersionedTransaction {
64 signatures: transaction.signatures,
65 message: VersionedMessage::Legacy(transaction.message),
66 };
67 let default_meta = TransactionStatusMeta {
68 status: Ok(()),
69 fee: 0,
70 pre_balances: vec![],
71 post_balances: vec![],
72 inner_instructions: None,
73 log_messages: None,
74 pre_token_balances: None,
75 post_token_balances: None,
76 rewards: None,
77 loaded_addresses: LoadedAddresses::default(),
78 return_data: None,
79 compute_units_consumed: None,
80 };
81 Some(VersionedTransactionWithStatusMeta {
82 transaction: versioned_transaction,
83 meta: default_meta,
84 })
85 } else {
86 None
88 }
89 }
90 TransactionWithStatusMeta::Complete(tx) => Some(tx),
91 }
92 })
93 .collect();
94
95 if txs.len() != expected_transaction_count {
96 return Err(ConvertBlockError::TransactionsMissing(
97 expected_transaction_count,
98 txs.len(),
99 ));
100 }
101
102 Ok(Self {
103 previous_blockhash: block.previous_blockhash,
104 blockhash: block.blockhash,
105 parent_slot: block.parent_slot,
106 transactions: txs,
107 rewards: block.rewards,
108 num_partitions: block.num_partitions,
109 block_time: block.block_time,
110 block_height: block.block_height,
111 })
112 }
113}
114
115#[derive(Debug, Error)]
116pub enum ConvertBlockError {
117 #[error("transactions missing after converted, before: {0}, after: {1}")]
118 TransactionsMissing(usize, usize),
119}
120
121impl From<VersionedConfirmedBlock> for solana_transaction_status::VersionedConfirmedBlock {
122 fn from(block: VersionedConfirmedBlock) -> Self {
123 Self {
124 previous_blockhash: block.previous_blockhash,
125 blockhash: block.blockhash,
126 parent_slot: block.parent_slot,
127 transactions: block.transactions.into_iter().map(Into::into).collect(),
128 rewards: block.rewards,
129 num_partitions: block.num_partitions,
130 block_time: block.block_time,
131 block_height: block.block_height,
132 }
133 }
134}