Skip to content

Building Token Metadata

Each token in a Zora 1155 or 721 contract has a metadata uri field which points to a JSON Metadata file, pinned to IPFS, containing information about the media associated with the token as well as additional descriptive info. The Zora Protocol SDK provides some utility methods to help build the JSON metadata needed for tokens. It does not provide an endpoint for pinning the JSON metadata to IPFS.

This guide will show how to use the SDK to build the metadata and pin it to IPFS using your preferred IPFS pinning method.

The general structure of Token Metadata is defined in a type exported from the SDK, TokenMetadataJson:

type TokenMetadataJson = {
  name: string;
  description?: string;
  /** Primary image file */
  image?: string;
  animation_url?: string | null;
  content?: {
    mime: string;
    uri: string;
  } | null;
  attributes?: {
    trait_type: string;
    value: string;
  };
};

Building Token Metadata using SDK helper methods

The Zora Protocol SDK provides a utility to build JSON metadata for a token with the helper method makeMediaTokenMetadata(). Note that the media must be pinned to IPFS outside of this function call. Once the token metadata is generated by this function, it must be pinned to IPFS. The Zora Protocol SDK doesn't provide a pinning service, but this example will show how to pin the necessary assets and corresponding json metadata using Pinata

example.ts
import { makeMediaTokenMetadata } from "@zoralabs/protocol-sdk";
import { pinFileWithPinata, pinJsonWithPinata } from "./pinata";
 
export async function makeImageTokenMetadata({
  imageFile,
  thumbnailFile,
}: {
  imageFile: File;
  thumbnailFile: File;
}) {
  // upload image and thumbnail to Pinata
  const mediaFileIpfsUrl = await pinFileWithPinata(imageFile);
  const thumbnailFileIpfsUrl = await pinFileWithPinata(thumbnailFile);
 
  // build token metadata json from the text and thumbnail file
  // ipfs urls
  const metadataJson = makeMediaTokenMetadata({
    mediaUrl: mediaFileIpfsUrl,
    thumbnailUrl: thumbnailFileIpfsUrl,
    name: imageFile.name,
  });
  // upload token metadata json to Pinata and get ipfs uri
  const jsonMetadataUri = await pinJsonWithPinata(metadataJson);
 
  return jsonMetadataUri;
}

Building Metadata for Text NFTs

Zora Text NFTs have text for the token media, and look like the following:

{
  "name": "My Text NFT",
  "content": {
    "mime": "text/plain",
    "uri": "{text file url}"
  },
  "image": "{text preview thumbnail image url}",
  "animation_url": "{text file url}"
}

The Zora Protocol SDK provides helper methods to create the files and build the metadata json needed for text NFTs.

The function generateTextNftMetadataFiles() takes in a string for the text, and returns a name, mediaUrlFile which is a .txt file containing the text, and a thumbnailUrl which is a generated thumbnail image file with part of the text drawn into it.

import { generateTextNftMetadataFiles} from '@zoralabs/protocol-sdk';
 
const { 
  name, 
  mediaUrlFile, 
  thumbnailFile
} = await generateTextNftMetadataFiles("Hello, World!");

Once the files are generated, they must be pinned to IPFS gateway. With the ipfs urls of those files, the final metadata json can be built and pinned to IPFS. Here's an example using the Pinata as an IPFS pinning service:

example.ts
import {
  generateTextNftMetadataFiles,
  makeTextTokenMetadata,
} from "@zoralabs/protocol-sdk";
import { pinFileWithPinata, pinJsonWithPinata } from "./pinata";
 
export async function makeTextNftMetadata({ text }: { text: string }) {
  // call the sdk helper method to build the files
  // needed for a text based nft
  const {
    name,
    // file containing the text
    mediaUrlFile,
    // generated thumbnail image from the text
    thumbnailFile,
  } = await generateTextNftMetadataFiles(text);
 
  // upload text file and thumbnail to ipfs with Pinata
  const mediaFileIpfsUrl = await pinFileWithPinata(mediaUrlFile);
  const thumbnailFileIpfsUrl = await pinFileWithPinata(thumbnailFile);
 
  // build token metadata json from the text and thumbnail file
  // ipfs urls
  const metadataJson = makeTextTokenMetadata({
    name,
    textFileUrl: mediaFileIpfsUrl,
    thumbnailUrl: thumbnailFileIpfsUrl,
  });
  // convert json object to json file
  const jsonMetadataUri = await pinJsonWithPinata(metadataJson);
 
  return jsonMetadataUri;
}