Skip to main content

jito_bundle/
types.rs

1use serde::{Deserialize, Serialize};
2
3/// Generic JSON-RPC request payload wrapper.
4#[derive(Debug, Serialize)]
5pub struct JsonRpcRequest<T: Serialize> {
6    /// JSON-RPC protocol version.
7    pub jsonrpc: &'static str,
8    /// Request id used for matching responses.
9    pub id: u64,
10    /// RPC method name.
11    pub method: &'static str,
12    /// Method-specific parameters.
13    pub params: T,
14}
15
16/// Generic JSON-RPC response payload wrapper.
17#[derive(Debug, Deserialize)]
18pub struct JsonRpcResponse<T> {
19    /// JSON-RPC protocol version.
20    pub jsonrpc: String,
21    /// Response id corresponding to request id.
22    pub id: u64,
23    /// Success result payload when present.
24    pub result: Option<T>,
25    /// Error payload when present.
26    pub error: Option<JsonRpcError>,
27}
28
29/// JSON-RPC error object.
30#[derive(Debug, Deserialize)]
31pub struct JsonRpcError {
32    /// JSON-RPC error code.
33    pub code: i64,
34    /// Human-readable error message.
35    pub message: String,
36}
37
38/// Jito tip-floor API response entry.
39#[derive(Debug, Deserialize, Clone)]
40pub struct JitoTipFloorResponse {
41    /// Response timestamp.
42    pub time: String,
43    /// 25th percentile landed tip (SOL units).
44    pub landed_tips_25th_percentile: f64,
45    /// 50th percentile landed tip (SOL units).
46    pub landed_tips_50th_percentile: f64,
47    /// 75th percentile landed tip (SOL units).
48    pub landed_tips_75th_percentile: f64,
49    /// 95th percentile landed tip (SOL units).
50    pub landed_tips_95th_percentile: f64,
51    /// 99th percentile landed tip (SOL units).
52    pub landed_tips_99th_percentile: f64,
53    /// EMA 50th percentile landed tip (SOL units).
54    pub ema_landed_tips_50th_percentile: f64,
55}
56
57/// High-level bundle landing status.
58#[derive(Clone)]
59pub enum BundleStatus {
60    /// Bundle is still pending.
61    Pending,
62    /// Bundle landed with optional slot.
63    Landed { slot: Option<u64> },
64    /// Bundle failed with optional error details.
65    Failed { error: Option<String> },
66    /// Status could not be determined.
67    Unknown,
68}
69
70impl std::fmt::Debug for BundleStatus {
71    /// Formats bundle status in a compact human-readable form.
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        match self {
74            BundleStatus::Pending => write!(f, "Pending"),
75            BundleStatus::Landed { slot } => write!(f, "Landed(slot: {slot:?})"),
76            BundleStatus::Failed { error } => write!(f, "Failed(error: {error:?})"),
77            BundleStatus::Unknown => write!(f, "Unknown"),
78        }
79    }
80}
81
82/// Result returned after bundle submission.
83#[derive(Debug)]
84pub struct BundleResult {
85    /// Whether submission succeeded.
86    pub success: bool,
87    /// Returned bundle id when submission succeeds.
88    pub bundle_id: Option<String>,
89    /// Error message when submission fails.
90    pub error: Option<String>,
91    /// Transaction signatures from submitted bundle.
92    pub signatures: Vec<String>,
93    /// Explorer URL for bundle status.
94    pub explorer_url: Option<String>,
95}
96
97/// Parameters for Helius `simulateBundle` call.
98#[derive(Debug, Serialize)]
99#[serde(rename_all = "camelCase")]
100pub struct SimulateBundleParams {
101    /// Base64-encoded transactions in bundle order.
102    pub encoded_transactions: Vec<String>,
103}
104
105/// Top-level Helius `simulateBundle` result.
106#[derive(Debug, Deserialize)]
107#[serde(rename_all = "camelCase")]
108pub struct SimulateBundleApiResult {
109    /// Simulation context metadata.
110    pub context: SimulateBundleContext,
111    /// Simulation output payload.
112    pub value: SimulateBundleValue,
113}
114
115/// Simulation context metadata.
116#[derive(Debug, Deserialize)]
117#[serde(rename_all = "camelCase")]
118pub struct SimulateBundleContext {
119    /// API version that handled simulation.
120    pub api_version: String,
121    /// Slot used for simulation context.
122    pub slot: u64,
123}
124
125/// Full simulation output.
126#[derive(Debug, Deserialize)]
127#[serde(rename_all = "camelCase")]
128pub struct SimulateBundleValue {
129    /// Overall simulation summary.
130    pub summary: SimulateBundleSummary,
131    /// Per-transaction simulation results.
132    pub transaction_results: Vec<TransactionSimulationResult>,
133}
134
135/// Overall simulation summary state.
136#[derive(Debug, Deserialize)]
137#[serde(rename_all = "camelCase")]
138pub enum SimulateBundleSummary {
139    /// All transactions simulated successfully.
140    Succeeded,
141    /// Simulation failed with details.
142    Failed(SimulateBundleFailure),
143}
144
145/// Failure payload returned by Helius simulation.
146#[derive(Debug, Deserialize)]
147#[serde(rename_all = "camelCase")]
148pub struct SimulateBundleFailure {
149    /// Raw simulation error object.
150    pub error: serde_json::Value,
151    /// Optional failing transaction signature.
152    pub tx_signature: Option<String>,
153}
154
155impl SimulateBundleFailure {
156    /// Extracts a readable error message from Helius failure payload.
157    pub fn error_message(&self) -> String {
158        if let Some(tx_failure) = self.error.get("TransactionFailure")
159            && let Some(arr) = tx_failure.as_array()
160            && let Some(msg) = arr.get(1).and_then(|v| v.as_str())
161        {
162            return msg.to_string();
163        }
164        self.error.to_string()
165    }
166}
167
168/// Per-transaction simulation result entry.
169#[derive(Debug, Deserialize)]
170#[serde(rename_all = "camelCase")]
171pub struct TransactionSimulationResult {
172    /// Transaction-level error when present.
173    pub err: Option<serde_json::Value>,
174    /// Program logs emitted during execution.
175    pub logs: Option<Vec<String>>,
176    /// Compute units consumed by transaction.
177    pub units_consumed: Option<u64>,
178    /// Optional program return data.
179    pub return_data: Option<ReturnData>,
180    /// Optional pre-execution account states.
181    pub pre_execution_accounts: Option<Vec<AccountState>>,
182    /// Optional post-execution account states.
183    pub post_execution_accounts: Option<Vec<AccountState>>,
184}
185
186/// Account snapshot in simulation response.
187#[derive(Debug, Deserialize)]
188#[serde(rename_all = "camelCase")]
189pub struct AccountState {
190    /// Base58-encoded account pubkey.
191    pub pubkey: String,
192    /// Account lamports balance.
193    pub lamports: u64,
194    /// Account data payload.
195    pub data: Vec<String>,
196    /// Base58-encoded owner program id.
197    pub owner: String,
198    /// Whether account is executable.
199    pub executable: bool,
200    /// Account rent epoch.
201    pub rent_epoch: u64,
202}
203
204/// Program return data from simulation.
205#[derive(Debug, Deserialize)]
206#[serde(rename_all = "camelCase")]
207pub struct ReturnData {
208    /// Program id that returned the data.
209    pub program_id: String,
210    /// Encoded return data payload.
211    pub data: Vec<String>,
212}