defuse_core/
tokens.rs

1use near_sdk::{AccountIdRef, Gas, near};
2use serde_with::{DisplayFromStr, serde_as};
3use std::{borrow::Cow, collections::BTreeMap};
4
5use crate::{amounts::Amounts, intents::tokens::Transfer};
6
7pub const MAX_TOKEN_ID_LEN: usize = 127;
8
9pub const MT_ON_TRANSFER_GAS_MIN: Gas = Gas::from_tgas(5);
10pub const MT_ON_TRANSFER_GAS_DEFAULT: Gas = Gas::from_tgas(30);
11
12#[cfg(feature = "imt")]
13pub mod imt {
14    use defuse_token_id::{TokenId, imt::ImtTokenId};
15    use near_sdk::{AccountIdRef, near};
16    use serde_with::{DisplayFromStr, serde_as};
17    use std::{borrow::Cow, collections::BTreeMap};
18
19    use crate::{
20        DefuseError, Result, amounts::Amounts, intents::imt::ImtMint, tokens::MAX_TOKEN_ID_LEN,
21    };
22
23    pub type ImtTokens = Amounts<BTreeMap<defuse_nep245::TokenId, u128>>;
24
25    impl ImtTokens {
26        #[inline]
27        pub fn into_generic_tokens(
28            self,
29            minter_id: &AccountIdRef,
30        ) -> Result<Amounts<BTreeMap<TokenId, u128>>> {
31            let tokens = self
32                .into_iter()
33                .map(|(token_id, amount)| {
34                    if token_id.len() > MAX_TOKEN_ID_LEN {
35                        return Err(DefuseError::TokenIdTooLarge(token_id.len()));
36                    }
37
38                    let token = ImtTokenId::new(minter_id, token_id).into();
39
40                    Ok((token, amount))
41                })
42                .collect::<Result<_, _>>()?;
43
44            Ok(Amounts::new(tokens))
45        }
46    }
47
48    #[near(serializers = [json])]
49    #[derive(Debug, Clone)]
50    pub struct ImtMintEvent<'a> {
51        pub receiver_id: Cow<'a, AccountIdRef>,
52
53        #[serde_as(as = "Amounts<BTreeMap<_, DisplayFromStr>>")]
54        pub tokens: ImtTokens,
55
56        #[serde(default, skip_serializing_if = "Option::is_none")]
57        pub memo: Option<Cow<'a, str>>,
58    }
59
60    impl<'a> From<&'a ImtMint> for ImtMintEvent<'a> {
61        #[inline]
62        fn from(intent: &'a ImtMint) -> Self {
63            Self {
64                receiver_id: Cow::Borrowed(&intent.receiver_id),
65                tokens: intent.tokens.clone(),
66                memo: intent.memo.as_deref().map(Cow::Borrowed),
67            }
68        }
69    }
70}
71
72#[near(serializers = [json])]
73#[derive(Debug, Clone)]
74pub struct TransferEvent<'a> {
75    pub receiver_id: Cow<'a, AccountIdRef>,
76
77    #[serde_as(as = "Amounts<BTreeMap<_, DisplayFromStr>>")]
78    pub tokens: Amounts,
79
80    #[serde(default, skip_serializing_if = "Option::is_none")]
81    pub memo: Option<Cow<'a, str>>,
82}
83
84impl<'a> From<&'a Transfer> for TransferEvent<'a> {
85    #[inline]
86    fn from(intent: &'a Transfer) -> Self {
87        Self {
88            receiver_id: Cow::Borrowed(&intent.receiver_id),
89            tokens: intent.tokens.clone(),
90            memo: intent.memo.as_deref().map(Cow::Borrowed),
91        }
92    }
93}