aurora_engine_sdk/
promise.rs

1use aurora_engine_types::parameters::{
2    PromiseBatchAction, PromiseCreateArgs, PromiseWithCallbackArgs,
3};
4use aurora_engine_types::types::PromiseResult;
5
6#[derive(Debug, Eq, PartialEq, Copy, Clone)]
7pub struct PromiseId(u64);
8
9impl PromiseId {
10    #[must_use]
11    pub const fn new(id: u64) -> Self {
12        Self(id)
13    }
14
15    #[must_use]
16    pub const fn raw(self) -> u64 {
17        self.0
18    }
19}
20
21pub trait PromiseHandler {
22    type ReadOnly: ReadOnlyPromiseHandler;
23
24    fn promise_results_count(&self) -> u64;
25    fn promise_result(&self, index: u64) -> Option<PromiseResult>;
26
27    /// # Safety
28    /// Creating calls to other contracts using the Engine account is dangerous because
29    /// it has special admin privileges (especially with itself), for example minting
30    /// bridged tokens. Therefore, this function must be used with extreme caution to prevent
31    /// security vulnerabilities. In particular, it must not be possible for users to execute
32    /// arbitrary calls using the Engine.
33    unsafe fn promise_create_call(&mut self, args: &PromiseCreateArgs) -> PromiseId;
34
35    /// Combine more than one promise into one.
36    /// # Safety
37    /// Safe because of use `promise_create_call` function under the hood.
38    unsafe fn promise_create_and_combine(&mut self, args: &[PromiseCreateArgs]) -> PromiseId;
39
40    /// # Safety
41    /// See note on `promise_create_call`.
42    unsafe fn promise_attach_callback(
43        &mut self,
44        base: PromiseId,
45        callback: &PromiseCreateArgs,
46    ) -> PromiseId;
47
48    /// # Safety
49    /// See note on `promise_create_call`. Promise batches in particular must be used very
50    /// carefully because they can take destructive actions such as deploying new contract
51    /// code or adding/removing access keys.
52    unsafe fn promise_create_batch(&mut self, args: &PromiseBatchAction) -> PromiseId;
53
54    /// # Safety
55    /// See note on `promise_create_call`. Promise batches in particular must be used very
56    /// carefully because they can take destructive actions such as deploying new contract
57    /// code or adding/removing access keys.
58    unsafe fn promise_attach_batch_callback(
59        &mut self,
60        base: PromiseId,
61        args: &PromiseBatchAction,
62    ) -> PromiseId;
63
64    fn promise_return(&mut self, promise: PromiseId);
65
66    /// # Safety
67    /// See note on `promise_create_call`.
68    unsafe fn promise_create_with_callback(&mut self, args: &PromiseWithCallbackArgs) -> PromiseId {
69        let base = self.promise_create_call(&args.base);
70        self.promise_attach_callback(base, &args.callback)
71    }
72
73    fn read_only(&self) -> Self::ReadOnly;
74
75    /// Returns `None` if there were no prior promises
76    /// (i.e. the method was not called as a callback). Returns `Some(true)` if
77    /// there was at least one promise result and all results were successful.
78    /// Returns `Some(false)` if there was at least one failed promise result.
79    fn promise_result_check(&self) -> Option<bool> {
80        let num_promises = self.promise_results_count();
81        if num_promises == 0 {
82            return None;
83        }
84        for index in 0..num_promises {
85            if let Some(PromiseResult::Failed | PromiseResult::NotReady) =
86                self.promise_result(index)
87            {
88                return Some(false);
89            }
90        }
91        Some(true)
92    }
93}
94
95pub trait ReadOnlyPromiseHandler {
96    fn ro_promise_results_count(&self) -> u64;
97    fn ro_promise_result(&self, index: u64) -> Option<PromiseResult>;
98}
99
100impl<T: PromiseHandler> ReadOnlyPromiseHandler for T {
101    fn ro_promise_results_count(&self) -> u64 {
102        self.promise_results_count()
103    }
104
105    fn ro_promise_result(&self, index: u64) -> Option<PromiseResult> {
106        self.promise_result(index)
107    }
108}
109
110/// A promise handler which does nothing. Should only be used when promises can be safely ignored.
111#[derive(Debug, Copy, Clone)]
112pub struct Noop;
113
114impl PromiseHandler for Noop {
115    type ReadOnly = Self;
116
117    fn promise_results_count(&self) -> u64 {
118        0
119    }
120
121    fn promise_result(&self, _index: u64) -> Option<PromiseResult> {
122        None
123    }
124
125    unsafe fn promise_create_call(&mut self, _args: &PromiseCreateArgs) -> PromiseId {
126        PromiseId::new(0)
127    }
128
129    unsafe fn promise_create_and_combine(&mut self, _args: &[PromiseCreateArgs]) -> PromiseId {
130        PromiseId::new(0)
131    }
132
133    unsafe fn promise_attach_callback(
134        &mut self,
135        _base: PromiseId,
136        _callback: &PromiseCreateArgs,
137    ) -> PromiseId {
138        PromiseId::new(0)
139    }
140
141    unsafe fn promise_create_batch(&mut self, _args: &PromiseBatchAction) -> PromiseId {
142        PromiseId::new(0)
143    }
144
145    unsafe fn promise_attach_batch_callback(
146        &mut self,
147        _base: PromiseId,
148        _args: &PromiseBatchAction,
149    ) -> PromiseId {
150        PromiseId::new(0)
151    }
152
153    fn promise_return(&mut self, _promise: PromiseId) {}
154
155    fn read_only(&self) -> Self::ReadOnly {
156        Self
157    }
158}