Create an Early Access NFT with TypeScript and React

Create an Early Access NFT with TypeScript and React

In this guide, we are going to make our own early access NFTs using TypeScript.

We are going to create an NFT using an Edition Drop and also set the price and the number of claimable NFTs.

The edition drop allows us to create ERC1155 tokens, which means that each NFT in the collection can have more than one owner or more than one "copy".

Once we create the NFT and set up the claim condition, we will display the NFT alongside a "Connect Wallet" and a "Claim" buttons using React.

All the code for this guide is available on this GitHub repository.

Create Edition Drop

Our first step is to create an Edition Drop contract.

This can be done in the dashboard.

  • Head to the thirdweb dashboard,
  • Click "Deploy New Contract"
  • Click "Deploy Now" on the Edition Drop pre-built contract.
  • Configure the metadata for the contract, and deploy to the Goerli test network.

Project Set-Up

Create a new TypeScript + React project using the CLI, by running:

npx thirdweb create --cra --ts

Instantiate the SDK

To create, configure and interact with our NFTs we will need to use the SDK.

Instead of initializing it each time we use it, let's make a function that initializes it and then can be called as needed.

Start by making a new folder called scripts at the root of your project and then make a file in that folder called getContract.mjs.

In getContract.mjs, follow these steps:

Import the libraries we'll need:

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

Instantiate and connect to the contract using the contract address found in the dashboard. Then export the contract.

// Learn more about securely accessing your private key: https://portal.thirdweb.com/web3-sdk/set-up-the-sdk/securing-your-private-key
const privateKey = "<your-private-key-here>";
// instantiate the SDK based on your private key, with the desired chain to connect to
const sdk = ThirdwebSDK.fromPrivateKey(privateKey, "goerli");

// Set variable for the edition drop contract address which can be found after creating an edition drop in the dashboard
const editionDropAddress = "your-edition-drop-contract-address";
// Initialize the edition drop module with the contract address
const editionDrop = sdk.getEditionDrop(editionDropAddress);

export default editionDrop;

Create the NFT

Now that we can connect to the SDK, we can move to the exciting step of creating our NFT!

Make a new file in the scripts folder and call it createNft.mjs. In this file we can follow these steps:

Import our edition from our previous script:

import editionDrop from "./getContractmjs";

Use the createBatch method to create our NFT. This method allows for the creation of multiple NFTs but we are only going to create one for now.

const createNFT = async () => {
  try {
    await editionDrop.createBatch([
      {
        name: "Early Access",
        description: "This NFT will give you early access!",
        // Get the NFT from a file uploaded to IPFS
        image: "ipfs://<IPFS_FILE_CID>",
      },
    ]);
    console.log("✅ Successfully created a new NFT!");
  } catch (error) {
    console.error("Failed to create the new NFT. Error: ", error);
  }
};

createNFT();

In your root directory, run the code with this command in your console:

node ./scripts/createNft.mjs

And you should see the success message in your console:

1-early-access-nft

Awesome! We have our early access NFT ☺️

Set NFT Price and Supply

Now that we have our NFT, we need to set the start time, price, and supply. We can also set the number of NFTs that can be claimed in one transaction, create an allowlist and adjust other settings.

For our project, we are only going to set the start time, price, and supply. We can do this in a new file called nftConfig.mjs.

We create a function called nftConfig and add the code to adjust the config of our NFT.

import editionDrop from "./getContract.mjs";

const nftConfig = async () => {
  const claimConditions = [
    {
      startTime: new Date(),
      maxQuantity: 1000,
      price: 0.01,
    },
  ];
  try {
    await editionDrop.claimConditions.set("0", claimConditions); // 0 refers to token ID - the ID of our NFT
    console.log("🎉 Successfully added the claim condition!");
  } catch (error) {
    console.log("Failed to set claim condition. Error: ", error);
  }
};

nftConfig();

In your root directory, run the code with this command in your console:

node scripts/nftConfig.mjs

And you should see the success message in your console:

2-early-access-nft

Amazing! We now have 1000 claimable NFTs! We just need a frontend for our users to interact with. Let's do it☺️

Display the NFT

We are going to display our NFT using the get method from the SDK with the token id as the param.

To do this, we will work in the src folder in our React app.

Our first step is to create a file called Nft.tsx which will be our component used to display the NFT.

We start off by installing the relevant library:

npm install @thirdweb-dev/react

Then we can import the libraries we will need to the component:

import { useEffect, useState } from "react";
import { useEditionDrop } from "@thirdweb-dev/react";

Create the Nft component:

import { ThirdwebNftMedia, useEditionDrop, useNFT } from "@thirdweb-dev/react";

const Nft = () => {
  const editionDrop = useEditionDrop("<CONTRACT_ADDRESS>");

  const { data: nft } = useNFT(editionDrop, 0); // 0 is the token id

  return (
    <div style={{ margin: "10vh" }}>
      <h1 style={{ fontSize: "28px", marginBottom: "10vh" }}>
        Claim your early access NFT!
      </h1>

      {nft && <ThirdwebNftMedia metadata={nft?.metadata} />}
    </div>
  );
};

export default Nft;

Claim Button

Okay. We have our NFT displayed and all we need is a button for users to claim NFTs. Let's create a new component in a file called ClaimButton.tsx.

First, we import the libraries:

import { useState } from "react";
import { useEditionDrop, useMetamask, useAddress } from "@thirdweb-dev/react";

We will use the useMetamask and useAddress thirdweb hooks to allow users to connect to their MetaMask wallets. We will check if the user is connected and if so, we will allow them to claim an NFT using the claim method with the token id and quantity as params.

const ClaimButton = () => {
  const connectWithMetamask = useMetamask();

  const editionDrop = useEditionDrop("<CONTRACT_ADDRESS>");

  const address = useAddress();

  // State to track when a user is claiming an NFT
  const [claiming, setClaiming] = useState(false);

  // Claim our NFT with the claim method - (token id, quantity)
  const onClick = async () => {
    setClaiming(true);
    try {
      await editionDrop?.claim(0, 1);
      alert("Successfully Claimed!");
      setClaiming(false);
    } catch (error) {
      console.log("Failed to claim. Error: ", error);
      setClaiming(false);
    }
  };

  return (
    <div>
      {address ? (
        <button
          disabled={claiming}
          style={{
            padding: "10px 20px",
            textAlign: "center",
            backgroundColor: "#05A266",
            color: "white",
          }}
          className="btn"
          onClick={onClick}
        >
          {claiming ? "Claiming..." : "Claim Early Access NFT"}
        </button>
      ) : (
        <button onClick={connectWithMetamask}>Connect MetaMask Wallet</button>
      )}
    </div>
  );
};

export default ClaimButton;

Wrap Up

We have created and configured our NFT. We are displaying it and we have a connect/claim button. All that is left to do is to display the NFT and button by adding the button to our NFT component and then adding the NFT component to our App.tsx.

After adding the button, Nft.tsx should look like this:

import { useEffect, useState } from "react";
import { useEditionDrop } from "@thirdweb-dev/react";
import ClaimButton from "./ClaimButton";

const Nft = () => {
  const editionDrop = useEditionDrop("<CONTRACT_ADDRESS>");
  const [nft, setNft] = useState("");

  async function fetchNft() {
    try {
      const nft = await editionDrop?.get("0");
      if (nft?.metadata.image) {
        setNft(nft?.metadata.image);
      }
    } catch (error) {
      console.log("Failed to get NFT. Error: ", error);
    }
  }

  useEffect(() => {
    fetchNft();
  }, []);

  return (
    <div style={{ margin: "10vh" }}>
      <h1 style={{ fontSize: "28px", marginBottom: "10vh" }}>
        Claim your early access NFT!
      </h1>
      <img
        alt="early access nft"
        src={nft}
        width="250px"
        height="250px"
        style={{ marginBottom: "5vh" }}
      />
      <ClaimButton />
    </div>
  );
};

export default Nft;

In index.tsx we need to start by importing the thirdweb provider and setting out desired chain. It should look like this:

import React from "react";
import { createRoot } from "react-dom/client";
import reportWebVitals from "./reportWebVitals";
import { ChainId, ThirdwebProvider } from "@thirdweb-dev/react";
import Nft from "./Nft";

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

const container = document.getElementById("root");
const root = createRoot(container!);
root.render(
  <React.StrictMode>
    <ThirdwebProvider desiredChainId={activeChainId}>
      <Nft />
    </ThirdwebProvider>
  </React.StrictMode>,
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

Next Steps

To preview your application, run:

npm run start

Congrats🥳 You've got a claimable early access NFT! Yours could like something like this:

3-early-access-nft

4-early-access-nft

5-early-access-nft
And remember, you can check all the code for this guide on this GitHub repository.