diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f7ab2df5..8c9d50620 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ ### Fixed - Fixed invalid import from "legacy" feature flag from stabilized collection. [PR 960](https://github.com/near/near-sdk-rs/pull/960) +### Removed +- Deprecated declarative macros for NFT impl code generation. [PR 1042](https://github.com/near/near-sdk-rs/pull/1042) + ## [4.1.0] - 2022-11-09 ### Added diff --git a/examples/non-fungible-token/nft/src/lib.rs b/examples/non-fungible-token/nft/src/lib.rs index c5892ac3d..b89f580b7 100644 --- a/examples/non-fungible-token/nft/src/lib.rs +++ b/examples/non-fungible-token/nft/src/lib.rs @@ -15,16 +15,21 @@ NOTES: - To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. */ +use std::collections::HashMap; use near_contract_standards::non_fungible_token::metadata::{ NFTContractMetadata, NonFungibleTokenMetadataProvider, TokenMetadata, NFT_METADATA_SPEC, }; use near_contract_standards::non_fungible_token::NonFungibleToken; use near_contract_standards::non_fungible_token::{Token, TokenId}; +use near_contract_standards::non_fungible_token::approval::NonFungibleTokenApproval; +use near_contract_standards::non_fungible_token::core::{NonFungibleTokenCore, NonFungibleTokenResolver}; +use near_contract_standards::non_fungible_token::enumeration::NonFungibleTokenEnumeration; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; use near_sdk::collections::LazyOption; use near_sdk::{ env, near_bindgen, require, AccountId, BorshStorageKey, PanicOnDefault, Promise, PromiseOrValue, }; +use near_sdk::json_types::U128; #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] @@ -100,9 +105,72 @@ impl Contract { } } -near_contract_standards::impl_non_fungible_token_core!(Contract, tokens); -near_contract_standards::impl_non_fungible_token_approval!(Contract, tokens); -near_contract_standards::impl_non_fungible_token_enumeration!(Contract, tokens); +#[near_bindgen] +impl NonFungibleTokenCore for Contract { + #[payable] + fn nft_transfer(&mut self, receiver_id: AccountId, token_id: TokenId, approval_id: Option, memo: Option) { + self.tokens.nft_transfer(receiver_id, token_id, approval_id, memo); + } + + #[payable] + fn nft_transfer_call(&mut self, receiver_id: AccountId, token_id: TokenId, approval_id: Option, memo: Option, msg: String) -> PromiseOrValue { + self.tokens.nft_transfer_call(receiver_id, token_id, approval_id, memo, msg) + } + + fn nft_token(&self, token_id: TokenId) -> Option { + self.tokens.nft_token(token_id) + } +} + +#[near_bindgen] +impl NonFungibleTokenResolver for Contract { + #[private] + fn nft_resolve_transfer(&mut self, previous_owner_id: AccountId, receiver_id: AccountId, token_id: TokenId, approved_account_ids: Option>) -> bool { + self.tokens.nft_resolve_transfer(previous_owner_id, receiver_id, token_id, approved_account_ids) + } +} + +#[near_bindgen] +impl NonFungibleTokenApproval for Contract { + #[payable] + fn nft_approve(&mut self, token_id: TokenId, account_id: AccountId, msg: Option) -> Option { + self.tokens.nft_approve(token_id, account_id, msg) + } + + #[payable] + fn nft_revoke(&mut self, token_id: TokenId, account_id: AccountId) { + self.tokens.nft_revoke(token_id, account_id); + } + + #[payable] + fn nft_revoke_all(&mut self, token_id: TokenId) { + self.tokens.nft_revoke_all(token_id); + + } + + fn nft_is_approved(&self, token_id: TokenId, approved_account_id: AccountId, approval_id: Option) -> bool { + self.tokens.nft_is_approved(token_id, approved_account_id, approval_id) + } +} + +#[near_bindgen] +impl NonFungibleTokenEnumeration for Contract { + fn nft_total_supply(&self) -> U128 { + self.tokens.nft_total_supply() + } + + fn nft_tokens(&self, from_index: Option, limit: Option) -> Vec { + self.tokens.nft_tokens(from_index, limit) + } + + fn nft_supply_for_owner(&self, account_id: AccountId) -> U128 { + self.tokens.nft_supply_for_owner(account_id) + } + + fn nft_tokens_for_owner(&self, account_id: AccountId, from_index: Option, limit: Option) -> Vec { + self.tokens.nft_tokens_for_owner(account_id, from_index, limit) + } +} #[near_bindgen] impl NonFungibleTokenMetadataProvider for Contract { diff --git a/near-contract-standards/src/non_fungible_token/approval/mod.rs b/near-contract-standards/src/non_fungible_token/approval/mod.rs index 2b415b4c4..735698ac8 100644 --- a/near-contract-standards/src/non_fungible_token/approval/mod.rs +++ b/near-contract-standards/src/non_fungible_token/approval/mod.rs @@ -17,6 +17,45 @@ use near_sdk::Promise; /// /// [approval management standard]: https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html /// [core non-fungible token standard]: https://nomicon.io/Standards/NonFungibleToken/Core.html +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashMap; +/// use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near_bindgen, Promise}; +/// use near_contract_standards::non_fungible_token::{TokenId, NonFungibleToken, NonFungibleTokenApproval}; +/// +/// #[near_bindgen] +/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] +/// pub struct Contract { +/// tokens: NonFungibleToken, +///} +/// +/// #[near_bindgen] +/// impl NonFungibleTokenApproval for Contract { +/// #[payable] +/// fn nft_approve(&mut self, token_id: TokenId, account_id: AccountId, msg: Option) -> Option { +/// self.tokens.nft_approve(token_id, account_id, msg) +/// } +/// +/// #[payable] +/// fn nft_revoke(&mut self, token_id: TokenId, account_id: AccountId) { +/// self.tokens.nft_revoke(token_id, account_id); +/// } +/// +/// #[payable] +/// fn nft_revoke_all(&mut self, token_id: TokenId) { +/// self.tokens.nft_revoke_all(token_id); +/// +/// } +/// +/// fn nft_is_approved(&self, token_id: TokenId, approved_account_id: AccountId, approval_id: Option) -> bool { +/// self.tokens.nft_is_approved(token_id, approved_account_id, approval_id) +/// } +/// } +/// ``` +/// pub trait NonFungibleTokenApproval { /// Add an approved account for a specific token. /// diff --git a/near-contract-standards/src/non_fungible_token/core/mod.rs b/near-contract-standards/src/non_fungible_token/core/mod.rs index e75160f7e..659de459d 100644 --- a/near-contract-standards/src/non_fungible_token/core/mod.rs +++ b/near-contract-standards/src/non_fungible_token/core/mod.rs @@ -19,6 +19,37 @@ use near_sdk::PromiseOrValue; /// understand how the cross-contract call work. /// /// [core non-fungible token standard]: +/// +/// # Examples +/// +/// ``` +/// use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near_bindgen}; +/// use near_contract_standards::non_fungible_token::{core::NonFungibleTokenCore, NonFungibleToken, TokenId, Token}; +/// +/// #[near_bindgen] +/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] +/// pub struct Contract { +/// tokens: NonFungibleToken, +///} +/// #[near_bindgen] +/// impl NonFungibleTokenCore for Contract { +/// #[payable] +/// fn nft_transfer(&mut self, receiver_id: AccountId, token_id: TokenId, approval_id: Option, memo: Option) { +/// self.tokens.nft_transfer(receiver_id, token_id, approval_id, memo); +/// } +/// +/// #[payable] +/// fn nft_transfer_call(&mut self, receiver_id: AccountId, token_id: TokenId, approval_id: Option, memo: Option, msg: String) -> PromiseOrValue { +/// self.tokens.nft_transfer_call(receiver_id, token_id, approval_id, memo, msg) +/// } +/// +/// fn nft_token(&self, token_id: TokenId) -> Option { +/// self.tokens.nft_token(token_id) +/// } +///} +/// ``` +/// pub trait NonFungibleTokenCore { /// Simple transfer. Transfer a given `token_id` from current owner to /// `receiver_id`. diff --git a/near-contract-standards/src/non_fungible_token/core/resolver.rs b/near-contract-standards/src/non_fungible_token/core/resolver.rs index 696ac2e86..63b2da4ad 100644 --- a/near-contract-standards/src/non_fungible_token/core/resolver.rs +++ b/near-contract-standards/src/non_fungible_token/core/resolver.rs @@ -3,6 +3,29 @@ use near_sdk::{ext_contract, AccountId}; use std::collections::HashMap; /// Used when an NFT is transferred using `nft_transfer_call`. This is the method that's called after `nft_on_transfer`. This trait is implemented on the NFT contract. +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashMap; +/// use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near_bindgen}; +/// use near_contract_standards::non_fungible_token::{NonFungibleToken, NonFungibleTokenResolver, TokenId}; +/// +/// #[near_bindgen] +/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] +/// pub struct Contract { +/// tokens: NonFungibleToken, +///} +/// #[near_bindgen] +/// impl NonFungibleTokenResolver for Contract { +/// #[private] +/// fn nft_resolve_transfer(&mut self, previous_owner_id: AccountId, receiver_id: AccountId, token_id: TokenId, approved_account_ids: Option>) -> bool { +/// self.tokens.nft_resolve_transfer(previous_owner_id, receiver_id, token_id, approved_account_ids) +/// } +/// } +/// ``` +/// #[ext_contract(ext_nft_resolver)] pub trait NonFungibleTokenResolver { /// Finalize an `nft_transfer_call` chain of cross-contract calls. diff --git a/near-contract-standards/src/non_fungible_token/enumeration/mod.rs b/near-contract-standards/src/non_fungible_token/enumeration/mod.rs index f38f513d1..0711ff12d 100644 --- a/near-contract-standards/src/non_fungible_token/enumeration/mod.rs +++ b/near-contract-standards/src/non_fungible_token/enumeration/mod.rs @@ -5,6 +5,42 @@ use near_sdk::json_types::U128; use near_sdk::AccountId; /// Offers methods helpful in determining account ownership of NFTs and provides a way to page through NFTs per owner, determine total supply, etc. +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashMap; +/// use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near_bindgen, Promise}; +/// use near_contract_standards::non_fungible_token::{NonFungibleToken, NonFungibleTokenEnumeration, TokenId, Token}; +/// use near_sdk::json_types::U128; +/// +/// #[near_bindgen] +/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] +/// pub struct Contract { +/// tokens: NonFungibleToken, +///} +/// +/// #[near_bindgen] +/// impl NonFungibleTokenEnumeration for Contract { +/// fn nft_total_supply(&self) -> U128 { +/// self.tokens.nft_total_supply() +/// } +/// +/// fn nft_tokens(&self, from_index: Option, limit: Option) -> Vec { +/// self.tokens.nft_tokens(from_index, limit) +/// } +/// +/// fn nft_supply_for_owner(&self, account_id: AccountId) -> U128 { +/// self.tokens.nft_supply_for_owner(account_id) +/// } +/// +/// fn nft_tokens_for_owner(&self, account_id: AccountId, from_index: Option, limit: Option) -> Vec { +/// self.tokens.nft_tokens_for_owner(account_id, from_index, limit) +/// } +/// } +/// ``` +/// pub trait NonFungibleTokenEnumeration { /// Returns the total supply of non-fungible tokens as a string representing an /// unsigned 128-bit integer to avoid JSON number limit of 2^53. diff --git a/near-contract-standards/src/non_fungible_token/macros.rs b/near-contract-standards/src/non_fungible_token/macros.rs index c6a37a794..ecd98045a 100644 --- a/near-contract-standards/src/non_fungible_token/macros.rs +++ b/near-contract-standards/src/non_fungible_token/macros.rs @@ -1,6 +1,9 @@ /// The core methods for a basic non-fungible token. Extension standards may be /// added in addition to this macro. #[macro_export] +#[deprecated( + note = "implement the near_contract_standards::non_fungible_token::NonFungibleTokenCore and near_contract_standards::non_fungible_token::NonFungibleTokenResolver traits manually instead." +)] macro_rules! impl_non_fungible_token_core { ($contract: ident, $token: ident) => { use $crate::non_fungible_token::core::NonFungibleTokenCore; @@ -60,6 +63,9 @@ macro_rules! impl_non_fungible_token_core { /// Non-fungible token approval management allows for an escrow system where /// multiple approvals per token exist. #[macro_export] +#[deprecated( + note = "implement the near_contract_standards::non_fungible_token::NonFungibleTokenApproval trait manually instead." +)] macro_rules! impl_non_fungible_token_approval { ($contract: ident, $token: ident) => { use $crate::non_fungible_token::approval::NonFungibleTokenApproval; @@ -101,6 +107,9 @@ macro_rules! impl_non_fungible_token_approval { /// Non-fungible enumeration adds the extension standard offering several /// view-only methods to get token supply, tokens per owner, etc. #[macro_export] +#[deprecated( + note = "implement the near_contract_standards::non_fungible_token::NonFungibleTokenEnumeration trait manually instead." +)] macro_rules! impl_non_fungible_token_enumeration { ($contract: ident, $token: ident) => { use $crate::non_fungible_token::enumeration::NonFungibleTokenEnumeration; diff --git a/near-contract-standards/src/non_fungible_token/mod.rs b/near-contract-standards/src/non_fungible_token/mod.rs index ef936b161..5bc8d4863 100644 --- a/near-contract-standards/src/non_fungible_token/mod.rs +++ b/near-contract-standards/src/non_fungible_token/mod.rs @@ -20,7 +20,11 @@ pub use self::token::{Token, TokenId}; mod utils; pub use utils::*; -pub use self::core::NonFungibleToken; pub use macros::*; +pub use self::approval::NonFungibleTokenApproval; +pub use self::core::NonFungibleToken; +pub use self::core::NonFungibleTokenResolver; +pub use self::enumeration::NonFungibleTokenEnumeration; + pub mod events;