👷Create an NFT Collection

Let's go over the steps to create an NFT Collection on the Ethernity Chain. We are going to use the standard ERC-721 inheriting from battle tested Open Zeppelin contracts.

Requirements

  • Node.js and npm: download and install both packages here

  • Ethereum Wallet: Metamask or any other non-custodial Ethereum wallet, since you will need the private key

  • ETH: You can get some Sepolia ETH and then bridge it to Ethernity

  • Solidity and CLI knowledge

1. Initialize a Hardhat TypeScript project

Open your terminal and create a new directory for your project, then navigate into it:

mkdir nft && cd nft

Initialize an npm project:

npm init -y

Install the necessary packages for Hardhat, TypeScript and Open Zeppelin:

npm install --save-dev hardhat ts-node typescript @nomiclabs/hardhat-ethers ethers @openzeppelin/contracts

Start a new Hardhat project with TypeScript:

npx hardhat init

When prompted, make the following selections:

  • Choose "Create a TypeScript project".

  • For the .gitignore prompt, select "Yes" (or y).

  • For installing the projects dependencies select "Yes" (or y).

npx hardhat

888    888                      888 888               888
888    888                      888 888               888
888    888                      888 888               888
8888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888
888    888      88b 888P   d88  888 888  88b      88b 888
888    888 .d888888 888    888  888 888  888 .d888888 888
888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.
888    888  Y888888 888      Y88888 888  888  Y888888  Y888

👷 Welcome to Hardhat v2.18.2 👷‍

✔ What do you want to do? · Create a TypeScript project
✔ Hardhat project root: · /Users/Ethernity/nft
✔ Do you want to add a .gitignore? (Y/n) · y
✔ Do you want to install this sample project's dependencies with npm (@nomicfoundation/hardhat-toolbox)? (Y/n) · y

2. Create the Art

Grab your piece of art you want to immortalize ("for Ethernity") and convert it to a JPG file no larger than 5Mb (recommended). Aspect ratio can be whatever you choose but we recommend square or rectangle with ratio close to a square. If your art piece is an animation, you will need an MP4 video with H.264 standard video compression, no larger than 15Mb (recommended). Aspect ratio we recommend square or rectangular with ratio close to a square. For videos we also recommend to export a still (which should be a scene of the animation) in JPG no larger than 1Mb (recommended).

Once you have your art image (or the animation and its still) you have to upload it to a content delivery network (CDN). You can upload to a centralized CDN (i.e. Google Cloud, AWS, your own hosting, etc.) or to a decentralized network (i.e. IPFS).

Centralized CDN:

- Pros: faster delivery, can "update" files, can host larger files - Cons: if CDN provider goes bust, or is hacked, the NFT art can be changed or gone! User perception is also affected when you store your decentralized digital asset media in a centralized CDN

If you choose this route, upload the file(s) and write down the public URL (the URL to access the image or video + the still) . You can use Bluehost, Google Cloud Storage, Amazon S3, Amazon CloudFront, etc.

Decentralized CDN:

- Pros: Permanent, "read only", follows same philosophy as blockchain. Most NFT projects use this, IPFS is almost the "de facto standard". - Cons: Super slow (will time out some times), still need to pay pinning services

If you choose this route, first get a pinning service i.e. pinata.cloud or infura.io (both have free plans). Upload the file(s) as instructed and write down the content identifier(s) (CID).

3. Create the Metadata

Now let's create the metadata (data about the NFT). For ERC-721, each NFT is identified by a token ID. and each token ID has its own metadata file. There is no "standard" but the convention is that the token ID is the filename, and the conventional format of the metadata file is:

{
  "name": "Ethernity Genesis",
  "description": "Ethernity Genesis NFT description",
  "image": "<image URI>",
  "animation_url": "<animation URI>"
  "external_url": "https://ethernity.io",
  "attributes": {
    "trait 1": "value 1",
    "trait 2": "value 2"
  }
}

<image URI>: if you chose the centralized CDN, simply paste here the URL from the step above. If you chose IPFS, youc an either put "ipfs://<CID>" or the entire URL "https://ipfs.io/ipfs/<CID>".

<animation URI>: (if you have an animation, if not just omit this key) same as above, for centralized CDN just paste the public URL, if IPFS either "ipfs://<CID>" or "https://ipfs.io/ipfs/<CID>".

Create one file per token ID in a directory in your local computer. You need one file per token ID, and the file name can simply be <token ID> or <token ID>.json.

Once you have all the files, upload them to (again ...) either centralized or decentralized CDN (the directory). For centralized, write down the public URL, for decentralized, the CID.

4. Write the NFT Smart Contract

In the contracts directory, delete the sample smart contract Lock.sol and then create a new file named Nft.sol.

With auto-increment token ID when minting

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract Nft is ERC721URIStorage, Ownable {
    uint256 private _tokenIds;

    constructor(string memory name, string memory symbol, string memory baseTokenURI) ERC721(name, symbol) {
        _baseTokenURI = baseTokenURI;
    }

    function mint(address recipient) public onlyOwner returns (uint256) {
        _tokenIds++;
        uint256 newItemId = _tokenIds;
        _mint(recipient, newItemId);
        _setTokenURI(newItemId, _baseURI());
        return newItemId;
    }

    function _baseURI() internal view override returns (string memory) {
        return _baseTokenURI;
    }

    string private _baseTokenURI;
}

With specific token ID when minting

If you want to specify a token ID at the time of minting, the contract would look something like this:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract Nft is ERC721URIStorage, Ownable {

    constructor(string memory name, string memory symbol, string memory baseTokenURI) ERC721(name, symbol) {
        _baseTokenURI = baseTokenURI;
    }

    function mint(
        address recipient, uint256 _tokenId
    ) public onlyOwner {
        _mint(recipient, _tokenId);
        _setTokenURI(_tokenIdId, _baseURI());
    }

    function _baseURI() internal view override returns (string memory) {
        return _baseTokenURI;
    }

    string private _baseTokenURI;
}

5. Configure Harhdat for Ethernity

Edit the hardhat.config.ts file to include Ethernity Chain Testnet settings:

import "@nomiclabs/hardhat-ethers";

import { HardhatUserConfig } from "hardhat/config";

const config: HardhatUserConfig = {
  networks: {
    ethernity-testnet: {
      url: "https://testnet.ethernitychain.io",
      chainId: 233,
      accounts: ["PRIVATE_KEY"] // DO NOT SHARE THIS!
    }
  },
  solidity: "0.8.0",
};

export default config;

Replace PRIVATE_KEY with your Ethereum wallet private key.

IMPORTANT: Do not push your hardhat.config.ts file to github or share your private key with anyone.

6. Compile

Compile the smart contract:

npx hardhat compile

7. Deploy

In the scripts directory, create a new file named deploy.ts:

import { ethers } from "hardhat";

async function main() {
    const Token = await ethers.getContractFactory("Token");
    const token = await Token.deploy();
    await token.deployed();
    console.log("Token deployed to:", token.address);
}

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

Now you can deploy the smart contract to Ethernity Testnet:

npx hardhat run scripts/deploy.ts --network ethernity-testnet

8. Verify

Follow these instructions to verify the token contract.

9. Mint

See your brand new NFT deployed on the Ethernity Testnet block explorer (ERNScan): https://testnet.ernscan.io. Enter the contract address from the command line, then go to Contract and trigger the mint() function.

Last updated