diff --git a/neps/nep-0171.md b/neps/nep-0171.md index 400df70bc..2d6278007 100644 --- a/neps/nep-0171.md +++ b/neps/nep-0171.md @@ -6,7 +6,9 @@ DiscussionsTo: https://github.com/near/NEPs/discussions/171 Status: Final Type: Standards Track Category: Contract +Version: 1.1.0 Created: 03-Mar-2022 +Updated: 07-Mar-2023 Requires: 297 --- @@ -216,21 +218,21 @@ function nft_on_transfer( ### Events -NEAR and third-party applications need to track `mint`, `transfer`, `burn` events for all NFT-driven apps consistently. +NEAR and third-party applications need to track `mint`, `transfer`, `burn`, and `contract_metadata_update` events for all NFT-driven apps consistently. This extension addresses that. Keep in mind that applications, including NEAR Wallet, could require implementing additional methods to display the NFTs correctly, such as [`nft_metadata`][Metadata] and [`nft_tokens_for_owner`][NFT Enumeration]). -### Events Interface +#### Events Interface -Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.0.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, and `data` must be of one of the following relevant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[]`: +Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.1.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, or `contract_metadata_update`, and `data` must be of one of the following relevant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftContractMetadataUpdateLog[]`: ```ts interface NftEventLogData { standard: "nep171", - version: "1.0.0", - event: "nft_mint" | "nft_burn" | "nft_transfer", - data: NftMintLog[] | NftTransferLog[] | NftBurnLog[], + version: "1.1.0", + event: "nft_mint" | "nft_burn" | "nft_transfer" | "contract_metadata_update", + data: NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftContractMetadataUpdateLog[], } ``` @@ -273,16 +275,23 @@ interface NftTransferLog { token_ids: string[], memo?: string } + +// An event log to capture contract metadata updates. Note that the updated contract metadata is not included in the log, as it could easily exceed the 16KB log size limit. Listeners can query `nft_metadata` to get the updated contract metadata. +// Arguments +// * `memo`: optional message +interface NftContractMetadataUpdateLog { + memo?: string +} ``` -## Examples +#### Examples Single owner batch minting (pretty-formatted for readability purposes): ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_mint", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]} @@ -295,7 +304,7 @@ Different owners batch minting: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_mint", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, @@ -309,7 +318,7 @@ Different events (separate log entries): ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_burn", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, @@ -320,7 +329,7 @@ EVENT_JSON:{ ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_transfer", "data": [ {"old_owner_id": "user1.near", "new_owner_id": "user2.near", "token_ids": ["meme"], "memo": "have fun!"} @@ -333,7 +342,7 @@ Authorized id: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_burn", "data": [ {"owner_id": "owner.near", "token_ids": ["goodbye", "aurevoir"], "authorized_id": "thirdparty.near"} @@ -341,29 +350,62 @@ EVENT_JSON:{ } ``` -## Further Event Methods +Contract metadata update: + +```js +EVENT_JSON:{ + "standard": "nep171", + "version": "1.1.0", + "event": "contract_metadata_update", + "data": [] +} +``` + +#### Events for Other NFT Methods -Note that the example events covered above cover two different kinds of events: -1. Events that are not specified in the NFT Standard (`nft_mint`, `nft_burn`) -2. An event that is covered in the [NFT Core Standard](https://nomicon.io/Standards/NonFungibleToken/Core.html#nft-interface). (`nft_transfer`) +Note that the example events above cover two different kinds of events: +1. Events that do not have a dedicated trigger function in the NFT Standard (`nft_mint`, `nft_burn`, `contract_metadata_update`) +2. An event that has a relevant trigger function [NFT Core Standard](https://nomicon.io/Standards/NonFungibleToken/Core.html#nft-interface) (`nft_transfer`) -This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html), it may emit an event for `nft_approve` if that's deemed as important by the developer community. +This event standard also applies beyond the events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html), it may emit an event for `nft_approve` if that's deemed as important by the developer community. Please feel free to open pull requests for extending the events standard detailed here as needs arise. + ## Reference Implementation [Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/core/mod.rs) [NFT Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/core/core_impl.rs) -## Errata -* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. +## Changelog + +### 1.0.0 - Initial version +This NEP had several pre-1.0.0 iterations that led to the following errata updates to this NEP: + +* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. * **2021-12-20**: updated `nft_resolve_transfer` argument `approved_account_ids` to be type `null|Record` instead of `null|string[]`. This gives contracts a way to restore the original approved accounts and their approval IDs. More information can be found in [this](https://github.com/near/NEPs/issues/301) discussion. * **2021-07-16**: updated `nft_transfer_call` argument `approval_id` to be type `number|null` instead of `string|null`. As stated, approval IDs are not expected to exceed the JSON limit of 2^53. +### 1.1.0 - Add `contract_metadata_update` Event + +The extension NEP-0423 that added Contract Metadata to this NEP-0171 was approved by Contract Standards Working Group members (@frol, @abacabadabacaba, @mfornet) on January 13, 2023 ([meeting recording](https://youtu.be/pBLN9UyE6AA)). + +#### Benefits + +* This new event type will help indexers to invalidate their cached values reliably and efficiently +* This NEP extension only introduces an additional event type, so there is no breaking change to the original NEP + +#### Concerns + +| # | Concern | Resolution | Status | +| - | - | - | - | +| 1 | Old NFT contracts do not emit JSON Events at all; more recent NFT contracts will only emit mint/burn/transfer events, so when it comes to legacy contracts support, we won’t benefit from this new event type and only further fragment the implementations | Legacy contracts usage will die out eventually and new contracts will support new features in a non-breaking way | Resolved | +| 2 | There is a need to have a similar event type for individual NFT updates | It is outside of the scope of this NEP extension. Feel free to create a follow-up proposal | Resolved | + + ## Copyright [copyright]: #copyright diff --git a/specs/Standards/Tokens/NonFungibleToken/Event.md b/specs/Standards/Tokens/NonFungibleToken/Event.md index b9a50d3a7..bd87c2f29 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Event.md +++ b/specs/Standards/Tokens/NonFungibleToken/Event.md @@ -1,29 +1,28 @@ # Events -Version `1.0.0` +Version `1.1.0` ## Summary -Standard interface for NFT contract actions. -Extension of [NEP-297](../../EventsFormat.md) +Standard interface for NFT contract actions based on [NEP-297](../../EventsFormat.md). ## Motivation -NEAR and third-party applications need to track `mint`, `transfer`, `burn` events for all NFT-driven apps consistently. +NEAR and third-party applications need to track `mint`, `transfer`, `burn` and `contract_metadata_update` events for all NFT-driven apps consistently. This extension addresses that. Keep in mind that applications, including NEAR Wallet, could require implementing additional methods to display the NFTs correctly, such as [`nft_metadata`](Metadata.md) and [`nft_tokens_for_owner`](Enumeration.md). ## Interface -Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.0.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, and `data` must be of one of the following relavant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[]`: +Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.1.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, `contract_metadata_update`, and `data` must be of one of the following relavant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftContractMetadataUpdateLog[]`: ```ts interface NftEventLogData { standard: "nep171", - version: "1.0.0", - event: "nft_mint" | "nft_burn" | "nft_transfer", - data: NftMintLog[] | NftTransferLog[] | NftBurnLog[], + version: "1.1.0", + event: "nft_mint" | "nft_burn" | "nft_transfer" | "contract_metadata_update", + data: NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftContractMetadataUpdateLog[], } ``` @@ -66,6 +65,13 @@ interface NftTransferLog { token_ids: string[], memo?: string } + +// An event log to capture contract metadata updates. Note that the updated contract metadata is not included in the log, as it could easily exceed the 16KB log size limit. Listeners can query `nft_metadata` to get the updated contract metadata. +// Arguments +// * `memo`: optional message +interface NftContractMetadataUpdateLog { + memo?: string +} ``` ## Examples @@ -75,7 +81,7 @@ Single owner batch minting (pretty-formatted for readability purposes): ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_mint", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]} @@ -88,7 +94,7 @@ Different owners batch minting: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_mint", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, @@ -102,7 +108,7 @@ Different events (separate log entries): ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_burn", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, @@ -113,7 +119,7 @@ EVENT_JSON:{ ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_transfer", "data": [ {"old_owner_id": "user1.near", "new_owner_id": "user2.near", "token_ids": ["meme"], "memo": "have fun!"} @@ -126,7 +132,7 @@ Authorized id: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_burn", "data": [ {"owner_id": "owner.near", "token_ids": ["goodbye", "aurevoir"], "authorized_id": "thirdparty.near"} @@ -134,12 +140,23 @@ EVENT_JSON:{ } ``` -## Further methods +Contract metadata update: + +```js +EVENT_JSON:{ + "standard": "nep171", + "version": "1.1.0", + "event": "contract_metadata_update", + "data": [] +} +``` + +## Events for Other NFT Methods -Note that the example events covered above cover two different kinds of events: -1. Events that are not specified in the NFT Standard (`nft_mint`, `nft_burn`) -2. An event that is covered in the [NFT Core Standard](Core.md). (`nft_transfer`) +Note that the example events above cover two different kinds of events: +1. Events that do not have a dedicated trigger function in the NFT Standard (`nft_mint`, `nft_burn`, `contract_metadata_update`) +2. An event that has a relevant trigger function [NFT Core Standard](Core.md#nft-interface) (`nft_transfer`) -This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](ApprovalManagement.md), it may emit an event for `nft_approve` if that's deemed as important by the developer community. +This event standard also applies beyond the events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](ApprovalManagement.md), it may emit an event for `nft_approve` if that's deemed as important by the developer community. Please feel free to open pull requests for extending the events standard detailed here as needs arise.