use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use crate::error::Result;
use crate::intent::Intent;
use crate::route::{Route, RouteLeg, Venue};
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct Conviction(pub f64);
impl Conviction {
pub fn clamped(v: f64) -> Self {
Self(v.clamp(0.0, 1.0))
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Solution {
pub intent_digest: String,
pub route: Route,
pub conviction: Conviction,
pub rationale: String,
}
#[async_trait]
pub trait RoutePolicy: Send + Sync {
async fn solve(&self, intent: &Intent) -> Result<Solution>;
}
pub struct ReferenceRoutePolicy;
#[async_trait]
impl RoutePolicy for ReferenceRoutePolicy {
async fn solve(&self, intent: &Intent) -> Result<Solution> {
let leg = RouteLeg {
venue: Venue::Jupiter,
input_mint: intent.input_mint.clone(),
output_mint: intent.output_mint.clone(),
split_bps: 10_000,
expected_out: intent.amount_in,
};
let route = Route {
legs: vec![leg],
expected_out: intent.amount_in,
};
Ok(Solution {
intent_digest: intent.digest(),
route,
conviction: Conviction::clamped(0.5),
rationale: "reference single-venue stub (no live pricing)".to_string(),
})
}
}