visit
We could follow an already published nice Counters.sol
so we will deploy and mint NFT without such contracts in this article.
Now, let’s create a project folder; let’s say Nikola NFT
. After that, your project directory has to follow the following format. Don’t worry, you don’t need all the files and folders now shown in the following directory; they come stepwise.
Log in to your Pinata account, and upload two images. Here, I have uploaded two images of Nikola Tesla(NikolaT1.jpg
and NikolaT2.jpg
). You can upload your desired one like your own art. Please note the CIDs of each image which are required in metadata.
For the first NikolaT1.jpg
, the JSON file is nikola1.json
{
"attributes": [
{
"trait_type": "Occupation",
"value": "Inventor"
},
{
"trait_type": "Known For",
"value": "AC Power"
}
],
"description": "Nikola T1. Renowned inventor known for AC Power.",
"image": "ipfs://QmbzK6GPksM4SiQTXurV4eYoEdTZwDdhG5rko2dXwaDq8P",
"name": "Nikola T1"
}
For the first NikolaT2.jpg
, the JSON file is nikola2.json
{
"attributes": [
{
"trait_type": "Occupation",
"value": "Inventor"
},
{
"trait_type": "Known For",
"value": "AC Power"
}
],
"description": "Nikola T2. Renowned inventor known for AC Power.",
"image": "ipfs://QmXuvshQJ7jAKy1TeHwFjbs4mfwDerighf45JcnfRhbtet",
"name": "Nikola T2"
}
Please feel free to add your image attributes for your NFT metadata in the above JSON codes. Upload the two .json
files in Pinata following the same procedures as uploading two images.
Download the MetaMask browser extension, create a new wallet, note down the secret phrases, and create .secret.json
file in the project’s root directory Nikola NFT.
{
"mnemonic": "idiot flatter systematic rose phone fluse pest physics open comb annual pot"
}
Please note the secret phrases have to be kept safely. You have to add your phrases to the .json
file.
You need to have some tRBTC in your MetaMask wallet address. Go to the site to get it. Once you’re done, you should have 0.05 tRBTC in your wallet, check it via the Rootstock testnet by pasting your wallet address.
Create a contract deployment script (scripts/deploy.js
) in your project’s root directory.
async function main() {
const nftContractFactory = await ethers.getContractFactory('NikolaTesla');
const nftContract = await nftContractFactory.deploy();
await nftContract.deployed();
console.log(`Nikola Tesla NFT deployed to: ${nftContract.address}`);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Now, you need to configure the Hardhat with the file hardhat.config.js
.The script sets up Hardhat to deploy and mint our NFTs on the RSK Testnet. Here, I have arranged the code to import the necessary modules and load the mnemonic from .secret.json
file. The code defines tasks to deploy the NikolaTesla NFT
contract and mint new NFTs using IPFS CIDs sequentially.
/* eslint-disable no-undef */
require('@nomiclabs/hardhat-waffle');
const { mnemonic } = require('./.secret.json');
task('deploy', 'Deploys smart contract to a blockchain').setAction(async () => {
const [deployer] = await ethers.getSigners();
const nikolaTeslaContractFactory = await ethers.getContractFactory('NikolaTesla');
const nikolaTeslaNft = await nikolaTeslaContractFactory.deploy(deployer.address);
await nikolaTeslaNft.deployed();
console.log(
`NikolaTesla NFT deployed to: ${nikolaTeslaNft.address}\nCopy this address and paste to the 'mint' task in 'hardhat.config.js'`,
);
});
task('mint', 'Mint new NFT collectibles').setAction(async () => {
const deployedAddress = '0xD04c326B3c1E6C2dDc28cAedCd52AFe17Ff4330b'; // Update this to the correct address after deployment
const newCIDsToMint = [
'QmbX6jmxLAq62rFkGPvAkLpihuyhT63SWxegEaSPoaUw7A',
'Qmd9pWgVUywEhki1BpXc1FxYdjgBnoSebMVrDr4K9onZqP',
];
const api = (await ethers.getContractFactory('NikolaTesla')).interface;
const [signer] = await ethers.getSigners();
const nikolaTeslaNft = new ethers.Contract(deployedAddress, api, signer);
async function mintSequentially() {
const cid = newCIDsToMint.shift();
if (cid) {
const tx = await nikolaTeslaNft.mintNFT(signer.address, `ipfs://${cid}`);
const receipt = await tx.wait();
console.log(receipt.events); // Add this line to debug events
if (receipt.events && receipt.events.length > 0) {
const { tokenId } = receipt.events[0].args;
console.log(`Minted NFT ${deployedAddress} #${tokenId}`);
await mintSequentially();
} else {
console.log('No events found in receipt');
}
}
}
await mintSequentially();
});
module.exports = {
solidity: '0.8.20',
defaultNetwork: 'rsktestnet',
networks: {
hardhat: {},
rsktestnet: {
chainId: 31,
url: '//public-node.testnet.rsk.co/',
accounts: {
mnemonic,
path: "m/44'/60'/0'/0",
},
},
},
};
Here are two CIDs under const newCIDsToMint = [
, are from .json
files uploaded on Pinata not the CIDs of your images. If you add CIDs of images, you will get the blank NFTs at the end.
For now, you need not necessarily change the wallet address 0xD04c326B3c1E6C2dDc28cAedCd52AFe17Ff4330b
in the code; you are doing this later. Please remember this step! For a more detailed code breakdown, please care to follow this .
Create a contracts
folder in the root directory, and create a solidity file entitled NikolaTesla.sol
in it.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract NikolaTesla is ERC721URIStorage, Ownable {
uint256 private _tokenIds;
constructor(address initialOwner) ERC721("NikolaTesla", "NT") Ownable(initialOwner) {}
function mintNFT(address recipient, string memory tokenURI) public onlyOwner returns (uint256) {
_tokenIds++;
uint256 newItemId = _tokenIds;
_mint(recipient, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
npm install @openzeppelin/contracts
Please note that the recent OpenZeppelin contracts library doesn’t contain the counters.sol
file mentioned in the contract example of the project’s . So, I’ve made a significant modification to this NikolaTesla.sol
file to get in tune with the recent updates from OpenZeppelin. It doesn’t need counters.sol
to deploy and mint my NFTs.
If you prefer to have it, you might manually add it from to the node_modules
directory. Here, we are just importing two contracts ERC721URIStorage.sol
and Ownable.sol
from OpenZeppelin.
npx hardhat compile
npx hardhat deploy --network rsktestnet
Now, do you catch it? I asked you to remember the step earlier 😊. Copy the deployed address, and replace the address in hardhat.config.js
npx hardhat mint --network rsktestnet
If everything is ok, you will be able to locate contract addresses and token IDs for two NFTs followed by #
like as shown in the figure. In our case, we have two IDs #1
and #2
for the token’s contract address 0xD04c326B3c1E6C2dDc28cAedCd52AFe17Ff4330b
So, how to see your NFTs? Well, this can be your genuine question because you may not see your NFTs in your MetaMask wallet yet. Let’s follow the following steps:
On your MetaMask wallet, go to Select Network>Add network>Custom RPC, and then enter the following information.
RSK Testnet
//public-node.testnet.rsk.co
31
tRBTC
Select the recently added network navigate the NFTs section, and select Import NFT. Fill in the Address and Token ID displayed on the terminal.
Modify your hardhat.config.js
to point to the Rootstock mainnet. Update the networks section as follows:
module.exports = {
solidity: '0.8.20',
defaultNetwork: 'rskmainnet',
networks: {
hardhat: {},
rskmainnet: {
chainId: 30,
url: '//public-node.rsk.co/',
accounts: {
mnemonic,
path: "m/44'/60'/0'/0",
},
},
},
};
npx hardhat deploy --network rskmainnet
Update the deployedAddress
with the mainnet contract address in your configuration file hardhat.config.js
and run the mint task:
npx hardhat mint --network rskmainnet