> For the complete documentation index, see [llms.txt](https://ourzora.gitbook.io/zoraos/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ourzora.gitbook.io/zoraos/dev/zdk/minting-media.md).

# 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.&#x20;

To construct the metadata of a piece of cryptomedia, use the `generateMetadata` function defined in `metadata.ts`. For more info visit [Metadata](/zoraos/dev/zdk/metadata.md).

**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:

```typescript
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);
      }
    });
  });
}


```
