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 cost_units: None,
81 };
82 Some(VersionedTransactionWithStatusMeta {
83 transaction: versioned_transaction,
84 meta: default_meta,
85 })
86 } else {
87 None
89 }
90 }
91 TransactionWithStatusMeta::Complete(tx) => Some(tx),
92 }
93 })
94 .collect();
95
96 if txs.len() != expected_transaction_count {
97 return Err(ConvertBlockError::TransactionsMissing(
98 expected_transaction_count,
99 txs.len(),
100 ));
101 }
102
103 Ok(Self {
104 previous_blockhash: block.previous_blockhash,
105 blockhash: block.blockhash,
106 parent_slot: block.parent_slot,
107 transactions: txs,
108 rewards: block.rewards,
109 num_partitions: block.num_partitions,
110 block_time: block.block_time,
111 block_height: block.block_height,
112 })
113 }
114}
115
116#[derive(Debug, Error)]
117pub enum ConvertBlockError {
118 #[error("transactions missing after converted, before: {0}, after: {1}")]
119 TransactionsMissing(usize, usize),
120}
121
122impl From<VersionedConfirmedBlock> for solana_transaction_status::VersionedConfirmedBlock {
123 fn from(block: VersionedConfirmedBlock) -> Self {
124 Self {
125 previous_blockhash: block.previous_blockhash,
126 blockhash: block.blockhash,
127 parent_slot: block.parent_slot,
128 transactions: block.transactions.into_iter().map(Into::into).collect(),
129 rewards: block.rewards,
130 num_partitions: block.num_partitions,
131 block_time: block.block_time,
132 block_height: block.block_height,
133 }
134 }
135}