Build, Deploy and Mint KIP17 Token on Klaytn

Build, Deploy and Mint KIP17 Token on Klaytn

Learn how to create, deploy and mint KIP17 NFTs using Hardhat + Visualize your NFT on Opensea.

·

8 min read

Introduction

With the recent boom and increasing popularity of NFT's (Non-fungible Tokens), enthusiasts, users and developers are looking for ways to explore and build around this innovation. Different use cases ranging from gaming, digital ownership, virtual worlds, proof of membership, and much more have been emerging in recent times and all are practical real world uses to explore.

With that said, this is an excellent opportunity to understand this innovation yourself by deploying your own NFT (KIP-17 Token) on the Klaytn blockchain.

So let's get started! In this tutorial, we’ll go through the following:

  • What is Non-Fungible Token?

  • What is KIP-17?

  • Getting Started

  • Writing KIP-17 Smart Contract

  • Creating and Uploading Metadata

  • Minting and Visualizing our NFT

  • Conclusion

What is a Non-Fungible Token?

A Non-Fungible Token (NFT) is used to identify something or someone that has unique characteristics and values. This type of token is perfect to be used on platforms that offer collectible items, lottery tickets, numbered seats for concerts and sports matches, etc. This special type of token has amazing possibilities, and it’s important that some form of standard regulates them. The KIP-17 solves just that!

What is KIP-17?

KIP stands for Klaytn Improvement Proposal, and 17 is the proposal identifier number. KIP's are application-level standards in the Klaytn ecosystem. The KIP-17 standard allows for the implementation of a standard API for NFTs within smart contracts. This standard provides basic functionality to track and transfer NFTs. NFTs can represent ownership over digital or physical assets such as:

  • Physical property — houses, unique artwork
  • Virtual collectibles — unique pictures of kittens, collectible cards
  • "Negative value" assets — loans, burdens and other responsibilities

Click here to learn more about this standard.

What we are building

In this guide, we will walk through creating and deploying KIP-17 smart contract on the Klaytn test network using Solidity ↗, Hardhat ↗, Kaikas ↗, Nft Storage ↗.

By the end of this tutorial - you'll be able to mint an NFT and visualize it on Opeansea↗.

openseaMe.png

Getting Started

1. Prerequisites

To follow this tutorial, the following are the pre-requisites:

Not familiar with the above? Learn the basics by clicking the links above, before proceeding with this tutorial.

2. Setting Up Development Environment

To make use of hardhat, we need to set up our development environment and get hardhat installed. Let's do this in the following steps:

  • Step 1: Open your projects folder in your terminal and run
git clone https://github.com/AyDeveloper/Hardhat_Klaytn_Example.git
cd Hardhat_Klaytn_Example
  • Step 2: Install dependencies by running this command

npm install

  • Step 4: Create a .env file

Now lets create our .env file. This file helps us load environment variables from a .env file into process.env. After creating our file, let's configure our .env file to look like this:

 KLAYTN_URL='https://api.baobab.klaytn.net:8651'
 PRIVATE_KEY= your private key copied from kaikas wallet
  • Step 4: Setup Hardhat Configs

We are only adding the gasPrice field in our project

const config: HardhatUserConfig = {
  solidity: "0.8.4",
  networks: {
    klaytn: {
      url: process.env.KLAYTN_URL || "",
      gasPrice: 250000000000,
      accounts:
        process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [],
    },
  },
  gasReporter: {
    enabled: process.env.REPORT_GAS !== undefined,
    currency: "USD",
  },
  etherscan: {
    apiKey: process.env.ETHERSCAN_API_KEY,
  },
};

Now that we have our development environment all set, lets get into writing our NFT smart contract.

Write, Compile and Deploy KIP-17 Smart Contract

For this guide, we are going to be using the Klaytn contracts library. To utilize this library, run the command below:

npm i @klaytn/contracts

Once this has been installed, navigate to the contracts folder and create a new file called Nft.sol

Below is our NFT smart contract code. Copy and paste the contents below into your myNft.sol file.

// SPDX-License-Identifier: GPL-3.0

//Declare the version of solidity to compile this contract.
pragma solidity ^0.8.0;

//import implementation of KIP-17 from our installed library
import "@klaytn/contracts/KIP/token/KIP17/extensions/KIP17URIStorage.sol";

//imports a library to increment and decrement uint
import "@klaytn/contracts/utils/Counters.sol";

// declares the contract and its  name

contract MYNFT is KIP17URIStorage {

      //a counter to keep track of the tokens minted 
      using Counters for Counters.Counter;

      Counters.Counter private currentTokenId;

    // sets the token information: name and symbol
    constructor() KIP17("MYNFT", "MNFT") {}

    // takes in two arguments:
    //address recipient: address that will receive newly minted NFT
    //tokenURI: describes the tokens metadata
      function mintNftTo(address recipient, string memory tokenURI)
        public 
        returns (uint256)
    {
        currentTokenId.increment();

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

        return newItemId;
    }
}

Now that we have our contract code, its time to compile and deploy

  • To compile our contract, run this command

npx hardhat compile

  • To deploy our contract, lets navigate to our scripts folder and modify our deploy.ts file by pasting the following code:
  import { ethers } from "hardhat";


async function main() {
    const deployerAddr = "Your kaikas wallet address";
    const deployer = await ethers.getSigner(deployerAddr);

    console.log(`Deploying contracts with the account: ${deployer.address}`);
    console.log(`Account balance: ${(await deployer.getBalance()).toString()}`);

    //  Fetch the compiled contract using ethers.js
    const myNft = await ethers.getContractFactory("MYNFT");

    // calling deploy() will return an async Promise that we can await on 
    const nft = await myNft.connect(deployer).deploy();
    await  nft.deployed();

    console.log(`Contract deployed to address: ${nft.address}`);
}

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

Now run the command below to deploy to baobab

npx hardhat run scripts/deploy.ts --network klaytn

Our Contract was deployed to address: 0x5Fd499eDf8774590285358a9CFd3C671ca8241C1

Lets head over to KlatynScope to view our newly deployed Nft contract

scope.png

Creating and Uploading Metadata

Create two directories in your project root: /images and /metadata. The /images directory will store all your images, which we will need to upload first and /metadata will store all the JSON files for the tokens in your NFT contract and we will upload all of them at once as a compiled IPFS Car.

Note: We would be using just one image and you can use as much as you want. Feel free to use your own images.

Once you have your images in the /images directory, pack them to an IPFS-compatible CAR using a handy CLI command:

npx ipfs-car --pack images --output images.car

Note: You do not have this package installed and you would be asked to install it by clicking yes after running the above command.

You have this result below

root CID: bafybeighk6vlcaudajgkxxwa5vxc3qkadna6neekxwxncyja55sgu5h4yi output: images.car

Next let's navigate to the NFT Storage Files ↗ page to upload this CAR file to IPFS:

nftStorage.png

nftStorage2.png

nftStorage3.png

Click on the image CID to view the image, copy the image link. This link is to be included in your token metadata.

imageCid.png

Now that we have our image stored on ipfs, we can begin to create our metadata JSON files, with IPFS images included. In /metadata folder, go ahead and create a file named 1 (don't worry about not adding a file extension). Fill these files with sample data such as below:

{
    "attributes" : [
       {
          "trait_type" : "level",
          "value" : 5
       },
       {
          "trait_type" : "stamina",
          "value" : 70.5
       },
       {
          "trait_type" : "personality",
          "value" : "Agile"
       },
       {
          "display_type" : "boost_number",
          "trait_type" : "aqua_power",
          "value" : 50
       },
       {
          "display_type" : "boost_percentage",
          "trait_type" : "stamina_increase",
          "value" : 70
       },
       {
          "display_type" : "number",
          "trait_type" : "generation",
          "value" : 1
       }
    ],
    "description" : "A young and grateful fellow thanking God for adding to his years on earth.",
    "image" : "https://bafybeighk6vlcaudajgkxxwa5vxc3qkadna6neekxwxncyja55sgu5h4yi.ipfs.nftstorage.link/images/pampam.jpg",
    "name" : "Oxpam_pam"
 }

Note: This is a sample metadata that you can edit to your choice. Feel free to change the image value and some other property. To learn more about metadata standard, click here.

To further get our metadata hosted on IPFS, use the same IPFS-CAR CLI command from earlier on the metadata folder and upload that as well to NFT Storage:

npx ipfs-car --pack metadata --output metadata.car

We have our result below

root CID: bafybeigtfhnfoyh2fw73tqhinxy4bfz5ijnug3wjx3mvtia2iuqpkixfke output: metadata.car

Next is to upload our metadata.car to NFT Storage as we did to our image. Once this is done, your metadata is ready to be set onto your smart contract!

metaCid.png

Miniting our NFT

Now that we have our token metadata, lets head up to mint our NFT. To do this, navigate to your scripts folder and create a file named mint.ts and paste this code below:

  import { ethers } from "hardhat";

async function main() {
   const deployerAddr = "Your kaikas wallet address";
   const deployer = await ethers.getSigner(deployerAddr);

// gets the instance of the already deployed contract
 const myNftInstance = await ethers.getContractAt("MYNFT", "your contract address");

// you can add the link to your metadata here
  const uri = "https://bafybeigtfhnfoyh2fw73tqhinxy4bfz5ijnug3wjx3mvtia2iuqpkixfke.ipfs.nftstorage.link/metadata/1";

    const mint = await myNftInstance.connect(deployer).mintNftTo(deployerAddr, uri);
    const tx = await mint.wait()
    console.log(tx);

    const bal = await myNftInstance.balanceOf(deployerAddr);
    console.log(bal);
}

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

To mint our NFT lets run the command below

npx hardhat run scripts/mint.ts --network klaytn

Let's check our console for results. Once you have your transaction receipt and balance increased, you have successfully minted your NFT on Klaytn.

consoleRes.png

Now, let's navigate to Opensea↗, an NFT marketplace.

Connect your kaikas wallet to Opensea testnet marketplace and you'll be able to view your minted NFT there!

openseaCon.png

openseaMe.png

Conclusion

Congratulations on making it to the end and for creating and minting your first NFT on Klaytn.

Now that you have fully gone through the process, it’s time to experiment more! Can you think of anything that could be improved? Here is an idea:

Add a minting cost i.e Charge a specific amount to call the mintNftTo. Here is how the mint function could be modified:

   uint256 public constant MINT_PRICE = 5 ether;
  function mintTo(address recipient) public payable returns (uint256) {
    require(msg.value >= MINT_PRICE, "value not equals the mint price");

       currentTokenId.increment();

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

        return newItemId;
  // }

You might also want to consider building a full-stack dApp to mint, display and transfer NFTs.

This was a very comprehensive tutorial on writing, compiling, and deploying our KIP-17 NFT smart contract to Klaytn Baobab using Hardhat and Ethers js. If you followed along with this guide, it would be awesome to check out the complete source code here on github.

If you have any questions, suggestions or comments, drop them below, or reach out to me on Twitter!

Happy Building!!