Skip to content
You are reading Palm development version documentation and some displayed features may not be available in the stable release. You can switch to stable version using the version box at screen bottom.

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


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.


What our code will do


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)
        returns (uint256)

        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:


  1. 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 than web3.js, resulting in leaner code.

    Let’s start by requiring the correct libraries:

  2. 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;
  3. 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, our ethers.provider object retrieves all the connection details from hardhat.config.js.

    Add this line to mint.js:

    let provider = ethers.provider;
  4. 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:

    Copy your media file's URI

  5. 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 a JSON 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 following JSON code to match your NFT’s specifications. Now would be the time to add the URI 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 its URI and add it to the tokenURI variable.

    const tokenURI = "<`URI` of your metadata file>";

    The variable we just declared,tokenURI will be passed as an argument to the contract’s mintNFT function.

  6. 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:

    `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"
  7. Set up Ethers.js signer and wallet

    The 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);
  8. Set up Ethers.js contract

    An 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 our MintNFT function.

    Add these lines of code to mint.js:

    const nft = new ethers.Contract(
  9. Build the main function

    Finally, create the main function, which will asynchronously call the MintNFT 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:

    const contract = require("../artifacts/contracts/NFT.sol/NFT.json");
    const contractInterface = contract.abi;
    let provider = ethers.provider;
    const tokenURI = "";
    const privateKey = `0x${process.env.PRIVATE_KEY}`;
    const wallet = new ethers.Wallet(privateKey);
    wallet.provider = provider;
    const signer = wallet.connect(provider);
    const nft = new ethers.Contract(
    const main = () => {
      console.log("Waiting 5 blocks for confirmation...");
        .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));
  10. 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.


Any question? Drop them on our Discord

Questions or feedback? You can discuss and obtain community support on Palm Discord.
For additional support, contact Palm on Palm website.