Skip to main content

defuse_core/
tokens.rs

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