1use serde::{Deserialize, Serialize};
2use std::{collections::HashMap, time::Duration};
3
4use crate::tool::cal_slippage_amount;
5
6#[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#[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#[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#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct PlatformFee {
52 pub amount: String,
53 pub fee_bps: u16,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct RoutePlan {
59 pub swap_info: SwapInfo,
60 pub percent: u8,
61}
62
63#[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#[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#[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#[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#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct TokenExtensions {
107 pub coingecko_id: Option<String>,
108 pub website: Option<String>,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct IndexedRouteMapResponse {
114 pub indexed_route_map: IndexedRouteMap,
115}
116
117#[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#[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 pub fn is_retriable(&self) -> bool {
140 match self {
141 JupiterError::NetworkError(_) => true,
142 JupiterError::RequestFailed(msg) => {
143 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#[derive(Debug, Clone)]
175pub struct RateLimiter {
176 requests_per_second: u32,
177 }
179
180impl RateLimiter {
181 pub fn new(requests_per_second: u32) -> Self {
183 Self {
184 requests_per_second,
185 }
186 }
187
188 pub fn acquire(&self) -> impl std::future::Future<Output = ()> {
190 async {
193 tokio::time::sleep(Duration::from_millis(
194 1000 / self.requests_per_second as u64,
195 ))
196 .await;
197 }
198 }
199}
200
201#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
203pub enum TransactionStatusType {
204 Pending,
205 Confirmed,
206 Finalized,
207 Failed,
208 Timeout,
209}
210
211#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct TransactionStatus {
214 pub signature: String,
216 pub status: TransactionStatusType,
218 pub slot: u64,
220 pub confirmation_status: Option<String>,
222 pub err: Option<serde_json::Value>,
224}
225
226#[derive(Debug, Clone)]
228pub struct AdvancedSwapConfig {
229 pub max_slippage_bps: u16,
231 pub preferred_amms: Vec<String>,
233 pub excluded_amms: Vec<String>,
235 pub max_price_impact_bps: u16,
237 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, use_versioned_transaction: true,
249 }
250 }
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize)]
255pub struct BatchQuoteRequest {
256 pub requests: Vec<QuoteRequest>,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
262pub struct BatchQuoteResponse {
263 pub quotes: Vec<QuoteResponse>,
265}
266
267#[derive(Debug, Clone)]
269pub struct SwapExecutionResult {
270 pub quote: QuoteResponse,
272 pub swap_response: crate::types::SwapResponse,
274 pub config: AdvancedSwapConfig,
276}
277
278impl SwapExecutionResult {
279 pub fn get_expected_output(&self) -> u64 {
281 self.quote.out_amount.parse().unwrap_or(0)
282 }
283
284 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 pub fn get_price_impact(&self) -> f64 {
292 self.quote.price_impact_pct.parse().unwrap_or(0.0)
293 }
294}