Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement] NFT: deprecate declarative macros. #1042

Merged
merged 14 commits into from
Jul 11, 2023
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
74 changes: 71 additions & 3 deletions examples/non-fungible-token/nft/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
frol marked this conversation as resolved.
Show resolved Hide resolved
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)]
Expand Down Expand Up @@ -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 {
frol marked this conversation as resolved.
Show resolved Hide resolved
#[payable]
fn nft_transfer(&mut self, receiver_id: AccountId, token_id: TokenId, approval_id: Option<u64>, memo: Option<String>) {
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<u64>, memo: Option<String>, msg: String) -> PromiseOrValue<bool> {
self.tokens.nft_transfer_call(receiver_id, token_id, approval_id, memo, msg)
}

fn nft_token(&self, token_id: TokenId) -> Option<Token> {
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<HashMap<AccountId, u64>>) -> 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<String>) -> Option<Promise> {
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<u64>) -> 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<U128>, limit: Option<u64>) -> Vec<Token> {
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<U128>, limit: Option<u64>) -> Vec<Token> {
self.tokens.nft_tokens_for_owner(account_id, from_index, limit)
}
}

#[near_bindgen]
impl NonFungibleTokenMetadataProvider for Contract {
Expand Down
39 changes: 39 additions & 0 deletions near-contract-standards/src/non_fungible_token/approval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>) -> Option<Promise> {
/// 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<u64>) -> bool {
/// self.tokens.nft_is_approved(token_id, approved_account_id, approval_id)
/// }
/// }
/// ```
///
pub trait NonFungibleTokenApproval {
/// Add an approved account for a specific token.
///
Expand Down
31 changes: 31 additions & 0 deletions near-contract-standards/src/non_fungible_token/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,37 @@ use near_sdk::PromiseOrValue;
/// understand how the cross-contract call work.
///
/// [core non-fungible token standard]: <https://nomicon.io/Standards/NonFungibleToken/Core.html>
///
/// # 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<u64>, memo: Option<String>) {
/// 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<u64>, memo: Option<String>, msg: String) -> PromiseOrValue<bool> {
/// self.tokens.nft_transfer_call(receiver_id, token_id, approval_id, memo, msg)
/// }
///
/// fn nft_token(&self, token_id: TokenId) -> Option<Token> {
/// self.tokens.nft_token(token_id)
/// }
///}
/// ```
///
pub trait NonFungibleTokenCore {
/// Simple transfer. Transfer a given `token_id` from current owner to
/// `receiver_id`.
Expand Down
23 changes: 23 additions & 0 deletions near-contract-standards/src/non_fungible_token/core/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<HashMap<AccountId, u64>>) -> 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<U128>, limit: Option<u64>) -> Vec<Token> {
/// 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<U128>, limit: Option<u64>) -> Vec<Token> {
/// 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.
Expand Down
5 changes: 5 additions & 0 deletions near-contract-standards/src/non_fungible_token/macros.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -60,6 +63,7 @@ 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;
Expand Down Expand Up @@ -101,6 +105,7 @@ 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;
Expand Down
6 changes: 5 additions & 1 deletion near-contract-standards/src/non_fungible_token/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ pub use self::token::{Token, TokenId};
mod utils;
pub use utils::*;

pub use self::core::NonFungibleToken;
pub use macros::*;
frol marked this conversation as resolved.
Show resolved Hide resolved

pub use self::approval::NonFungibleTokenApproval;
pub use self::core::NonFungibleToken;
pub use self::core::NonFungibleTokenResolver;
pub use self::enumeration::NonFungibleTokenEnumeration;

pub mod events;
Loading