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 #[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 AddPublicKey(AddPublicKey),
40
41 RemovePublicKey(RemovePublicKey),
43
44 InvalidateNonces(InvalidateNonces),
46
47 Transfer(Transfer),
49
50 FtWithdraw(FtWithdraw),
52
53 NftWithdraw(NftWithdraw),
55
56 MtWithdraw(MtWithdraw),
58
59 NativeWithdraw(NativeWithdraw),
61
62 StorageDeposit(StorageDeposit),
64
65 TokenDiff(TokenDiff),
67
68 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}