How to mint your own NFT token with react

Overview

Mint your own basic off chain NFT

Description

This project teaches you how to mint your own NFT token. Here are some important packages that we will be using:

hardhat

We will be using hardhat to set up our local blockchain environment to run tests on and mint some NFTs locally.

@openzeppelin/contracts

This package is a collection of Solidity contracts that help us mint NFTs.

ethers

ethers is a typescript friendly package that we will be using to connect to a user's metamask wallet and perform transactions to mint and NFT.

Note: Make sure to have Metamask installed and working.

Stack

We will be using Solidity to write our smart contract, nextjs for some backend needs along with SSR and reactjs on the front end.

Versions

  • npm: 7.10.0
  • node: 16.0.0

Create a basic NFT minting contract

We will start by create a basic NFT minting contract which will console log a message.

  1. Create a directory mkdir minting-an-nft
  2. Create package.json file
npm init -y
  1. Install hardhat
npx hardhat install

Select Create a basic sample project and say Yes to everything. Your console output would look something like this:

npx-hardhat-install

  1. Test hardhat installation by running npx hardhat run ./scripts/sample-script.js

You should see Hello Hardhat printed in your console along with other things:

npx-hardhat-test

  1. Delete contracts/Greeter.sol file. Keep the contracts folder.
  2. Delete scripts/sample-script.js file. Keep the scripts folder.
  3. Delete test/sample-test.js file. Keep the test folder.
  4. Create contracts/MintingContract.sol file and add the content from this gist.
  5. Create scripts/run.js file and add the following content.

Note: see this gist for detailed notes on this script.

process.exit(0)) .catch((error) => { console.error(error); process.exit(1); }); ">
const hre = require("hardhat");

async function main() {
  const contract = await hre.ethers.getContractFactory("MintingContract");
  const token = await contract.deploy();

  await token.deployed();

  console.log("Greeter deployed to:", token.address);
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });
  1. Run the run.js script. The output should contain the console log string and a hash that is the address of the contract. This address will be useful for our frontend.
npx hardhat run ./scripts/run.js

npx-hardhat-run-script-first-time

Start the next app

We need start out next app to create an endpoint which out NFT minting contract can use to general NFT metadata.

  1. Create nextjs app. I called it website.
  1. Navigate to website folder and start dev server.
cd website && yarn dev

The next app should be started on localhost:3000.

  1. Replace the content of website/pages/index.tsx with the following content.

Note: see this gist for detailed notes on this component.

{ const [comments, setComments] = useState (["Initialized"]); const handleAddComment = useCallback((comment: string, ...args: any[]) => { console.log(comment, args); setComments((prevState) => [...prevState, comment]); }, []); useEffect(() => { handleAddComment('Ready to code.'); }, []); return ( ); }; export default Home; ">
import type { NextPage } from "next";
import Head from "next/head";
import { useState, useCallback, useEffect } from "react";

import styles from "../styles/Home.module.css";

const Home: NextPage = () => {
  const [comments, setComments] = useState<string[]>(["Initialized"]);
  const handleAddComment = useCallback((comment: string, ...args: any[]) => {
    console.log(comment, args);
    setComments((prevState) => [...prevState, comment]);
  }, []);

  useEffect(() => {
    handleAddComment('Ready to code.');
  }, []);

  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>
          Welcome to <a href="https://nextjs.org">NFT Minting Example</a>
        </h1>

        <div className={styles.grid}>
          <a href="#" className={styles.card} style={{ width: '100%' }}>
            <h2>Mint Basic NFT</h2>
            <ul>
              {comments.map((comment, index) => (
                <li key={index}>{comment}</li>
              ))}
            </ul>
          </a>
        </div>
      </main>
    </div>
  );
};

export default Home;
  1. Delete website/api/hello.ts file. Keep the folders.
  2. While in website directory, create pages/api/tokens/[id].ts.
mkdir -p "pages/api/tokens" && touch "pages/api/tokens/[id].ts"
  1. Write the following code in the new website/pages/api/tokens[id].ts file.

Note: see this gist for detailed notes on this handler.

import type { NextApiRequest, NextApiResponse } from "next";

async function handler(req: NextApiRequest, res: NextApiResponse) {
  const tokenId = req.query.id as string;

  res.status(200).json({
    image: `https://media.giphy.com/media/X7IoVUJXtO3wk/giphy.gif`,
    name: `Giphy #${tokenId}`,
  });
}

export default handler;
  1. Test the new api/tokens/[id] handler.
curl --location --request GET 'localhost:3000/api/tokens/1'

handler-test

Finish smart contract logic

  1. Replace contracts/MintingContract.sol content with content in this gist.
  2. Replace scripts/run.js content with the following.

Note: see this gist for detailed notes on this script.

process.exit(0)) .catch((error) => { console.error(error); process.exit(1); }); ">
const hre = require("hardhat");

async function main() {
  const contract = await hre.ethers.getContractFactory("MintingContract");
  const token = await contract.deploy('http://localhost:3000/api/tokens/');

  await token.deployed();

  console.log("Greeter deployed to:", token.address);

  let txn = await token.mintBasicNFT();
  await txn.wait();

  txn = await token.mintBasicNFT();
  await txn.wait();
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });
  1. While in root folder. Run the contract.
npx hardhat run ./scripts/run.js

Note: make sure the next app is running, otherwise this script will fail

The output should look something like this.

npx-hardhat-test-2

Deploy Next App to Vercel

Feel free to deploy your next app to hosting service of your choice, I am going to deploy Vercel. Follow this guide to deploy your next app.

My deployment link is https://website-kzspirq6d-ximxim.vercel.app/.

Running curl --location --request GET 'https://website-kzspirq6d-ximxim.vercel.app/api/tokens/1' successfully returns our NFT metadata.

vercel-test

Deploy Smart Contract

We will use Rinkeby test net. This way we don't use real money when deploying.

  1. Create secrets.json file.
> secrets.json ">
echo '{"ALCHEMY_KEY": "", "PRIVATE_KEY": ""}' >> secrets.json
  1. Create an Alchemy Key and place it in secrets.json.
  2. Get Metamask Private Key and place it in secrets.json.

secrets-json

  1. Modify hardhat.config.js and add networks key to default export using our secrets.json file.

Note: see this gist for detailed notes on this script.

{ const accounts = await hre.ethers.getSigners(); for (const account of accounts) { console.log(account.address); } }); module.exports = { solidity: "0.8.4", networks: { rinkeby: { url: secret.ALCHEMY_KEY, accounts: [secret.PRIVATE_KEY], }, } }; ">
const secret = require('./secrets.json');
require("@nomiclabs/hardhat-waffle");

task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
  const accounts = await hre.ethers.getSigners();

  for (const account of accounts) {
    console.log(account.address);
  }
});

module.exports = {
  solidity: "0.8.4",
  networks: {
    rinkeby: {
      url: secret.ALCHEMY_KEY,
      accounts: [secret.PRIVATE_KEY],
    },
  }
};
  1. Create a deploy script.
cp scripts/run.js scripts/deploy.js
  1. Replace http://localhost:3000 in scripts/deploy.js with your vercel url https://website-kzspirq6d-ximxim.vercel.app/

Note: see this gist for detailed notes on this script.

process.exit(0)) .catch((error) => { console.error(error); process.exit(1); }); ">
const hre = require("hardhat");

async function main() {
  const contract = await hre.ethers.getContractFactory("MintingContract");
  const token = await contract.deploy('https://website-kzspirq6d-ximxim.vercel.app/api/tokens/');

  await token.deployed();

  console.log("Greeter deployed to:", token.address);

  let txn = await token.mintBasicNFT();
  await txn.wait();

  txn = await token.mintBasicNFT();
  await txn.wait();
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });
  1. Deploy to rinkeby network.
npx hardhat run --network rinkeby ./scripts/deploy.js

Note: Keep track of the address hash, we will need this to make requests from the frontend.

npx-hardhat-rinkeby

The contract is deployed and an NFT should be minted at this point. Try navigating to this link https://testnets.opensea.io/assets/ /1 .

Also, try https://rinkeby.etherscan.io/address/ .

Finish front end

  1. While in root directory. Copy MintingContract.json from artifacts/contracts to your frontend project.
cp artifacts/contracts/MintingContract.sol/MintingContract.json website/MintingContract.json
  1. Install ethers package.
cd website && npm install ethers
  1. Replace the content of website/pages/index.tsx with the content this gist.

That's all, we have a working DAPP that mints NFTs for us.

You might also like...
Crypt Eye, Your very own personal crypto currancy journal.
Crypt Eye, Your very own personal crypto currancy journal.

Crypt Eye Description Crypt Eye, Your very own personal crypto currancy journal. Patch 1.0 Features: TradingView Powered Chart Widget Stay on top of y

NFT Marketplace prototype using Typescript, WalletConnect, Metamask, Web3, Solidity, React and Storybook

ERC721 NFT Marketplace Prototype of a NFT Marketplace based on openZeppelin abstract upgradeable ERC721 contracts and Minting/uploading images to IPFS

Ethereum nft marketplace template using react

ethereum-marketplace-template ⭐️ Star us If this boilerplate helps you build Ethereum dapps faster - please star this project, every star makes us ver

Ethereum's missing NFT swap library for web3 developers. Written in TypeScript. Powered by 0x.
Ethereum's missing NFT swap library for web3 developers. Written in TypeScript. Powered by 0x.

NFT Swap SDK _The missing NFT swap SDK for Ethereum and EVM compatible chains, powered by the 0x protocol, written in TypeScript for web3 developers.

Youtube Tutorial showcasing how to create a fullstack NFT mingint dapp.
Youtube Tutorial showcasing how to create a fullstack NFT mingint dapp.

Emoji Faces NFT Minting dApp This a complete example of fullstack NFT minting dApp. EmojiFaces is built with the purpose of providing an entry point f

This is a proof of concept of an NFT vending machine built using Solana Pay, Metaplex, Phantom Mobile, and Next.js

Solana NFT Vending Machine This is a proof of concept of an NFT vending machine built using Solana Pay, Metaplex, Phantom Mobile, and Next.js. This wa

A React Custom able cursor that can decorate your site also your hand is open to manipulate the cursor with css

custom-react-cursor A React Custom able cursor that can decorate your site also your hand is open to manipulate the cursor with css Demo live Installi

Live coding in your browser with your favourite language.
Live coding in your browser with your favourite language.

Live coding in your browser with your favourite language.

LocateJS predicts your location by analyzing your connection and system data.

LocateJS predicts your location by analyzing your connection and system data.

Owner
null
This Project is a fork of Ethereum Boilerplate and demonstrates how you can build your own NFT Rarity Ranker.

This Project is a fork of Ethereum Boilerplate and demonstrates how you can build your own NFT Rarity Ranker.

null 85 Aug 28, 2022
React-NFT-App - NFT-Web-Application built using Third web , ReactJs and use Crypto Punks with API

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Ali Aftab Sheikh 7 Aug 17, 2022
Complete token authentication system for react + redux that supports isomorphic rendering.

Simple, secure authentication for react + redux TL;DR - View the Live Demo You can see a complete working example here. The code for the demo is here.

Lynn Dylan Hurley 2.1k Sep 19, 2022
SpaceCoin token liquidity pool

SpaceCoin token liquidity pool

Sunny Vempati 1 Mar 29, 2022
JWT generator - An open-source JSON Web Token (JWT) generator created by enabler

JWT generator An open-source JSON Web Token (JWT) generator created by enabler View Demo · Report Bug JWT generator allows you to generate JWT in an e

Enabler AS 3 May 31, 2022
Write your own version of React. Why? Because you CAN!

Write your own version of React. Why? Because you CAN!

vutr 24 Sep 2, 2022
A guide to building your own React stack, explaining options and tradeoffs along the way

Custom React Stack React has a very rich ecosystem. For anything you want to do, there is probably a library or a framework available for it. That's g

Naresh Bhatia 13 Aug 10, 2022
my-watchlist is a web application for creating your own watchlist.

my-watchlist is a web application for creating your own watchlist. The website tracks your created watchlist, so that you can comeback anytime and pick from where you left.

Ashish Poudel 4 Jun 25, 2022