thirdweb

Create an early access NFT with TypeScript and React

Create an early access NFT with TypeScript and React

Published on:

February 10, 2022

Easily create an early access NFT and a frontend for users to claim the NFT

Mordi Goldstein

Introduction

In this guide, we are going to make our own early access NFTs using TypeScript. We are going to create an NFT using the bundledrop module and then we are going to set the price and the number of claimable NFTs using a claim condition factory. The bundledrop module allows us to create ERC1155 tokens which means that you can set up a collection of NFTs with a customizable number of each NFT. Once we create the NFT and the claim condition, we will display the NFT with connect wallet and claim buttons in a React project.

Let's begin

1. Create Module

Our first step is to create a bundle drop module. This can be done in the dashboard and if you aren't sure how to create the module please check this guide.

2. Project Set-Up

Create a new React project with TypeScript and then install the dependencies:

  • @3rdweb/sdk - thirdweb TypeScript SDK.
  • ethers - will give us very useful utils.
  • dotenv - to hide our private key.
  • tslib - utility package
npx create-react-app my-app --template typescript npm install @3rdweb/sdk ethers dotenv fs npm install --save-dev ts-node tslib

3. Instantiate the SDK

To create, configure and interact with our NFTs we will need to use the thirdweb 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 in the root of your project and then make a file in that folder called getModule.ts.

In getModule.ts , follow these steps:

Import the libraries we'll need:

// Importing libraries import { ThirdwebSDK } from '@3rdweb/sdk'; import { ethers } from 'ethers'; import dotenv from 'dotenv'; // Use dotenv for private key dotenv.config();

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

const sdk = new ThirdwebSDK( new ethers.Wallet( // Your wallet private key process.env.PRIVATE_KEY as string, // RPC URL ethers.getDefaultProvider('https://rinkeby-light.eth.linkpool.io/') ) ); // Set variable for the bundle drop module contract address which can be found after creating a bundle drop module in the dashboard const bundleDropAddress = '<MODULE_ADDRESS>'; // Initialize the bundle drop module with the contract address const bundleDrop = sdk.getBundleDropModule(bundleDropAddress); export default bundleDrop;

(PS: We're using the Rinkeby testnet in this guide)

4. 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.ts. In this file we can follow these steps:

Import our module and the necessary library:

import { readFileSync } from 'fs'; import bundleDrop from './getModule';

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. The image we want mint as an NFT can be added to a new folder called assets which we can add inside our scripts folder.

const createNFT = async () => { try { await bundleDrop.createBatch([ { name: 'Early Access', description: 'This NFT will give you early access!', // Get the NFT from a file in our project image: readFileSync('scripts/assets/earlyAccessNft.jpg') } ]); 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: npx ts-node scripts/createNft.ts

And you should see the success message in your console:

Awesome! We have our early access NFT☺️

PS: This is a TypeScript project. Don't forget that you will need a tsconfig.json file - here is documentation where you can find examples.

5. 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 a white-list and adjust other settings. You can see a full example here (look at the 3rd example).

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.ts. Start by importing our module and the necessary library.

import { ethers } from 'ethers'; import bundleDrop from './getModule';

Then we create a function called nftConfig and add the code to create a claim conditions factory which we use to adjust the config of our NFT.

const nftConfig = async () => { const factory = bundleDrop.getClaimConditionFactory(); const claimPhase = factory.newClaimPhase({ startTime: new Date(), maxQuantity: 1000 }); claimPhase.setPrice( // price cannot be set above, use this way instead ethers.utils.parseUnits('0.5'), // use the contract address of the token that we want to be used to purchase the NFTs '<TOKEN_ADDRESS>' ); };

Now we can add the call to our module which will update the claim condition of our NFT. We add it to the nftConfig function so that it now looks like this:

const nftConfig = async () => { const factory = bundleDrop.getClaimConditionFactory(); const claimPhase = factory.newClaimPhase({ startTime: new Date(), maxQuantity: 1000 }); claimPhase.setPrice( // price cannot be set above, use this way instead ethers.utils.parseUnits('0.5'), // use the contract address of the token that we want to be used to purchase the NFTs '<TOKEN_ADDRESS>' ); try { await bundleDrop.setClaimCondition('1', factory); console.log('🎉 Successfully added the claim condition!'); } catch (error) { console.log('Failed to set claim condition. Error: ', error); } // 1 refers to token id }; nftConfig();

In your root directory, run the code with this command in your console: npx ts-node scripts/nftConfig.ts

And you should see the success message in your console:

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

6. Display the NFT with a connect wallet button

We are going to display our NFT with a claim button to allow users to claim an NFT. We also have to offer a connect button for first-time users who have never connected their wallets to our site.

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

npm install @3rdweb/react @3rdweb/hooks

Then we can import all the libraries:

import { useEffect, useState } from 'react'; import { useWeb3 } from '@3rdweb/hooks'; import { ThirdwebSDK } from '@3rdweb/sdk'; import { ConnectWallet } from '@3rdweb/react';

Instantiate the SDK with the bundledrop module address found in the dashboard:

const sdk = new ThirdwebSDK('rinkeby'); const bundleDrop = sdk.getBundleDropModule( '<MODULE_ADDRESS>' );

Create the Nft function and with a useEffect to fetch the NFT using the SDK and the token id (which is found in the dashboard) as a param:

const Nft = () => { // Use state to store the NFT's url const [nft, setNft] = useState(''); async function fetchNft() { try { const nft = await bundleDrop.get('0'); if (nft.metadata.image) { setNft(nft.metadata.image); } } catch (error) { console.log('Failed to get NFT. Error: ', error); } } useEffect(() => { fetchNft(); }, []); return ( <div> <h1>Claim your early access NFT!</h1> <img alt='early access nft' src={nft} width='250px' height='250px' /> </div> ); }; export default Nft;

7. Add a connect wallet button

Before users can claim an NFT, they need to connect their wallets. Thirdweb makes this incredibly easy! We can simply use the ThirdwebProvider context with the ConnectWallet component to make it happen. For all the details, please check out this guide.

After going through that guide, our App.tsx file should look similar to this:

import { ThirdwebProvider } from "@3rdweb/react"; import React from "react"; import "./App.css"; // The config for the thirdweb wallet connect component const supportedChainIds = [1, 4, 137, 250, 43114, 80001]; const connectors = { injected: {}, walletconnect: {}, walletlink: { appName: "early-access", url: "https://thirdweb.com", darkMode: false, }, }; function App() { return ( <ThirdwebProvider connectors={connectors} supportedChainIds={supportedChainIds} > <div className="App"></div> </ThirdwebProvider> ); } export default App;

This context makes adding the WalletConnect component very simple! We only want to display our NFT (and claim button) to users who are connected so in the Nft function in Nft.tsx, we've added some code to do this. There are comments on the lines we added.

const Nft = () => { const [nft, setNft] = useState(""); // If the user is connected, we can get their address const { address } = useWeb3(); async function fetchNft() { try { const nft = await bundleDrop.get("1"); if (nft.metadata.image) { setNft(nft.metadata.image); } } catch (error) { console.log("Failed to get NFT. Error: ", error); } } useEffect(() => { fetchNft(); }, []); // If the user is not connected, we can display the ConnectWallet component. See the guide referenced above for details. if (!address) { return ( <div style={{ margin: "10vh" }}> <h1 style={{ fontSize: "28px", marginBottom: "10vh" }}> Please connect to claim your early access NFT </h1>{" "} <ConnectWallet /> </div> ); } return ( <div> <h1>Claim your early access NFT!</h1> <img alt="early access nft" src={nft} width="250px" height="250px" /> </div> ); }; export default Nft;

8. Add a claim button

Okay. We have our NFT displayed and a connect button. 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 and initialize the module:

import { useState, useEffect } from 'react'; import { ThirdwebSDK } from '@3rdweb/sdk'; import { useWeb3 } from '@3rdweb/hooks'; const sdk = new ThirdwebSDK('rinkeby'); const bundleDrop = sdk.getBundleDropModule( '<MODULE_ADDRESS>' );

Then we can create a function called ClaimButton. Please follow along the comments in the code:

const ClaimButton = () => { // State to track when a user is claiming an NFT const [claiming, setClaiming] = useState(false); // Get provider and then signer from the context const { provider } = useWeb3(); const signer = provider ? provider.getSigner() : undefined; useEffect(() => { if (signer) { sdk.setProviderOrSigner(signer); } }, [signer]); // Claim our NFT with the claim method - (token id, quantity) const onClick = async () => { setClaiming(true); try { await bundleDrop.claim(0, 1); alert("Successfully Claimed!"); setClaiming(false); } catch (error) { console.log("Failed to claim. Error: ", error); setClaiming(false); } }; return ( <button disabled={claiming} style={{ padding: "10px 20px", textAlign: "center", backgroundColor: "#05A266", color: "white", }} className="btn" onClick={onClick} > {claiming ? "Claiming..." : "Claim Early Access NFT"} </button> ); }; export default ClaimButton;

Next Steps

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

Connect Button

Connect Button

Connected and ready to claim

Connected and ready to claim

While claiming the NFT

While claiming the NFT

If you want to take this project further, you can explore how we could use the balanceOf method to check whether or not a user has minted one of our NFTs! Check out our code examples here.


Ready to build your first web3 app? Get early access & add web3 features to your project today.

Mordi Goldstein

Contents

Introduction

Let's begin

1. Create Module

2. Project Set-Up

3. Instantiate the SDK

4. Create the NFT

5. Set NFT Price and Supply

6. Display the NFT with a connect wallet button

7. Add a connect wallet button

8. Add a claim button

Next Steps