The rise of non-fungible tokens (NFTs) has introduced countless creators and developers to the world of Web3. By deploying and minting unique digital assets on the Ethereum blockchain—specifically using the ERC-721 standard—you can participate in this dynamic ecosystem.
This guide provides a step-by-step walkthrough for minting and displaying your own NFT using tools like MetaMask, Hardhat, Alchemy, Pinata, and the Goerli test network.
Prerequisites
Before you begin, ensure you have:
- A MetaMask wallet with test ETH (available from a Goerli faucet)
- An Alchemy account and API key
- Node.js and npm installed
- Basic knowledge of Solidity and smart contract deployment
This tutorial assumes you have already written and deployed an ERC-721 smart contract. If not, please refer to our previous guide on writing and deploying an NFT contract before continuing.
Installing Web3.js
To interact with your deployed smart contract, you’ll need a JavaScript library. While Ethers.js is common, we’ll use Alchemy Web3.js—a robust library with automatic retries and WebSocket support.
Run the following in your project’s root directory:
npm install @alch/alchemy-web3Creating the Minting Script
Inside your scripts folder, create a file named mint-nft.js and add the following:
require("dotenv").config();
const API_URL = process.env.API_URL;
const { createAlchemyWeb3 } = require("@alch/alchemy-web3");
const web3 = createAlchemyWeb3(API_URL);Retrieving the Contract ABI
The Application Binary Interface (ABI) enables your script to interact with the smart contract. Hardhat automatically generates the ABI when you compile your contract.
Import your contract’s ABI into mint-nft.js:
const contract = require("../artifacts/contracts/NewNFT.sol/NewNFT.json");
console.log(JSON.stringify(contract.abi));Run the script to confirm the ABI logs correctly:
node scripts/mint-nft.jsConfiguring NFT Metadata with IPFS
NFT metadata—such as name, description, and image—defines the token’s attributes. You’ll store this metadata in a JSON file on IPFS using Pinata, a decentralized storage platform.
- Upload your NFT image to Pinata and copy its Content Identifier (CID).
- Create a
nft-metadata.jsonfile with the following structure:
{
"attributes": [
{
"trait_type": "Breed",
"value": "Ape"
},
{
"trait_type": "Eye",
"value": "Glasses"
},
{
"trait_type": "Face",
"value": "Smiled"
}
],
"description": "Very powerful programmer ape.",
"image": "ipfs://QmXectapuW3yBCWwgjf78h3Dqdo2zpD5qaq4zXb63qXbp9",
"name": "Caesar"
}- Replace the
imagefield with your own IPFS CID. - Upload the JSON file to Pinata and copy the new CID.
Initializing the Contract Instance
To interact with your deployed contract, create a contract instance using its address and ABI.
Add this to mint-nft.js:
const contractAddress = "0x094180BBc8f5e8e9697C0F633D4004e3ecea6510";
const nftContract = new web3.eth.Contract(contract.abi, contractAddress);👉 Explore more smart contract strategies
Updating Environment Variables
Your .env file should include your Alchemy API URL, MetaMask public key, and private key:
API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key"
PRIVATE_KEY = "your-metamask-private-key"
PUBLIC_KEY = "your-metamask-address"Never share your private key or commit it to version control.
Creating and Signing the Transaction
1. Building the Transaction
Define a mintNFT function that:
- Fetches the account nonce
- Estimates gas costs
- Encodes the function call
async function mintNFT(tokenURI) {
const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, "latest");
const tx = {
from: PUBLIC_KEY,
to: contractAddress,
nonce: nonce,
gas: 500000,
data: nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI(),
};
}2. Signing the Transaction
Sign the transaction using your private key:
const signPromise = web3.eth.accounts.signTransaction(tx, PRIVATE_KEY);
signPromise
.then((signedTx) => {
web3.eth.sendSignedTransaction(signedTx.rawTransaction, (err, hash) => {
if (!err) {
console.log(
"Transaction Hash:",
hash,
"\nCheck Alchemy Mempool for status."
);
} else {
console.log("Error:", err);
}
});
})
.catch((err) => {
console.log("Promise failed:", err);
});Executing the Minting Function
Call mintNFT with your metadata URI:
mintNFT("ipfs://QmZ643xL21yDh2BzBNHHuVqpXmYnDDfy69Asn3QSJxcbcu");Run the script:
node scripts/mint-nft.jsIf successful, you’ll receive a transaction hash. Use this to track your transaction on Etherscan or Alchemy.
Viewing Your NFT in MetaMask
Once the transaction is confirmed:
- Open MetaMask mobile app or browser extension.
- Ensure you’re on the Goerli testnet.
- Go to the "NFTs" tab and click "Import NFT".
- Enter your contract address and token ID (from the transaction log).
- Your NFT should appear shortly.
Frequently Asked Questions
What is an NFT?
An NFT (non-fungible token) is a unique cryptographic token representing ownership of a digital or physical asset. Unlike cryptocurrencies, NFTs are not interchangeable.
Why use the Goerli testnet?
Goerli is a test network for Ethereum that allows developers to experiment without spending real ETH. It mimics the mainnet environment without financial risk.
What is IPFS, and why is it important for NFTs?
IPFS (InterPlanetary File System) is a decentralized storage network. Storing NFT metadata on IPFS ensures permanence and avoids central points of failure.
How do I get test ETH for Goerli?
You can obtain Goerli test ETH from faucets like Alchemy’s Goerli Faucet or the Goerli Authenticated Faucet.
Can I mint multiple NFTs with the same metadata?
Yes, but they will be identical except for their token IDs. To create unique NFTs, use different metadata URIs.
What if my NFT doesn’t appear in MetaMask?
Double-check the contract address and token ID. Delays are common—wait a few minutes and try again.
Conclusion
You’ve now successfully minted and displayed an NFT on the Ethereum Goerli testnet. This process involves writing and deploying a smart contract, configuring metadata, executing transactions, and verifying results.
By mastering these steps, you’re well-equipped to explore further possibilities in the Web3 space, from creating digital art to building full-fledged decentralized applications.
Welcome to the world of Web3 development