Minting Media

Cryptomedia is the foundational primitive of the Zora Protocol.

Cryptomedia is a medium for anyone on the internet to create universally accessible and individually ownable hypermedia.

To create new cryptomedia using the ZDK, you must call the mint function.

The mint function on a Zora instance expects two parameters: MediaData and BidShares

MediaData

MediaData type is comprised of four fields.

To construct the metadata of a piece of cryptomedia, use the generateMetadata function defined in metadata.ts. For more info visit Metadata.

tokenURI

The uri where the cryptomedia's content is hosted. This could link to any storage provider on the internet. Zora strongly recommends using a decentralized storage provider such as ipfs or arweave. The contentHash field is a sha-256 hash of the content of the content file. It is imperative that this hash is correct, because once it is written to the blockchain it cannot be changed.

metadataURI / metadataHash

The uri where the cryptomedia's metadata is hosted. This could link to any storage provider on the internet. Zora strongly recommends using a decentralized storage provider such as ipfs or arweave. The metadataHash field is a sha-256 hash of the content of the metadata file. It is imperative that this hash is correct, because once it is written to the blockchain it cannot be changed.

BidShares

The BidShares type is composed of three fields:

type DecimalValue = { value: BigNumber }

type BidShares = {
  owner: DecimalValue
  prevOwner: DecimalValue
  creator: DecimalValue
}

Each field represents the share that each stakeholder of a piece of cryptomedia has on the next accepted bid. At the time of mint, the indivduals bid shares (creator, owner, prevOwner) must sum to 100.

creator

The immutable, perpetual equity (%) the creator gets from each accepted bid of the piece of cryptomedia.

owner

The equity (%) the current owner gets from the next accepted bid of the piece of cryptomedia.

prevOwner

The equity (%) the previous owner gets from the next accepted bid of the piece of cryptomedia.

Complete minting example:

import { constructMediaData, sha256FromBuffer, generateMetadata, isMediaDataVerified, Zora } from '@zoralabs/zdk'

async function uploadToDecentralizedStorage(data: Buffer) {
  // function that uploads buffer to decentralized storage
  // and returns url of uploaded file from a gateway.
  return 'https://ipfs.io/ipfs/CID';
}

async function mintZNFT({
  zora: typeof Zora,
  content: Buffer,
  mimeType: string,
  name: string,
  description: string,
  previewImageUrl?: string = ''
}) {
  
  const metadataJSON = generateMetadata('zora-20210101', {
    description,
    mimeType: 'text/plain',
    image_url: previewImageUrl
    name,
    version: 'zora-20210604',
  })
  
  const contentURI = await uploadToDecentralizedStorage(content);
  const metadataURI = await uploadToDecentralizedStorage(Buffer.from(metadataJSON));
  
  const contentHash = sha256FromBuffer(content);
  const metadataHash = sha256FromBuffer(Buffer.from(metadataJSON));
  const mediaData = constructMediaData(
    contentURI,
    metadataURI,
    contentHash,
    metadataHash
  );
  
  // Verifies hashes of content to ensure the hashes match
  const verified = await isMediaDataVerified(mediaData);
  if (!verified){
    throw new Error("MediaData not valid, do not mint");
  }
  
  // BidShares should sum up to 100%
  const bidShares = constructBidShares(
    10, // creator share percentage
    90, // owner share percentage
    0 // prevOwner share percentage
  );
  
  const tx = await zora.mint(mediaData, bidShares);
  return new Promise((resolve) => {
    // This listens for the nft transfer event
    zora.media.on(
      "Transfer", 
      (from: string, to: string, tokenId: BigNumber) => {
      if (
        from === "0x0000000000000000000000000000000000000000" &&
        to === tx.from.address
      ) {
        promise.resolve(tokenId);
      }
    });
  });
}

Last updated