# How to Create an NFT Token

NFT(Non-Fungible Tokens) are tokens used to represent digital assets with inherent properties that are unique and that cannot be exchanged or interchanged(fungible), in many cases, they are used to represent items like images, art, etc. The Ethereum blockchain has a unique standard called the ERC721 for defining the functionality of these tokens. We will follow the template pattern of using Hardhat, Metamask, Alchemy, etc to build our smart contract just like in our other solidity [tutorials](https://blog.michaeltech.xyz/deploying-a-custom-created-cryptocurrency-on-the-ethereum-network)

### Project Setup

```bash
mkdir MikNFT
cd MikNFT
npm init -y

npm install --save-dev hardhat
npx hardhat

npm i @openzeppelin/contracts
```

The code below imports the ERC721 library and inherits all the function implementation for ERC721, it also uses the Counters library which will be used for counting the number of tokens and giving each a unique positive integer value.

The contract is initialized with the name and symbol for the token the *mintNFT* function takes into two parameters the *address* where the NFT will be sent and the *tokenURI* which gives the metadata description of the token, it then returns the unique integer id of the token

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract MikNFT is ERC721URIStorage {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    constructor() ERC721("MikNFT", "NFT") {}

    function mintNFT(address recipient, string memory tokenURI)
        public
        
        returns (uint256)
    {
        _tokenIds.increment();

        uint256 newItemId = _tokenIds.current();
        _mint(recipient, newItemId);
        _setTokenURI(newItemId, tokenURI);

        return newItemId;
    }
}
```

after it has successfully complied with this command,

```bash
npx hardhat compile
```

we'll install the *dotenv* package to enable us to interact with our environment variables. The environment variables that will be used are the wallet private key, *API\_URL,* and *API\_KEY,* these will be kept in a *.env* file that will be added to the project's *.gitignore* list as these variables are quite sensitive and are not to be uploaded to a public repository.

```bash
npm install dotenv --save
```

```bash
API_URL = "https://eth-goerli.g.alchemy.com/v2/api-key"
PRIVATE_KEY = "metamask-private-key"
API_KEY = "api-key"
```

We'll go straight ahead to create our *hardhat.config.js* in the root folder and *deploy.js* in the scripts folder respectively, the *deploy.js* script uses the *Ethers.js* library to handle the deployment of our smart contract.

```javascript
require('dotenv').config();
require("@nomiclabs/hardhat-ethers");


const { API_URL, PRIVATE_KEY } = process.env;

module.exports = {
  solidity: "0.8.17",
  defaultNetwork: "goerli",
  networks: {
    hardhat: {},
    goerli: {
       url: API_URL,
       accounts: [`0x${PRIVATE_KEY}`]
    }
 },
};
```

```javascript


async function main() {
  
// Grab Contract Factory
  const MikNFT = await ethers.getContractFactory("MikNFT");

     // Start deployment, returning a promise that resolves to a contract object
  const mikNFT= await MikNFT.deploy(); // Instance of the contract 

  console.log(
    "Contract deployed to address:", mikNFT.address );
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(()=> process.exit(0))
.catch((error) => {
  console.error(error);
  process.exit(1);
});
```

Let's deploy the smart contract on the goerli testnet

```bash
npx hardhat run scripts/deploy.js --network goerli
```

At the end of the deployment, the contract address will be shown, this is what we'll use to check the details of our transaction on goerli etherscan

```bash
Contract deployed to address: 0x52Fb82C6D01F4077F18508C1ab59560c651A9099
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677502583866/aef4ae65-baa1-4ae9-8b6f-8c75fcf82fac.png align="center")

You have successfully deployed your NFT smart contract! The next step is to use the contract to mint an NFT

### Minting NFT

So we will decide what we want to put up as an NFT, I 'dreamed' up a really cool art piece using an AI image generation [tool](https://dream.ai/) called Wombo, you can check it out.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677510545877/8f7846e1-dabc-403b-93a7-29759a5d5a2d.png align="center")

The primary way to store NFTs is on IPFS(Interplanetary File System) platforms which are decentralized file-sharing networks for keeping data. We'll use [Pinata](https://www.pinata.cloud/) for our example. After creating an account on the platform, we'll upload our image and copy the hash code or content identifier that was generated from the successful upload, the address of the image will be represented like this [https://gateway.pinata.cloud/ipfs/](https://gateway.pinata.cloud/ipfs/)[&lt;](https://gateway.pinata.cloud/ipfs/QmarPqdEuzh5RsWpyH2hZ3qSXBCzC5RyK3ZHnFkAsk7u2f)hash-code&gt;

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677505110141/ffd9c678-bd89-4234-89ee-4db404ab322d.png align="center")

Then go ahead to create a nft-metadata.json file that provides all the vital attributes for your NFT, make sure the image points to the address of the image, and when this is done make sure this is also uploaded to Pinata and the URL address noted.

```json
{
    "attributes" : [ {
      "trait_type" : "Background",
      "value" : "forest"
    }, {
      "trait_type" : "flag",
      "value" : "Nigeria"
    } ],
    "description" : "car moving in a country background, flag seen in the skyline, locally dressed man",
    "image" : "https://gateway.pinata.cloud/ipfs/Qmcp8yj1rBBSJAHmUq3rd3oYF5Uhy2ftBLGLGG4SpPSvzP",
    "name" : "Nairaland"
}
```

we then create a mint-nft.js file that will execute the minting of our NFT, we'll use the contracts' ABI for that, the ABI is a json formatted interface used to interact with the contract, it is automatically generated by hardhat when the contract is compiled, the ABI for this contract is generated in this location.

```javascript
const contract = require("../artifacts/contracts/MikNFT.sol/MikNFT.json");
```

the contract will use the ether library to connect with our node provider using our API key earlier defined in our .env file, it will also use the wallet's private key, the contract's address and the contract's abi to define the contract

```javascript
require('dotenv').config();
const { AlchemyProvider } = require('@ethersproject/providers');
const ethers= require('ethers');

// Get Alchemy API key
const API_KEY= process.env.API_KEY;
// Define an Alchemy Provider
const provider= new ethers.providers.AlchemyProvider('goerli', API_KEY);

const privateKey=process.env.PRIVATE_KEY;
const signer= new ethers.Wallet(privateKey, provider);
// Get contract ABI and address
const abi=contract.abi;
const contractAddress='0x52fb82c6d01f4077f18508c1ab59560c651a9099';

// Create a contract instance
const myNftContract= new ethers.Contract(contractAddress, abi, signer);
```

the *tokenURI* for our NFT image will now be used and defined in our script, this is how the final version of our *mint-nft.js* script will look like

```javascript
const contract = require("../artifacts/contracts/MikNFT.sol/MikNFT.json");
require('dotenv').config();
const { AlchemyProvider } = require('@ethersproject/providers');
const ethers= require('ethers');

// Get Alchemy API key
const API_KEY= process.env.API_KEY;
// Define an Alchemy Provider
const provider= new ethers.providers.AlchemyProvider('goerli', API_KEY);




const privateKey=process.env.PRIVATE_KEY;
const signer= new ethers.Wallet(privateKey, provider);

// Get contract ABI and address
const abi=contract.abi;
const contractAddress='0x52fb82c6d01f4077f18508c1ab59560c651a9099';

// Create a contract instance
const myNftContract= new ethers.Contract(contractAddress, abi, signer);

const tokenUri= "https://gateway.pinata.cloud/ipfs/QmQRJK9mMtueyJN9APfQGCdsT1pHELZ9dKN1mcjaRV8qHo";

// Call mintNFT function
const mintNFT = async () => {
    let nftTxn = await myNftContract.mintNFT(signer.address, tokenUri)
    await nftTxn.wait()
    console.log(`NFT Minted! Check it out at: https://goerli.etherscan.io/tx/${nftTxn.hash}`)
}

mintNFT()
    .then(() => process.exit(0))
    .catch((error) => {
        console.error(error);
        process.exit(1);
    });
```

run the below command to execute our script

```bash
node scripts/mint-nft.js
```

Our output will be like this

```bash
NFT Minted! Check it out at: https://goerli.etherscan.io/tx/0x907e775d3b45507eb17af5bd97b65c58457b7354354157c7ef148e32f2f8f31c
```

Awesome! what cool NFT project can you spin-off? Happy NFTing!
