-
Notifications
You must be signed in to change notification settings - Fork 161
NEP: SBT Metadata Standard #504
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
Changes from 6 commits
634ee11
3394cd0
ca6b0a7
2540920
1705709
ab36573
37aaa74
35d179c
1308eba
c19b2d9
b5eebfe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,242 @@ | ||||||
| --- | ||||||
| NEP: 504 | ||||||
| Title: SBT Metadata Interface | ||||||
| Authors: Robert Zaremba (@robert-zaremba) | ||||||
| Status: New | ||||||
| DiscussionsTo: https://github.com/nearprotocol/neps/pull/0000 | ||||||
| Type: Contract Standard | ||||||
| Version: 1.0.0 | ||||||
| Created: 2023-08-21 | ||||||
| LastUpdated: 2023-09-06 | ||||||
| --- | ||||||
|
|
||||||
| ## Summary | ||||||
|
|
||||||
| A standard interface for [SBT](https://github.com/near/NEPs/pull/393) Metadata: tokens, classes and issuers. | ||||||
| This allows an SBT registry and issuers to be interrogated for its name and for details an SBT represent. | ||||||
|
|
||||||
| The proposal addresses potential challenges related to metadata reconstruction, off-chain storage security, owner/operator dependence, and data privacy. | ||||||
|
|
||||||
| ## Motivation | ||||||
|
|
||||||
| [NEP-393](https://github.com/near/NEPs/pull/393) defines a standard for Soul Bound Tokens, which are a foundational for Decentralized Society. SBTs can represent certificates, badges and anything that should be bound to a "soul". | ||||||
| The contract issuers often need more details than what NEP-393 defines. Such details are meant to be set in the `reference` field, which has an open, non standardized format. | ||||||
|
|
||||||
| NEAR doesn't have a well structured Metadata standard. The [NFT Metadata](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) doesn't clearly define the `reference` extension. In fact, the NEP-393 Metadata is defined based on NFT Metadata. The schema defined here can be used by other token variations as well. | ||||||
|
|
||||||
| Issuers, contract implementers and users demand a guideline and a minimum schema to make better integration with tools and projects. This document defines a minimum common schema for reference fields of `ContractMetadata` and `TokenMetadata`. Moreover, while working with various issuers, we found that issuers and minters often duplicate lot of data in the `TokenMetadata`. We found that it is unnecessary and it would be useful to create a new type: `ClassMetadata`, that defines common data for all tokens of a given (issuer, class) pair. | ||||||
|
|
||||||
| ## Specification | ||||||
|
|
||||||
| NEP-393 `TokenMetadata` is minimalistic. It only requires data which a contract can reason about, and all user facing details (such as title, description) are meant to be part of the reference. | ||||||
| Similarly, `ContractMetadata` only defines issuer basic info. | ||||||
|
|
||||||
| ### Class Metadata | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The big question is: where the class metadata is actually used? Any API (view/call methods)?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should represent information about the whole class. For example see the "SBT" cards https://i-am-human.app/community-sbts - it will use information from the class metadata (currently this is hardcoded in the UI).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @robert-zaremba I think I still don't get whether it's returned via API, or is posted as a log string in the L1 block (?).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added in the paragraph below |
||||||
|
|
||||||
| We start by defining a `ClassMetadata` which will contain all common information about tokens of the same class. | ||||||
| This will allow to avoid duplicating such information in all `TokenMetadata` and potentially allow to leave `TokenMetadata.reference` empty, if the tokens only differentiate by the class, issued_at and expires_at attributes. | ||||||
|
|
||||||
| ```rust | ||||||
| pub struct ClassMetadata { | ||||||
| /// Issuer class name. Required. | ||||||
| pub name: String, | ||||||
| /// If defined, should be used instead of `contract_metadata.symbol`. | ||||||
| pub symbol: Option<String>, | ||||||
| /// Icon content (SVG) or a link to an Icon. If it doesn't start with a scheme (eg: https://) | ||||||
| /// then `contract_metadata.base_uri` should be prepended. | ||||||
| pub icon: Option<String>, | ||||||
robert-zaremba marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| /// JSON or an URL to a JSON file with more info. If it doesn't start with a scheme | ||||||
| /// (eg: https://) then base_uri should be prepended. | ||||||
| pub reference: Option<String>, | ||||||
| /// Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. | ||||||
| pub reference_hash: Option<Base64VecU8>, | ||||||
|
||||||
| reference: string|null, // URL to a JSON file with more info | |
| reference_hash: string|null, // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. |
reference field is designed to be a link and nothing else.
If you want to have more fields stored as part of ClassMetadata, just add those fields on the same level as name, symbol, ... fields - this is not a breaking change and won't affect consumers of the API as they will just ignore unsupported fields. There is no need in string-encoding JSON data into the reference field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- For link vs having reference directly. For small content, I think it makes sense to store it directly, rather than querying another resource.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Issue about adding more records to the ClassMetadata vs requiring them in reference
ClassMetadata is not open ended. If we would like to add it, then we would need to add bunch of optional maps: social_media, contact, icon....
My reasoning is to have a strict minimum amount of keys in ClassMetadata, and add more structure for other common requirements, so tools and websites can display more information about tokens.
So, I'm not against the @frol suggestion (adding all fields from the ReferenceBase to the ClassMetadata and potentially to the IssuerMetadata). Maybe this is a solution? In such case, we would need to extend the ClassMetadata as more requirements will emerge from the ecosystem. So far, for the SBTs we were working with, we need different pictures (size / format), website address, social_media links ...
I would like to hear more opinions from the tool designers and other projects dealing with tokens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My reasoning is to have a strict minimum amount of keys in ClassMetadata, and add more structure for other common requirements, so tools and websites can display more information about tokens.
There is no reason to overcomplicate things. If you want to standardize fields, add them to ClassMetadata optional or not. reference is needed when the metadata is too big to be stored inline. There is no reason to store JSON as a string inside JSON value.
In such case, we would need to extend the ClassMetadata as more requirements will emerge from the ecosystem. So far, for the SBTs we were working with, we need different pictures (size / format), website address, social_media links ...
If you will want to standardize on those, you will still need to extend the NEP and some structure, be it ClassMetadata or some other struct, it does not really change things. Also, you don't always need to standardize every single field as that may limit the usability of the whole spec if those fields will be used sparsely.
I would like to hear more opinions from the tool designers and other projects dealing with tokens.
Sure, make a call in community channels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you will still need to extend the NEP and some structure
This is what an appendix is for.
We need to have a structure to make sure tools will have a common way to handle the data we describe in this PR. Can be in reference (as originally proposed), or by adding more optional attributes to the top level Metadata. Either way we need to have that structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to have a structure to make sure tools will have a common way to handle the data we describe in this PR. Can be in reference (as originally proposed), or by adding more optional attributes to the top level Metadata. Either way we need to have that structure.
I don't argue against having the defined structure, I just suggest moving it to where it belongs (new optional fields on ClassMetadata), instead of abusing reference field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'm OK with that, see the second part of the comment above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ClassMetadata is not open ended.
It is, actually, open ended by JSON spec, and that should be encouraged to be used whenever it makes sense.
Sure, I'm OK with that, see the second part of the #504 (comment).
Alright, so you are waiting for inputs from someone else besides me, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, so you are waiting for inputs from someone else besides me, right?
Yes, with @codingshot we left countless messages to get the input.
robert-zaremba marked this conversation as resolved.
Show resolved
Hide resolved
robert-zaremba marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we should have one more nesting level, to indicate the picture size? This will allow to set multiple sizes. Example:
"png": {"200x100": "link1", "4000x2000": "link2"}
Similarly we can do with vide and audio: video.mp4.full_hd = "link..."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@robert-zaremba ...or it may be just a part of the URL: "https://image.com/?w=1024&h=748"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if a http server doesn't support that?
Uh oh!
There was an error while loading. Please reload this page.