Null `metadata` property from `token` APIs

I think you need to read the docs how metadata works: https://docs.moralis.io/misc/faq#why-is-metadata-null-for-some-nfts

Metadata is not guaranteed - it depends on how it’s stored, we can only index reliable decentralized metadata (and even that is not guaranteed atm - we are scaling our systems to index faster)

using token_uri you can resolve yourself in other cases

also - please keep positive tone in forums, when you write a lot of “…” - it’s negative somehow, we are here to help for free its easier if you are more happy :wink:

1 Like

Sorry for the excessive dots. Just trying to help
:grinning: :smiley: :innocent: :fireworks: :fireworks:

hehe perfect, thanks, yes please inform us of all issues you find, we are here to fix :raised_hands::raised_hands:

Keep up the good work :pray:

1 Like

Here’s a fix

I could probably make something much stronger on the server-side if you guys (@cryptokid @ivan) could point me in the right direction

2 Likes

nice sent to Dmitry who is doing the boilerplate maintanance, thanks

resolving token_uri has to be from frontend because a big issue is rate-limits by 3rd party servers holding metadata - backend is gonna get rate limited fast while clients may be able to fetch the token_uri contents they need

This hook also handles the rate limits and retries.

Sure, it’s work, but it would make a speedy UI, which is good UX, which is what makes Moralis so much better then the rest.

So, I might need to develop this on the server anyways and it would probably take me event less time to just improve the existing stuff.

Just a suggestion though. No worries. ╰(°▽°)╯

Thank you @niknak

Amazing work! Already tested and merged :star_struck:

1 Like

Thanks, Dmitry.
Glad I could help!

For anyone who is still unsure on how to bypass metadata and display the URI properties without dismantling your code Moralis provides a very easy way to add and or replace metadata. Look for the useNFTBalance or the useNFTTokenIds hooks in the repository.

Inside the useEffect function you can easily add whatever metadata you want to replace by adding some short lines of code. See below.

useEffect(async () => {
    if (data?.result) {
      const NFTs = data.result;
      setFetchSuccess(true);
      for (let NFT of NFTs) {
        if (NFT?.metadata) {
          NFT.metadata = JSON.parse(NFT.metadata);
          NFT.image = resolveLink(NFT.metadata?.image);
        } else if (NFT?.token_uri) {
          try {
            await fetch(NFT.token_uri)
              .then((response) => response.json())
              .then((data) => {
                NFT.image = resolveLink(data.image);
              });
          } catch (error) {
            setFetchSuccess(false);

This part here is the trick… Use the NFT.image = resolveLink(data.image) as a guideline.

else if (NFT?.token_uri) {
          try {
            await fetch(NFT.token_uri)
              .then((response) => response.json())
              .then((data) => {
                NFT.image = resolveLink(data.image); <------- RIGHT HERE!!
              });

If you want to replace the name of the NFT metadata with the URI name add the name property

NFT.name = resolveLink(data.name);

If you want to replace the description metadata with the URI description add.

NFT.description = resolveLink(data.description);

At the end, your new hook should look something like this.

useEffect(async () => {
    if (data?.result) {
      const NFTs = data.result;
      setFetchSuccess(true);
      for (let NFT of NFTs) {
        if (NFT?.metadata) {
          NFT.metadata = JSON.parse(NFT.metadata);
          NFT.image = resolveLink(NFT.metadata?.image);
        } else if (NFT?.token_uri) {
          try {
            await fetch(NFT.token_uri)
              .then((response) => response.json())
              .then((data) => {
                NFT.image = resolveLink(data.image);
                NFT.name = resolveLink(data.name); <--- REPLACED DATA
                NFT.description = resolveLink(data.description);  <--- REPLACED DATA
              });
          } catch (error) {
            setFetchSuccess(false);

This will automatically pick up any metadata from the metadata source or the URI source “null” or not and display it. I hope this helps for now :slight_smile:

PS You can also add other custom properties that are in the metadata such as external_url and more.

@DevWill Thanks for this!

Is there a way to just push the whole resolved link into the metadata “null” field? ive tried but no luck. The individual elements do show up when tried as in your example


Hello,
I encountered same issue.
I used getAllTokenIds API to get metadata and token_uri.
but both are null. so I can’t show correct images for some token Ids.
I would appreciate if you can let me know how can I fix it.
My email address is
[email protected]
My telegram id
@skyhdev

Thanks
Asato

you can try to use resync metadata endpoint:
https://docs.moralis.io/moralis-server/web3-sdk/token#resyncmetadata

I tried to use resync metadata endpoint.
but still same issue.
please check my code and let me know your opnion.
thanks

can you paste the token_id, chain and contract address?

contract address: 0x7328829b9aea89933e891687a2683692c92dbb4a
chain: rinkeby network (chainId 4)
token_id: 17

ok, I get this output:

x = await Moralis.Web3API.token.getTokenIdMetadata({"address":"0x7328829b9aea89933e891687a2683692c92dbb4a","token_id":"17","chain":"rinkeby"})

=>

amount: "1"
block_number: "10070268"
block_number_minted: "10070268"
contract_type: "ERC721"
frozen: 0
is_valid: 0
metadata: null
name: "Lacedameon"
owner_of: "0x616bb70bade325ace258b5d5c2b9e8ebf0d0dce9"
symbol: "LDMN"
synced_at: "2022-02-24T23:40:09.870Z"
syncing: 2
token_address: "0x7328829b9aea89933e891687a2683692c92dbb4a"
token_id: "17"
token_uri: null

did you try to resync the token_uri?

I tried to resync only metadata.

do I need to resync the token_uri, too?

In this particular case it looks like the token uri needs to be resynced as it is null now