Skip to content

Commit

Permalink
refactor(contract-standards): deprecate declarative macros in NFT hel…
Browse files Browse the repository at this point in the history
…pers, promote explicit trait implementations instead (#1042)
  • Loading branch information
ruseinov authored Jul 11, 2023
1 parent bb8a7f8 commit 7563f4a
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 4 deletions.
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;
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 {
#[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
36 changes: 36 additions & 0 deletions near-contract-standards/src/non_fungible_token/enumeration/mod.rs
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
9 changes: 9 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,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;
Expand Down Expand Up @@ -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;
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::*;

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

pub mod events;

0 comments on commit 7563f4a

Please sign in to comment.