Create Simultaneous Allowlists drop with Signature Drop and Next.js

Create Simultaneous Allowlists drop with Signature Drop and Next.js - thirdweb Guides

In this guide, we are going to create a Signature drop where users
will be able to connect their wallets to the website and claim an NFT from the drop.

We'll set up simultaneous allowlists where different users can buy NFTs from the drop at a different price based on which allowlist they are in.

Once the user clicks Mint, we will make an
API request that checks if the user is in one of our allowlists.

Based on the check, we will generate a signature with a different price for each allowlist! Let's get started.

Setup

I am going to use the Next typescript starter template for this guide.

If you are following along with the guide, you can create a project with the
Next TypeScript template using the thirdweb CLI:

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@5
  • Add MetaMask authentication to the site. You can follow this guide 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 { ThirdwebProvider } from "@thirdweb-dev/react";
import "../styles/globals.css";

// This is the chain your dApp will work on.
// Change this to the chain your app is built for.
// You can also import additional chains from `@thirdweb-dev/chains` and pass them directly.
const activeChain = "mumbai";

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

export default MyApp;

Setting up our Signature Drop Contract

To begin, head to the Contracts page in your thirdweb Dashboard and hit "Deploy new contract":

deploy new contract

You will be taken to our Explore page — where you can browse smart contracts built by the top protocols in web3 and deploy them in just a few clicks!

Note: You can also use the thirdweb CLI to set up a smart contract environment by running the below command from your terminal:

npx thirdweb create contract

This will take you through an easy-to-follow flow of steps for you to create your contract. Learn more about this in our CLI guide.

Otherwise, let's get back to Explore:

thirdweb explore page


In here, select your smart contract of choice. For this guide, we're going to use the Signature Drop contract to create our NFT collection:

thirdweb's Signature Drop Contract

Set up your smart contract with an image, name, description, etc., and configure which wallet address will receive the funds from primary and secondary sales:

Populate metadata and deploy contract

You can select any network you like; for this guide, I am choosing Mumbai. Learn more about the different networks we have available below:

Which Blockchain & Network Should I Use?
Learn the typical workflow for deploying smart contracts on to a blockchain, with an overview of the different options available to you on thirdweb.

Once deployed, you can follow the guide below to batch upload your NFTs if you haven't done so already.

How to use batch upload with an NFT Drop
Learn How To Batch Upload NFTs Using the thirdweb Dashboard To Lazy Mint Multiple NFTs At Once Ready For Users To Mint.

Making the website

Creating an API for generating a signature

We are going to use the signature minting on our backend to check the price at which this user will mint the NFT!

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
endpoint, you will get a response of Gm wagmi.

Get request from api

Let's now initialize the thirdweb SDK!

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

Ensure you store and access your private key securely.

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

Learn more about securely accessing your private key.

We also need to import the ThirdwebSDK:

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

Determining the price of the NFT

I am creating 2 hardcoded arrays in this example, but you can get them from a JSON file, from a database, or anything you like!

So add these 2 arrays and a function to determine the price:

const teamMembers = ["0x39Ab29fAfb5ad19e96CFB1E1c492083492DB89d4"];

const allowList = ["0x6bF08768995E7430184a48e96940B83C15c1653f"];

const determinePrice = (): number => {
  if (teamMembers.includes(address)) {
    return 0;
  }
  if (allowList.includes(address)) {
    return 1;
  }
  return 2;
};

So if the person is in the allowlist they will mint the NFT for 1 MATIC, if they are a team member they will mint the NFT for 0 MATIC,
and if they are not in an allowlist, they will mint the NFT for 2 MATIC.

Generating the signature
Finally, we are going to access the Signature Drop using the sdk and generate a signature from it:

const { address } = req.body;

const contract = await sdk.getContract(
  "0x167edf3DDCFa1bfA625ad7DC8768A7e90a806D48",
  "signature-drop"
);

try {
  const signedPayload = await contract.signature.generate({
    to: address,
    price: determinePrice(),
    quantity: 1,
  });

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

Calling the API from the frontend

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

<div className={styles.container}>
  {address ? (
    <button className={styles.button} onClick={mint} disabled={loading}>
      {loading ? "Loading..." : "Mint NFT"}
    </button>
  ) : (
    <ConnectWallet />
  )}
</div>

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

const { contract } = useContract(
  "0x167edf3DDCFa1bfA625ad7DC8768A7e90a806D48",
  "signature-drop"
);
const [loading, setLoading] = useState(false);

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

  const signedPayload = await signedPayloadReq.json();

  try {
    const nft = await contract?.signature.mint(signedPayload.signedPayload);
    return nft;
  } catch (err) {
    return;
  } finally {
    setLoading(false);
  }
};

If we now try minting the NFT, we will be able to mint the NFT successfully at different prices! 🎉

Conclusion

This was a lot, now pat yourself on the back and share your amazing apps with us!
If you want to have a look at the code, check out the GitHub Repository.