defuse_core/intents/
mod.rs

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