5

I have been testing my erc-721 contract with a link to my ipfs hash ipfs://QmeB87321i121xN88bXZzmjSUXqS46B8bU3H9ocyTb8tJf as the base token URI. The contracts are deployed and the items have been minted by me, but OpenSea can't read that metadata uri as expected. The documentation on OpenSea suggests that it should be sufficient.

My Contract

pragma solidity ^0.5.0;

import "./ERC721Tradable.sol";
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";

contract Creature is ERC721Tradable {
    constructor(address _proxyRegistryAddress)
        public
        ERC721Tradable("StygianCoins", "STG", _proxyRegistryAddress)
    {}

    function baseTokenURI() public pure returns (string memory) {
        return "https://ipfs.io/ipfs/QmeB87321i121xN88bXZzmjSUXqS46B8bU3H9ocyTb8tJf";
    }

    function contractURI() public pure returns (string memory) {
        return "https://contract-abis.herokuapp.com/api/contract/stygian-coins";
    }
}
TylerH
  • 20,799
  • 66
  • 75
  • 101
YourNewEmpire
  • 153
  • 3
  • 9

3 Answers3

13

Instead of pointing to your folder that has your files in IPFS, you'll need to point to a metadata file.

A Metadata file is a json formatted file that has information about the tokenId. You'd place your image URI in the image section. Here is an example:

{
    "name": "You NFT token name",
    "description": "Something Cool here",
    "image": "ipfs://QmTgqnhFBMkfT9s8PHKcdXBn1f5bG3Q5hmBaR4U6hoTvb1?filename=Chainlink_Elf.png",
    "attributes": []
}

So on IPFS you'd have 2 files:

  • One with the image
  • One with the metadata.json which contains the URI from the image

Then, in your contract, you'll have to call the _setTokenURI(tokenId, _tokenURI); function (imported by the openzepplin erc721 package)

_setTokenURI(tokenId, _tokenURI);

The _tokenURI should be your metadata URL/URI. And the tokenId is the id of your NFT.

Here is an example TokenURI in IPFS

And then how it renders on OpenSea.

More information on deploying and listing on opensea.

Patrick Collins
  • 5,621
  • 3
  • 26
  • 64
  • _setTokenUri uses tokenId, not hash. Is there a recommended way to set the token URI using the hash? – Jonas Arcangel Apr 04 '21 at 22:09
  • 1
    What do you mean? TokenURI is based on the TokenID. What do you mean tokenhash? – Patrick Collins Apr 04 '21 at 22:11
  • The URI for IPFS ends with the hash. _setTokenURI uses token ID. How is the token ID mapped to the hash? Do we override _setTokenURI in our token's contract, and maintain a mapping there? – Jonas Arcangel Apr 04 '21 at 22:39
  • 1
    You don’t use the hash, you use the URI of the hash. For example: https://ipfs.io/ipfs/QmT3nSKpJrEUWgeqGNiQPNEWcP2cousZNfQ72qX8qnBtWk?filename=mainnet-chainlink-elf.json – Patrick Collins Apr 04 '21 at 22:56
  • 1
    Dont know if standard is bad or can we do it otherwise, but this will imply we need to set URI for each NFT, which will cost a lot and we would like to set it once and then just use token id for each, but your example doesn't offer that as files are stored with name on the ipfs – Blissful Jun 24 '21 at 23:35
  • You don't need to store the files with a name on IPFS. But you could also just override each NFTs tokenURI function to point to the same function, so you could set it and forget it. – Patrick Collins Jun 25 '21 at 08:32
  • Do you know whether Opensea also supports ipfs:// type URLs? – Nicolai Schmid Jan 20 '22 at 17:04
  • They do support those – Patrick Collins Jan 20 '22 at 19:33
  • Might I ask you how did you implement such rich storefront presentation on opensea with all those social button-links at the top? – Qwerty Jan 24 '22 at 00:36
  • 1
    Oh, that's just something opensea offers on their UI. You don't do that in the solidity code – Patrick Collins Jan 24 '22 at 00:44
0

as of my understanding (still haven't done it), the tokenURI has to return an URL that points yo uto the metadata, that metadata containing the actual IPFS url. Take this with a grain of salt

fedeb
  • 122
  • 1
  • 4
0

FWIW - I had the same issue on openseas. Works with the URI of BOTH:

  1. JSON ends in .JSON
  2. IMAGE file ends in .PNG