Skip to main content

scemadex_sdk/
intent.rs

1use serde::{Deserialize, Serialize};
2
3use crate::primitives::{Address, Amount};
4
5/// What the caller is optimizing for. The RL policy weights its route search by
6/// this objective — and, crucially, can optimize *timing* and *footprint*, which
7/// static pathfinders cannot.
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
9pub enum Objective {
10    /// Best effective price / minimal slippage.
11    Price,
12    /// Fastest confirmation; price is secondary.
13    Speed,
14    /// Minimal MEV footprint — split and time the order to resist sandwiching.
15    Stealth,
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
19pub enum Side {
20    Buy,
21    Sell,
22}
23
24/// Hard limits the solver must respect; a solution that violates any of these is
25/// rejected before bonding.
26#[derive(Clone, Debug, Serialize, Deserialize)]
27pub struct Constraints {
28    pub max_slippage_bps: u32,
29    /// Deadline in unix seconds; `0` means "no explicit deadline" in the scaffold.
30    pub deadline_unix: u64,
31    /// Optional cap on how many legs/splits the route may use.
32    pub max_legs: Option<u8>,
33}
34
35/// A declarative request: *what* the caller wants, not *how* to route it. The
36/// [`crate::policy::RoutePolicy`] turns this into a [`crate::policy::Solution`].
37#[derive(Clone, Debug, Serialize, Deserialize)]
38pub struct Intent {
39    pub input_mint: Address,
40    pub output_mint: Address,
41    pub amount_in: Amount,
42    pub side: Side,
43    pub objective: Objective,
44    pub constraints: Constraints,
45}
46
47impl Intent {
48    /// Stable content digest used as a key for metering, caching, and bonds.
49    ///
50    /// Uses an FNV-1a hash over the canonical JSON encoding to avoid pulling a
51    /// crypto-hash dependency into the lean core. Good enough as a scaffold key;
52    /// the `scematica` feature can swap in a stronger hash where it matters.
53    pub fn digest(&self) -> String {
54        let s = serde_json::to_string(self).unwrap_or_default();
55        let mut h: u64 = 0xcbf2_9ce4_8422_2325;
56        for b in s.bytes() {
57            h ^= b as u64;
58            h = h.wrapping_mul(0x0000_0100_0000_01b3);
59        }
60        format!("{h:016x}")
61    }
62}