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
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:
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;
}