Get nft metadata as part of the 'get all NFTs owned by address' API?

Is there a way to configure the ‘get all NFTs owned by address’ so to also return the metadata per each owned nft? I am especially interested in the image & name fields though I suspect that if you return a single metadata field you probably return them all.

Alternatively, if the above is a no-go - can this API be configured to return the token uri - as received by ERC721.togetUri() - per each nft?

Thanks
Gilad

1 Like

What address did you try with what options?
It looks like Moralis.Web3API.account.getNFTs returns metadata and uri for an address that I tested

I was not aware that getNfts return, by default, nft metadata. If that’s the case we’re good

Have you found a solution for that problem? I am also interested in getting the metadata for a specific NFT. I tried to use eb3Api.token.getNFTMetadata but it doesn’t give me the metadata that I want, for example, it doesn’t give me the image URL of the NFT neither the CID.

Can you give an example of your API call with getNFTMetadata?

1 Like

I tried the example code from the docs. It doesn’t give me the image URL, which is what I need the most.

import React from "react";
import { useMoralisWeb3Api } from "react-moralis";
const Web3Api = useMoralisWeb3Api();
const fetchNFTMetadata = async () => {
const options = {
address: "0x7dE3085b3190B3a787822Ee16F23be010f5F8686",
chain: "eth",
};
const metaData = await Web3Api.token.getNFTMetadata(options);
console.log(metaData);
};

I think that metadata for a nft contract is not something that is on chain.
what metadata you expect to get?

This gets the contract/collection metadata only. If you want metadata for a specific NFT you can use getTokenIdMetadata.

If you want to get all NFTs for the contract, you can use getAllTokenIds.

1 Like

Thanks Glad. I did what you suggested and I was able to get the data on json.
Here is the data that I am getting.

1. amount: "1"
2. block_number: "10541767"
3. block_number_minted: "10541767"
4. contract_type: "ERC1155"
5. metadata: "{\"name\":\"p[opopopopo\",\"description\":\"popopopo\",\"image\":\"https://ipfs.moralis.io:2053/ipfs/QmcPePGEGoKLsGpHuRqPNBQScBJWEoR6Ux5etpJw51dKcc\"}"
6. name: null
7. owner_of: "0xe8774d8cc8eb58e3183594c3e3922c8813c20bb7"
8. symbol: null
9. synced_at: "2022-04-21T07:43:00.481Z"
10. token_address: "0x7247d02546ea6d0f1a46403081f1874463fbe08a"
11. token_hash: "d4a6bed90c2060adc36d031ab71d24fb"
12. token_id: "42"
13. token_uri: "https://ipfs.moralis.io:2053/ipfs/QmXUjjJbbj8P4Nm12Gs

It is a json. I don’t know why when I copy and paste from the browser, it becomes like a numerated list. Anyways, the problem that I am facing now is that the code that I wrote is not showing anything in my cards.
Here is the code.

import React, { useState , useEffect } from "react";
import { useMoralis } from "react-moralis";
import CircularProgress from '@mui/material/CircularProgress';
import Card from '@mui/material/Card';
import CardMedia from '@mui/material/CardMedia';
import CardContent from '@mui/material/CardContent';
import { useVerifyMetadata } from "hooks/useVerifyMetadata";
import Typography from '@mui/material/Typography';
import {
  useParams
} from "react-router-dom";

const styles = {
  NFTs: {
    display: "flex",
    flexWrap: "wrap",
    WebkitBoxPack: "start",
    justifyContent: "flex-start",
    margin: "0 auto",
    maxWidth: "1000px",
    width: "100%",
    gap: "10px",
  },
};

function NFTDetails() {

    const { Moralis, isInitialized } = useMoralis();
    const { verifyMetadata } = useVerifyMetadata();
    const [metadata, setMetadata] = useState(null);

    let params = useParams();

const fetchNFTMetadata = async () => {
    const options = { chain: "rinkeby", address: params.token_address, token_id: params.token_id };
    const result = await Moralis.Web3API.token.getTokenIdMetadata(options);
    setMetadata(result);

}
useEffect(() => {
  if (isInitialized) {
  fetchNFTMetadata();
  }
}, [isInitialized]);
  console.log(" metadata " , metadata);

    return (
        <div style={{ padding: "15px", maxWidth: "1030px", width: "100%" }}>
          <h1>NFT Details</h1>
          <div style={styles.NFTs}>
           {metadata==null ? (
                   <CircularProgress color="secondary" />
                ) : (
                 <br />
                )}
          {/*  <Skeleton loading={!NFTBalances?.result}>  */}
              {metadata?.result &&
                metadata.result.map((nft, index) => {
                  //Verify Metadata
                  nft = verifyMetadata(nft);

        return (

                     <Card sx={{ maxWidth: 290 }} style={ { display: nft?.token_id === params.token_id ? 'block' : 'none' } } >

                                {console.log(" image ", nft?.metadata)}
                                      <CardMedia
                                              component="img"
                                              height="300"
                                              image={nft?.image || "error"}
                                              alt=""
                                          />
                                                <CardContent>
                                                  <Typography gutterBottom variant="h5" component="div">
                                                          {nft?.metadata?.name ?? "- No Name -"}
                                                  </Typography>
                                                        <Typography variant="h6" color="text.secondary">
                                                        Token ID: {nft?.token_id}
                                                        </Typography>
                                                        <Typography variant="body2" color="text.secondary">
                                                        {nft.token_address}
                                                        </Typography>
                                                </CardContent>
                                          </Card>
                  );
                })}
          </div>

        </div>
      );
}
export default NFTDetails;

So, I know that the output of metadata is correct because the console.log command outputs the contents of metadata. But the html doesn’t show anything in the card. Am I doing something wrong?

I think the problem has to do with these lines.

       {metadata?.result &&
                metadata.result.map((nft, index) => {
                  //Verify Metadata
                  nft = verifyMetadata(nft);

Is it correct to assume that the result of the json will be “result”? Or should I write something else here?

You will have to JSON.parse that metadata to get it into a usable state. You can do this to update the result with the updated metadata:

const result = await Moralis.Web3API.token.getTokenIdMetadata(options);
setMetadata({ ...result, metadata: JSON.parse(result.metadata) });

You are storing result directly into metadata so you don’t use metadata.result, you can access values directly.

if (!metadata) return null;

return (
    <ul>
      <li>{metadata.token_id}</li>
      <li>{metadata.metadata.name}</li>
      <li>
        <img src={metadata.metadata.image} />
      </li>
    </ul>
);

I would recommend renaming your state variable metadata to nft.

1 Like

Hi glad, thanks a lot. After all, I got my code to work. I will post it here so that it can help other people that might be facing the same problem.

This solution is currently working.

import React, { useState , useEffect } from "react";
import { useMoralis } from "react-moralis";
import CircularProgress from '@mui/material/CircularProgress';
import Card from '@mui/material/Card';
import CardMedia from '@mui/material/CardMedia';
import CardContent from '@mui/material/CardContent';
import { useVerifyMetadata } from "hooks/useVerifyMetadata";
import Typography from '@mui/material/Typography';
import {
  useParams
} from "react-router-dom";

const styles = {
  NFTs: {
    display: "flex",
    flexWrap: "wrap",
    WebkitBoxPack: "start",
    justifyContent: "flex-start",
    margin: "0 auto",
    maxWidth: "1000px",
    width: "100%",
    gap: "10px",
  },
};

function NFTDetails() {

    const { Moralis, isInitialized } = useMoralis();
    const { verifyMetadata } = useVerifyMetadata();
    
    const [metadata, setMetadata] = useState([]);
    const [myImage, setMyImage] = useState([]);
    const [myName, setMyName] = useState([]);
    let params = useParams();

const fetchNFTMetadata = async () => {
    const options = { chain: "rinkeby", address: params.token_address, token_id: params.token_id };
    const response = await Moralis.Web3API.token.getTokenIdMetadata(options);
    setMetadata(response);

      const NFTObject = JSON.parse(response.metadata);
      const myImageURI = NFTObject.image;
      const myNameObject = NFTObject.name;
      setMyImage(myImageURI);
      setMyName(myNameObject);
}
useEffect(() => {
  if (isInitialized) {
  fetchNFTMetadata();
  }
}, [isInitialized]);
  console.log(" metadata " , metadata.metadata);
  console.log(" image ", myImage);

    return (
    <Card sx={{ maxWidth: 290 }}  >
        <CardMedia
                component="img"
                height="300"
                image={myImage || "error"}
                alt=""
            />
                  <CardContent>
                    <Typography gutterBottom variant="h5" component="div">
                            {myName ?? "- No Name -"}
                           
                    </Typography>
                          <Typography variant="h6" color="text.secondary">
                          Token ID: {metadata.token_id}
                          </Typography>
                          <Typography variant="body2" color="text.secondary">
                          {metadata.token_address}
                          </Typography>
                  </CardContent>
            </Card>
      );
}

export default NFTDetails;