You have a lot of questions in there. Let's find the relevant references first.
Specification
The standard is specified at https://eips.ethereum.org/EIPS/eip-721
The specifications are the tokenURI
documentation:
/// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
/// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
/// 3986. The URI may point to a JSON file that conforms to the "ERC721
/// Metadata JSON Schema".
function tokenURI(uint256 _tokenId) external view returns (string);
and the JSON metadata schema specification:
{
"title": "Asset Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Identifies the asset to which this NFT represents"
},
"description": {
"type": "string",
"description": "Describes the asset to which this NFT represents"
},
"image": {
"type": "string",
"description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."
}
}
}
Your questions
You need to read the above very literally (i.e. using RFC 2119) and know about URIs to answer the questions. Your questions are, implicitly, "how can I do this?" and "will an implementation that does this be a valid ERC-721 implementation as specified by the standard?"
... the tokenUri
[is] an HTTP link in a server or using IPFS ...
Typically, yes. To my knowledge, every implementation does use URLs. I have never seen a deployed project using data URIs.
But not necessarily. The set of all URIs include uniform resource locators like HTTP and IPFS links, but URIs also include uniform resource names. There is also a literal "data URI" syntax that you could use.
is my implementation compliant with the standard if I add random fields to the JSON
Yes. The JSON schema only attributes meaning to specific fields. It does not restrict you from adding additional fields. The only way you could make a JSON file that is NOT compliant with the ERC721 Metadata JSON Schema is if it does any of the following:
- Has a root element type of array, string, true, false or null (rather than the required object type)
- The root object has a property with a key of
name
and the value of that name
is not of the string type
- The root object has a property with a key of
description
and the value of that description
is not of the string type
- The root object has a property with a key of
image
and the value of that image
is not of the string type
- The root object has a property with a key of
image
and the value of that image
is a string but it is not a URI pointing to a resource with mime type image/* representing the asset to which this NFT represents
Also, to be perfectly clear it is not required that tokenUri
point to a valid JSON document satisfying the ERC721 Metadata JSON Schema.
If this sounds wishy-washy then you need to understand that ERC-721 was written to make many possible implementations be considered valid. It also allows you to adopt other conventions if you would like additional interoperability.
what happens on OpenSea if I add random fields
OpenSea will show them to people that buy your stuff.
Does the tokenUri
only store a link and inside of that you have to put the json?
This is the most popular implementation. You could store other stuff in tokenUri
. And you could use other ways to point the tokenUri
to a JSON file. See above.
Best Answer
The approach of using an IPFS address as the token URI is intended to ensure its immutability, since the generated hash within the IPFS address will be unique for the file you are pointing to.
In your case, if you need to dynamically change contents in the metadata, the URI can be pointing to an https file that you can update at any time. However, in my understanding, you lose the concept of immutability or even worst -if the site is attacked, you can be showing tampered data.
Just one precision: if you are referring to ERC1155, the URI is passed in the constructor when you create the NFT and remains unchangeable. Therefore, when you mint tokens for that NFT, the URI remains the same (which is different to ERC721, in which you pass the URI for every new NFT).
One alternative could be saving your dynamic data also in a smart contract, where you would have a mapping between the NFT and the additional information. In this case, you need to estimate how often you will update data and its associated cost of doing this on-chain.
The approach you take will depend on your needs: if you are talking about a unique collectible cards, you should be using an IPFS-like method to ensure immutability. On the other hand, if the tokens can have dynamic metadata, you might be pointing to external data (off-chain) that you will manage accordingly.