testnumbat_wasm/api/
call_value_api.rs

1use super::{ErrorApi, ManagedTypeApi};
2use crate::{
3    err_msg,
4    types::{BigUint, DcdtTokenPayment, DcdtTokenType, ManagedVec, TokenIdentifier},
5};
6
7pub trait CallValueApi: ManagedTypeApi + ErrorApi + Sized {
8    fn check_not_payable(&self);
9
10    /// Retrieves the REWA call value from the VM.
11    /// Will return 0 in case of an DCDT transfer (cannot have both REWA and DCDT transfer simultaneously).
12    fn rewa_value(&self) -> BigUint<Self>;
13
14    /// Retrieves the DCDT call value from the VM.
15    /// Will return 0 in case of an REWA transfer (cannot have both REWA and DCDT transfer simultaneously).
16    fn dcdt_value(&self) -> BigUint<Self>;
17
18    /// Returns the call value token identifier of the current call.
19    /// The identifier is wrapped in a TokenIdentifier object, to hide underlying logic.
20    ///
21    /// A note on implementation: even though the underlying api returns an empty name for REWA,
22    /// but the REWA TokenIdentifier is serialized as `REWA`.
23    fn token(&self) -> TokenIdentifier<Self>;
24
25    /// Returns the nonce of the received DCDT token.
26    /// Will return 0 in case of REWA or fungible DCDT transfer.
27    fn dcdt_token_nonce(&self) -> u64;
28
29    /// Returns the DCDT token type.
30    /// Will return "Fungible" for REWA.
31    fn dcdt_token_type(&self) -> DcdtTokenType;
32
33    /// Will return the REWA call value,
34    /// but also fail with an error if DCDT is sent.
35    /// Especially used in the auto-generated call value processing.
36    fn require_rewa(&self) -> BigUint<Self> {
37        if !self.token().is_rewa() {
38            self.signal_error(err_msg::NON_PAYABLE_FUNC_DCDT);
39        }
40        self.rewa_value()
41    }
42
43    /// Will return the DCDT call value,
44    /// but also fail with an error if REWA or the wrong DCDT token is sent.
45    /// Especially used in the auto-generated call value processing.
46    fn require_dcdt(&self, token: &[u8]) -> BigUint<Self> {
47        if self.token().as_managed_buffer() != token {
48            self.signal_error(err_msg::BAD_TOKEN_PROVIDED);
49        }
50        self.dcdt_value()
51    }
52
53    /// Returns both the call value (either REWA or DCDT) and the token identifier.
54    /// Especially used in the `#[payable("*")] auto-generated snippets.
55    /// The method might seem redundant, but there is such a hook in Andes
56    /// that might be used in this scenario in the future.
57    fn payment_token_pair(&self) -> (BigUint<Self>, TokenIdentifier<Self>) {
58        let token = self.token();
59        if token.is_rewa() {
60            (self.rewa_value(), token)
61        } else {
62            (self.dcdt_value(), token)
63        }
64    }
65
66    fn dcdt_num_transfers(&self) -> usize;
67
68    fn dcdt_value_by_index(&self, index: usize) -> BigUint<Self>;
69
70    fn token_by_index(&self, index: usize) -> TokenIdentifier<Self>;
71
72    fn dcdt_token_nonce_by_index(&self, index: usize) -> u64;
73
74    fn dcdt_token_type_by_index(&self, index: usize) -> DcdtTokenType;
75
76    fn get_all_dcdt_transfers(&self) -> ManagedVec<Self, DcdtTokenPayment<Self>> {
77        let num_transfers = self.dcdt_num_transfers();
78        let mut transfers = ManagedVec::new(self.clone());
79
80        for i in 0..num_transfers {
81            let token_type = self.dcdt_token_type_by_index(i);
82            let token_identifier = self.token_by_index(i);
83            let token_nonce = self.dcdt_token_nonce_by_index(i);
84            let amount = self.dcdt_value_by_index(i);
85
86            transfers.push(DcdtTokenPayment::<Self> {
87                token_type,
88                token_identifier,
89                token_nonce,
90                amount,
91            });
92        }
93
94        transfers
95    }
96}