defuse/
intents.rs

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