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

feat: add NFT mint/transfer/burn event standard #256

Merged
merged 32 commits into from Oct 22, 2021
Merged
Changes from 28 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f9a0885
feat: add batch
Sep 8, 2021
ecc0d62
refactor: change interface to typescript
Sep 9, 2021
8d8af42
feat: update batch standard
Sep 27, 2021
f260197
feat: update standard https://github.com/near/NEPs/issues/254#issueco…
Sep 27, 2021
6c68eaa
feat: update docs
Sep 27, 2021
e8d9a70
feat: update issue
Sep 27, 2021
285003e
feat: add `owner_id` https://github.com/near/NEPs/issues/254#issuecom…
Sep 27, 2021
4f54dee
feat: add `event_json` https://github.com/near/NEPs/issues/254#issuec…
Sep 29, 2021
d6ec110
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 10, 2021
1dcc59f
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 10, 2021
2bb7941
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 10, 2021
67660a7
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 10, 2021
f27284b
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 10, 2021
bfb082a
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 10, 2021
a7222af
feat: update specs/Standards/NonFungibleToken/Event.md https://github…
Oct 13, 2021
76655a0
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 13, 2021
d00daef
feat: add single line sentence
Oct 13, 2021
6d7d8d4
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 13, 2021
02b4e3d
feat: add memo
Oct 13, 2021
b99596d
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 13, 2021
4dfbd6e
feat: bake `token_ids`
Oct 13, 2021
a544365
feat: add delegatee
Oct 14, 2021
ebd8412
feat: add delegatee description
Oct 14, 2021
b3dbea3
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 15, 2021
e3c7f2a
feat: add authorised_id
Oct 18, 2021
4de0431
feat: apply suggestions from code review
Oct 18, 2021
947e575
feat: update specs/Standards/NonFungibleToken/Event.md
Oct 18, 2021
ab02604
feat: update transfer event
Oct 18, 2021
6fafebd
feat: add EventJsonLog comment
Oct 19, 2021
77cb81c
feat: update `EventJsonLog`
Oct 19, 2021
45c6dbe
Created "Events" and "Examples" sections
frol Oct 20, 2021
ad4c8c4
feat: use authorized
Oct 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions specs/Standards/NonFungibleToken/Event.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Non-Fungible Token Event

Version `1.0.0`

## Summary

Standard interfaces for NFT contract actions.

## Motivation

NFT-driven apps perform many similar actions.
For example - `minting`, `burning` and `transferring`.
Each app may have their own way of performing these actions.
This introduces inconsistency in capturing these events.
This extension addresses that.

It's common for NFT apps to transfer many or one token at a time.
Other applications need to track these and similar events consistently.
If not, tracking state across many NFT-driven apps become infeasible.

We need a standard way to capture events.
This was discussed here https://github.com/near/NEPs/issues/254.

## Interface

Many apps use different interfaces that represent the same action.
This interface standardizes that process.
It captures these actions through logs.

```ts
// Interface to capture an event
// and return formatted event string.
interface EventJsonLog {
// Takes `EventLogData` and returns
// `EVENT_JSON: <EVENT_LOG_DATA>`
(e:EventLogData):string
Copy link
Contributor

@telezhnaya telezhnaya Oct 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's important to mention here that string representation of json should not contain line breaks (Ideally: get rid of all space symbols unless they are in string fields).

When Indexer parses these lines, for each line, it just cuts off "EVENT_JSON:", trims everything else, and passes the result into json parsing library.

If you pass

EVENT_JSON: {
"my_valid_json": true
}

It will give an error because there are 3 lines instead of 1, where the first line contains invalid json, second and third lines do not start from "EVENT_JSON:".

We also need to decide, are we OK with other messages here (without "EVENT_JSON:" at the beginning). We need to say explicitly in the NEP, whether we ignore or restrict them

@mikedotexe @frol

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure that we don't want to put everything into json with the structure like

{
"type": "event_json",
"data": [...] // here could be all events
}

?

It simplifies everything, we don't need to overcomplicate this doc, Indexer does not need the logic with cutting/trimming.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@telezhnaya Individual calls to near_sdk::env::log are recorded as individual strings in the logs array of the execution outcome, so we don't care about new lines inside. We only want to specify that each event should be a separate call to the log host function.

Proof: https://explorer.testnet.near.org/transactions/326HmzvgRYND7skVCdTpCnHMji6qiU8JFhQMNuvS2b74
image

Contract:

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::{near_bindgen, setup_alloc};

setup_alloc!();

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, Default)]
pub struct Test {}

#[near_bindgen]
impl Test {
    pub fn test_log(&mut self) {
        near_sdk::env::log(r#"EVENT_JSON:{
            "standard": "nep",
            "version": "1.0.0",
            "event": "mint",
            "data": [
                {"owner_id": "frol.near", "token_ids": ["house"]}
            ]
        }"#.as_bytes());
        near_sdk::env::log("EVENT_JSON:{\"standard\": \"nep\", \n \"version\": \"1.0.0\",    \n   \"event\": \"burn\", \"data\": [{\"owner_id\": \"frol.near\", \"token_ids\": [\"house\"]}]}".as_bytes());
    }
}

}

// Interface to capture data
// about an event
// Arguments
// * `standard`: name of standard e.g. nep171
// * `version`: e.g. 1.0.0
// * `event`: `nft_mint` | `nft_burn` | `nft_transfer`
// * `data`: associate event data
interface EventLogData {
standard:string,
version:string,
event:string,
data: NftMintLog[]|NftTransferLog[]|NftBurnLog[]
}

// An event log to capture token minting
// Arguments
// * `owner_id`: "account.near"
// * `token_ids`: ["1", "abc"]
// * `memo`: optional message
interface NftMintLog {
owner_id:string,
token_ids:string[],
memo?:string
}

// An event log to capture token burning
// Arguments
// * `owner_id`: owner of tokens to burn
// * `authorised_id`: approved account to burn, if applicable
// * `token_ids`: ["1","2"]
// * `memo`: optional message
interface NftBurnLog {
owner_id:string,
authorised_id?:string,
token_ids:string[],
memo?:string
}

// An event log to capture token transfer
// Arguments
// * `authorised_id`: approved account to transfer
// * `old_owner_id`: "owner.near"
// * `new_owner_id`: "receiver.near"
// * `token_ids`: ["1", "12345abc"]
// * `memo`: optional message
interface NftTransferLog {
authorised_id?:string,
old_owner_id:string,
new_owner_id:string,
token_ids:string[],
memo?:string
}
```

## Further 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`)

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.

Please feel free to open pull requests for extending the events standard detailed here as needs arise.

## Drawbacks

There is a known limitation of 16kb strings when capturing logs.
This can be observed if `token_ids` vary in length across different apps.
This impacts the amount of events that can be processed.