jup_sdk/
types.rs

1use serde::{Deserialize, Serialize};
2use std::{collections::HashMap, time::Duration};
3
4use crate::tool::cal_slippage_amount;
5
6/// Represents token information including metadata and extensions
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct TokenInfo {
9    pub address: String,
10    pub chain_id: u64,
11    pub decimals: u8,
12    pub name: String,
13    pub symbol: String,
14    pub logo_uri: String,
15    pub tags: Vec<String>,
16    pub extensions: Option<TokenExtensions>,
17}
18
19/// Request structure for getting swap quotes
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct QuoteRequest {
22    pub input_mint: String,
23    pub output_mint: String,
24    pub amount: u64,
25    pub slippage_bps: u16,
26    pub fee_bps: Option<u16>,
27    pub only_direct_routes: Option<bool>,
28    pub as_legacy_transaction: Option<bool>,
29    pub restrict_middle_tokens: Option<bool>,
30}
31
32/// Response structure containing swap quote details
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct QuoteResponse {
35    pub input_mint: String,
36    pub output_mint: String,
37    pub in_amount: String,
38    pub out_amount: String,
39    pub other_amount_threshold: String,
40    pub swap_mode: String,
41    pub slippage_bps: u16,
42    pub platform_fee: Option<PlatformFee>,
43    pub price_impact_pct: String,
44    pub route_plan: Vec<RoutePlan>,
45    pub context_slot: u64,
46    pub time_taken: f64,
47}
48
49/// Platform fee information
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct PlatformFee {
52    pub amount: String,
53    pub fee_bps: u16,
54}
55
56/// Individual route information within a swap route plan
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct RoutePlan {
59    pub swap_info: SwapInfo,
60    pub percent: u8,
61}
62
63/// Swap information for a specific route step
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct SwapInfo {
66    pub amm_key: String,
67    pub label: String,
68    pub input_mint: String,
69    pub output_mint: String,
70    pub in_amount: String,
71    pub out_amount: String,
72    pub fee_amount: String,
73    pub fee_mint: String,
74}
75
76/// Request structure for executing a swap
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct SwapRequest {
79    pub quote_response: QuoteResponse,
80    pub user_public_key: String,
81    pub wrap_and_unwrap_sol: Option<bool>,
82    pub compute_unit_price: Option<u64>,
83    pub prioritization_fee_lamports: Option<u64>,
84}
85
86/// Response structure containing swap transaction details
87#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct SwapResponse {
89    pub swap_transaction: String,
90    pub last_valid_block_height: u64,
91    pub prioritization_fee_lamports: Option<u64>,
92}
93
94/// Price information response for a token
95#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct PriceResponse {
97    pub id: String,
98    pub mint_symbol: String,
99    pub vs_token: String,
100    pub vs_token_symbol: String,
101    pub price: f64,
102}
103
104/// Token extension metadata
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct TokenExtensions {
107    pub coingecko_id: Option<String>,
108    pub website: Option<String>,
109}
110
111/// Response containing indexed route map data
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct IndexedRouteMapResponse {
114    pub indexed_route_map: IndexedRouteMap,
115}
116
117/// Indexed route map structure for efficient route lookup
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct IndexedRouteMap {
120    pub mint_keys: Vec<String>,
121    pub indexed_route_map: HashMap<String, Vec<usize>>,
122}
123
124/// Error types for Jupiter operations
125#[derive(Debug, Clone)]
126pub enum JupiterError {
127    RequestFailed(String),
128    InvalidInput(String),
129    NetworkError(String),
130    ValidationError(String),
131    RateLimitExceeded(String),
132    TransactionFailed(String),
133    ParseError(String),
134    Error(String),
135}
136
137impl JupiterError {
138    /// Determines if the error is retriable
139    pub fn is_retriable(&self) -> bool {
140        match self {
141            JupiterError::NetworkError(_) => true,
142            JupiterError::RequestFailed(msg) => {
143                // Retry on 5xx server errors
144                msg.contains("500") || msg.contains("502") || msg.contains("503")
145            }
146            JupiterError::RateLimitExceeded(_) => true,
147            JupiterError::InvalidInput(_) => false,
148            JupiterError::ParseError(_) => false,
149            JupiterError::TransactionFailed(_) => false,
150            JupiterError::Error(_) => false,
151            JupiterError::ValidationError(_) => false,
152        }
153    }
154}
155
156impl std::fmt::Display for JupiterError {
157    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158        match self {
159            JupiterError::RequestFailed(msg) => write!(f, "Request failed: {}", msg),
160            JupiterError::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
161            JupiterError::NetworkError(msg) => write!(f, "Network error: {}", msg),
162            JupiterError::ParseError(msg) => write!(f, "Parse error: {}", msg),
163            JupiterError::Error(msg) => write!(f, "Parse error: {}", msg),
164            JupiterError::ValidationError(msg) => write!(f, "Parse error: {}", msg),
165            JupiterError::RateLimitExceeded(msg) => write!(f, "Parse error: {}", msg),
166            JupiterError::TransactionFailed(msg) => write!(f, "Parse error: {}", msg),
167        }
168    }
169}
170
171impl std::error::Error for JupiterError {}
172
173/// Rate limiter for API requests
174#[derive(Debug, Clone)]
175pub struct RateLimiter {
176    requests_per_second: u32,
177    // Can be implemented using governor or tower::limit::RateLimit
178}
179
180impl RateLimiter {
181    /// Creates a new rate limiter with specified requests per second
182    pub fn new(requests_per_second: u32) -> Self {
183        Self {
184            requests_per_second,
185        }
186    }
187
188    /// Acquires permission to make a request, waiting if necessary
189    pub fn acquire(&self) -> impl std::future::Future<Output = ()> {
190        // Simplified rate limiting implementation
191        // In practice, use governor crate for more precise rate limiting
192        async {
193            tokio::time::sleep(Duration::from_millis(
194                1000 / self.requests_per_second as u64,
195            ))
196            .await;
197        }
198    }
199}
200
201/// Transaction status types
202#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
203pub enum TransactionStatusType {
204    Pending,
205    Confirmed,
206    Finalized,
207    Failed,
208    Timeout,
209}
210
211/// Transaction status monitoring - used for tracking transaction confirmation status
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct TransactionStatus {
214    /// Transaction signature
215    pub signature: String,
216    /// Transaction status
217    pub status: TransactionStatusType,
218    /// Block slot
219    pub slot: u64,
220    /// Confirmation status
221    pub confirmation_status: Option<String>,
222    /// Error information (if any)
223    pub err: Option<serde_json::Value>,
224}
225
226/// Advanced swap configuration - for fine-grained swap control
227#[derive(Debug, Clone)]
228pub struct AdvancedSwapConfig {
229    /// Maximum slippage tolerance (basis points)
230    pub max_slippage_bps: u16,
231    /// Preferred AMM list
232    pub preferred_amms: Vec<String>,
233    /// Excluded AMM list
234    pub excluded_amms: Vec<String>,
235    /// Maximum price impact tolerance (basis points)
236    pub max_price_impact_bps: u16,
237    /// Whether to use versioned transactions
238    pub use_versioned_transaction: bool,
239}
240
241impl Default for AdvancedSwapConfig {
242    fn default() -> Self {
243        Self {
244            max_slippage_bps: 50,
245            preferred_amms: Vec::new(),
246            excluded_amms: Vec::new(),
247            max_price_impact_bps: 500, // 5%
248            use_versioned_transaction: true,
249        }
250    }
251}
252
253/// Batch quote request - for getting multiple swap quotes in one request
254#[derive(Debug, Clone, Serialize, Deserialize)]
255pub struct BatchQuoteRequest {
256    /// Multiple quote requests
257    pub requests: Vec<QuoteRequest>,
258}
259
260/// Batch quote response - contains multiple quote results
261#[derive(Debug, Clone, Serialize, Deserialize)]
262pub struct BatchQuoteResponse {
263    /// List of quote results
264    pub quotes: Vec<QuoteResponse>,
265}
266
267/// Swap execution result - encapsulates complete swap operation result
268#[derive(Debug, Clone)]
269pub struct SwapExecutionResult {
270    /// Quote used for the swap
271    pub quote: QuoteResponse,
272    /// Swap transaction response
273    pub swap_response: crate::types::SwapResponse,
274    /// Configuration used
275    pub config: AdvancedSwapConfig,
276}
277
278impl SwapExecutionResult {
279    /// Gets the expected output amount
280    pub fn get_expected_output(&self) -> u64 {
281        self.quote.out_amount.parse().unwrap_or(0)
282    }
283
284    /// Gets the minimum output amount considering slippage
285    pub fn get_minimum_output(&self) -> u64 {
286        let out_amount: u64 = self.quote.out_amount.parse().unwrap_or(0);
287        cal_slippage_amount(out_amount, self.quote.slippage_bps)
288    }
289
290    /// Calculates price impact percentage
291    pub fn get_price_impact(&self) -> f64 {
292        self.quote.price_impact_pct.parse().unwrap_or(0.0)
293    }
294}