Create on-demand access pass minting (ERC 721)
Tags: nextjs, nft, web3
Published: 2022-08-17 13:11:52

## What is thirdweb?

[thirdweb](https://thirdweb.com/dashboard?utm_source=devto&utm_medium=crosspost&utm_campaign=on-demand-pass) is a platform that lets you deploy smart contracts without having to know Solidity, you can do it by using TypeScript, Python or Go or even without writing any code.

## Introduction

In this guide, we will create an [NFT collection](https://portal.thirdweb.com/pre-built-contracts/nft-collection?utm_source=devto&utm_medium=crosspost&utm_campaign=on-demand-pass) where users can connect their wallets to the website and mint an NFT by generating a signature. The metadata of the signature will be the same for everyone but this will help us send ERC 721 tokens which are unique to all the users.

This collection of passes will be similar to the [Fnatic passes drop](https://opensea.io/collection/fnatic-citizen)!

Before we get started, below are some helpful resources where you can learn more about the tools we will use in this guide.

- [View Project Source Code](https://github.com/thirdweb-dev/examples/tree/main/typescript/on-demand-pass)

- [NFT Collection Contract](https://portal.thirdweb.com/pre-built-contracts/nft-collection?utm_source=devto&utm_medium=crosspost&utm_campaign=on-demand-pass)

Let's get started.

## Setup

I am going to use the [Next typescript starter template](https://github.com/thirdweb-example/next-typescript-starter) for this guide.

If you are following along with the guide, you can create a project with the
[Next TypeScript template](https://github.com/thirdweb-example/next-typescript-starter) using the [thirdweb CLI](https://portal.thirdweb.com/cli?utm_source=devto&utm_medium=crosspost&utm_campaign=on-demand-pass):

```
npx thirdweb create --next --ts
```

If you already have a Next.js app you can simply follow these steps to get started:

- Install `@thirdweb-dev/react` and `@thirdweb-dev/sdk` and `ethers`
- Add MetaMask authentication to the site. You can follow this [guide](https://portal.thirdweb.com/guides/add-connectwallet-to-your-website?utm_source=devto&utm_medium=crosspost&utm_campaign=on-demand-pass) to do this.

By default the network in `_app.tsx` is Mainnet, we need to change it to Mumbai

```
import type { AppProps } from "next/app";
import { ChainId, ThirdwebProvider } from "@thirdweb-dev/react";

// This is the chainId your dApp will work on.
const activeChainId = ChainId.Mumbai;

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ThirdwebProvider desiredChainId={activeChainId}>
      <Component {...pageProps} />
    </ThirdwebProvider>
  );
}

export default MyApp;
```

## Creating an NFT collection

We also need to create an NFT collection contract where all the passes will live.
So, go to the [thirdweb dashboard](https://thirdweb.com/dashboard) and create an NFT collection!

Fill out the details and deploy the contract!

![Deploy NFT Collection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ohixrurpf4j45pjlia02.png)

We don't need to do anything else for now, all the NFTs will be minted as the users start minting! So let's get started with the code.

## Making the website

### Creating an API for generating a signature

We are going to use the signature minting on our backend. You can also add different checks if you want like different price for different wallets, allowing users to mint only 1 pass, etc.

Create a new folder `api` in the pages folder and `generate-mint-sig.ts` inside it.

We will now build a basic API that will output "gm wagmi"

```
import type { NextApiRequest, NextApiResponse } from "next";

const generateMintSignature = async (
  req: NextApiRequest,
  res: NextApiResponse
) => {
  res.send("gm wagmi");
};

export default generateMintSignature;
```

This creates a basic API for us, if you now go to the [`api/generate-mint-sig`](http://localhost:3000/api/generate-mint-sig)
endpoint, you will get a response of `gm wagmi`.

![Api endpoint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w0eui0ocepm4q2kqh2ax.png)
 
Let's now initialize the [thirdweb SDK](https://portal.thirdweb.com/building-web3-apps/setting-up-the-sdk?utm_source=devto&utm_medium=crosspost&utm_campaign=on-demand-pass)!

```
const sdk = ThirdwebSDK.fromPrivateKey(
  process.env.PRIVATE_KEY as string,
  "mumbai"
);
```

As you can see, we are using an environment variable to initialize the sdk.
The variable is called `PRIVATE_KEY`, which is the wallet's private key.
Create a new file `.env.local` and add your private key.

```
PRIVATE_KEY=<private_key>
```

**How to export your private key**

Learn how to [export your private key](https://portal.thirdweb.com/guides/create-a-metamask-wallet?utm_source=devto&utm_medium=crosspost&utm_campaign=on-demand-pass#export-your-private-key) from your wallet.

To do this, create a file called `.env.local` at the root of your project, and add the following to it:

```
PRIVATE_KEY=your-private-key-here
```

**Warning**

Ensure you store and access your private key securely.

- **Never** commit any file that may contain your private key to your source control.

We also need to import the `ThirdwebSDK`:

```
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
```

**Generating the signature**

Finally, we are going to access the NFT Collection using the sdk and generate a signature from it:

```
const { address } = JSON.parse(req.body);

const collection = sdk.getNFTCollection(
  "0xeED8165505d78D2CA9f2b4fA6Aff179CeBd4dCA4"
);

const metadata = {
  name: "Thirdweb",
  description: "Build web3 apps, easily.",
  image: readFileSync(path.join(process.cwd(), "public", "thirdweb.svg")),
  properties: {
    web: "3",
  },
};

try {
  const signedPayload = await collection.signature.generate({
    to: address,
    metadata,
  });

  return res.status(200).json({
    signedPayload,
  });
} catch (error) {
  console.log(error);
  return res.status(500).json({
    error,
  });
}
```

This is an example of a free mint, you can pass in different properties like price to customize your NFT collection! And as you can see we have created a new metadata object with data of the pass so you need to change the details like name, image, description, and properties based on your needs! For the image we are using a local file which is in the public folder so make sure to put in the correct path.

### Calling the API from the frontend

In `index.tsx` update the address ternary and add the Mint button:

```
<div>
  {address ? (
    <button onClick={mint}>Mint</button>
  ) : (
    <button onClick={connectWithMetamask}>Connect with Metamask</button>
  )}
</div>
```

Now we will create the mint function that makes an api call to the backend and mints the NFT:

```
const collection = useNFTCollection(
  "0xeED8165505d78D2CA9f2b4fA6Aff179CeBd4dCA4"
);

const mint = async () => {
  const signedPayloadReq = await fetch("/api/generate-mint-sig", {
    method: "POST",
    body: JSON.stringify({ address }),
  });

  const signedPayload = await signedPayloadReq.json();

  try {
    const nft = await collection?.signature.mint(signedPayload.signedPayload);
    return nft;
  } catch (err) {
    console.error(err);
    return null;
  }
};
```

If we now try minting the NFT, we will be able to mint the NFT successfully!