use axum::{
extract::Json,
routing::{get, post},
Router,
};
use std::net::SocketAddr;
use tower_http::cors::{CorsLayer, Any};
use tracing_subscriber::EnvFilter;
mod mev;
mod quote;
mod mining;
use swap_kit_types::{
MineRequest, MineResult, QuoteRequest, QuoteResponse, SimulateRequest, SimulateResponse,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| {
EnvFilter::new("swap_kit_engine=info,tower_http=info")
}))
.init();
let cors = CorsLayer::new()
.allow_origin(Any) .allow_methods(Any)
.allow_headers(Any);
let app = Router::new()
.route("/health", get(health))
.route("/simulate", post(simulate_mev))
.route("/quote", post(get_quote))
.route("/mine", post(mine_hook_address))
.layer(cors);
let addr = SocketAddr::from(([0, 0, 0, 0], 3030));
tracing::info!("swap-kit-engine listening on {}", addr);
let listener = tokio::net::TcpListener::bind(addr).await?;
axum::serve(listener, app).await?;
Ok(())
}
async fn health() -> &'static str {
"ok"
}
async fn simulate_mev(Json(req): Json<SimulateRequest>) -> Json<SimulateResponse> {
let report = mev::simulator::simulate(&req)
.await
.unwrap_or_else(|e| {
tracing::warn!("MEV simulation failed: {e}, returning safe default");
mev::simulator::safe_default()
});
Json(report)
}
async fn get_quote(Json(req): Json<QuoteRequest>) -> Json<QuoteResponse> {
let quotes = quote::scanner::get_best_quote(&req)
.await
.unwrap_or_default();
Json(quotes)
}
async fn mine_hook_address(Json(req): Json<MineRequest>) -> Json<MineResult> {
let result = tokio::task::spawn_blocking(move || mining::hook_miner::mine(req))
.await
.unwrap_or_else(|_e| MineResult {
salt: String::new(),
address: String::new(),
attempts: 0,
found: false,
});
Json(result)
}