defuse/contract/tokens/nep245/
enumeration.rs

1use crate::contract::{Contract, ContractExt};
2use defuse_core::token_id::TokenIdType;
3use defuse_near_utils::UnwrapOrPanicError;
4use defuse_nep245::{Token, enumeration::MultiTokenEnumeration};
5use near_sdk::{AccountId, json_types::U128, near};
6
7#[near]
8impl MultiTokenEnumeration for Contract {
9    fn mt_tokens(&self, from_index: Option<U128>, limit: Option<u32>) -> Vec<Token> {
10        let from_index = from_index.map_or(0, |v| v.0);
11        let from_index: usize = from_index.try_into().unwrap_or_panic_display();
12
13        let iter = self
14            .state
15            .total_supplies
16            .iter()
17            .skip(from_index)
18            .map(|(token_id, _amount)| Token {
19                token_id: token_id.to_string(),
20                // Note: There is no way to fill this field currently (which is required for NEP-171/NFTs),
21                // as it requires reverse look-up for tokens and that's expensive for storage.
22                // We will postpone this decision for the future when it's needed.
23                owner_id: None,
24            });
25
26        match limit {
27            Some(l) => iter.take(l.try_into().unwrap_or_panic_display()).collect(),
28            None => iter.collect(),
29        }
30    }
31
32    fn mt_tokens_for_owner(
33        &self,
34        account_id: AccountId,
35        from_index: Option<U128>,
36        limit: Option<u32>,
37    ) -> Vec<Token> {
38        let from_index = from_index.map_or(0, |v| v.0);
39        let from_index: usize = from_index.try_into().unwrap_or_panic_display();
40
41        let Some(account) = self.accounts.get(&account_id) else {
42            return Vec::new();
43        };
44
45        let iter = account
46            .as_inner_unchecked()
47            .state
48            .token_balances
49            .iter()
50            .skip(from_index)
51            .map(|(token_id, _amount)| Token {
52                token_id: token_id.to_string(),
53                owner_id: match TokenIdType::from(token_id) {
54                    TokenIdType::Nep171 => Some(account_id.clone()),
55                    TokenIdType::Nep141 | TokenIdType::Nep245 => None,
56                    #[cfg(feature = "imt")]
57                    TokenIdType::Imt => None,
58                },
59            });
60
61        match limit {
62            Some(l) => iter.take(l.try_into().unwrap_or_panic_display()).collect(),
63            None => iter.collect(),
64        }
65    }
66}