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(opens in a new tab) 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(opens in a new tab). For the more visual learners, we highly recommend this excellent Full Modern React Tutorial(opens in a new tab) 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(opens in a new tab).
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(opens in a new tab), 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(opens in a new tab) 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"(opens in a new tab).
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(opens in a new tab) 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(opens in a new tab) 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
(opens in a new tab) - 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>✍️ Description: </h2>34 <input35 type="text"36 placeholder="e.g. Even cooler than cryptokitties ;)"37 onChange={(event) => setDescription(event.target.value)}38 />39 </form>40 <button id="mintButton" onClick={onMintPressed}>41 Mint NFT42 </button>43 <p id="status">{status}</p>44 </div>45)46அனைத்தையும் காட்டு
Finally, let's address where is this Minter component added.
If you go to the App.js
file, which is the main component in React that acts as a container for all other components, you'll see that our Minter component is injected on line 7.
In this tutorial, we'll only be editing the Minter.js file
and adding files in our src
folder.
Now that we understand what we're working with, let's set up our Ethereum wallet!
##: Set up your Ethereum wallet {#set-up-your-ethereum-wallet}
For users to be able to interact with your smart contract they will need to connect their Ethereum wallet to your dapp.
Download MetaMask
For this tutorial, we’ll use MetaMask, a virtual wallet in the browser used to manage your Ethereum account address. If you want to understand more about how transactions on Ethereum work, check out this page.
You can download and create a MetaMask account for free here(opens in a new tab). When you are creating an account, or if you already have an account, make sure to switch over to the “Ropsten Test Network” in the upper right (so that we’re not dealing with real money).
Add ether from a Faucet
In order to mint our NFTs (or sign any transactions on the Ethereum blockchain), we’ll need some fake Eth. To get Eth you can go to the Ropsten faucet(opens in a new tab) and enter your Ropsten account address, then click “Send Ropsten Eth.” You should see Eth in your MetaMask account soon after!
Check your balance
To double check our balance is there, let’s make an eth_getBalance(opens in a new tab) request using Alchemy’s composer tool(opens in a new tab). This will return the amount of Eth in our wallet. After you input your MetaMask account address and click “Send Request”, you should see a response like this:
1{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}2
NOTE: This result is in wei not eth. Wei is used as the smallest denomination of ether. The conversion from wei to eth is: 1 eth = 10¹⁸ wei. So if we convert 0xde0b6b3a7640000 to decimal we get 1*10¹⁸ which equals 1 eth.
Phew! Our fake money is all there!
Connect MetaMask to your UI
Now that our MetaMask wallet is set up, let's connect our dapp to it!
Because we want to prescribe to the MVC(opens in a new tab)