How To Build A Classic Web3 NFT Minting Dapp with React and Solidity: Part 1
Tags: solidity, web3, react, decentralizedweb
Published: 2022-04-01 15:57:00

What you will be building, see the [live demo](https://adulam-nft.web.app/) and [GitHub repo](https://github.com/Daltonic/adulamNFT) for more info, don’t forget to star the project.

![Adulam](https://paper-attachments.dropbox.com/s_B943DEA2D9DE04F4E6769C58A5163AA00E6F7443D4974DFEA284EED252598331_1648809570346_adulam-nft.gif)

## Introduction

The world of software development as you know it has changed and so is the demand for new skills. The Web3 revolution has come to stay with exponential growths recorded in various sectors of software development.

Web3 skills are being demanded by various tech companies, groups, and teams who are on the mission to create Web3 solutions for the ever-growing demands of users.

All these developments indicate that you need to jump into the decentralized-web space and equip yourself with the in-demand skills to stay relevant in the tech world.

I want to help you enter, learn, and profit from this Web3 space and we will do that one build at a time.

In this tutorial, you will learn the following;


- How to set up an Error-free Web3 project.
- How to code an NFT minting smart contract.
- How to code the frontend for NFT minting with Tailwind CSS.
- How to use Truffle and Ganache CLI for blockchain development.
- How to Deploy a Smart Contract.
- How to Write Tests for your Smart Contracts.
- How to Write Scripts for your Smart Contracts.
- Lot’s more…

Stay pumped, because we’re in for a snippet ride…

[Watch my FREE web3 tutorials on Youtube now](https://www.youtube.com/channel/UCQteXYZ5mC-cuTxplzM4Hlw?sub_confirmation=1).


## Prerequisite

You will need the following for crushing this tutorial;

- [NodeJs](https://nodejs.org/en/download/) installed on your machine.
- [Yarn package manager](https://classic.yarnpkg.com/en/docs/install#windows-stable) installed.
- [Truffle](https://trufflesuite.com/docs/truffle/getting-started/installation.html) installed.
- [Ganache-CLI](https://docs.nethereum.com/en/latest/ethereum-and-clients/ganache-cli/) installed.
- And an unbending attitude to learn Web3.

There aren’t so many lessons out there to properly walk you through this thick world of Web3. I will soon be releasing some courses to help you profit as a blockchain developer, so watch out. **[You can also contact me for lessons…](https://daltonic.github.io)**


## Installing App Dependencies

To save you time and painful experiences of configuring a Web3 project, I’ve prepared you a [starter kit on my git repo](https://github.com/Daltonic/tailwind_truffle_starter_kit). Clone and install the dependencies with the instructions below. Please don’t forget to leave a star on the project.

On your terminal, navigate to the location of your project and run the code below:


    # Make sure you have the above prerequisites installed already!
    git clone https://github.com/Daltonic/truffle-starter-kit.git adulamNFT
    cd adulamNFT # Navigate to the new folder.
    yarn install # Installs all the dependencies.

Freely recommending, please use [**vs code**](https://code.visualstudio.com/download) for the tutorial, it has all you will need for coding.

If you’re done with that, let’s proceed to the next step…


## Coding the Smart Contract

Open the project in **VS code**, head on to the **src >> contracts** directory, you will see an existing contract named **Migration.sol**.

Create a new solidity contract named **Adulam.sol**. Inside of the file, define the following structures.


    // SPDX-License-Identifier: MIT
    pragma solidity >=0.7.0 <0.9.0;
    import "./ERC721.sol";
    import "./ERC721Enumerable.sol";
    import "@openzeppelin/contracts/access/Ownable.sol";
    
    contract Adulam is ERC721Enumerable, Ownable {
      // Codes goes here
    }

We are using a particular ERC721 version for our smart contract, let’s say it favors us over the newer versions.

The code snippet above describes a smart contract that inherited some attributes, properties, and methods from ERC721. The ERC721 is a smart contract standard for writing NFT based smart contracts.

Note: In solidity, declaring a smart contract in your code is like declaring a class, they are just similar, so your object-oriented programming skills could give you an added advantage.

Let’s proceed with the rest of the smart contract…


    // Defining essential variables...
    using Strings for uint256;
    mapping(string => uint8) public existingURIs;
    uint256 public cost = 0.01 ether;
    uint256 public maxSupply = 100;
    uint256 public supply;
    string public baseURI;

We make sure that a uint256 variable can call up a function in the string library. Next, we created an existingURIs variable that returns 0 or 1 when an NFT URI is passed into it.

We use the cost variable for setting up the sales price of our NFT, while maxSupply indicates the total number of NFTs available for minting.

Lastly, the supply variable will track the number of NFTs minted and baseURI tracks the location of our NFT folder on IPFS.


    // Sales event structure
    event Sale(
        uint256 id,
        address indexed from,
        address indexed to,
        uint256 cost,
        string metadataURI,
        uint256 timestamp
    );

The code block above describes the information that will be logged to the client on each mint or sale of NFT art.

It will keep track of the tokenId, the buyer and seller addresses, the cost of the NFT, the URI of the artwork, and also the time at which the NFT was purchased.


    // The sales object of an NFT
    struct SaleStruct {
        uint256 id;
        address from;
        address to;
        uint256 cost;
        string title;
        string description;
        uint256 timestamp;
    }
    SaleStruct[] minted;

This struct seems almost like interfaces on TypeScript. The job of this struct is to help us define complex datatypes where one datatype is insufficient to describe our data.

If you observe the SaleStruct above, you’ll discover that it has multiple data types in it such as uint256, address, and string. Solidity makes combining data super easy through the use of structs.


    constructor(
        string memory _name,
        string memory _symbol,
        string memory _baseURI
    ) ERC721(_name, _symbol) {
        supply = totalSupply();
        baseURI = _baseURI;
    }

Now, this is the constructor function set up for your soon-to-be-deployed smart contract. You should be aware that any information supplied here will be taken into the blockchain network. If your smart contract is not designed to be updateable, incorrect data will be irreversible.


    function payToMint(
        string memory title,
        string memory description
        ) public payable {
        // Specifies criteria for minting NFTs
        require(supply <= maxSupply, "Sorry, all NFTs have been minted!");
        require(msg.value > 0 ether, "Ether too low for minting!");
        require(msg.sender != owner(), "This is not permitted!");
        
        // Defines critical math operations
        supply += 1;
        string memory URI = concat(Strings.toString(supply + 1));
        existingURIs[URI] = 1;
        sendMoneyTo(owner(), msg.value);
        
        // Saves minted NFT in an array
        minted.push(
            SaleStruct(
                supply,
                msg.sender,
                owner(),
                msg.value,
                title,
                description,
                block.timestamp
            )
        );
        
        // Logs out NFT sales information
        emit Sale(
            supply,
            msg.sender,
            owner(),
            msg.value,
            URI,
            block.timestamp);
        
        // Mint the NFT with the ERC721 safeMint method
        _safeMint(msg.sender, supply);
    }

This payToMint method is responsible for basically five things, which include;


- Receiving NFT details from the front end and pass them to the smart contract.
- Checking if all criteria for minting NFTs are met.
- Performing mathematical operations including sending the minting money to the deployer.
- Including the NFT in the minted array for further references.
- Logging the sales details to the client and also recording them on the ethereum network.
- Minting the NFT using the ERC721 inherited **_safeMint** method.


    // returns all minted NFTs
    function getAllNFTs() public view returns (SaleStruct[] memory) {
        return minted;
    }

Currently, the array variable we declared earlier on is keeping track of all minted NFTs. We prepared this method for retrieving all the minted NFTs from the smart contract when we’ll be consuming them on React.


    function getAnNFTs(
        uint256 tokenId
        ) public view returns (SaleStruct memory) {
        return minted[tokenId - 1];
    }

This method returns a particular NFT object when called. It fetches the NFT by specifying its tokenId. Since arrays start their indexes from 0, we have to subtract 1 from the tokenId to get the exact NFT we want.


    function concat(
        string memory str
        ) internal view returns (string memory) {
        return string(abi.encodePacked(baseURI, "", str));
    }

This is an internal method which means it’s only accessible within this particular smart contract. We use this method to join the tokenId with the baseURI. This is done this way so that each NFT can point to their exact location on the IPFS folder sitting somewhere online.


    function sendMoneyTo(address to, uint256 amount) internal {
        (bool success1, ) = payable(to).call{value: amount}("");
        require(success1);
    }

Lastly, this is another internal method callable by this smart contract alone. It has to send ethers to a specified address. This is the function that ensures that the money used for purchasing an NFT is sent to the owner of the NFT or in this case the deployer.

That’s all the codes we will need for our smart contract, here is the full code snippet.


{% gist https://gist.github.com/Daltonic/54d57646044fe2a4eed3b23a8e0e4a68 %}


Now that we’ve coded our smart contract we need to test it to ensure that it’s bug-free and performs the task we created it for.


## Setting up the Migration File

Let's create the migration script in the **migrations** folder before we start testing the smart contract.

![Migrations Folder](https://paper-attachments.dropbox.com/s_B943DEA2D9DE04F4E6769C58A5163AA00E6F7443D4974DFEA284EED252598331_1648819702869_screenshoteasy+27.png)


Head to the migrations folder and create a new file called **2_deploy_contracts.js**. Paste the following codes inside the *2_deploy_contracts.js* file.


    const Adulam = artifacts.require('Adulam')
    module.exports = async function (deployer) {
      const BASEURI = `https://bafybeidfpvjszubegtoomoknmc7zcqnay7noteadbwxktw46guhdeqohrm.ipfs.infura-ipfs.io/`
      await deployer.deploy(Adulam, 'Adulam', 'ADU', BASEURI)
    }
    

That configuration will do it. And… yes, you can use my NFT art collection IPFS URI.

## Testing the Smart Contract

Start Ganache and make sure it's up and running. Run the command below on the terminal.


    npm install -g ganache-cli #Skip if already installed 
    ganache-cli -a #spins up the blockchain server
![](https://paper-attachments.dropbox.com/s_B943DEA2D9DE04F4E6769C58A5163AA00E6F7443D4974DFEA284EED252598331_1648823004482_Screenshot+257.png)


Next, locate the **test** folder and create a file called **Adulam.test.js**.

Paste the code snippet inside of it.

{% gist https://gist.github.com/Daltonic/75b2b7c959f8cca8821e96756538cce0 %}


Now run the test script using the command below.


    truffle test

The result should look this one below.


![Test Cases](https://paper-attachments.dropbox.com/s_B943DEA2D9DE04F4E6769C58A5163AA00E6F7443D4974DFEA284EED252598331_1648821044947_Screenshot+258.png)


The prior test is intended to ensure that our smart contract can sell NFTs. Writing a script to interact with your smart contract is an extra precaution to ensure that it runs properly. Let's get started.

## Interacting with the Smart Contract

This is the most effective method for validating the functionality of your smart contract. We'd like to create a script that simulates the sales process.

Head to the **scripts folder** and create a file called **BuyNFT.js**. Next, paste the following codes inside of it.


{% gist https://gist.github.com/Daltonic/c688849c9ab81bc21bd2537ca169e368 %}


Terrific, now run the following command on the terminal after you've created and pasted the codes above. Please ensure that your ganache-CLI is still operational before running the code below.


    truffle migrate --reset


![](https://paper-attachments.dropbox.com/s_B943DEA2D9DE04F4E6769C58A5163AA00E6F7443D4974DFEA284EED252598331_1648823165520_Screenshot+255.png)


Observe the following result on your terminal.

If you've made it this far, congratulations! Let's run the BuyNFT script by typing this code into the terminal.


    truffle exec scripts/BuyNFT.js

You should have the minting process play out on the terminal…

We can be happy that our smart contract is functional. Let’s deploy it to the **rinkeby test net**.

**Deploying to Alchemy**

![Alchemy Blockchain Development and Deployment](https://res.cloudinary.com/practicaldev/image/fetch/s--I9yVl3N7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_80FE02C51945E8808FE82A228922BC93294E036898C1D5C62FBCFC631D57D794_1642323006875_screenshoteasy%2B19.png)


At the moment, our smart contract can only run on our computer, and no one else can connect to it. We will use alchemy to make it available to everyone at no cost.
Sign up with them now, or [**log in**](https://auth.alchemyapi.io/?redirectUrl=https%3A%2F%2Fdashboard.alchemyapi.io) if you already have an account.

![Authentication Page](https://res.cloudinary.com/practicaldev/image/fetch/s--MYXhSZhY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_80FE02C51945E8808FE82A228922BC93294E036898C1D5C62FBCFC631D57D794_1642323341163_screenshoteasy%2B20.png)


When you log in, you will see the dashboard page, which allows you to create a new blockchain application.

![Alchemy Dashboard](https://res.cloudinary.com/practicaldev/image/fetch/s--bXG7t98Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_80FE02C51945E8808FE82A228922BC93294E036898C1D5C62FBCFC631D57D794_1642323555226_screenshoteasy%2B22.png)


**Creating an Alchemy App**
Click on the **CREATE APP** button and enter the information shown in the image below, making sure to include the **Rinkeby test** network.

![Create New App Popup](https://paper-attachments.dropbox.com/s_B943DEA2D9DE04F4E6769C58A5163AA00E6F7443D4974DFEA284EED252598331_1648824765601_screenshoteasy+17.png)


After you've created the app, you can view its information by clicking on the app's name or the view the details button.

![Created App](https://paper-attachments.dropbox.com/s_B943DEA2D9DE04F4E6769C58A5163AA00E6F7443D4974DFEA284EED252598331_1648824868951_screenshoteasy+28.png)


Copy the **WSS URL** as shown in the image below by clicking on the **VIEW KEY** button.

![Web Socket Endpoint](https://res.cloudinary.com/practicaldev/image/fetch/s--nddNAv6u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_D720F64E38BC9DEB85A924EA9228240E9E0724DBBDD5C2A1518C2F4F4FE8CAB0_1648042628712_screenshoteasy%2B31.png)


Amazing, now proceed as shown in the images below to obtain your **Rinkeby** account. Please keep in mind that we are not using the regular account address, but rather the private key to that account.

![Step One](https://res.cloudinary.com/practicaldev/image/fetch/s--lcixkq3L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_80FE02C51945E8808FE82A228922BC93294E036898C1D5C62FBCFC631D57D794_1642325264360_Screenshot%2B244.png)

![Step Two](https://res.cloudinary.com/practicaldev/image/fetch/s--D0Bk5OE8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_80FE02C51945E8808FE82A228922BC93294E036898C1D5C62FBCFC631D57D794_1642325264934_Screenshot%2B246.png)

![Step Three](https://res.cloudinary.com/practicaldev/image/fetch/s--42VQJ0Rj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_80FE02C51945E8808FE82A228922BC93294E036898C1D5C62FBCFC631D57D794_1642325264802_Screenshot%2B245.png)

![Step Four](https://res.cloudinary.com/practicaldev/image/fetch/s--eKgsEsB_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_80FE02C51945E8808FE82A228922BC93294E036898C1D5C62FBCFC631D57D794_1642325264304_Screenshot%2B247.png)

    ENDPOINT_URL=<YOUR_ALCHEMY_WSS_URL>
    SECRET_KEY=<YOUR_METAMASK_SECRET_PHRASE>
    DEPLOYER_KEY=<YOUR_METAMASK_PRIVATE_KEY>

Please do not use your real **Metamask details**; these keys must be kept secret. That's why we put them in the environment file and tell git to ignore them.

After you've entered the above keys into their respective variables, execute the commands below.


    truffle migrate --reset --network rinkeby

As we can see below, your smart contract will be deployed on the Rinkeby test net.

![Compiling Smart Contract](https://res.cloudinary.com/practicaldev/image/fetch/s--w_ehk16_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_D720F64E38BC9DEB85A924EA9228240E9E0724DBBDD5C2A1518C2F4F4FE8CAB0_1648044203469_Screenshot%2B256.png)


You've worked extremely hard to get to this point. You've just completed the deployment of an appealing smart contract to the Ethereum blockchain network. In [PART TWO](https://dev.to/daltonic/how-to-build-a-classic-web3-nft-minting-dapp-with-react-and-solidity-part-2-59la) of this tutorial, we'll connect it to a ReactJs frontend.

[Check out my YouTube channel for FREE web3 tutorials now](https://www.youtube.com/channel/UCQteXYZ5mC-cuTxplzM4Hlw?sub_confirmation=1).


## Conclusion

What a grind, hope this tutorial provided you with much value, I’m currently preparing some courses around these various blockchain use-cases. Please send me a private note if you will like to learn from me.

The Web3 industry is booming, but there aren’t enough guides that know this stuff to help you. You will have to do a lot of path clearing before you can make a road for yourself. Luckily, you don’t have to do all that yourself, you can [reach out to me](https://daltonic.github.io/) for a personal tutoring session. It's currently limited to only a small portion of students.

Till next time!


## About the Author

Gospel Darlington kick-started his journey as a software engineer in 2016. Over the years, he has grown full-blown skills in JavaScript stacks such as React, ReactNative, VueJs, and now blockchain.

He is currently freelancing, building apps for clients, and writing technical tutorials teaching others how to do what he does.

Gospel Darlington is open and available to hear from you. You can reach him on [LinkedIn](https://www.linkedin.com/in/darlington-gospel-aa626b125/), [Facebook](https://www.facebook.com/darlington.gospel01), [Github](https://github.com/Daltonic), or on his [website](https://daltonic.github.io/).