use anyhow::Result;
use swap_kit_types::{QuoteRequest, QuoteResponse, SingleQuote};
pub async fn get_best_quote(req: &QuoteRequest) -> Result<QuoteResponse> {
let (uniswap, paraswap, oneinch) = tokio::join!(
quote_uniswap_v4(req),
quote_paraswap(req),
quote_1inch_fusion(req),
);
let mut quotes = Vec::new();
if let Ok(q) = uniswap {
quotes.push(q);
}
if let Ok(q) = paraswap {
quotes.push(q);
}
if let Ok(q) = oneinch {
quotes.push(q);
}
quotes.sort_by(|a, b| {
let a_out: u128 = a.amount_out.parse().unwrap_or(0);
let b_out: u128 = b.amount_out.parse().unwrap_or(0);
b_out.cmp(&a_out)
});
Ok(QuoteResponse { quotes })
}
async fn quote_uniswap_v4(req: &QuoteRequest) -> Result<SingleQuote> {
let from_amount: u128 = req.from_amount.parse().unwrap_or(0);
let amount_out = from_amount.checked_mul(98).unwrap_or(0) / 100;
let gas_cost = 130_000u128.checked_mul(2_000_000_000).unwrap_or(0);
Ok(SingleQuote {
protocol: "uniswap-v4".to_string(),
amount_out: amount_out.to_string(),
gas_cost_wei: gas_cost.to_string(),
price_impact_bps: 30,
})
}
async fn quote_paraswap(req: &QuoteRequest) -> Result<SingleQuote> {
let from_amount: u128 = req.from_amount.parse().unwrap_or(0);
let amount_out = from_amount.checked_mul(97).unwrap_or(0) / 100;
let gas_cost = 150_000u128.checked_mul(2_000_000_000).unwrap_or(0);
Ok(SingleQuote {
protocol: "paraswap".to_string(),
amount_out: amount_out.to_string(),
gas_cost_wei: gas_cost.to_string(),
price_impact_bps: 25,
})
}
async fn quote_1inch_fusion(req: &QuoteRequest) -> Result<SingleQuote> {
let from_amount: u128 = req.from_amount.parse().unwrap_or(0);
let amount_out = from_amount.checked_mul(985).unwrap_or(0) / 1000;
Ok(SingleQuote {
protocol: "1inch-fusion".to_string(),
amount_out: amount_out.to_string(),
gas_cost_wei: "0".to_string(), price_impact_bps: 20,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_get_best_quote() {
let req = QuoteRequest {
from_token: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".to_string(),
to_token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".to_string(),
from_amount: "1000000000000000000".to_string(), chain_id: 1,
};
let result = get_best_quote(&req).await.unwrap();
assert_eq!(result.quotes.len(), 3);
let first_out: u128 = result.quotes[0].amount_out.parse().unwrap();
let last_out: u128 = result.quotes[2].amount_out.parse().unwrap();
assert!(first_out >= last_out);
}
}