defuse/
intents.rs

1use defuse_core::{
2    Deadline, Result, accounts::AccountEvent, engine::deltas::InvariantViolated, fees::Pips,
3    intents::IntentEvent, payload::multi::MultiPayload,
4};
5
6use near_plugins::AccessControllable;
7use near_sdk::{Promise, PublicKey, ext_contract, near};
8use serde_with::serde_as;
9
10use crate::fees::FeesManager;
11
12#[ext_contract(ext_intents)]
13pub trait Intents: FeesManager {
14    fn execute_intents(&mut self, signed: Vec<MultiPayload>);
15
16    fn simulate_intents(&self, signed: Vec<MultiPayload>) -> SimulationOutput;
17}
18
19#[cfg_attr(
20    all(feature = "abi", not(target_arch = "wasm32")),
21    serde_as(schemars = true)
22)]
23#[cfg_attr(
24    not(all(feature = "abi", not(target_arch = "wasm32"))),
25    serde_as(schemars = false)
26)]
27#[near(serializers = [json])]
28#[derive(Debug, Clone)]
29pub struct SimulationOutput {
30    /// Intent hashes along with corresponding signers
31    pub intents_executed: Vec<IntentEvent<AccountEvent<'static, ()>>>,
32
33    /// Minimum deadline among all simulated intents
34    pub min_deadline: Deadline,
35
36    /// Unmatched token deltas needed to keep the invariant.
37    /// If not empty, can be used along with fee to calculate `token_diff` closure.
38    #[serde(default, skip_serializing_if = "Option::is_none")]
39    pub invariant_violated: Option<InvariantViolated>,
40
41    /// Additional info about current state
42    pub state: StateOutput,
43}
44
45impl SimulationOutput {
46    pub fn into_result(self) -> Result<(), InvariantViolated> {
47        if let Some(unmatched_deltas) = self.invariant_violated {
48            return Err(unmatched_deltas);
49        }
50        Ok(())
51    }
52}
53
54#[near(serializers = [json])]
55#[derive(Debug, Clone)]
56pub struct StateOutput {
57    pub fee: Pips,
58}
59
60#[ext_contract(ext_relayer_keys)]
61pub trait RelayerKeys: AccessControllable {
62    /// Adds access key for calling `execute_signed_intents`
63    /// with allowance passed as attached deposit via `#[payable]`
64    /// NOTE: requires 1yN for security purposes
65    fn add_relayer_key(&mut self, public_key: PublicKey) -> Promise;
66
67    fn do_add_relayer_key(&mut self, public_key: PublicKey);
68
69    /// NOTE: requires 1yN for security purposes
70    fn delete_relayer_key(&mut self, public_key: PublicKey) -> Promise;
71}