NFT Minter Tutorial
One of the greatest challenges for developers coming from a Web2 background is figuring out how to connect your smart contract to a frontend project and interact with it.
By building an NFT minter — a simple UI where you can input a link to your digital asset, a title, and a description — you'll learn how to:
- Connect to MetaMask via your frontend project
- Call smart contract methods from your frontend
- Sign transactions using MetaMask
In this tutorial, we will be using React as our frontend framework. Because this tutorial is primarily focused on Web3 development, we won't be spending much time breaking down React fundamentals. Instead, we'll be focusing on bringing functionality to our project.
As a prerequisite, you should have a beginner-level understanding of React—know how components, props, useState/useEffect, and basic function calling works. If you've never heard of any of those terms before, you may want to check out this Intro to React tutorial. For the more visual learners, we highly recommend this excellent Full Modern React Tutorial video series by Net Ninja.
And if you haven't already, you'll definitely need an Alchemy account to complete this tutorial as well as build anything on the blockchain. Sign up for a free account here.
Without further ado, let's get started!
Making NFTs 101
Before we even start looking at any code, it's important to understand how making an NFT works. It involves two steps:
Publish an NFT smart contract on the Ethereum blockchain
The biggest difference between the two NFT smart contract standards is that ERC-1155 is a multi-token standard and includes batch functionality, whereas with the ERC-721 is a single-token standard and therefore only supports transferring one token at a time.
Call the minting function
Usually, this minting function requires you to pass in two variables as parameters, first the recipient
, which specifies the address that will receive your freshly minted NFT, and second the NFT's tokenURI
, a string that resolves to a JSON document describing the NFT's metadata.
An NFT's metadata is really what brings it to life, allowing it to have properties, such as a name, description, image (or different digital asset), and other attributes. Here's an example of a tokenURI, which contains an NFT's metadata.
In this tutorial, we're going to focus on part 2, calling an existing NFT's smart contract minting function using our React UI.
Here's a link to the ERC-721 NFT smart contract we will be calling in this tutorial. If you'd like to learn how we made it, we highly recommend that you check out our other tutorial, "How to Create an NFT".
Cool, now that we understand how making an NFT works, let's clone our starter files!
Clone the starter files
First, go to the nft-minter-tutorial GitHub repository to get the starter files for this project. Clone this repository into your local environment.=
When you open this cloned nft-minter-tutorial
repository, you'll notice that it contains two folders: minter-starter-files
and nft-minter
.
minter-starter-files
contains the starter files (essentially the React UI) for this project. In this tutorial, we will be working in this directory, as you learn how to bring this UI to life by connecting it to your Ethereum wallet and an NFT smart contract.nft-minter
contains the entire completed tutorial and is there for you as a reference if you get stuck.
Next, open your copy of minter-starter-files
in your code editor, and then navigate into your src
folder.
All of the code we'll write will live under the src
folder. We'll be editing the Minter.js
component and writing additional javascript files to give our project Web3 functionality.
Step 2: Check out our starter files
Before we start coding, it's important to check out what's already provided for us in the starter files.
Get your react project running
Let's start by running the React project in our browser. The beauty of React is that once we have our project running in our browser, any changes we save will be updated live in our browser.
To get the project running, navigate to the root directory of the minter-starter-files
folder, and the run npm install
in your terminal to install the dependencies of the project:
cd minter-starter-filesnpm install
Once those have finished installing, run npm start
in your terminal:
npm start
Doing so should open http://localhost:3000/ in your browser, where you'll see the frontend for our project. It should consist of 3 fields: a place to input a link to your NFT's asset, enter the name of your NFT, and provide a description.
If you try clicking "Connect Wallet" or "Mint NFT" buttons, you'll notice they don't work—that's because we still need to program their functionality! :)
The Minter.js component
NOTE: Make sure you're in the minter-starter-files
folder and not the nft-minter
folder!
Let's go back into the src
folder in our editor and open the Minter.js
file. It's super important that we understand everything in this file, as it is the primary React component we will be working on.
At the top of our this file, we have our state variables that we will update after specific events.
1//State variables2const [walletAddress, setWallet] = useState("")3const [status, setStatus] = useState("")4const [name, setName] = useState("")5const [description, setDescription] = useState("")6const [url, setURL] = useState("")7
Never heard of React state variables or state hooks? Check out these docs.
Here's what each of the variables represent:
walletAddress
- a string that stores the user's wallet addressstatus
- a string that contains a message to display at the bottom of the UIname
- a string that stores the NFT's namedescription
- a string that stores the NFT's descriptionurl
- a string that is a link to the NFT's digital asset
After the state variables, you'll see three un-implemented functions: useEffect
, connectWalletPressed
, and onMintPressed
. You'll notice that all of these functions are async
, that's because we will be making asynchronous API calls in them! Their names are eponymous with their functionalities:
1useEffect(async () => {2 //TODO: implement3}, [])45const connectWalletPressed = async () => {6 //TODO: implement7}89const onMintPressed = async () => {10 //TODO: implement11}12Показати все
useEffect
- this is a React hook that is called after your component is rendered. Because it has an empty array[]
prop passed into it (see line 3), it will only be called on the component's first render. Here we'll call our wallet listener and another wallet function to update our UI to reflect whether a wallet is already connected.connectWalletPressed
- this function will be called to connect the user's MetaMask wallet to our dapp.onMintPressed
- this function will be called to mint the user's NFT.
Near the end of this file, we have the UI of our component. If you scan this code carefully, you'll notice that we update our url
, name
, and description
state variables when the input in their corresponding text fields change.
You'll also see that connectWalletPressed
and onMintPressed
are called when the buttons with IDs mintButton
and walletButton
are clicked respectively.
1//the UI of our component2return (3 <div className="Minter">4 <button id="walletButton" onClick={connectWalletPressed}>5 {walletAddress.length > 0 ? (6 "Connected: " +7 String(walletAddress).substring(0, 6) +8 "..." +9 String(walletAddress).substring(38)10 ) : (11 <span>Connect Wallet</span>12 )}13 </button>1415 <br></br>16 <h1 id="title">🧙♂️ Alchemy NFT Minter</h1>17 <p>18 Simply add your asset's link, name, and description, then press "Mint."19 </p>20 <form>21 <h2>🖼 Link to asset: </h2>22 <input23 type="text"24 placeholder="e.g. https://gateway.pinata.cloud/ipfs/<hash>"25 onChange={(event) => setURL(event.target.value)}26 />27 <h2>🤔 Name: </h2>28 <input29 type="text"30 placeholder="e.g. My first NFT!"31 onChange={(event) => setName(event.target.value)}32 />33 <h2>