Updated on March 18, 2022
How to mint an NFT on the Palm network using Hardhat
This guide walks you through minting an NFT on the Palm network using Hardhat
Important
This article is a follow-up to: “Deploy an NFT contract using Hardhat”. You’ll probably want to read this first before applying the below.
The previous article in this series: “Deploy an NFT contract using Hardhat”, describes how to deploy an ERC-721
smart contract on the Palm network. The below goes further and proposes one way to publish an ERC-721
token on the Palm network, or, in simpler terms, minting an NFT.
Prerequisite
- Reading and applying: “Deploy an NFT contract using Hardhat”.
What our code will do
Note
The complete source code explained in this article is available for download.
We are about to write the code logic that triggers a ‘minting’ transaction. Let’s take a quick look at what minting means in the context of the contract we deployed:
function mintNFT(address recipient, string memory tokenURI)
public
returns (uint256)
{
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_safeMint(recipient, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
This is what our solidity code’s mintNFT
function does:
-
_tokenIds.increment();
: ‘_tokenIds’ inherits from Open Zeppelin’s counter functions,’increment()’. It will increase a counter by 1, thus enabling our code to generate a unique Token ID, -
uint256 newItemId = _tokenIds.current();
: assigns the current count number to a new instance of _’tokenIds’ named ‘newItemId’ -
_safeMint(recipient, newItemId);
: mints ‘newItemId’ and assigns it to ‘recipient’ (an address). -
_setTokenURI(newItemId, tokenURI);
: sets ‘tokenURI’ as the URI of our NFT’s metadata file, we’ll explain what an NFT’s metadata file is later in this article.
In short, the above code will send a transaction that will transfer a unique NFT instance to a particular Ethereum address.
The following explains how to write a script that calls the minting function in the contract we deployed earlier:
Steps
-
Create a
mint.js
file:Inside your scripts directory, create a
mint.js
file.We will use the Hardhat-flavored version of the
ethers.js
library, which provides more abstractions thanweb3.js
, resulting in leaner code.Let’s start by requiring the correct libraries:
require("dotenv").config(); require("@nomiclabs/hardhat-ethers");
-
Create a variable representing your contract’s
ABI
:Our contract’s ABI (Application Binary Interface) is the interface enabling our js script to interact with our smart contract. Hardhat generates and stores the ABI version of our contract in the
artifacts
folder as a JSON file.Add the following to
mint.js
:const contract = require("../artifacts/contracts/NFT.sol/NFT.json"); const contractInterface = contract.abi;
-
Add a provider:
In
Ethers.js
parlance, a provider represents a connection to an Ethereum blockchain. We’ll add one to enable your app to interact with the Palm network. In this scenario, because we’re using the Hardhat plugin version of Ethers.js, ourethers.provider
object retrieves all the connection details fromhardhat.config.js
.Add this line to
mint.js
:let provider = ethers.provider;
-
Upload a media file to IPFS:
This step consists of adding a media file of your choice to IPFS, the decentralized storage system. In order to help ensure this file’s availability, you can “pin” the file in IPFS. There are several pinning services available that will maintain your file on IPFS. Here are a few:
Here we’ll use NFT Storage. Simply log into NFT Storage’s website, upload your file and save its
URI
, you’ll need it in the next step: -
Create your NFT’s Metadata file:
An NFT Metadata file serves as a descriptor for the media file your NFT represents. It enables you to specify the NFT’s name,
URI
, and other attributes. The Metadata file is aJSON
document, and in this article, we’ll implement the ERC721 Metadata JSON Schema.In the root directory, create a new file called
nft-metadata.json
, edit the followingJSON
code to match your NFT’s specifications. Now would be the time to add theURI
of the image you saved in step 4.{ description: "pfp", image: "URI-of-profile-picture", name: "pfp #123", attributes: [ { trait_type: "Background", value: "White" }, { trait_type: "Hair Style", value: "Long Straight Bangs" }, { trait_type: "Hair Color", value: "Black" }, { trait_type: "Accessories", value: "" } ] }
Upload
nft-metadata.json
to NFT Storage, then copy itsURI
and add it to thetokenURI
variable.const tokenURI = "<`URI` of your metadata file>";
The variable we just declared,
tokenURI
will be passed as an argument to the contract’smintNFT
function. -
Update your
.env
file:Add your public key to a
PUBLIC_KEY
variable in your.env
file:PUBLIC_KEY = "your-account-address"
Get the address of the contract you deployed earlier (it is the address returned by Hardhat upon deployment) and create a
.env
variable pointing to that address:```bash `CONTRACT_ADDRESS = "deployed-contract-address"` ```
If you followed the instructions in the previous article, your
.env
file should now contain the following variables:API_URL = "your-provider-api-url" PRIVATE_KEY = "your-private-account-address" PUBLIC_KEY = "your-public-account-address" CONTRACT_ADDRESS = "deployed-contract-address"
-
Set up
Ethers.js
signer and walletThe wallet is a convenient class in
Ethers.js
, it represents an Ethereum account and enables one to sign transactions and messages like an EOA would.Add the following to
mint.js
:const privateKey = `0x${process.env.PRIVATE_KEY}`; const wallet = new ethers.Wallet(privateKey); wallet.provider = provider; const signer = wallet.connect(provider);
-
Set up
Ethers.js
contractAn
Ethers.js
contract is a representation of the actual contract that has been deployed. This class enables you to interact with your contract using javascript. You can send it a transaction; in this case, we will use it to trigger ourMintNFT
function.Add these lines of code to
mint.js
:const nft = new ethers.Contract( process.env.CONTRACT_ADDRESS, contractInterface, signer );
-
Build the
main
functionFinally, create the
main
function, which will asynchronously call theMintNFT
function passing as arguments:-
Your address (or any other recipient address you chose)
-
The
URI
of your NFT’s metadata
Your
mint.js
file should now look like this:require("dotenv").config(); require("@nomiclabs/hardhat-ethers"); const contract = require("../artifacts/contracts/NFT.sol/NFT.json"); const contractInterface = contract.abi; // https://hardhat.org/plugins/nomiclabs-hardhat-ethers.html#provider-object let provider = ethers.provider; const tokenURI = "https://bafkreifvtwuiypleu4vv7edh4zclmymp5ixh44xxmd3hb2imiqa7mp2c3a.ipfs.dweb.link/"; const privateKey = `0x${process.env.PRIVATE_KEY}`; const wallet = new ethers.Wallet(privateKey); wallet.provider = provider; const signer = wallet.connect(provider); // https://docs.ethers.io/v5/api/contract/contract const nft = new ethers.Contract( process.env.CONTRACT_ADDRESS, contractInterface, signer ); const main = () => { console.log("Waiting 5 blocks for confirmation..."); nft .mintNFT(process.env.PUBLIC_KEY, tokenURI) .then((tx) => tx.wait(5)) .then((receipt) => console.log(`Your transaction is confirmed, its receipt is: ${receipt.transactionHash}`)) .catch((e) => console.log("something went wrong", e)); }; main();
-
-
Call
mint.js
Now, all you need to do is run
mint.js
to deploy your NFT:npx hardhat run scripts/mint.js --network palm_testnet
npx hardhat run scripts/mint.js --network palm_mainnet
We required the confirmation to be 5 blocks, as you can see in your code in the
main
function:tx.wait(5))
, it’ll therefore take a few seconds before seeing the following response in your terminal:Your transaction is confirmed, its receipt is:
0x10e5062309de0cd0be7edc92e8dbab191aa2791111c44274483fa766039e0e00``You can now look up your minted token on the Palm network block explorer by pasting the receipt hash above in the search bar:
Your NFT is minted. Note that your deployed contract can act as an NFT factory, enabling you to mint any number of tokens.
If you want to see your token appear in your MetaMask wallet, go to MetaMask, choose “Import token”, paste the address of the contract that you used to mint your NFT, and add a name and zero as decimal.
Question
Any question? Drop them on our Discord