use { serde::{Deserialize, Serialize}, solana_account_decoder::{ parse_token::{real_number_string_trimmed, UiTokenAmount}, StringAmount, }, solana_sdk::{deserialize_utils::default_on_eof, transaction::Result}, solana_transaction_status::{ InnerInstructions, Reward, RewardType, TransactionStatusMeta, TransactionTokenBalance, }, std::str::FromStr, }; pub mod convert; pub type StoredExtendedRewards = Vec; #[derive(Serialize, Deserialize)] pub struct StoredExtendedReward { pubkey: String, lamports: i64, #[serde(deserialize_with = "default_on_eof")] post_balance: u64, #[serde(deserialize_with = "default_on_eof")] reward_type: Option, } impl From for Reward { fn from(value: StoredExtendedReward) -> Self { let StoredExtendedReward { pubkey, lamports, post_balance, reward_type, } = value; Self { pubkey, lamports, post_balance, reward_type, } } } impl From for StoredExtendedReward { fn from(value: Reward) -> Self { let Reward { pubkey, lamports, post_balance, reward_type, .. } = value; Self { pubkey, lamports, post_balance, reward_type, } } } #[derive(Serialize, Deserialize)] pub struct StoredTokenAmount { pub ui_amount: f64, pub decimals: u8, pub amount: StringAmount, } impl From for UiTokenAmount { fn from(value: StoredTokenAmount) -> Self { let StoredTokenAmount { ui_amount, decimals, amount, } = value; let ui_amount_string = real_number_string_trimmed(u64::from_str(&amount).unwrap_or(0), decimals); Self { ui_amount: Some(ui_amount), decimals, amount, ui_amount_string, } } } impl From for StoredTokenAmount { fn from(value: UiTokenAmount) -> Self { let UiTokenAmount { ui_amount, decimals, amount, .. } = value; Self { ui_amount: ui_amount.unwrap_or(0.0), decimals, amount, } } } #[derive(Serialize, Deserialize)] pub struct StoredTransactionTokenBalance { pub account_index: u8, pub mint: String, pub ui_token_amount: StoredTokenAmount, } impl From for TransactionTokenBalance { fn from(value: StoredTransactionTokenBalance) -> Self { let StoredTransactionTokenBalance { account_index, mint, ui_token_amount, } = value; Self { account_index, mint, ui_token_amount: ui_token_amount.into(), } } } impl From for StoredTransactionTokenBalance { fn from(value: TransactionTokenBalance) -> Self { let TransactionTokenBalance { account_index, mint, ui_token_amount, } = value; Self { account_index, mint, ui_token_amount: ui_token_amount.into(), } } } #[derive(Serialize, Deserialize)] pub struct StoredTransactionStatusMeta { pub status: Result<()>, pub fee: u64, pub pre_balances: Vec, pub post_balances: Vec, #[serde(deserialize_with = "default_on_eof")] pub inner_instructions: Option>, #[serde(deserialize_with = "default_on_eof")] pub log_messages: Option>, #[serde(deserialize_with = "default_on_eof")] pub pre_token_balances: Option>, #[serde(deserialize_with = "default_on_eof")] pub post_token_balances: Option>, #[serde(deserialize_with = "default_on_eof")] pub rewards: Option>, } impl From for TransactionStatusMeta { fn from(value: StoredTransactionStatusMeta) -> Self { let StoredTransactionStatusMeta { status, fee, pre_balances, post_balances, inner_instructions, log_messages, pre_token_balances, post_token_balances, rewards, } = value; Self { status, fee, pre_balances, post_balances, inner_instructions, log_messages, pre_token_balances: pre_token_balances .map(|balances| balances.into_iter().map(|balance| balance.into()).collect()), post_token_balances: post_token_balances .map(|balances| balances.into_iter().map(|balance| balance.into()).collect()), rewards: rewards .map(|rewards| rewards.into_iter().map(|reward| reward.into()).collect()), } } } impl From for StoredTransactionStatusMeta { fn from(value: TransactionStatusMeta) -> Self { let TransactionStatusMeta { status, fee, pre_balances, post_balances, inner_instructions, log_messages, pre_token_balances, post_token_balances, rewards, } = value; Self { status, fee, pre_balances, post_balances, inner_instructions, log_messages, pre_token_balances: pre_token_balances .map(|balances| balances.into_iter().map(|balance| balance.into()).collect()), post_token_balances: post_token_balances .map(|balances| balances.into_iter().map(|balance| balance.into()).collect()), rewards: rewards .map(|rewards| rewards.into_iter().map(|reward| reward.into()).collect()), } } }