use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone)]
pub struct VaeaConfig {
pub api_url: String,
pub source: Source,
}
impl Default for VaeaConfig {
fn default() -> Self {
Self {
api_url: "https://api.vaea.fi".to_string(),
source: Source::Sdk,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum Source {
Sdk,
Ui,
Protocol,
}
impl fmt::Display for Source {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Source::Sdk => write!(f, "sdk"),
Source::Ui => write!(f, "ui"),
Source::Protocol => write!(f, "protocol"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum VaeaErrorCode {
InsufficientLiquidity,
TokenNotSupported,
SlippageExceeded,
FeeTooHigh,
RepayFailed,
TxExpired,
SourceUnavailable,
ProgramPaused,
InvalidAmount,
InsufficientSolForFee,
ApiError,
NetworkError,
}
impl fmt::Display for VaeaErrorCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
VaeaErrorCode::InsufficientLiquidity => write!(f, "INSUFFICIENT_LIQUIDITY"),
VaeaErrorCode::TokenNotSupported => write!(f, "TOKEN_NOT_SUPPORTED"),
VaeaErrorCode::SlippageExceeded => write!(f, "SLIPPAGE_EXCEEDED"),
VaeaErrorCode::FeeTooHigh => write!(f, "FEE_TOO_HIGH"),
VaeaErrorCode::RepayFailed => write!(f, "REPAY_FAILED"),
VaeaErrorCode::TxExpired => write!(f, "TX_EXPIRED"),
VaeaErrorCode::SourceUnavailable => write!(f, "SOURCE_UNAVAILABLE"),
VaeaErrorCode::ProgramPaused => write!(f, "PROGRAM_PAUSED"),
VaeaErrorCode::InvalidAmount => write!(f, "INVALID_AMOUNT"),
VaeaErrorCode::InsufficientSolForFee => write!(f, "INSUFFICIENT_SOL_FOR_FEE"),
VaeaErrorCode::ApiError => write!(f, "API_ERROR"),
VaeaErrorCode::NetworkError => write!(f, "NETWORK_ERROR"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CapacityResponse {
pub updated_at: u64,
pub tokens: Vec<TokenCapacity>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TokenCapacity {
pub symbol: String,
pub mint: String,
pub name: String,
pub decimals: u8,
pub route_type: String,
pub source_protocol: String,
pub max_amount: f64,
pub max_amount_usd: f64,
pub fee_sdk: FeeInfo,
pub fee_ui: FeeInfo,
pub status: String,
pub updated_at: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FeeInfo {
pub bps: u16,
pub pct: f64,
pub total_pct: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuoteResponse {
pub token: String,
pub mint: String,
pub amount_requested: f64,
pub source: String,
pub route: RouteQuote,
pub fee_breakdown: FeeBreakdown,
pub price_impact: f64,
pub valid_until: u64,
pub valid_for_slots: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouteQuote {
#[serde(rename = "type")]
pub route_type: String,
pub steps: Vec<RouteStep>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouteStep {
pub action: String,
pub protocol: String,
pub token: String,
pub amount: f64,
pub expected_output: Option<f64>,
pub price_impact: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FeeBreakdown {
pub source_fee: f64,
pub vaea_fee: f64,
pub total_fee_sol: f64,
pub total_fee_usd: f64,
pub total_fee_pct: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BuildRequest {
pub token: String,
pub amount: f64,
pub user_pubkey: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub slippage_bps: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_fee_bps: Option<u16>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiInstructionData {
pub program_id: String,
pub data: String,
pub accounts: Vec<ApiAccountMeta>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiAccountMeta {
pub pubkey: String,
pub is_signer: bool,
pub is_writable: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BuildResponse {
pub prefix_instructions: Vec<ApiInstructionData>,
pub suffix_instructions: Vec<ApiInstructionData>,
pub lookup_tables: Vec<String>,
pub estimated_fee_lamports: u64,
pub valid_for_slots: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthResponse {
pub status: String,
pub timestamp: u64,
pub components: serde_json::Value,
pub sources: serde_json::Value,
}
pub struct BorrowParams {
pub token: String,
pub amount: f64,
pub instructions: Vec<solana_sdk::instruction::Instruction>,
pub slippage_bps: Option<u16>,
pub max_fee_bps: Option<u16>,
}
pub const VAEA_API_URL: &str = "https://api.vaea.fi";
pub const VAEA_PROGRAM_ID: &str = "VAEAmcjQ5RB9yonyrCRSkRT8womX6uqm5PS7PXr528b";
pub const VAEA_LOOKUP_TABLE: solana_sdk::pubkey::Pubkey =
solana_sdk::pubkey!("CsfmCd4gBs2VNsBQu37kjKttKJTMzePrQwYCDdLnuLDs");
pub const SUPPORTED_TOKENS: &[&str] = &[
"SOL", "USDC", "USDT", "JitoSOL", "JupSOL", "JUP", "JLP", "cbBTC",
"mSOL", "bSOL",
"INF", "laineSOL",
];
pub const FEE_BPS_SDK: u16 = 2;
pub const FEE_BPS_UI: u16 = 2;
pub const FEE_BPS_CPI: u16 = 2;
#[derive(Debug, Clone)]
pub struct SimulateResult {
pub success: bool,
pub error: Option<String>,
pub compute_units: u64,
pub logs: Vec<String>,
}
pub struct MultiBorrowRequest {
pub token: String,
pub amount: f64,
}
pub struct BorrowMultiParams {
pub loans: Vec<MultiBorrowRequest>,
pub instructions: Vec<solana_sdk::instruction::Instruction>,
pub slippage_bps: Option<u16>,
pub max_fee_bps: Option<u16>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FlashTier {
Sdk = 0,
Ui = 1,
Protocol = 2,
}
impl FlashTier {
pub fn from_u8(v: u8) -> Option<Self> {
match v {
0 => Some(Self::Sdk),
1 => Some(Self::Ui),
2 => Some(Self::Protocol),
_ => None,
}
}
pub fn fee_bps(&self) -> u16 {
match self {
Self::Sdk => FEE_BPS_SDK,
Self::Ui => FEE_BPS_UI,
Self::Protocol => FEE_BPS_CPI,
}
}
}
#[derive(Debug, Clone)]
pub struct FlashStateInfo {
pub payer: solana_sdk::pubkey::Pubkey,
pub token_mint: solana_sdk::pubkey::Pubkey,
pub amount: u64,
pub fee: u64,
pub source_tier: u8,
pub tier: FlashTier,
pub slot_created: u64,
pub bump: u8,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SourceCapacity {
pub protocol: String,
pub pool: String,
pub available: f64,
pub available_usd: f64,
pub utilization_pct: f64,
pub status: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AggregatedTokenCapacity {
#[serde(flatten)]
pub base: TokenCapacity,
pub sources: Vec<SourceCapacity>,
pub total_available: f64,
pub total_available_usd: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MatrixTokenEntry {
pub mint: String,
pub symbol: String,
pub name: String,
pub decimals: u8,
pub is_direct: bool,
pub liquidity: std::collections::HashMap<String, f64>,
pub total_liquidity: f64,
pub total_liquidity_usd: f64,
pub cheapest_source_fee_bps: u16,
pub best_protocol: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MatrixResponse {
pub updated_at: u64,
pub total_tokens: u32,
pub total_direct: u32,
pub protocols: Vec<String>,
pub tokens: Vec<MatrixTokenEntry>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiscoverySummary {
pub direct_count: Option<u32>,
pub total_count: Option<u32>,
pub scan_duration_ms: Option<u64>,
#[serde(default)]
pub protocols: Vec<String>,
pub updated_at: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouteCandidate {
pub strategy_type: String,
pub protocol: String,
pub available_liquidity: f64,
pub protocol_fee_bps: u16,
pub vaea_fee_bps: u16,
pub total_cost_bps: u16,
pub total_cost_usd: f64,
pub sufficient_liquidity: bool,
pub feasible: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResolvedRoute {
pub token_mint: String,
pub token_symbol: String,
pub amount: f64,
pub amount_usd: f64,
pub strategy: serde_json::Value, pub candidates: Vec<RouteCandidate>,
pub reasoning: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProtocolInfo {
pub id: String,
pub name: String,
pub program_id: String,
pub token_count: u32,
pub tokens: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FeeTierInfo {
pub bps: u16,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SourcesResponse {
pub discovery: String,
pub protocols: Vec<ProtocolInfo>,
pub fee_tiers: std::collections::HashMap<String, FeeTierInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AggregatedCapacityResponse {
pub updated_at: u64,
pub tokens: Vec<serde_json::Value>,
}