Mint Your NFT#
Before we dive into coding#
Introduction#
This tutorial aims at making you discover how to code in solidity in order to interact with the blockchain. You are going to learn how to code a Smart Contract, deploy a NFT and mint it in your wallet.
To write this assignment, I was greatly inspired by an article published on freecodecamp. This site is a real gold mine if you want to learn how to code or simply familirize yourself with the computer science world. Every content is free of access and of very good quality, have a look here : https://www.freecodecamp.org/.
đ Disclaimer This tutorial is easily accessible if you are familiar with programming tool. If itâs the first time you hear about terminal, bash, code editor or node.js, you may need to spend a little bit more time reading outside documentations to get familiar with these notions. Along this tutorial I put external links for you to get more information. Itâs not wasted time for you to do so as itâs more and more useful to understand what these tools are used for in our society where computer science takes a growing part in our lives.
Open your crypto wallet#
First we need to open a wallet to store our crypto currency and our digital assets.
There are many wallet provider, but I advice you to open a MetaMak wallet as it is one of the most spread.
đĄ Here is a nice Tutorial to open a MetaMask Ethereum wallet.
Design your avatar#
We are going to code a smart contract hosting a NFT. This NFT will be your âavatarâ for the class. Design an avatar that you will eventually mint as a NFT. It can be whatever you want but it should be a png file.
Download a source code editor#
A source code editor is a software that enables you to open (almost) any type of code file. This will make it possible for you to open, edit and write your own programs.
If you donât already have one I advice you to download VScode or Sublime text. If you are a beginner, you should choose VScode as it provides more hand-holding and is a great option for its debugging functionality.
Here is a tutorial on how to install VScode and Sublime Text.
Install Node.JS on your computer#
We will be using NodeJS for the project.
đĄ If you donât have it installed, follow this simple tutorial : https://phoenixnap.com/kb/install-node-js-npm-on-windows/.
Connect to an Ethereum node with Alchemy#
To interact with the Ethereum Network, you will need to be connected to an Ethereum Node.
Running your own Node and maintaining the infrastructure is a project on its own. Luckily, there are nodes-as-a-service providers which host the infrastructure for you. We will be using Alchemy as our node provider.
â Head over to their website, create an account, choose Ethereum as your network and create your app. You can choose Sepolia as your network. You can also use Goerli although it is in the process of being deprecated. It is recommended to use your dashboard, click âview detailsâ on your app, then click âview keyâ. Save your http key somewhere as we will need that later.
Also, as you noticed, we will be using the Sepolia testnet. Sepolia is a testnet i.e. an instance of Ethereum blockchain used for testing and experimentation without risk to loose real funds or the main chain. That way youâll learn to write smart contracts and mint NFTs without wasting money if you do a mistake using the mainnet.
â To get some Sepolia, go to one of the faucets (e.g. https://sepoliafaucet.com/), connect with your Alchemy account and copy paste your public key.
Deploy your Smart Contract#
Set up your repository#
We are going to use the terminal to create folders and run files throughout the tutorial. If you are not familiar with using your terminal, I suggest you read this article.
Make sure you are in the C:\Users\Name
folder and run this command to create a new directory for your project:
mkdir nft-project # this will create a folder in the root file of your computer
cd nft-project # this will enter the created folder
Now, letâs make another directory, ethereum/
, inside nft-project/
and initialize it with Hardhat. Hardhat is a development environment that makes it easy to deploy and test your Ethereum software.
mkdir ethereum #this will create a new folder within the nft-project one
cd ethereum #this will enter the newly created ethereum folder
npm init # this will "initialize" node.js and create a "package" file in your ethereum folder.
Answer the questions however you want. You can press enter to all of them if you want to keep default features. Then, run those commands to make a Hardhat project:
npm install --save-dev hardhat # install hardhat on your computer, be careful, don't forget the "-" between save and dev otherwise it won't work
npx hardhat init
After waiting a moment, you will see this prompt:
888 888 888 888 888
888 888 888 888 888
888 888 888 888 888
8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888
888 888 "88b 888P" d88" 888 888 "88b "88b 888
888 888 .d888888 888 888 888 888 888 .d888888 888
888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.
888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888
Welcome to Hardhat v2.0.8
? What do you want to do? âŚ
Create a sample project
⯠Create an empty hardhat.config.js
Quit
Select create an empty hardhat.config.js and enter. This will generate an empty hardhat.config.js
file in your ethereum/
folder that we will later update.
Define your environment#
Remember the Alchemy key we grabbed from our test project earlier? We will use that along with our Metamask accountâs public and private keys to interact with the blockchain.
Run the following commands to make a file called .env
inside your ethereum/
directory, and install dotenv. We will use them later.
npm install touch-cli -g #use npm to install the touch package
touch .env #create the .env file
npm install dotenv --save #add a package
Open your .env
file with your code editor and put the following keys:
Alchemycode . key you have exported in the beginning
Private key (follow those instructions to grab your Metamaskâs private key)
Public key (i.e. wallet address)
đ¨ Be extremely careful when handling your private key. Never share it, never copy paste it in a document accessible to any other person than you.
Open the .env file with the code editor of your choice (I personnaly use VS Code, but Sublime text or any other of your choice will fit) and add your keys.
Your .env file should look like this:
API_URL = "YOUR_ALCHEMY_KEY"
PRIVATE_KEY = "YOUR_METAMASK_PRIVATE_KEY"
PUBLIC_KEY = "YOUR_METAMASK_ADDRESS"
For the API_URL, be careful to copy paste the whole URL and not only your key.
Code the file#
Go to the ethereum/
folder and create two more directories: contracts and scripts. A simple hardhat project contains those folders.
contracts/
contains the source files of your contractsscripts/
contains the scripts to deploy and mint our NFTs
mkdir contracts
mkdir scripts
contracts/ is where weâll keep our NFT smart contract code
scripts/ is where weâll keep scripts to deploy and interact with our smart contract
Then, install OpenZeppelin. OpenZeppelin Contract is an open-sourced library with pre-tested reusable code to make smart contract development easier.
npm install @openzeppelin/contracts
Finally, we will be writing the Smart Contract for our NFT. Navigate to your contracts directory and create a file titled avatar.sol
. You can name your NFTs however you see fit.
The .sol
extension refers to the Solidity language, which is what we will use to program our Smart Contract. We will only be writing 14 lines of code with Solidity, so no worries if you havenât seen it before.
Start with this article to learn more about Smart Contract languages. You can also directly jump to this Solidity cheat sheet which contains the main syntax.
cd contracts
touch avatar.sol //create a solidity file
code avatar.sol //opens your file with your default code editor
Open the avatar.sol
file with your code editor and copy paste the following code (this is our Smart Contract):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17; // latest version of solidity
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract avatar is ERC721 {
uint256 private _tokenIdCounter;
constructor() ERC721("avatarname", "NAME") {} //please here replace name and NAME by your real name
function _baseURI() internal pure override returns (string memory) {
return "YOUR_API_URL/api/erc721/"; //here you will replace it later by an URL
}
function mint(address to) public {
uint256 tokenId = _tokenIdCounter;
_safeMint(to, tokenId);
_tokenIdCounter += 1;
}
}
Letâs go through the code and understand what is going on:
At the top of the file, we specified which OpenZeppelin module to import. We need the ERC721 contract as it is the âbaseâ of our Smart Contract. It has already implemented all the methods specified in EIP-721 so we can safely use it. See here for documentation on the different types of smart contracts (token standards) : https://ethereum.org/en/developers/docs/standards/tokens/
A Counter is useful to generate incremental ids for our NFTs. Using the
Counters
library, we define unique IDs for every NFT minted using our smart contract. We named the variable_tokenIdCounter
In the constructor, we initialized our ERC721 with its name and its symbol. I chose avatar and NAME.
We override the default
_baseURI
function by returning our own. We will get to build that in a second.In summary, it is the URL that will be added as âprefixâ to all our tokenURIs. In the above example, the metadata of our NFTs will live in a JSON file at
OUR_API_URL/[api/erc721/](https://e110-99-121-58-31.ngrok.io/api/erc721/)1
.We implement the âmintâ function. It is the function that lets you publish an instance of this Smart Contract on the blockchain. I required the
_tokenIdCounter
variable to be less than 1 as I will only create one instance of my NFT. You can change that if you want to mint more.Finally, inside the mint function, we increment the
_tokenIdCounter
**variable by 1, so in the case you want to mint many NFTs, our id will be 1, followed by 2, followed by 3 etc until the number your put in line 18.Then, we call the function provided by OpenZeppelin
_safeMint
to publish the token.
Web app & metadata#
For the web app, we will use Next.js to initialize a fully-functional web app.
Go back to the root directory nft-project/
and initialize a boilerplate Next.js app called web:
cd .. #command to go back to the previous repository (folder)
mkdir web #create a new repository "web"
cd web #go into that newly created repository
npx create-next-app@latest #create a new app using the default Next.js template
You will be asked to name your project. Feel free to name it however your want. In this tutorial, we will name our project âavatarâ.
Troubleshooting: If the command ânpx create-next-app@latestâ fail to create a new folder, create it manually. Also reject creating /src and App router folders when generating the next app.
Code the metadata#
Metadata is a central pillar of blockchain. It is used to provide additional information or data about an asset that may be useful when trying to complete a transaction with the asset itself. Indeed, our file (our png avatar) canât be stored directly on chain otherwhise it would be insanely costly to run the network as there would be much more data for computers to process. So we need to host it off-chain.
Each NFT will refer to a file stored on the internet and retrieve the file each time it is asked to. ff-line. NFTs usually point to an IPFS (InterPlanetary File System) hash or an HTTP URL somewhere on the Internet. For more information about metadata, read this post.
In our case, we will be building a simple API endpoint which resolve in our NFTâs information as a JSON file.
Our Next.js project gives us a handy way to develop API routes.
Go to the web/
folder, find the api/
folder within the pages/
folder, and make our dynamic [id].js
route in a erc721/
folder.
You can do it by hand or type the following code in your temrinal
cd web
cd avatar
cd pages
cd api
mkdir erc721 //create a new folder called erc721, this is usefull in case you have many different types of contracts
cd erc721
touch [id].js
code [id].js //this command wil open the file with your default code editor
Then open the file with your code editor and code your metadata:
const metadata = {//we add a constant in case we wanted to do a series/collection of many NFTs. This enables to have only 1 JSON file for the metadata of all your NFTs.
0: {
description: "Name's avatar for the Blockchain class", //replace Name by your name
image: "https://i.ibb.co/DC4BPR3/fmex6-avgaei3ue.jpg", // replace with the png or jpg of your avatar !
name: "Name's avatar",//replace Name by your name
}
};
export default function handler(req, res) {
res.status(200).json(metadata[req.query.id] || {});
}
đĄ We are naming the file [id].js
and not 0.js
for instance because we want to give the possibility to create many js files (1 for each NFT we want to mint) in case we wante to create a whole collection of NFT.
As we donât have a server to store our image, we will use a free online host service. I used imgbb but feel free to use anyone you want. However, never upload personal or sensitive image on such servers.
đ¨ To ensure your picture appears on Opensea, itâs crucial to complete the tutorial before the ngrok link expires, typically within an hour.
đ¨ For the sake of this project, I made the code as easily understandable as possible. This is definitely not suited for production, you should add details, maybe properties to your NFT to make it more scarce, give it some properties.
Now, go to /web
directory then /avatar
, and start your Next.js app (be careful to run it in /avatar
and not in /web
otherwise it wonât work):
cd .. //go back to the avatar directory
npm run dev
It may take some time to run.
Your app should be running on localhost:3000. To make sure our endpoint works, go to http://localhost:3000/api/erc721/0 and it should resolve with a JSON object of your first NFTâs metadata.
To stop npm program from running in your terminal, do ctrl + C and enter Y (for Yes).
Publish your metadata#
Since your app is hosted locally, other apps cannot access it. Using a tool like ngrok, we can expose our local host to a publicly accessible URL.
Go to ngrok.com and complete the registration process
Unzip the downloaded package and double click on ngork
A terminal should appear, make sure you cd into the folder where you unzipped your ngrok package (this is very important)
Follow the instruction on your dashboard and run
ngrok authtoken YOUR_AUTH_TOKEN //get your token on ngrok dashboard and copy past it here
Then, run this command to create a tunnel to your web app hosted on localhost:3000
ngrok http 3000
On your terminal, you should see something like this:
ngrok by @inconshreveable (Ctrl+C to quit)
Session Status online
Account YOUR_ACCOUNT (Plan: Free)
Version 2.3.40
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://YOUR_NGROK_ADDRESS -> http://localhost:3000
Forwarding https://YOUR_NGROK_ADDRESS -> http://localhost:3000
Go to https://YOUR_NGROK_ADDRESS/api/erc721/1
to make sure your endpoint works correctly. Note that in the instruction will work solely if you keep running ânpm run devâ
You should see that (same as when you configure your terminal to work with ngrok by adding the ngrok executable to your PATH/api/erc721/1)
Deploy the Smart Contract#
Now that we have done all the ground work, letâs go back to our ethereum/
folder and get ready to deploy our NFT (you can close and reopen your terminal to go faster).
Change the _baseURI
function in your ethreum/contracts/avatar.sol
file **to return your ngrok address.
// ethereum/conrtacts/avatar.sol
contract avatar is ERC721 {
...
function _baseURI() internal pure override returns (string memory) {
return "https://YOUR_NGROK_ADDRESS/api/erc721/";
}
...
}
To deploy our NFT, we will first need to compile it using Hardhat. To make the process easier, we will install ethers.js.
npm install @nomiclabs/hardhat-ethers --save-dev
Now letâs update our hardhat.config.js in our ethereum/
folder:
require("dotenv").config();
require("@nomiclabs/hardhat-ethers");
module.exports = {
solidity: "0.8.17",
defaultNetwork: "sepolia",
networks: {
hardhat: {},
sepolia: {
url: API_URL,
accounts: [`0x${PRIVATE_KEY}`]
}
},
}
Be careful to have the same solidity version as the one of your avatar.sol
file (it might be more recent than â0.8.17â). Note: Remove $ and {} when entering your private key.
To learn more about the hardhat configuration file, take a look at their documentation. We have configured the Sepolia network with our Alchemy URL and provided it with the private key of your metamask account.
Finally, go back to the ethereum/
folder and run:
npx hardhat compile
This lets hardhat generate two files per compiled contract. We should see a newly created artifacts/
folder that contains your compiled contracts in the contracts/
folder. To learn more about how that works, read this tutorial by the Hardhat team.
Now, letâs write a script to finally deploy our NFT to the test network. In your scripts/
folder, create a file called deploy.js
.
async function main() {
const Avatar = await ethers.getContractFactory("avatar")
const avatar = await Avatar.deploy()
await avatar.deployed()
console.log("Contract deployed to address:", avatar.address)
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error)
process.exit(1)
})
This code is inspired by the hardhat deployment tutorial.
A ContractFactory
in ethers.js is an abstraction used to deploy new smart contracts, so avatar
here is a factory for instances of our token contract. Calling deploy()
on a ContractFactory
will start the deployment, and return a Promise
that resolves to a Contract
. This is the object that has a method for each of your smart contract functions.
In your terminal, go to the /ethereum
folder and run the deployment script:
npx hardhat --network sepolia run scripts/deploy.js
You should see in your terminal avatar deployed: SOME_ADDRESS
. This is the address where your Smart Contract is deployed on the Sepolia test network.
Keep this adress closely as we will need it for the mint.
View the Smart Contract on the blockchain#
If you head over to https://sepolia.etherscan.io/address/SOME_ADDRESS
, you should see your freshly deployed Smart Contract.
You can also access it by copy pasting your MetaMask Wallet address.
Mint your NFT#
Code the mint.js file#
Now that you have deployed your NFT, itâs time to mint it for yourself! Create a new file called mint.js
in your /scripts
folder. We will be using ethers.js to help us.
cd scripts //go to the scripts folder
touch mint.js //create a mint.js file
npm install --save ethers //add the ether.js package
code mint.js //open the file with your code editor
Then, in the mint.js file, code the following:
require("dotenv").config();
const { ethers } = require("ethers");
const contract = require("../artifacts/contracts/avatar.sol/avatar.json");
const contractInterface = contract.abi;
// https://docs.ethers.io/v5/api/providers
const provider = ethers.getDefaultProvider("sepolia", {
alchemy: process.env.API_URL,
});
// https://docs.ethers.io/v5/api/signer/#Wallet
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
//https://docs.ethers.io/v5/api/contract/contract
const Avatar = new ethers.Contract(
"YOUR_NFT_ADDRESS", // replace by the NFT adresse given by the last step (adress of the smart contract)
contractInterface,
wallet
);
const main = () => {
Avatar
.mint(process.env.PUBLIC_KEY)
.then((transaction) => console.log(transaction))
.catch((e) => console.log("something went wrong", e));
};
main();
Some comments to where you can find more information about the different methods:
We first grab the contractâs interface (ABI). From ethereum.org: An application binary interface, or ABI, is the standard way to interact with contracts. Your ABI defines how others interact with your contract. Then, we created our provider with Alchemy (remember about node-as-a-service). Finally, we initialize our wallet with our private key.
The
main()
function calls themint
method in the Smart Contract we had just deployed. Themint
method takes only one parameter,to
, which indicate the receiver of the token. Since we are minting for ourself, we put the public address of our Metamask account.
Now run in your ethereum folder:
node scripts/mint.js
Troubleshooting: If you run into an error message, check the following thread. Note that the issue should not prevent you from minting your NFT.
If everything goes well, after a couple of seconds, you should see a response like this in your terminal:
The hash of your transaction is: xxxxxxxxxxxxxxxxx // a long hash
Check Alchemy's Mempool to view the status of your transaction!
Grab the hash
property and go to https://sepolia.etherscan.io/tx/YOUR_HASH
. You should see the minting transaction there!
View the NFT in your wallet#
First dowload the mobile version of Metamask.
Then, log into your account. You should see an NFTs tab along with an add NFT button.
Click on the button and enter the address of your Smart Contract along with the ids that you have minted. In our case, we only minter 1 NFT so id should be 1
.
Further content to get more familiar with solidity#
If you want to go further into learning Solidity, there is a very nice tutorial named cryptozombies. This will drive you step by step to Code Blockchain DApps by Building Simple Games.