Skip to main content

defuse/contract/tokens/nep171/
deposit.rs

1use defuse_core::{
2    DefuseError,
3    token_id::{
4        TokenId,
5        nep171::{self, Nep171TokenId},
6    },
7    tokens::MAX_TOKEN_ID_LEN,
8};
9use near_contract_standards::non_fungible_token::core::NonFungibleTokenReceiver;
10use near_plugins::{Pausable, pause};
11use near_sdk::{AccountId, FunctionError, PromiseOrValue, env, json_types::U128, near};
12
13use crate::{
14    contract::{Contract, ContractExt},
15    intents::{Intents, ext_intents},
16    tokens::{DepositAction, DepositMessage},
17};
18
19#[near]
20impl NonFungibleTokenReceiver for Contract {
21    /// Deposit non-fungible token.
22    ///
23    /// `msg` contains [`AccountId`] of the internal recipient.
24    /// Empty `msg` means deposit to `sender_id`
25    #[pause]
26    fn nft_on_transfer(
27        &mut self,
28        sender_id: AccountId,
29        previous_owner_id: AccountId,
30        token_id: nep171::TokenId,
31        msg: String,
32    ) -> PromiseOrValue<bool> {
33        if token_id.len() > MAX_TOKEN_ID_LEN {
34            DefuseError::TokenIdTooLarge(token_id.len()).panic();
35        }
36
37        let DepositMessage {
38            receiver_id,
39            action,
40        } = if msg.is_empty() {
41            DepositMessage::new(sender_id.clone())
42        } else {
43            msg.parse().unwrap_or_else(|e| panic!("{e}"))
44        };
45
46        let core_token_id: TokenId =
47            Nep171TokenId::new(env::predecessor_account_id(), token_id.clone()).into();
48
49        self.deposit(
50            receiver_id.clone(),
51            [(core_token_id.clone(), 1)],
52            Some("deposit"),
53        )
54        .unwrap_or_else(|err| err.panic());
55
56        let Some(action) = action else {
57            return PromiseOrValue::Value(false);
58        };
59
60        match action {
61            DepositAction::Notify(notify) => Self::notify_on_transfer(
62                sender_id,
63                vec![previous_owner_id],
64                receiver_id.clone(),
65                vec![core_token_id.to_string()],
66                vec![U128(1)],
67                notify,
68            )
69            .then(
70                Self::ext(env::current_account_id())
71                    .with_static_gas(Self::mt_resolve_deposit_gas(1))
72                    .with_unused_gas_weight(0)
73                    .nft_resolve_deposit(receiver_id, env::predecessor_account_id(), token_id),
74            )
75            .into(),
76            DepositAction::Execute(execute) => {
77                if !execute.execute_intents.is_empty() {
78                    if execute.refund_if_fails {
79                        self.execute_intents(execute.execute_intents);
80                    } else {
81                        ext_intents::ext(env::current_account_id())
82                            .execute_intents(execute.execute_intents)
83                            .detach();
84                    }
85                }
86
87                PromiseOrValue::Value(false)
88            }
89        }
90    }
91}
92
93#[near]
94impl Contract {
95    #[private]
96    #[allow(clippy::needless_pass_by_value)]
97    pub fn nft_resolve_deposit(
98        &mut self,
99        receiver_id: AccountId,
100        contract_id: AccountId,
101        nft_token_id: nep171::TokenId,
102    ) -> PromiseOrValue<bool> {
103        let mut amount = 1u128;
104
105        self.resolve_deposit_internal(
106            &receiver_id,
107            [(
108                Nep171TokenId::new(contract_id, nft_token_id).into(),
109                &mut amount,
110            )],
111        );
112        PromiseOrValue::Value(amount != 0)
113    }
114}