Skip to main content

defuse_core/intents/
mod.rs

1pub mod account;
2pub mod auth;
3pub mod token_diff;
4pub mod tokens;
5
6#[cfg(feature = "imt")]
7pub mod imt;
8
9use derive_more::derive::From;
10use serde::{Deserialize, Serialize};
11use serde_with::{base58::Base58, serde_as};
12
13#[cfg(feature = "imt")]
14use crate::intents::imt::{ImtBurn, ImtMint};
15
16use crate::{
17    AccountIdRef, Result,
18    engine::{Engine, Inspector, State},
19    intents::{account::SetAuthByPredecessorId, auth::AuthCall},
20};
21
22use self::{
23    account::{AddPublicKey, RemovePublicKey},
24    token_diff::TokenDiff,
25    tokens::{FtWithdraw, MtWithdraw, NativeWithdraw, NftWithdraw, StorageDeposit, Transfer},
26};
27
28#[cfg_attr(feature = "schemars-v0_8", derive(::schemars::JsonSchema))]
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct DefuseIntents {
31    /// Sequence of intents to execute in given order. Empty list is also
32    /// a valid sequence, i.e. it doesn't do anything, but still invalidates
33    /// the `nonce` for the signer
34    /// WARNING: Promises created by different intents are executed concurrently and does not rely on the order of the intents in this structure
35    #[serde(default, skip_serializing_if = "Vec::is_empty")]
36    pub intents: Vec<Intent>,
37}
38
39#[cfg_attr(feature = "schemars-v0_8", derive(::schemars::JsonSchema))]
40#[derive(Debug, Clone, Serialize, Deserialize, From)]
41#[serde(tag = "intent", rename_all = "snake_case")]
42pub enum Intent {
43    /// See [`AddPublicKey`]
44    AddPublicKey(AddPublicKey),
45
46    /// See [`RemovePublicKey`]
47    RemovePublicKey(RemovePublicKey),
48
49    /// See [`Transfer`]
50    Transfer(Transfer),
51
52    /// See [`FtWithdraw`]
53    FtWithdraw(FtWithdraw),
54
55    /// See [`NftWithdraw`]
56    NftWithdraw(NftWithdraw),
57
58    /// See [`MtWithdraw`]
59    MtWithdraw(MtWithdraw),
60
61    /// See [`NativeWithdraw`]
62    NativeWithdraw(NativeWithdraw),
63
64    /// See [`StorageDeposit`]
65    StorageDeposit(StorageDeposit),
66
67    /// See [`TokenDiff`]
68    TokenDiff(TokenDiff),
69
70    /// See [`SetAuthByPredecessorId`]
71    SetAuthByPredecessorId(SetAuthByPredecessorId),
72
73    /// See [`AuthCall`]
74    AuthCall(AuthCall),
75
76    // See [`ImtMint`]
77    #[cfg(feature = "imt")]
78    ImtMint(ImtMint),
79
80    // See [`ImtBurn`]
81    #[cfg(feature = "imt")]
82    ImtBurn(ImtBurn),
83}
84
85pub trait ExecutableIntent {
86    fn execute_intent<S, I>(
87        self,
88        signer_id: &AccountIdRef,
89        engine: &mut Engine<S, I>,
90        intent_hash: [u8; 32],
91    ) -> Result<()>
92    where
93        S: State,
94        I: Inspector;
95}
96
97impl ExecutableIntent for DefuseIntents {
98    fn execute_intent<S, I>(
99        self,
100        signer_id: &AccountIdRef,
101        engine: &mut Engine<S, I>,
102        intent_hash: [u8; 32],
103    ) -> Result<()>
104    where
105        S: State,
106        I: Inspector,
107    {
108        for intent in self.intents {
109            intent.execute_intent(signer_id, engine, intent_hash)?;
110        }
111        Ok(())
112    }
113}
114
115impl ExecutableIntent for Intent {
116    fn execute_intent<S, I>(
117        self,
118        signer_id: &AccountIdRef,
119        engine: &mut Engine<S, I>,
120        intent_hash: [u8; 32],
121    ) -> Result<()>
122    where
123        S: State,
124        I: Inspector,
125    {
126        match self {
127            Self::AddPublicKey(intent) => intent.execute_intent(signer_id, engine, intent_hash),
128            Self::RemovePublicKey(intent) => intent.execute_intent(signer_id, engine, intent_hash),
129            Self::Transfer(intent) => intent.execute_intent(signer_id, engine, intent_hash),
130            Self::FtWithdraw(intent) => intent.execute_intent(signer_id, engine, intent_hash),
131            Self::NftWithdraw(intent) => intent.execute_intent(signer_id, engine, intent_hash),
132            Self::MtWithdraw(intent) => intent.execute_intent(signer_id, engine, intent_hash),
133            Self::NativeWithdraw(intent) => intent.execute_intent(signer_id, engine, intent_hash),
134            Self::StorageDeposit(intent) => intent.execute_intent(signer_id, engine, intent_hash),
135            Self::TokenDiff(intent) => intent.execute_intent(signer_id, engine, intent_hash),
136            Self::SetAuthByPredecessorId(intent) => {
137                intent.execute_intent(signer_id, engine, intent_hash)
138            }
139            Self::AuthCall(intent) => intent.execute_intent(signer_id, engine, intent_hash),
140            #[cfg(feature = "imt")]
141            Self::ImtMint(intent) => intent.execute_intent(signer_id, engine, intent_hash),
142            #[cfg(feature = "imt")]
143            Self::ImtBurn(intent) => intent.execute_intent(signer_id, engine, intent_hash),
144        }
145    }
146}
147
148/// Event that can be emitted either from a
149/// function call or after intent execution
150#[must_use = "make sure to `.emit()` this event"]
151#[serde_as]
152#[cfg_attr(feature = "schemars-v0_8", derive(::schemars::JsonSchema))]
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct MaybeIntentEvent<T> {
155    #[serde_as(as = "Option<Base58>")]
156    #[serde(default, skip_serializing_if = "Option::is_none")]
157    pub intent_hash: Option<[u8; 32]>,
158
159    #[serde(flatten)]
160    pub event: T,
161}
162
163impl<T> MaybeIntentEvent<T> {
164    #[inline]
165    pub const fn new_fn_call(event: T) -> Self {
166        Self {
167            intent_hash: None,
168            event,
169        }
170    }
171
172    #[inline]
173    pub const fn new_intent(event: T, intent_hash: [u8; 32]) -> Self {
174        Self {
175            intent_hash: Some(intent_hash),
176            event,
177        }
178    }
179}
180
181impl<T> From<T> for MaybeIntentEvent<T> {
182    fn from(event: T) -> Self {
183        Self::new_fn_call(event)
184    }
185}