defuse_core/intents/
mod.rs

1pub mod account;
2pub mod token_diff;
3pub mod tokens;
4
5use defuse_serde_utils::base58::Base58;
6use derive_more::derive::From;
7use near_sdk::{AccountIdRef, CryptoHash, near};
8use serde_with::serde_as;
9use tokens::{NativeWithdraw, StorageDeposit};
10
11use crate::{
12    Result,
13    engine::{Engine, Inspector, State},
14    intents::account::SetAuthByPredecessorId,
15};
16
17use self::{
18    account::{AddPublicKey, InvalidateNonces, RemovePublicKey},
19    token_diff::TokenDiff,
20    tokens::{FtWithdraw, MtWithdraw, NftWithdraw, Transfer},
21};
22
23#[near(serializers = [json])]
24#[derive(Debug, Clone)]
25pub struct DefuseIntents {
26    /// Sequence of intents to execute in given order. Empty list is also
27    /// a valid sequence, i.e. it doesn't do anything, but still invalidates
28    /// the `nonce` for the signer
29    /// WARNING: Promises created by different intents are executed concurrently and does not rely on the order of the intents in this structure
30    #[serde(default, skip_serializing_if = "Vec::is_empty")]
31    pub intents: Vec<Intent>,
32}
33
34#[near(serializers = [json])]
35#[serde(tag = "intent", rename_all = "snake_case")]
36#[derive(Debug, Clone, From)]
37pub enum Intent {
38    /// See [`AddPublicKey`]
39    AddPublicKey(AddPublicKey),
40
41    /// See [`RemovePublicKey`]
42    RemovePublicKey(RemovePublicKey),
43
44    /// See [`InvalidateNonces`]
45    InvalidateNonces(InvalidateNonces),
46
47    /// See [`Transfer`]
48    Transfer(Transfer),
49
50    /// See [`FtWithdraw`]
51    FtWithdraw(FtWithdraw),
52
53    /// See [`NftWithdraw`]
54    NftWithdraw(NftWithdraw),
55
56    /// See [`MtWithdraw`]
57    MtWithdraw(MtWithdraw),
58
59    /// See [`NativeWithdraw`]
60    NativeWithdraw(NativeWithdraw),
61
62    /// See [`StorageDeposit`]
63    StorageDeposit(StorageDeposit),
64
65    /// See [`TokenDiff`]
66    TokenDiff(TokenDiff),
67
68    /// See [`SetAuthByPredecessorId`]
69    SetAuthByPredecessorId(SetAuthByPredecessorId),
70}
71
72pub trait ExecutableIntent {
73    fn execute_intent<S, I>(
74        self,
75        signer_id: &AccountIdRef,
76        engine: &mut Engine<S, I>,
77        intent_hash: CryptoHash,
78    ) -> Result<()>
79    where
80        S: State,
81        I: Inspector;
82}
83
84impl ExecutableIntent for DefuseIntents {
85    fn execute_intent<S, I>(
86        self,
87        signer_id: &AccountIdRef,
88        engine: &mut Engine<S, I>,
89        intent_hash: CryptoHash,
90    ) -> Result<()>
91    where
92        S: State,
93        I: Inspector,
94    {
95        for intent in self.intents {
96            intent.execute_intent(signer_id, engine, intent_hash)?;
97        }
98        Ok(())
99    }
100}
101
102impl ExecutableIntent for Intent {
103    fn execute_intent<S, I>(
104        self,
105        signer_id: &AccountIdRef,
106        engine: &mut Engine<S, I>,
107        intent_hash: CryptoHash,
108    ) -> Result<()>
109    where
110        S: State,
111        I: Inspector,
112    {
113        match self {
114            Self::AddPublicKey(intent) => intent.execute_intent(signer_id, engine, intent_hash),
115            Self::RemovePublicKey(intent) => intent.execute_intent(signer_id, engine, intent_hash),
116            Self::InvalidateNonces(intent) => intent.execute_intent(signer_id, engine, intent_hash),
117            Self::Transfer(intent) => intent.execute_intent(signer_id, engine, intent_hash),
118            Self::FtWithdraw(intent) => intent.execute_intent(signer_id, engine, intent_hash),
119            Self::NftWithdraw(intent) => intent.execute_intent(signer_id, engine, intent_hash),
120            Self::MtWithdraw(intent) => intent.execute_intent(signer_id, engine, intent_hash),
121            Self::NativeWithdraw(intent) => intent.execute_intent(signer_id, engine, intent_hash),
122            Self::StorageDeposit(intent) => intent.execute_intent(signer_id, engine, intent_hash),
123            Self::TokenDiff(intent) => intent.execute_intent(signer_id, engine, intent_hash),
124            Self::SetAuthByPredecessorId(intent) => {
125                intent.execute_intent(signer_id, engine, intent_hash)
126            }
127        }
128    }
129}
130
131#[must_use = "make sure to `.emit()` this event"]
132#[cfg_attr(
133    all(feature = "abi", not(target_arch = "wasm32")),
134    serde_as(schemars = true)
135)]
136#[cfg_attr(
137    not(all(feature = "abi", not(target_arch = "wasm32"))),
138    serde_as(schemars = false)
139)]
140#[near(serializers = [json])]
141#[derive(Debug, Clone)]
142pub struct IntentEvent<T> {
143    #[serde_as(as = "Base58")]
144    pub intent_hash: CryptoHash,
145    #[serde(flatten)]
146    pub event: T,
147}
148
149impl<T> IntentEvent<T> {
150    #[inline]
151    pub const fn new(event: T, intent_hash: CryptoHash) -> Self {
152        Self { intent_hash, event }
153    }
154}