1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4#[derive(Debug, Clone)]
9pub struct VaeaConfig {
10 pub api_url: String,
11 pub source: Source,
12}
13
14impl Default for VaeaConfig {
15 fn default() -> Self {
16 Self {
17 api_url: "https://api.vaea.fi".to_string(),
18 source: Source::Sdk,
19 }
20 }
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
24#[serde(rename_all = "lowercase")]
25pub enum Source {
26 Sdk,
27 Ui,
28 Protocol,
29}
30
31impl fmt::Display for Source {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 match self {
34 Source::Sdk => write!(f, "sdk"),
35 Source::Ui => write!(f, "ui"),
36 Source::Protocol => write!(f, "protocol"),
37 }
38 }
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
46pub enum VaeaErrorCode {
47 InsufficientLiquidity,
48 TokenNotSupported,
49 SlippageExceeded,
50 FeeTooHigh,
51 RepayFailed,
52 TxExpired,
53 SourceUnavailable,
54 ProgramPaused,
55 InvalidAmount,
56 InsufficientSolForFee,
57 ApiError,
58 NetworkError,
59}
60
61impl fmt::Display for VaeaErrorCode {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 match self {
64 VaeaErrorCode::InsufficientLiquidity => write!(f, "INSUFFICIENT_LIQUIDITY"),
65 VaeaErrorCode::TokenNotSupported => write!(f, "TOKEN_NOT_SUPPORTED"),
66 VaeaErrorCode::SlippageExceeded => write!(f, "SLIPPAGE_EXCEEDED"),
67 VaeaErrorCode::FeeTooHigh => write!(f, "FEE_TOO_HIGH"),
68 VaeaErrorCode::RepayFailed => write!(f, "REPAY_FAILED"),
69 VaeaErrorCode::TxExpired => write!(f, "TX_EXPIRED"),
70 VaeaErrorCode::SourceUnavailable => write!(f, "SOURCE_UNAVAILABLE"),
71 VaeaErrorCode::ProgramPaused => write!(f, "PROGRAM_PAUSED"),
72 VaeaErrorCode::InvalidAmount => write!(f, "INVALID_AMOUNT"),
73 VaeaErrorCode::InsufficientSolForFee => write!(f, "INSUFFICIENT_SOL_FOR_FEE"),
74 VaeaErrorCode::ApiError => write!(f, "API_ERROR"),
75 VaeaErrorCode::NetworkError => write!(f, "NETWORK_ERROR"),
76 }
77 }
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct CapacityResponse {
86 pub updated_at: u64,
87 pub tokens: Vec<TokenCapacity>,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct TokenCapacity {
92 pub symbol: String,
93 pub mint: String,
94 pub name: String,
95 pub decimals: u8,
96 pub route_type: String,
97 pub source_protocol: String,
98 pub max_amount: f64,
99 pub max_amount_usd: f64,
100 pub fee_sdk: FeeInfo,
101 pub fee_ui: FeeInfo,
102 pub status: String,
103 pub updated_at: u64,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct FeeInfo {
108 pub bps: u16,
109 pub pct: f64,
110 pub total_pct: f64,
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct QuoteResponse {
119 pub token: String,
120 pub mint: String,
121 pub amount_requested: f64,
122 pub source: String,
123 pub route: RouteQuote,
124 pub fee_breakdown: FeeBreakdown,
125 pub price_impact: f64,
126 pub valid_until: u64,
127 pub valid_for_slots: u64,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct RouteQuote {
132 #[serde(rename = "type")]
133 pub route_type: String,
134 pub steps: Vec<RouteStep>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct RouteStep {
139 pub action: String,
140 pub protocol: String,
141 pub token: String,
142 pub amount: f64,
143 pub expected_output: Option<f64>,
144 pub price_impact: Option<f64>,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct FeeBreakdown {
149 pub source_fee: f64,
150 pub vaea_fee: f64,
151 pub total_fee_sol: f64,
152 pub total_fee_usd: f64,
153 pub total_fee_pct: f64,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct BuildRequest {
162 pub token: String,
163 pub amount: f64,
164 pub user_pubkey: String,
165 #[serde(skip_serializing_if = "Option::is_none")]
166 pub source: Option<String>,
167 #[serde(skip_serializing_if = "Option::is_none")]
168 pub slippage_bps: Option<u16>,
169 #[serde(skip_serializing_if = "Option::is_none")]
170 pub max_fee_bps: Option<u16>,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct ApiInstructionData {
175 pub program_id: String,
176 pub data: String,
177 pub accounts: Vec<ApiAccountMeta>,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct ApiAccountMeta {
182 pub pubkey: String,
183 pub is_signer: bool,
184 pub is_writable: bool,
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct BuildResponse {
189 pub prefix_instructions: Vec<ApiInstructionData>,
190 pub suffix_instructions: Vec<ApiInstructionData>,
191 pub lookup_tables: Vec<String>,
192 pub estimated_fee_lamports: u64,
193 pub valid_for_slots: u64,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct HealthResponse {
202 pub status: String,
203 pub timestamp: u64,
204 pub components: serde_json::Value,
205 pub sources: serde_json::Value,
206}
207
208pub struct BorrowParams {
213 pub token: String,
214 pub amount: f64,
215 pub instructions: Vec<solana_sdk::instruction::Instruction>,
216 pub slippage_bps: Option<u16>,
217 pub max_fee_bps: Option<u16>,
218}
219
220pub const VAEA_API_URL: &str = "https://api.vaea.fi";
225pub const VAEA_PROGRAM_ID: &str = "VAEAmcjQ5RB9yonyrCRSkRT8womX6uqm5PS7PXr528b";
226
227pub const VAEA_LOOKUP_TABLE: solana_sdk::pubkey::Pubkey =
230 solana_sdk::pubkey!("CsfmCd4gBs2VNsBQu37kjKttKJTMzePrQwYCDdLnuLDs");
231
232pub const SUPPORTED_TOKENS: &[&str] = &[
233 "SOL", "USDC", "USDT", "JitoSOL", "JupSOL", "JUP", "JLP", "cbBTC",
235 "mSOL", "bSOL",
237 "INF", "laineSOL",
239];
240
241pub const FEE_BPS_SDK: u16 = 2;
243pub const FEE_BPS_UI: u16 = 2;
244pub const FEE_BPS_CPI: u16 = 2;
245
246#[derive(Debug, Clone)]
252pub struct SimulateResult {
253 pub success: bool,
255 pub error: Option<String>,
257 pub compute_units: u64,
259 pub logs: Vec<String>,
261}
262
263pub struct MultiBorrowRequest {
265 pub token: String,
267 pub amount: f64,
269}
270
271pub struct BorrowMultiParams {
273 pub loans: Vec<MultiBorrowRequest>,
275 pub instructions: Vec<solana_sdk::instruction::Instruction>,
277 pub slippage_bps: Option<u16>,
279 pub max_fee_bps: Option<u16>,
281}
282
283#[derive(Debug, Clone, Copy, PartialEq, Eq)]
289pub enum FlashTier {
290 Sdk = 0,
291 Ui = 1,
292 Protocol = 2,
293}
294
295impl FlashTier {
296 pub fn from_u8(v: u8) -> Option<Self> {
297 match v {
298 0 => Some(Self::Sdk),
299 1 => Some(Self::Ui),
300 2 => Some(Self::Protocol),
301 _ => None,
302 }
303 }
304
305 pub fn fee_bps(&self) -> u16 {
306 match self {
307 Self::Sdk => FEE_BPS_SDK,
308 Self::Ui => FEE_BPS_UI,
309 Self::Protocol => FEE_BPS_CPI,
310 }
311 }
312}
313
314#[derive(Debug, Clone)]
316pub struct FlashStateInfo {
317 pub payer: solana_sdk::pubkey::Pubkey,
319 pub token_mint: solana_sdk::pubkey::Pubkey,
321 pub amount: u64,
323 pub fee: u64,
325 pub source_tier: u8,
327 pub tier: FlashTier,
329 pub slot_created: u64,
331 pub bump: u8,
333}
334
335#[derive(Debug, Clone, Serialize, Deserialize)]
337pub struct SourceCapacity {
338 pub protocol: String,
339 pub pool: String,
340 pub available: f64,
341 pub available_usd: f64,
342 pub utilization_pct: f64,
343 pub status: String,
344}
345
346#[derive(Debug, Clone, Serialize, Deserialize)]
348pub struct AggregatedTokenCapacity {
349 #[serde(flatten)]
350 pub base: TokenCapacity,
351 pub sources: Vec<SourceCapacity>,
352 pub total_available: f64,
353 pub total_available_usd: f64,
354}
355
356#[derive(Debug, Clone, Serialize, Deserialize)]
362pub struct MatrixTokenEntry {
363 pub mint: String,
364 pub symbol: String,
365 pub name: String,
366 pub decimals: u8,
367 pub is_direct: bool,
368 pub liquidity: std::collections::HashMap<String, f64>,
370 pub total_liquidity: f64,
371 pub total_liquidity_usd: f64,
372 pub cheapest_source_fee_bps: u16,
373 pub best_protocol: Option<String>,
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize)]
378pub struct MatrixResponse {
379 pub updated_at: u64,
380 pub total_tokens: u32,
381 pub total_direct: u32,
382 pub protocols: Vec<String>,
383 pub tokens: Vec<MatrixTokenEntry>,
384}
385
386#[derive(Debug, Clone, Serialize, Deserialize)]
392pub struct DiscoverySummary {
393 pub direct_count: Option<u32>,
394 pub total_count: Option<u32>,
395 pub scan_duration_ms: Option<u64>,
396 #[serde(default)]
397 pub protocols: Vec<String>,
398 pub updated_at: Option<u64>,
399}
400
401#[derive(Debug, Clone, Serialize, Deserialize)]
407pub struct RouteCandidate {
408 pub strategy_type: String,
409 pub protocol: String,
410 pub available_liquidity: f64,
411 pub protocol_fee_bps: u16,
412 pub vaea_fee_bps: u16,
413 pub total_cost_bps: u16,
414 pub total_cost_usd: f64,
415 pub sufficient_liquidity: bool,
416 pub feasible: bool,
417}
418
419#[derive(Debug, Clone, Serialize, Deserialize)]
421pub struct ResolvedRoute {
422 pub token_mint: String,
423 pub token_symbol: String,
424 pub amount: f64,
425 pub amount_usd: f64,
426 pub strategy: serde_json::Value, pub candidates: Vec<RouteCandidate>,
428 pub reasoning: String,
429}
430
431
432#[derive(Debug, Clone, Serialize, Deserialize)]
438pub struct ProtocolInfo {
439 pub id: String,
440 pub name: String,
441 pub program_id: String,
442 pub token_count: u32,
443 pub tokens: Vec<String>,
444}
445
446#[derive(Debug, Clone, Serialize, Deserialize)]
448pub struct FeeTierInfo {
449 pub bps: u16,
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize)]
454pub struct SourcesResponse {
455 pub discovery: String,
456 pub protocols: Vec<ProtocolInfo>,
457 pub fee_tiers: std::collections::HashMap<String, FeeTierInfo>,
458}
459
460#[derive(Debug, Clone, Serialize, Deserialize)]
466pub struct AggregatedCapacityResponse {
467 pub updated_at: u64,
468 pub tokens: Vec<serde_json::Value>,
469}
470