use serde::{Deserialize, Serialize};
use solana_account_decoder_client_types::{UiAccount, UiAccountEncoding};
use solana_clock::Slot;
use solana_commitment_config::{CommitmentConfig, CommitmentLevel};
use solana_rpc_client_api::response::RpcBlockhash;
use solana_signature::Signature;
use solana_transaction_error::TransactionError;
use solana_transaction_status::{
UiLoadedAddresses, UiTransactionEncoding, UiTransactionReturnData, UiTransactionTokenBalance,
};
use thiserror::Error;
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcBundleRequest {
pub encoded_transactions: Vec<String>,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct RpcSimulateTransactionAccountsConfig {
pub encoding: Option<UiAccountEncoding>,
pub addresses: Vec<String>,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcSimulateBundleConfig {
#[serde(default)]
pub pre_execution_accounts_configs: Vec<Option<RpcSimulateTransactionAccountsConfig>>,
#[serde(default)]
pub post_execution_accounts_configs: Vec<Option<RpcSimulateTransactionAccountsConfig>>,
pub transaction_encoding: Option<UiTransactionEncoding>,
pub simulation_bank: Option<SimulationSlotConfig>,
#[serde(default)]
pub skip_sig_verify: bool,
#[serde(default)]
pub replace_recent_blockhash: bool,
}
#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
#[serde(rename_all = "camelCase")]
pub enum SimulationSlotConfig {
Commitment(CommitmentConfig),
Slot(Slot),
Tip,
}
impl Default for SimulationSlotConfig {
fn default() -> Self {
Self::Commitment(CommitmentConfig {
commitment: CommitmentLevel::Confirmed,
})
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcSimulateBundleResult {
pub summary: RpcBundleSimulationSummary,
pub transaction_results: Vec<RpcSimulateBundleTransactionResult>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub enum RpcBundleSimulationSummary {
Failed {
error: RpcBundleExecutionError,
tx_signature: Option<String>,
},
Succeeded,
}
#[derive(Error, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum RpcBundleExecutionError {
#[error("The bank has hit the max allotted time for processing transactions")]
BankProcessingTimeLimitReached,
#[error("Error locking bundle because a transaction is malformed")]
BundleLockError,
#[error("Bundle execution timed out")]
BundleExecutionTimeout,
#[error("The bundle exceeds the cost model")]
ExceedsCostModel,
#[error("Invalid pre or post accounts")]
InvalidPreOrPostAccounts,
#[error("PoH record error: {0}")]
PohRecordError(String),
#[error("Tip payment error: {0}")]
TipError(String),
#[error("A transaction in the bundle failed to execute: [signature={0}, error={1}]")]
TransactionFailure(Signature, String),
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcSimulateBundleTransactionResult {
pub err: Option<TransactionError>,
pub logs: Option<Vec<String>>,
pub pre_execution_accounts: Option<Vec<UiAccount>>,
pub post_execution_accounts: Option<Vec<UiAccount>>,
pub units_consumed: Option<u64>,
pub loaded_accounts_data_size: Option<u32>,
pub return_data: Option<UiTransactionReturnData>,
pub replacement_blockhash: Option<RpcBlockhash>,
pub fee: Option<u64>,
pub pre_balances: Option<Vec<u64>>,
pub post_balances: Option<Vec<u64>>,
pub pre_token_balances: Option<Vec<UiTransactionTokenBalance>>,
pub post_token_balances: Option<Vec<UiTransactionTokenBalance>>,
pub loaded_addresses: Option<UiLoadedAddresses>,
}