Open shazow opened 3 years ago
Hi, thanks for bringing that up here for discussion.
Some comments:
As per EIP-721 spec and the URI spec that it refers implicitly, data: uri should be considered valid. They are one of the accepted URI scheme: https://datatracker.ietf.org/doc/html/rfc2397
They are also widely supported : https://caniuse.com/datauri
Each browser have different limit to the number of characters though.
as for the mediaType to use, the tokenURI is defined as JSON, as such the mediaType should be application/json
For mandalas.eth I used the generic text/plain
mediaType instead as I did not want to base64 encode the text and encountered some issue with application/json
mediaType and had to deploy before I could realise what was the problem:
With application/json
things like space need to be URI encoded, so space (`) becomes
%20while with
text/plain` no encoding is required.
Tested on chrome and firefox,
data:text/plain,{"test": "hello world"}
render finedata:application/json,{"test": "hello world"}
renders incorrectly with space removed from stringsdata:application/json,{"test": "hello%20world"}
renders finesimilarly the following
fetch('data:application/json,{"test": "hello world"}').then(r => r.json()).then(console.log)
outputs this :
{test: "helloworld"}
while this
fetch('data:application/json,{"test": "hello%20world"}').then(r => r.json()).then(console.log)
and this
fetch('data:text/plain,{"test": "hello world"}').then(r => r.json()).then(console.log)
output this :
{test: "hello world"}
Overall I don't think we need any new standard, but we should aim at making support for data uri based tokenURI more widespread.
@wighawag That's very useful, thank you for sharing your thought process!
I agree that data:text/plain
is a convenient shortcut which requires less encoding. I like that.
I also agree we don't necessarily need another standard, but I would love to get some agreement from stakeholders about data uri tokenURI usage in the existing standard. Especially as new players come into the space, would suck to have to repeat this over and over
In general, I like the rule of thumb of "any format that fetch(...)
supports is fair game (plus IPFS, etc)".
And then of course we have embedded images inside of the data URI, which should also be supported.
Procedurally Rendered NFTs
Proposal
To enable NFTs with on-chain procedurally-generated assets, renderers should support rendering inlined
data:...
tokenURI output.Background
ERC-721 is the NFT specification, but it under-specifies the output formats supported by
tokenURI
. It says:Most implementations assume this means an
https://...
URL or even anipfs://...
URL, but what about in-linedata:...
URIs?Why? Not all NFTs are just off-chain JPEGs. "Natural NFTs" which contain all of their relevant state on-chain benefit from being able to render themselves using on-chain code. The rendering happens client-side, so the only gas cost is to host the rendering code.
In The Wild
NFT can procedurally generate all of their assets on-chain and return them. Some examples:
data:application/json;base64,<base64-encoded JSON...>
(Example: Tweet)data:text/plain,{<JSON...>}
(Example: OpenSea API, OpenSea View)function svg(uint256 id) public returns (string memory)
imageData(uint256)
method which returns a<svg>...</svg>
string.data:text/plain;charset=utf-8,...<ascii art>
Marketplaces
Most marketplaces don't support
data:...
URIs, or do so on a case-by-case basis:NFT Renderers
How can we make it even better? Related challenges?