Metadata provider

Our smart contract holds a reference to token metadata on IPFS, not the metadata itself. The role of the MetadataProvider is to fetch the content from IPFS and translate it to a usable metadata object.

Create ./components/providers/MetadataProvider.tsx and add the following import statement:

import { createContext, useContext, useCallback } from 'react'

Token metadata should follow the tzip-21 specification. Let's define a subset of the standard properties:

interface ZombieMetadata {
  name: string
  description?: string
  displayUri: string
  thumbnailUri: string
  attributes: {
    alive: boolean
  }
}

We will define a context props interface for every provider. In this case:

interface MetadataProviderContextProps {
  fetchMetadata: (tokenInfo: string) => Promise<ZombieMetadata>
  ipfsUriToGateway: (ipfsUri: string) => string
}

Now we will define a helper function that replaces the IPFS URI with a HTTPS gateway, as most browsers still don't support IPFS natively. This isn't ideal because gateways are more centralised.

const ipfsUriToGateway = (ipfsUri: string) =>
  ipfsUri.replace("ipfs://", "https://cloudflare-ipfs.com/ipfs/")

We will be using next/image components. Since Next 13, the image component allows new customisation and optimisations for a smoother user experience. However, they require us to declare external image sources. Add the following object to next.config.js

As we will reuse the above function a few times, you might prefer to move it into a utilities file rather than importing it's use from this component (as we do in this tutorial)

Create an empty context:

And now the provider implementation, it simply uses the Fetch API to retrieve a JSON from the gateway and return a ZombieMetadata object.

It could be interesting here to save a cache of the metadata. It will be safe as well, as an IPFS URI is immutable.

Remember to include the Metadata provider in the app hierarchy in _app.tsx.

Last updated