solana_block_decoder/
lib.rs

1use {
2    solana_storage_utils::compression::compress_best,
3    solana_transaction_status::{
4        BlockEncodingOptions,
5        VersionedConfirmedBlock as SolanaVersionedConfirmedBlock,
6    },
7    solana_transaction_status_client_types::{
8        UiTransactionEncoding,
9    },
10    block::{
11        confirmed_block::ConfirmedBlock,
12        encoded_block::EncodedConfirmedBlock,
13        ui_block::UiConfirmedBlock,
14        versioned_block::VersionedConfirmedBlock,
15    },
16    std::sync::atomic::{AtomicBool, Ordering},
17};
18
19pub mod errors {
20    pub mod conversion_error;
21    pub mod decode_error;
22}
23
24pub mod block {
25    pub mod confirmed_block;
26    pub mod encoded_block;
27    pub mod versioned_block;
28    pub mod ui_block;
29}
30
31pub mod transaction {
32    pub mod transaction;
33    pub mod tx_status_meta;
34    pub mod tx_return_data;
35    pub mod tx_token_balance;
36    pub mod versioned_transaction;
37
38    pub use transaction::Transaction;
39}
40
41pub mod address {
42    pub mod address_table_lookup;
43    pub mod loaded_addresses;
44}
45
46pub mod instruction {
47    pub mod compiled_instruction;
48    pub mod inner_instruction;
49    pub use compiled_instruction::CompiledInstruction;
50    pub use inner_instruction::InnerInstruction;
51}
52
53pub mod message {
54    pub mod message;
55    pub mod message_v0;
56    pub mod versioned_message;
57}
58
59pub mod decodable;
60
61// Global runtime toggle that controls whether empty metadata should be injected
62// for transactions missing metadata when converting blocks.
63lazy_static::lazy_static! {
64    static ref ADD_EMPTY_TX_METADATA_IF_MISSING: AtomicBool = AtomicBool::new(
65        std::env::var("ADD_EMPTY_TX_METADATA_IF_MISSING")
66            .ok()
67            .map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
68            .unwrap_or(false)
69    );
70}
71
72/// Enable or disable injecting empty metadata for transactions that are missing it.
73pub fn set_add_empty_tx_metadata_if_missing(value: bool) {
74    ADD_EMPTY_TX_METADATA_IF_MISSING.store(value, Ordering::Relaxed);
75}
76
77/// Read the current setting for injecting empty metadata for missing transaction metadata.
78pub fn add_empty_tx_metadata_if_missing() -> bool {
79    ADD_EMPTY_TX_METADATA_IF_MISSING.load(Ordering::Relaxed)
80}
81
82pub async fn encode_block<T>(
83    data: T,
84) -> Result<Vec<u8>, Box<dyn std::error::Error>>
85    where
86        T: prost::Message,
87{
88    let mut buf = Vec::with_capacity(data.encoded_len());
89    data.encode(&mut buf).unwrap();
90    let data = compress_best(&buf)?;
91
92    Ok(data)
93}
94
95pub fn convert_block(
96    encoded_block: EncodedConfirmedBlock,
97    encoding: UiTransactionEncoding,
98    options: BlockEncodingOptions,
99) -> Result<SolanaVersionedConfirmedBlock, Box<dyn std::error::Error>> {
100    // Step 1: Convert EncodedConfirmedBlock to UiConfirmedBlock
101    let ui_block: UiConfirmedBlock = encoded_block.into();
102
103    // Step 2: Decode UiConfirmedBlock to ConfirmedBlock
104    let confirmed_block = ConfirmedBlock::decode_with_options(ui_block, encoding, options)?;
105
106    // Step 3: Try to convert ConfirmedBlock to VersionedConfirmedBlock
107    let versioned_block = VersionedConfirmedBlock::try_from(confirmed_block)?;
108
109    // Ok(convert_versioned_confirmed_block(&versioned_block))
110    Ok(versioned_block.into())
111}
112
113pub async fn encode_transaction<T>(
114    data: T,
115) -> Result<Vec<u8>, Box<dyn std::error::Error>>
116    where
117        T: prost::Message,
118{
119    let mut buf = Vec::with_capacity(data.encoded_len());
120    data.encode(&mut buf).unwrap();
121    let data = compress_best(&buf)?;
122
123    Ok(data)
124}
125
126// pub fn convert_transaction(
127//     encoded_tx: EncodedTransactionWithStatusMeta,
128//     encoding: UiTransactionEncoding,
129//     // options: BlockEncodingOptions,
130// ) -> Result<TransactionWithStatusMeta, Box<dyn std::error::Error>> {
131//
132//     let confirmed_tx = TransactionWithStatusMeta::decode(encoded_tx, encoding)?;
133//
134//     // Try to convert ConfirmedBlock to VersionedConfirmedBlock
135//     // let versioned_block = VersionedConfirmedBlock::try_from(confirmed_tx)?;
136//
137//     Ok(confirmed_tx)
138// }