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

SIP-016 Metadata for Tokens #44

Merged
merged 32 commits into from
Aug 26, 2022
Merged

Conversation

friedger
Copy link
Contributor

@friedger friedger commented Oct 20, 2021

This PR

  • adds a sip for metadata of token, this includes NFTs that are compliant to SIP-009, FTs that are compliant to SIP-010, or semi-fungible tokens.
  • addresses Metadata for NFTs #17

@friedger
Copy link
Contributor Author

I am looking for more real world examples like:

{
  "collection": "PoX Monks",
  "id": 1,
  "name": "PoX Monk 1",
  "image": "ipfs://ipfs/QmegB9FURt6Jz1kGbaQxNqhvoPk9G2b87rxUE1h9DLDbDF/PoX%20Monk%201.jpg",
  "attributes": [
    {
      "type": "body",
      "value": "buff monk"
    },
    {
      "type": "headwear",
      "value": "orange hat"
    }
  ]
}

Here we see additional properties: "collection" and "id", also "type" instead of "trait_type".

@friedger
Copy link
Contributor Author

The SIP contains a JSON schema definition written in JSON.
Makers of $65m NFT "First 5000 days" by Beeple mixed schema definition with schema values. Metadata should NOT look like this. While valid according to the sip, providing values in "description" fields is counter-intuitive.

{"title": "EVERYDAYS: THE FIRST 5000 DAYS", 
"name": "EVERYDAYS: THE FIRST 5000 DAYS", 
"type": "object", 
"imageUrl": "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", 
"description": "I made a picture from start to finish every single day from May 1st, 2007 - January 7th, 2021.  This is every motherfucking one of those pictures.", "attributes": [{"trait_type": "Creator", "value": "beeple"}], 
"properties": 
   {"name": {"type": "string", "description": "EVERYDAYS: THE FIRST 5000 DAYS"}, 
    "description": {"type": "string", "description": "I made a picture from start to finish every single day from May 1st, 2007 - January 7th, 2021.  This is every motherfucking one of those pictures."}, 
    "preview_media_file": {"type": "string", "description": "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq"}, 
    "preview_media_file_type": {"type": "string", "description": "jpg"}, "created_at": {"type": "datetime", "description": "2021-02-16T00:07:31.674688+00:00"}, "total_supply": {"type": "int", "description": 1}, 
    "digital_media_signature_type": {"type": "string", "description": "SHA-256"},
    "digital_media_signature": {"type": "string", "description": "6314b55cc6ff34f67a18e1ccc977234b803f7a5497b94f1f994ac9d1b896a017"}, 
     "raw_media_file": {"type": "string", "description": "https://ipfsgateway.makersplace.com/ipfs/QmXkxpwAHCtDXbbZHUwqtFucG1RMS6T87vi1CdvadfL7qA"}}}

@friedger
Copy link
Contributor Author

friedger commented Oct 20, 2021

Example with extensive use of properties. Here trait definitions (that can be defined in attributes) and properties are mixed into the "properties" value.

{
"name": "foo",
"image": "bar",
"properties": {
  "making_of_video": {
     "display_type":  "uri",
     "trait_type": "string",
     "value": "protocol://identifier"
  },
  "video_md": {
   "display_type": "none",
   "trait_type": "xml", // string???
   "value": " <xs:element name="VIDEOMD" type="videoType"/>
        <xs:element name="VIDEOSRC" type="videoType"/>
        <xs:annotation>
        <xs:documentation>VIDEOMD: LC-AV Video Metadata Extension Schema. VIDEOMD contains technical ...
 </xs:documentation>
        </xs:annotation>
        <xs:complexType name="videoType">
        <xs:annotation>
        <xs:documentation>A complexType for encapsulating and organizing within a singleparent element ...
</xs:documentation>
        </xs:annotation>
     ..."
    },
 }

@mardi00
Copy link

mardi00 commented Oct 20, 2021

Hoi Axopoa here. For most of the NFT collections where the "source" is "hosted", a format like this would (maybe) be ok.

{
  "name": "PoX Monks",
  "description": "A unique collection of monks",
  "author": "Monks Studio",
  "version": 1,
  "date": 1631645313396,
  "items": [
    {
      "id": 1,
      "name": "PoX Monk 1",
      "source": "ipfs://ipfs/QmegB9FURt6Jz1kGbaQxNqhvoPk9G2b87rxUE1h9DLDbDF/PoX%20Monk%201.jpg",
      "attributes": [
        {
          "type": "body",
          "value": "buff monk"
        },
        {
          "type": "headwear",
          "value": "orange hat"
        }
      ]
    },
    {
      "id": 2,
      "name": "PoX Monk 2",
      "source": "ipfs://ipfs/QmegB9FURt6Jz1kGbaQxNqhvoPk9G2b87rxUE1h9DLDbDF/PoX%20Monk%201.jpg",
      "attributes": [
        {
          "type": "body",
          "value": "slim monk"
        },
        {
          "type": "headwear",
          "value": "blue hat"
        }
      ]
    }
  ]
}

Edit: Seems like I miss a lot of information. I will do my homework and come back

@Jamil
Copy link

Jamil commented Oct 21, 2021

For new collections, stxnft.com goes with a format that looks something like this:

{
  "collection": "StacksArmy",
  "name": "StacksArmy Captain #9",
  "image": "ipfs://ipfs/QmPPQBNKohiDYAnjKkdrQcf2LupqixFMEpyvnNWQXz7ozq/StacksArmy%20Captain%20%239.png",
  "attributes": [
    {
      "trait_type": "class",
      "value": "Captain"
    }
  ]
}

This is similar to the OpenSea metadata format, with the addition of the additional field collection.

This is because right now SIP-009 doesn't support "collection-level" metadata (ERC721Metadata for example, specifies name() and symbol() functions). I'm not terribly opinionated on whether this should be done at the contract level with an additional function to get the name/symbol, or whether it should be handled in get-token-uri as we do now.

To me, the OpenSea metadata format works just fine with this collection-level metadata caveat. I'd support either (a) an extension to SIP-009 allowing for NFT contracts to return a name and symbol (e.g., get-name and get-symbol functions which take no arguments), or (b) adopting a metadata format that is OpenSea + some field to specify the collection name.

sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
@friedger
Copy link
Contributor Author

Which properties should be required?
This sip proposed "version", "name" and "image"

@friedger
Copy link
Contributor Author

friedger commented Oct 23, 2021

@MarvinJanssen This SIP tries to specifies metadata for any type of tokens. It should be applicable also for SIP-013 tokens (#42). Does it make sense?

@friedger friedger changed the title [WIP] Metadata for NFTs [WIP] Metadata for Tokens Oct 23, 2021
@friedger
Copy link
Contributor Author

To me, the OpenSea metadata format works just fine with this collection-level metadata caveat. I'd support either (a) an extension to SIP-009 allowing for NFT contracts to return a name and symbol (e.g., get-name and get-symbol functions which take no arguments), or (b) adopting a metadata format that is OpenSea + some field to specify the collection name.

@Jamil I support b). I propose field "properties.collection".

@MarvinJanssen
Copy link
Collaborator

MarvinJanssen commented Oct 23, 2021

Thanks @friedger this is great. I think bringing in lots of real world examples makes sense (like you have been doing). We should tap into our friends in the EVM space and see what they are doing these days too. As long as there is a version field, mentioned in #42, then I think we can come up with anything.

@Jamil
Copy link

Jamil commented Oct 23, 2021

Which properties should be required?
This sip proposed "version", "name" and "image"

On stxnft.com right now we'll render any metadata as long as name and image are provided.

However, are we going to require tokens which represent non-image data (e.g., bns, quotes) to have a corresponding render/image?

It'd certainly make things easier on my side but I'm not sure people will follow that for non-image NFTs.

@friedger
Copy link
Contributor Author

This sip is mainly about sip compatible contracts, not about native assets, like bns.

BNS needs a wrapper!

It would be great to specify an algorithm to display tokens without image like identicon.

Non-image NFTs would still need some kind of image to represent on a marketplace assuming users use the marketplace with their eyes. We need to think about accessibility!

@dantrevino
Copy link

dantrevino commented Oct 25, 2021

For new collections, stxnft.com goes with a format that looks something like this:

{
  "collection": "StacksArmy",
  "name": "StacksArmy Captain #9",
  "image": "ipfs://ipfs/QmPPQBNKohiDYAnjKkdrQcf2LupqixFMEpyvnNWQXz7ozq/StacksArmy%20Captain%20%239.png",
  "attributes": [
    {
      "trait_type": "class",
      "value": "Captain"
    }
  ]
}

This is similar to the OpenSea metadata format, with the addition of the additional field collection.

This is because right now SIP-009 doesn't support "collection-level" metadata (ERC721Metadata for example, specifies name() and symbol() functions). I'm not terribly opinionated on whether this should be done at the contract level with an additional function to get the name/symbol, or whether it should be handled in get-token-uri as we do now.

To me, the OpenSea metadata format works just fine with this collection-level metadata caveat. I'd support either (a) an extension to SIP-009 allowing for NFT contracts to return a name and symbol (e.g., get-name and get-symbol functions which take no arguments), or (b) adopting a metadata format that is OpenSea + some field to specify the collection name.

The specification for metadata should apply to individual NFTs ... for collection data, that should be included in attributes. ie. a "collection" is not an nft. Ie for Boom NFTs the metadata would look something like this below.

{
  "name": "Foo #101",
  "image": "ipfs://somerandomecid",
  "attributes": [
    { "collection_name":  "Foo Collection" },
    { "collection_size":  "10000" },
  ],
  "properties": {
    "prop_1": {
      "prop_type": "string",
      "display_type": "string",
     "value": "foo",
    },
    "prop_2": {
      "prop_type": "number",
      "display_type": "number",
      "value": 99,
    },
  },
    "localization": {
      "uri": "ipfs://somerandomcid/{locale}.json",
      "default": "en",
      "locales": ["en", "ar-eg", "de"]
  }
}

Further I suggest:
name - required
image - required, can be blank
attributes: optional. Client may optionally display.
properties: optional. Client may optionally display.

  • if properties are included, they should be in the format { "key": "value" }, where "value" is an object with:
    • prop_type - optional
    • display_type - optional
    • value - required
      localization - optional
  • if localization is included, it should follow the erc1155 metadata spec

@friedger
Copy link
Contributor Author

friedger commented Nov 3, 2021

@dantrevino properties and attributes should be swapped, shouldn't it? At least that is how opensea defines it: https://docs.opensea.io/docs/metadata-standards#metadata-structure

attributes consists of trait_type, display_type and value.

properties can be anything.

@dantrevino
Copy link

@dantrevino properties and attributes should be swapped, shouldn't it? At least that is how opensea defines it: https://docs.opensea.io/docs/metadata-standards#metadata-structure

attributes consists of trait_type, display_type and value.

properties can be anything.

yup got that backwards

@friedger friedger mentioned this pull request Nov 5, 2021
@friedger friedger changed the title [WIP] Metadata for Tokens Metadata for Tokens Nov 7, 2021
@friedger friedger marked this pull request as ready for review November 7, 2021 14:49
sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
sips/sip-x/sip-x-nft-metadata.md Outdated Show resolved Hide resolved
@friedger
Copy link
Contributor Author

@jcnelson The schema has been validated using JsonValidator. See https://github.com/Light-Labs/media-metadata-schemas
The found errors has been fixed.

@jcnelson
Copy link
Contributor

Just checking in. Is there a mainnet contract using this trait yet?

@jcnelson
Copy link
Contributor

jcnelson commented Jun 8, 2022

@friedger Feel free to advance the status of this SIP to Activation-in-Progress, per my earlier comment. I can't commit directly to your PR since it's in your repo.

@jcnelson jcnelson added the Activation-in-Progress SIP is in the process of activating label Jun 9, 2022
@Hero-Gamer
Copy link
Contributor

Hi all just wanna make sure this is captured officially.

During last Friday's weekly SIP call #79 (comment) I raised this point.

According to the activation criteria:
"This SIP is activated if 10 contracts are deployed that follows this
specification. This must happen before Bitcoin tip #750,000."

We are now at bitcoin block 749,565.
435 blocks left as of writing, which is approx. 3 days.

So I'm now working with the NFT marketplaces to fetch data to confirm 10 contracts have been deployed already.
Will update all how it goes.

@dantrevino
Copy link

There's a miss here @friedger ... this is not a contract sip, its a metadata sip. @Hero-Gamer there is no way to look at a contract and determine if the metadata supports sip-016. The contract only has a link to metadata, but, for instance, the boom-300 "contract" was deployed 10 months ago, before the sip was complete, and initially we created nfts that were not sip-016 compliant. However, now it is deploying nfts that are sip-016 compliant. Same contract.

https://explorer.stacks.co/txid/SP1QK1AZ24R132C0D84EEQ8Y2JDHARDR58R72E1ZW.boom-nft-300?chain=mainnet

both minted from the same contract:
non-sip016 nft, created jan 17: https://bafkreie3abg3pp4573zkjmxcgaosifpyof5hi5gxelnqutnyhelihjqeqq.ipfs.nftstorage.link/
sip016 nft, created recently: https://bafkreicg63zfryk2cvrucztb5bztg4vh6hj2e65yxcr7nld2rtryobigcy.ipfs.nftstorage.link/

@Jamil
Copy link

Jamil commented Aug 15, 2022

Our Create Portal contracts are almost SIP-16 compliant but not quite, since we don't have the required "sip" field in the JSON. Working with our developers to add that for all future contracts, but not sure 10 contracts like this will be deployed by Wednesday. What is the process if this SIP does not meet the requirements by then, and we have to re-start?

@dartman10
Copy link

I found these with "sip": 16 in metadata:

name contract metadata_url
Boombox [10th Edition] SP1QK1AZ24R132C0D84EEQ8Y2JDHARDR58R72E1ZW.boomboxes-cycle-32 https://cloudflare-ipfs.com/ipfs/bafkreigzei42ktazjl3b6ounitwazbmcz7zzn5vb7poevx2xoroau7ftnm
Boombox [12th Edition] - Bloombox by Grace Hye SP1QK1AZ24R132C0D84EEQ8Y2JDHARDR58R72E1ZW.boomboxes-cycle-36 ipfs://bafkreidowklqh7nub2dxrh2mj4tu46inqtapqfidqnwk5taown5w4li6pq
Boombox [13th Edition] SP1QK1AZ24R132C0D84EEQ8Y2JDHARDR58R72E1ZW.boomboxes-cycle-38 ipfs://bafkreibduyxkdcp3djswzjjoexoi6hcvk2suaoyri2uqpiuyxbhkh6bwxe
Boombox [14th Edition] - STX of Toys SPMS4E9RQ4GCGG68R6D15PKV01TYNCBPYZG1ZMFE.boomboxes-cycle-40 ipfs://bafkreieanobksr6qetgqupx7zpn2aebw742siwsqa4ef6i7aybxvnku2ze
Boombox [8th Edition] - Moonbox SP1QK1AZ24R132C0D84EEQ8Y2JDHARDR58R72E1ZW.boomboxes-cycle-28 https://cloudflare-ipfs.com/ipfs/bafkreic3emy7vy4azvm56sy3dwsuny4653uzi7ubb36ui63w424kagzfym
Boombox [8th Edition] - Moonbox SP1QK1AZ24R132C0D84EEQ8Y2JDHARDR58R72E1ZW.boomboxes-cycle-28-moonbox https://cloudflare-ipfs.com/ipfs/bafkreic3emy7vy4azvm56sy3dwsuny4653uzi7ubb36ui63w424kagzfym
Boombox [9th Edition] - Mushroom by Flower SP1QK1AZ24R132C0D84EEQ8Y2JDHARDR58R72E1ZW.boomboxes-cycle-30 https://cloudflare-ipfs.com/ipfs/bafkreibszx62vqkce7pefr6xtcqvyec7lo5xdjy6c7r3dhfd5bkl3wyvku

@jcnelson
Copy link
Contributor

jcnelson commented Aug 15, 2022

Technically yes, you would need to restart in general since it indicates that the SIP doesn't have enough interest. But it seems that in this specific case, the only reason this SIP hasn't activated was due to a bug in the implementation (e.g. a missing sip field in the JSON), but there is otherwise sufficient interest. In this case, it would be fine by me to just combine the whole "withdraw, re-submit, accept, recommend, activation-in-progress" sequence into simply the act of increasing the activation-in-progress block height to whatever you need (a week?). The effect is the same either way; the SIP text wouldn't be changing and the activation-in-progress section only needs the steering committee's sign-off (which right now is just me).

So yeah, go ahead and change the block height and keep everything else as-is.

@friedger
Copy link
Contributor Author

Here is another one: https://explorer.stacks.co/txid/SP1QK1AZ24R132C0D84EEQ8Y2JDHARDR58R72E1ZW.boom-nft-300?chain=mainnet Makes it 8.

@dartman10
Copy link

No. 9 - a new one deployed a few hours ago:
SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crashpunks-punkettes
https://explorer.stacks.co/txid/0x95c03cb957324a9983430b4419c4d4180d13ca5b067cda7e23d314df4f762443?chain=mainnet
ipfs://QmcUiKLAeYbx78UZWoCuyKdm5GhZH6Jhto9yhKt1oPvWHY/

@Hero-Gamer
Copy link
Contributor

153 bitcoin block time left, approx. 1 day. (current block time 749,847)
Who else/where else can we ask to find the last contract required?
almost there!

@Jamil
Copy link

Jamil commented Aug 17, 2022

The contract above (SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crashpunks-punkettes) was deployed with the Gamma Create Portal, which now has the sip field in the JSON.

The next contract deployed with the Gamma Portal will be the 10th :)

@dartman10
Copy link

dartman10 commented Aug 17, 2022

No. 10? This NFT has a dynamic metadata. The latest mint has a SIP-016 metadata, prior mints were not.

  • United States of Bitcoin
  • SP1JCPNPAMAQJ364AFHPTW3HY7X0HYZ3TJ0ZDGWZH.artificial-satoshi

Latest mint with "sip": 16 :

Earlier mint example without "sip": 16:

@Hero-Gamer
Copy link
Contributor

If all contracts checks out:
Current Bitcoin block height: 749,876
https://mempool.space/block/0000000000000000000894d96480628dcd38fd9424750e9d2638aa75233e19f0

@jcnelson
Copy link
Contributor

jcnelson commented Aug 22, 2022

Awesome to see! I will take a look as soon as I am able, and if it all checks out, it will be my pleasure and honor to advance this to Ratified 🎉

@jcnelson
Copy link
Contributor

jcnelson commented Aug 24, 2022

Here is another one: https://explorer.stacks.co/txid/SP1QK1AZ24R132C0D84EEQ8Y2JDHARDR58R72E1ZW.boom-nft-300?chain=mainnet Makes it 8.

@friedger I'm not sure where to look for the metadata URL here? This appears to be a contract deploy from 6 months ago.

The rest look good to me.

@dartman10
Copy link

Perhaps Xan Ditkoff can help. :)

name contract metadata_url
Xan Ditkoff #1 SP2VG7S0R4Z8PYNYCAQ04HCBX1MH75VT11VXCWQ6G.the-built-on-bitcoin-podcast ipfs://QmQBr6yGuiJmsWTmkYSbgkU1GX41BJpNB19mKNiLeFh3Lq/json/1.json
Xan Ditkoff #2 SP2VG7S0R4Z8PYNYCAQ04HCBX1MH75VT11VXCWQ6G.the-built-on-bitcoin-podcast ipfs://QmQBr6yGuiJmsWTmkYSbgkU1GX41BJpNB19mKNiLeFh3Lq/json/2.json
Xan Ditkoff #3 SP2VG7S0R4Z8PYNYCAQ04HCBX1MH75VT11VXCWQ6G.the-built-on-bitcoin-podcast ipfs://QmQBr6yGuiJmsWTmkYSbgkU1GX41BJpNB19mKNiLeFh3Lq/json/3.json
Xan Ditkoff #4 SP2VG7S0R4Z8PYNYCAQ04HCBX1MH75VT11VXCWQ6G.the-built-on-bitcoin-podcast ipfs://QmQBr6yGuiJmsWTmkYSbgkU1GX41BJpNB19mKNiLeFh3Lq/json/4.json
Xan Ditkoff #5 SP2VG7S0R4Z8PYNYCAQ04HCBX1MH75VT11VXCWQ6G.the-built-on-bitcoin-podcast ipfs://QmQBr6yGuiJmsWTmkYSbgkU1GX41BJpNB19mKNiLeFh3Lq/json/5.json
blobby SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.continuous-007 ipfs://QmRD1wKK6cMmfrgPBAzSR9LYj7ifKauETCEARJu1EpMZ9C/json/2.json

@jcnelson
Copy link
Contributor

@dartman10 thanks! Looks good to me.

It is my pleasure to inform everyone that this SIP has met all of the criteria for ratification! Please transition this SIP to "Ratified" and I'll merge it 🎉

@friedger
Copy link
Contributor Author

Great work everybody!

@jcnelson I changed the status to Ratified. Anything else to do?

@jcnelson
Copy link
Contributor

Nope; going to merge

@jcnelson jcnelson merged commit 7f10722 into stacksgov:main Aug 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Activation-in-Progress SIP is in the process of activating
Projects
None yet
Development

Successfully merging this pull request may close these issues.