NFT Tutorial

Imagine buying a piece of digital artwork on the Internet at a reasonable price and getting a unique digital token known which proves your authority over the artwork you bought. Wouldn’t it be great? Well, that opportunity exists now, thanks to NFTs.

The world of digital art and collectibles is currently awash in NFTs. NFTs are currently positioned as the digital alternative to collectibles, much as everyone believed that Bitcoin was the digital replacement for cash. As a result of the enormous sales to a new crypto audience, digital artists are witnessing changes in their life.

If you are interested in NFTs and want to explore more about what they are, you have come to the right place. Let’s dive in and see what all the fuss is about!

Table of Contents

What is NFT?

Unlike traditional cryptocurrencies, NFTs, also known as non-fungible tokens, are unique, digital items with blockchain-managed ownership. Each unit of an NFT can be considered one of a kind. These can consist of collectibles, game items, digital art, event tickets, domain names, and even contract ownership records for physical assets.

Technically speaking, NFTs are non-interchangeable data storage units that are resistant to replication, tampering, and destruction. They are stored on a blockchain. NFTs have extrinsic value as a result of the blockchain’s ability to verify them.

‘Non-fungible’ refers to an asset’s unique qualities and traits that make it completely standalone and non-replicable from other assets. Conversely, a good example of a fungible asset can be a currency. When dealing with currency, a five-dollar bill will always be replaceable by another five-dollar bill (or even five $1s).

Though non fungible tokens can seem complex, you can think of them as a vehicle to share virtually any form of media using the blockchain.

  • NFT stands for a non-fungible token, which means it can neither be replaced nor interchanged because it has unique properties.

Key Features of NFT – 

  • Digital Asset – NFT is a digital asset that represents Internet collectibles like art, music, and games with an authentic certificate created by blockchain technology that underlies Cryptocurrency. 
  • Unique – It cannot be forged or otherwise manipulated. 
  • Exchange – NFT exchanges take place with cryptocurrencies such as Bitcoin on specialist sites.

How Does NFT Work?

Now that you’ve taken your initial steps in understanding what an NFT is, you should continue on and learn about how an NFT works.

  • The majority of NFTs reside on the Ethereum cryptocurrency’s blockchain, a distributed public ledger that records transactions.
  • NFTs are individual tokens with valuable information stored in them.
  • Because they hold a value primarily set by the market and demand, they can be bought and sold just like other physical types of art.
  • NFTs’ unique data makes it easy to verify and validate their ownership and the transfer of tokens between owners.

What is NFT Used For?

People interested in Crypto-trading and people who like to collect artwork often use NFTs. Other than that, it has some other uses too like:

  • Digital Content – The most significant use of NFTs today is in digital content. Content creators see their profits enhanced by NFTs, as they power a creator economy where creators have the ownership of their content over to the platforms they use to publicize it.
  • Gaming Items – NFTs have garnered considerable interest from game developers. NFTs can provide a lot of benefits to the players. Normally, in an online game, you can buy items for your character, but that’s as far as it goes. With NFTs, you can recoup your money by selling the items once you’re finished with them.
  • Investment and Collaterals – Both NFT and DeFi (Decentralized Finance) share the same infrastructure. DeFi applications let you borrow money by using collateral. NFT and DeFi both work together to explore using NFTs as collateral instead.
  • Domain Names – NFTs provide your domain with an easier-to-remember name. This works like a website domain name, making its IP address more memorable and valuable, usually based on length and relevance.

Even celebrities like Snoop Dogg, Shawn Mendes, and Jack Dorsey are taking an interest in the NFT by releasing unique memories and artwork and selling them as securitized NFTs.

NFT Examples

Owning a digital collectible has its benefits over a physical collectible like a stamp or rare coin. Each NFT consists of distinguishable information that makes it unique from other NFTs and makes the verification of authenticity for a collectible easier.

For example, because the genuine object can be easily linked to its legitimate user, it renders the circulation of imitation artifacts pointless for artists. Additionally, unlike other NFT cryptocoins, you cannot directly exchange NFTs with anyone for the same reason that all NFTs are non-identical or distinct. For instance, even if you have two NFCs on the same platform that are the same size, color, and part of the collection, they still won’t be identical. Let’s look at few NFT project examples:

Blockchain Heroes– It is an original trading card series highlighting the similarities between personalities in the crypto and blockchain space.

Decentraland– In this game the players are allowed to buy the virtual world owned by the users. The owner of the virtual space can monetize their world with shops, advertising, etc.– It is a blockchain-based game, where the owned assets by the players are given to them in form of blockchain, and players earn NFT based on their gameplay.

Gods unchained– It is a digital collectible card game or online collectible card game, where the cards are in the form of NFTs that can be freely bought and sold.

CryptoKitties– It is a famous NFT game that includes breeding and collecting cats. These digital cats took NFTs to the mainstream with each token having distinctive ”cattributes”.

A brief History of NFTs

You would be hard-pressed not to mention NFTs in the same breath as entrepreneurs and developers make the move to developing in a Web 3.0 era. Although it may be tempting to dismiss NFTs as simply digital art, their usefulness extends far beyond the creation of digital treasures and social media profile images.

Although the ultimate impact of NFTs on business and culture remains to be seen, their growing popularity warrants anyone with a curious mind to take a deeper look into the existing ecosystem.

In this article, we’ll briefly explore the past, present, and future of NFTs and highlight the key developments of how we got to where we are today.

The Past: When was the first NFT created?

As is often the case with innovative technology, NFTs didn’t just appear out of nowhere, becoming a household name overnight. Which naturally leads to the question: when was the first NFT created?

That depends on who you ask. Some believe Colored Coins, created in 2012, maybe the rightful owner of being the first. As investor Andrew Steinworld shared on his Medium page:

One could argue that Colored Coins are the very first NFTs to exist. Colored Coins are made of small denominations of a bitcoin and can be as small as a single satoshi, the smallest unit of a bitcoin….

Colored Coins exemplified a huge leap in Bitcoin’s capabilities, however, their downside was they could only represent certain values if everyone agrees on their worth. Bitcoin’s scripting language was never meant to enable this type of behavior within its network, thus Colored Coins were only as powerful as their weakest participant.”

Others may consider Kevin McCoy’s “Quantum” NFT minted on the Namecoin blockchain May 2nd, 2014, the rightful owner of the “first NFT title.”

In 2017, a project launched by Dapper Labs on Ethereum called “CryptoKitties” was the first widely-recognized implementation of NFTs, launching on the new ERC-721 standard for Ethereum. These digital cats became wildly popular in the crypto boom of 2017, selling for as much as 600 Eth (or $172k) at the time, and attracted mainstream attention across the world.

Since then, we’ve seen the rise of thousands of NFT projects with massive levels of success. From Beeple’s $69 million NFT auction piece to the Bored Ape Yacht Club collection, the NFT space has changed many lives and continues to shape the new world of Web 3.0. Creating an NFT continues to become easier by the day.

The Present: Ethereum and NFTs, a love story

While the origins of NFTs are up for debate, Ethereum continues to play a critical role in them going mainstream, with the vast majority of NFT projects using the Ethereum blockchain to create, host, and distribute NFTs. The most used blockchain second to Bitcoin, the Ethereum ecosystem has also been incredibly favorable to NFTs, being the first blockchain to support the ERC-721 standard.

As the Ethereum organization highlights: “NFTs and Ethereum solve some of the problems that exist in the internet today. As everything becomes more digital, there’s a need to replicate the properties of physical items like scarcity, uniqueness, and proof of ownership. Not to mention that digital items often only work in the context of their product. For example, you can’t re-sell an iTunes mp3 you’ve purchased, or you can’t exchange one company’s loyalty points for another platform’s credit even if there’s a market for it.

The differences between an NFT internet and the internet today. (Image source)

As interest in cryptocurrency continues to surge, NFTs provide a unique onboarding opportunity for those who may not understand the technical complexities that make cryptocurrency run. For many, it’s easier to “get” NFTs than it is to understand Bitcoin fully.

Furthermore, the success of projects such as CryptoKitties and CryptoPunks inspired other blockchains to invest more heavily in NFT infrastructure and further expand the functionality and access of NFTs cross-chain. While Ethereum continues to be the blockchain of choice for most things involving NFTs, there are numerous other ecosystems springing up to support the market demand for NFTs.

For instance, Dapper Labs originally built CryptoKitties on Ethereum but have since launched Flow, a new developer-friendly blockchain that also supports the wildly popular NBA Top Shot collectibles. Similarly, other blockchains such as Solana, Polygon, and Avalanche are innovating rapidly, creating healthy competition within the world of NFTs.

(Image source)

The Future: Decentralized vs centralized, and fractionalized ownership of NFTS

We’ll definitely see more original solutions and use cases that go beyond art as the NFT business develops. Gaming, music, art, and ownership will all continue to experience disruption. Naturally, a discussion on the development of the NFT ecosystem will be necessary. Some of the issues raised won’t be simple to answer.

For example, if NFTs should be fully decentralized, how do we approach the current heavy reliance on using AWS servers to host metadata and platforms? Should NFT marketplaces also be necessarily decentralized to fulfill the promise of web3?

Should the likes of OpenSea have a moral obligation to lock suspected accounts of foul play? Or is the potential of being hacked something we should all expect?  

How will the development of other ecosystems advance the ease of use and onboarding of NFTs? With the likes of Phantom and Rainbow Wallet building for a mobile first world, there’s plenty of opportunity for new players to grab a healthy piece of the NFT gold rush.

(Image source)

Will NFT royalties empower creators to the point of no longer needing a middleman to produce art and music?  

How will the exciting development of fractionalized ownership transform how average consumers invest? From attempting to own part of the U.S constitution to owning a fraction of one of the most expensive CryptoPunks, the possibilities are truly endless.

While NFTs are still in their infancy, it’s clear they will continue to play a significant role in the world we live in today.

How to Create an NFT

Before we discuss how to build an NFT using two of the most well-known marketplaces, let’s first discuss the fundamentals about what an NFT is and the choices you might have to make before opting to sell one. (If you’re a little more familiar, skip to Step 3 to start the process of actually making a token.)


You don’t need to feel bad if you don’t know anything about NFTs if you’ve come here. Perhaps a friend suggested that you market that photograph of your pet as an NFT. However, it would definitely be preferable if you had some prior knowledge of what you were doing before you went through the process of developing and selling one.

We have an entire explainer going into NFTs and the culture around them, as well as an explainer on the blockchain technology that NFTs use. You don’t have to study every word in them, but the rest of this guide will make references to things like Ethereum, proof of work, and other similar concepts that you’ll get a better understanding of by reading our explainers.

But first, a little TL;DR. Digital tokens kept on the blockchain are referred to as NFTs, or non-fungible tokens. Each NFT is unique and can be sold as proof of ownership over some form of digital file, unlike cryptocurrencies where each coin is identical (there is no reason to favor one Bitcoin over another). Nearly never is NFT artwork actually stored on the blockchain.

The files are virtually never actually kept on the blockchain itself. Instead, a link to the file and the token serving as ownership verification for the content it points to are saved. Additionally, there is no restriction that two or more NFTs cannot exist for the same file; you can have editions of NFTs, much like trading cards. For instance, an NFT can be common if thousands of the same NFT have been “minted,” or added to the blockchain, as opposed to being uncommon if there are only 10 copies. There’s also nothing to stop someone from taking the file you’ve used for your NFT and creating their own NFT with it (though the blockchain entry will show that it came from their account, not yours).

Technically, any digital file can be sold as an NFT, but if you want to use a marketplace’s simple minting facilities, you’ll only be able to use those formats. You should keep in mind that your first NFT should most likely be some kind of image, video, or audio clip. We’ll talk more about that later. Such limitations could assist you in reducing the options if you are unsure of what you want to market as an NFT. Having stated that…


There are a few things to think about if you merely have the naive notion that you want to create an NFT because it seems like everyone else is, though. Transaction costs are the first significant one. Although you can construct NFTs on the sites we’ll discuss today for free, it can be more difficult to sell them. BEFORE SELLING A SINGLE NFT, YOU COULD FINALLY INVEST A LOT OF MONEY INTO THE BUSINESS.

Most NFTs are sold on the Ethereum blockchain (we’ll touch on ones that aren’t in the next section), and every transaction on the Ethereum blockchains costs fees that are paid to the miners. These fees are called “gas,” and the amount of gas you need for a transaction (and therefore how much that transaction will cost) can vary significantly. Almost everything you do on the blockchain, from minting an NFT to transferring it to someone else to bidding to purchase one, will cost gas (though there are some ways around this for creating NFTs, which we’ll go over in a moment).

It’s also worth noting that paying gas does not 100 percent guarantee your transfer will go through. You can pay more to give yourself a higher chance, but it is never a sure thing. To be clear, most transactions are likely to go through. However, if something does happen and your transaction isn’t completed, you won’t get the gas fees you paid back.

The environmental impact of NFTs comes next. Most of the most widely used NFT marketplaces are powered by the energy-intensive “proof of work” Ethereum blockchain.. While there’s debate on whether individually selling NFTs has an effect on the overall energy use of the blockchain, if your NFTs are built on Ethereum, you are making use of a system that has a big carbon footprint.

There are blockchains that employ less energy-intensive systems, and Ethereum has plans to switch to a proof-of-stake system in the future that is more effective. However, since that hasn’t happened yet, some people might become irate if others choose to sell NFTs.


There are dozens of platforms that let you sell NFTs across a wide variety of blockchains, so it’s almost impossible for any single guide to cover them all, much less tell you which one is the right one for your project. We’ll be covering two of the more popular marketplaces in this guide, but do know that there are alternatives if neither of these platforms fit what you want to do, like AtomicHub, which uses the Wax blockchain, or the Solana-based Solsea.

At this point, it’s also important to note that our guide will teach you the fundamental techniques. Even with NFT markets, there are many deep rabbit holes you can go down that are not addressed in this book, such as selling an NFT created using OpenSea on Rarible or creating collections like Bored Apes programmatically, for example. Just keep in mind that this is only meant to lead you down the right path and is not intended to be a thorough compendium on selling NFTs.

Both OpenSea and Rarible let you create NFTs on Ethereum without paying anything, thanks to what they call “lazy minting” systems. Lazy minting lets you create an NFT and put it up for sale without it actually being written to the blockchain, thus avoiding any fees. When someone actually buys it, the fees for writing your NFT to the blockchain will be bundled with the fees to transfer it to the buyer. That helps you avoid the situation where you pay $10 to $30 (or more!) to mint an NFT that no one ends up buying.WHEN IT COMES TO MINTING NFTS, MOST OPTIONS HAVE SOME SORT OF TRADE-OFF

There can be catches — with OpenSea, listing your first Ethereum NFT for sale will require initializing your account, which will cost money (during testing in June 2022, I saw prices around the $60-70 mark). It is a one-time fee, and after paying it, you’ll be able to lazy mint NFTs without having to pay anything.

With Rarible, I didn’t have to pay this sort of fee during my testing. However, trying to remove your NFT from sale will cost a fee (I saw prices around $6-8). Both Rarible and OpenSea will take a 2.5 percent fee from any sales you make — if you sell an NFT for 0.025 ETH, you’ll actually receive 0.024375 ETH.

There are, however, alternatives to the Ethereum blockchain. Rarible lets you sell NFTs using the Flow blockchain (the same one used by NBA Top Shot) if you sign up for it using the Blocto wallet, and both it and OpenSea will let you sell using the Polygon blockchain. Both options have much lower fees than those you pay for using the Ethereum blockchain, if any fees at all, so we will at least touch on using them.HEADS UP! THE POLYGON BLOCKCHAIN HAS NOTHING TO DO WITH VOX MEDIA’S GAMING-FOCUSED OUTLET POLYGON

As you might have guessed, if there were no catches or downsides to these low / no-fee blockchains, everyone would be using them. At the time of writing, choosing to use Flow on Rarible will limit you to single edition NFTs (one of ones), and you won’t be able to sell them with an auction. Additionally, when you’re using non-Ethereum blockchains like Flow or Polygon, people can’t use Ethereum to purchase your NFTs (at least, not without going through extra, fee-inducing steps). While both platforms do let buyers add funds to their wallet to complete a purchase, having to convert or outright buy another cryptocurrency to nab your NFT may put some collectors off.

(Note: Ethereum is supported by Polygon, although it is Polygon’s version of Ethereum. You can move Ethereum directly from the main blockchain to Polygon and back, but doing so will cost you gas.)


Technically, no. You can create your own smart contract, deploy it to the blockchain of your choice, and then mint your own tokens using it. But unless you’re extremely technical, you generally won’t want to take that risk and leap right in. The majority of users will wish to use one of the platforms mentioned above.


The software you use to store your cryptocurrencies, as well as any NFTs you wind up purchasing or minting, is known as a wallet. If you’re just getting started, the major concern is utilizing a wallet that is compatible with the blockchain you’re using. Coinbase offers a more detailed description of how wallets operate and the various options that are available.

MetaMask’s wallet is one of the wallets that’s widely supported by Ethereum-based applications like OpenSea, Foundation, and others and can be used either as a Chrome / Firefox extension or as an iOS / Android app. Coinbase also has its own wallet that you can use as an extension or an app, and it’s supported by most platforms. You may want to consider Coinbase’s wallet if you’re planning on getting into crypto more broadly, as it has support for blockchains not based on Ethereum, like Bitcoin.

MetaMask and Coinbase Wallet’s setup processes are similar. Once you have the browser extension or app installed (MetaMask can be downloaded here), click or tap the “Create new wallet” button. Coinbase will ask you for a username, and both will ask you for a password, which you’ll want to make sure is secure (preferably by generating it with and saving it in a password manager).

Keep your seed phrase as secure as you possibly can — both from prying eyes and the possibility of loss. Do not post it, even a blurred version of it, on the internet (as I am doing).

Finally, both MetaMask and Coinbase will give you what’s known as a “seed phrase,” which is 12 random words. It’s very important not to lose this, as it will let you recover your account if you, say, uninstall the app or need to set up your wallet on a new device.Make a copy of it and keep it in a very secure place, like a physical safe or password manager (or both). While Coinbase Wallet will ask you if you want to save an encrypted copy of the phrase on the cloud if you set it up using the app, MetaMask will ask you to repeat the word back. It will be the same process as MetaMask, where you will need to manually input the phrase again if you’re setting up Coinbase with the extension or if you decide to manually backup the data rather than saving it to the cloud.

If you lose your password and / or security phrase, you’ll be out of luck with both MetaMask and Coinbase Wallet — neither company can do anything to help you. That means you’ll lose access to any cryptocurrency or NFTs stored in that wallet, as well as the accounts that you’ve set up using it. So seriously, keep your password and secret phrase safe.

Finally, you’ll have access to your wallet, which won’t have anything in it yet!


After setting up your wallet, you must link it to the NFT marketplace you intend to use. This is made simple by OpenSea and Rarible; just click the Create button in the upper left to be prompted to link your wallet. Following that, you’ll see a selection of supported wallets; selecting yours will then prompt you to complete the connection process.

Connecting an account with MetaMask is simple if you have the browser extension installed.

You’ll notice a pop-up asking you whether you wish to connect your wallet if Metamask or Coinbase’s extension is installed; you can do this with a few mouse clicks. You can also access the market using the QR code scanner if you’re using the Coinbase Wallet app (which you can find to the right of your balance on the main wallet screen).

The QR button in the Coinbase Wallet app lets you scan a QR code to connect to NFT marketplaces or other apps that require a wallet.

A word of caution for the future: be careful if you see a request to connect to your wallet when you don’t expect it, as scammers could be trying to access your funds or NFTs. As long as you’re on a trusted site, you should generally be okay (at least, as long as something isn’t very wrong — be sure to check transactions to make sure they’re kosher). But if an unknown site asks to connect to your wallet, you should probably think twice before accepting.


After you’ve connected your wallet, you’ll arrive at the page you use to create an NFT (and if you don’t end up there, you can get there by clicking the Create button that both platforms put in the upper right-hand corner).

A word about collections before we get started building our NFTs. Both systems feature collections, which are pretty much what they sound like. On Rarible, you can build a collection directly from the NFT creation screen, to which the NFT you’re creating will be added, if you wish to make a number of NFTs. You must first click on your profile image in the top right corner of OpenSea, then select My Collections > Create a collection.

We won’t cover collections in this guide, but OpenSea will automatically place the NFT you create into an unnamed collection if you don’t specify one (you can either edit the collection later or move the NFT to another collection), and Rarible lets you sell an NFT as a Rarible Single without a collection.

Now, let’s finally get started on our NFT.


After clicking the Create button, you’ll be brought to the create new item page. To start, click the box with an image icon in it, which will let you upload the file you’ll be selling as an NFT (though, do make sure to take note of the file size and type limitations noted above the selector).

Give your file a name or title after you’ve added it. Additionally, you can include a URL pointing to your website or Twitter account in the External Link area and use the Description section to properly describe your NFT to potential customers.

Some file types, like videos or music, will ask for a second “preview” image.

If you’ve set up a collection for your NFT, you may select it under those fields. You can also add attributes, levels, or stats that can essentially serve as metadata. This is where you would enter the details for an NFT that, for instance, may serve as a character in a video game. Use the properties tab to add details about an artwork that you’re selling, such as the medium, year, etc. However, since each of these fields is optional, many users will likely be able to ignore them.

OpenSea also lets you add text that acts as unlockable content, which the buyer / owner of the NFT will be able to see. You could use this toggle-able field to include something like an invite link to a private Discord, a code to redeem something on an external website, or even just a message thanking them for buying. You can also use the explicit and sensitive content toggle if your NFT is NSFW in nature.

Be sure to pay close attention to which blockchain you’re minting on — you can’t change it later, and it could have a drastic effect on the fees you pay.

After those toggles and fields is the dropdown you use to select which blockchain you’re minting your NFT to — the Ethereum chain or the Polygon one. You can see Step 3 for more information on the pros and cons of each, but we’re going to go with Polygon for our example, as it currently doesn’t require paying any fees. If you’re minting with Polygon, you’ll also have the option to mint multiple copies of your NFT.

After you’ve chosen your blockchain, you’ll want to double-check everything. OpenSea lets you change the metadata afterward as long as you haven’t put it up for sale, but it’s good practice to make sure everything’s shipshape before doing anything blockchain-related. And note that you won’t be able to change which blockchain the NFT is on after the fact.

After you’re good to go, you can click the Create button. Depending on the options you’ve selected and what kind of file you’re selling as an NFT, there might be a bit of a wait as things upload. After it finishes, you’ll see a screen saying that your NFT was created.

Our NFT is on OpenSea but not written to the blockchain yet — that won’t happen until someone purchases it.

However, your NFT isn’t actually up for sale on OpenSea yet — to do that, you’ll have to click off of the congratulations screen to get to your NFT’s page (you can also get to it by clicking on your profile picture, clicking on the Created tab, and selecting the NFT). On the NFT’s page, there’ll be a Sell button.

This NFT has been created, but isn’t for sale — to list it, click the Sell button.

You can choose to establish a listing for a fixed price using NFTs listed on Polygon or Ethereum, and on Ethereum, you can also choose to conduct a timed auction. For a fixed-price listing, you just need to enter the price you want to charge for the item (stated in Ethereum, but it will provide a rough conversion in dollars below) and select how long you want the ad to be live for.

OpenSea’s Polygon implementation only supports fixed-price sales at time of writing.

Since the NFT will be available to purchase as soon as you list it, you can also make it only available to a specific buyer using the “More options” dropdown.

Simply click the “Complete listing” button to submit your NFT for sale. A few transactions will require your wallet’s confirmation, either through the browser extension or the app. You will receive a screen letting you know that your item has been placed on Polygon, where transactions are free.

An example signature request in the Coinbase Wallet app.

On Ethereum, you’ll have to do a one-time approval transaction to “initialize” your wallet if it’s your first NFT, which we discussed above. To do so, you’ll need to have Ethereum in your wallet. Buying crypto could be its own separate explainer, but here’s a guide to get you started.

The cost of this transaction is totally dependent on the current price of Ethereum’s gas fees because it just pays for gas, not a charge for OpenSea. Prices from about $240 to $450 were visible in my initial tests in December 2021, but by June 2022, they had decreased to between $50 and $60. It largely relies on the price of Ethereum and the volume of transactions being attempted, so if the fees appear high you might want to wait until the price reduces. To keep track of transaction costs, use a website like ETH Gas Station or keep an eye out for a high charge warning in MetaMask.

Registering to use Ethereum with OpenSea can be expensive.

After you’ve approved and signed all the transactions, your NFT will be listed for sale on OpenSea.


Rarible will initially inquire as to which blockchain you wish to mint your NFT on, giving you the choice between Ethereum, Flow, Tezos, or Polygon. In contrast to OpenSea, the website doesn’t pay Polygon fees, so if you’re utilizing that blockchain, you’ll have to pay to mint or sell an NFT. Ethereum will be used in this example.

Rarible starts you with an option right off the bat.

After selecting a blockchain, you must pick whether you want to make a single-edition NFT or a multiple-edition NFT—that is, whether you want to construct a limited-edition NFT that can be acquired by numerous individuals or one that is one-of-one. The pages you’ll arrive at are generally the same, but for this example, we’ll select single. You can only utilize Ethereum when creating a multiple-edition, and you’ll need to specify how many copies you wish to sell.

After choosing single on Rarible, you’ll end up on the NFT creation screen. The first thing to do is upload the digital file you’re hoping to sell as an NFT, using the Choose File button. Eventually, it’ll end up on the InterPlanetary File System, or IPFS, which is a decentralized way to store media, making it so that your NFT won’t disappear off the internet if one company decides to stop hosting it.

Like OpenSea, Rarible may ask you for a separate preview image for certain types of media, like videos or music — think of this as a video thumbnail or album art, which will display whenever your NFT shows up on the site.

Rarible gives you a few options for how you’ll sell your NFT.

Next, you’ll want to set your selling options. If you don’t want to sell your NFT just yet, you can flip off the “Put on marketplace” switch, which is on by default. If you do want to sell your NFT, though, you’ll have options.

  • “Fixed price” is like creating a store listing — you set a price for your NFT, and if someone wants to pay that price, they can just buy it.
  • “Open for bids” lets people submit offers to buy your NFT, which you can either accept or reject.
  • “Timed auction” is an auction — you can set a minimum price and choose when the auction will start and how long it will last.

We’ll use listing our NFT for a fixed price in this example, which we may do by typing it into the form. Additionally, you have a choice of the currency you want to receive (people can, however, send offers in different currencies). Keep in mind that Rarible will deduct 2.5 percent from the sale price of your NFT when determining your asking price.

After you choose your selling method and details, you’ll have the option to add unlockable content, which will be provided to the buyer. This could be something like an invite link to a private Discord, a code to redeem something on an external website, or even just a message thanking them for buying.

The following two options allow you to select your collection (we’ll use Rarible Singles as an example) and the Free Minting option, which allows you to decide whether to use Step 3-discussed Rarible’s lazy minting mechanism. You may need to pay a gas cost to mint your NFT at the end of this process if you disable it and are using the Ethereum network; the fee I tested was roughly $20.

Name and description will be important to help you stand out. Most people will want to leave the free minting option on.

The next step is to give your NFT a name, or title, and, if you choose, a description. The royalty % is the last option. This will alter the percentage of future sales that you receive as compensation. For instance, if someone buys your NFT for 0.2 ETH and then sells it for 1 ETH, you’ll also receive a portion of that sale (10% by default) (so 0.1 ETH in our example).

The last option is the Advanced Settings, which lets you add properties to your NFT (which is completely optional but could be useful if you were creating a series of characters with different properties) and alternative description text, which will help make your NFT more accessible.

Double-check that everything is exactly how you want it, as it could be expensive or impossible to change later. Then, when you’re sure your NFT is good to go, click the “Create Item” button.

Your wallet, in this case MetaMask, will ask you to sign a few transactions.

When you do this, a series of events will begin, during which you’ll need to authorize some transactions using your wallet. When Rarible requests your signature, if you’re using a browser extension, you should get a pop-up (if not, you may click on the extension’s icon in your browser, and it should present you with any requests). Open the app on your phone if you’re using one so that you can see the request there.

Your NFT has been created!

You’ll receive a notice stating that your NFT has been created after approving a few wallet requests and a brief delay. You can view it by clicking the “View NFT” button, and you can access your collection by clicking “My Profile” next to your profile photo in the top right corner.


If your wallet includes an NFT section and the NFT you created following this method doesn’t appear in it, don’t panic. Lazy minted NFTs aren’t actually written to the blockchain until someone buys them, so they won’t appear in your wallet right away. Your wallet reads entries from the blockchain to determine what it should display.


If all went according to plan, you should now have an NFT available for purchase on Rarible, OpenSea, or both. However, as sellers have informed me, that won’t likely get you very far. As you’ve seen, the procedure is fairly difficult, but the milieu surrounding NFTs is similar to a gold rush, which has encouraged many people to try their hand at producing one. You’ll probably need to find a way to stand out from the crowd if you want your product to actually sell, whether it’s through slick marketing or creating art that is truly special (and then probably doing some snazzy marketing). I’ll leave that responsibility in your hands, though.

What is NFT Used For?

People interested in Crypto-trading and people who like to collect artwork often use NFTs. Other than that, it has some other uses too like:

  • Digital Content – Digital material is currently where NFTs are used most extensively. NFTs fuel a creator economy where creators transfer ownership of their work to the platforms they use to promote it, boosting the profitability of content providers.
  • Gaming Items – NFTs have garnered considerable interest from game developers. NFTs can provide a lot of benefits to the players. Normally, in an online game, you can buy items for your character, but that’s as far as it goes. With NFTs, you can recoup your money by selling the items once you’re finished with them.
  • Investment and Collaterals -The infrastructure is shared by DeFi (Decentralized Finance) and NFT. DeFi programs allow you to borrow money with the use of security. Together, NFT and DeFi investigate the possibility of using NFTs as collateral instead.
  • Domain Names – NFTs provide your domain with an easier-to-remember name. This works like a website domain name, making its IP address more memorable and valuable, usually based on length and relevance.

Even celebrities like Snoop Dogg, Shawn Mendes, and Jack Dorsey are taking an interest in the NFT by releasing unique memories and artwork and selling them as securitized NFTs.

How to Mint an NFT Using Ethers.js

The ethers.js library, our smart contract from Part I: How to Create an NFT, and Ethers are used to mint an NFT on the Ethereum network in this tutorial. We’ll also look at fundamental tests.

In this exercise, we’re going to walk you through an alternative implementation using version 4 of the OpenZeppelin library as well as the Ethers.js Ethereum library instead of Web3.

We’ll also cover the basics of testing your contract with Hardhat and Waffle. For this tutorial I’m using Yarn, but you can use npm/npx if you prefer.

Lastly, we’ll use TypeScript. This is fairly well documented, so we won’t cover it here.

In all other respects, this tutorial works the same as the Web3 version, including tools such as Pinata and IPFS.

A Quick Reminder

As a reminder, “minting an NFT” is the act of publishing a unique instance of your ERC721 token on the blockchain. This tutorial assumes that that you’ve successfully deployed a smart contract to the Goerli network in Part I of the NFT tutorial series, which includes .

Step 1: Create your Solidity contract

OpenZeppelin is a library for creating safe smart contracts. You just extend the behavior to suit your needs by inheriting their implementations of well-known standards like ERC20 or ERC721. This file will be located at contracts/MyNFT.sol.

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

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

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

    constructor() ERC721("MyNFT", "MNFT") {}

    function mintNFT(address recipient, string memory tokenURI)
    returns (uint256)

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

        return newItemId;

Step 2: Create Hardhat tasks to deploy our contract and mint NFT’s

Create the file tasks/nft.ts containing the following:

import { task, types } from "hardhat/config";
import { Contract } from "ethers";
import { TransactionResponse } from "@ethersproject/abstract-provider";
import { env } from "../lib/env";
import { getContract } from "../lib/contract";
import { getWallet } from "../lib/wallet";

task("deploy-contract", "Deploy NFT contract").setAction(async (_, hre) => {
  return hre.ethers
    .getContractFactory("MyNFT", getWallet())
    .then((contractFactory) => contractFactory.deploy())
    .then((result) => {
      process.stdout.write(`Contract address: ${result.address}`);

task("mint-nft", "Mint an NFT")
  .addParam("tokenUri", "Your ERC721 Token URI", undefined, types.string)
  .setAction(async (tokenUri, hre) => {
    return getContract("MyNFT", hre)
      .then((contract: Contract) => {
        return contract.mintNFT(env("ETH_PUBLIC_KEY"), tokenUri, {
          gasLimit: 500_000,
      .then((tr: TransactionResponse) => {
        process.stdout.write(`TX hash: ${tr.hash}`);

Step 3: Create helpers

You’ll notice our tasks imported a few helpers. Here they are.


import { Contract, ethers } from "ethers";
import { getContractAt } from "@nomiclabs/hardhat-ethers/internal/helpers";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { env } from "./env";
import { getProvider } from "./provider";

export function getContract(
  name: string,
  hre: HardhatRuntimeEnvironment
): Promise {
  const WALLET = new ethers.Wallet(env("ETH_PRIVATE_KEY"), getProvider());
  return getContractAt(hre, name, env("NFT_CONTRACT_ADDRESS"), WALLET);


export function env(key: string): string {
  const value = process.env[key];
  if (value === undefined) {
    throw `${key} is undefined`;
  return value;


Note that the final getProvider() function uses the ropsten network. This argument is optional and defaults to “homestead” if omitted. We’re using Alchemy of course, but there are several supported alternatives.

import { ethers } from "ethers";

export function getProvider(): ethers.providers.Provider {
  return ethers.getDefaultProvider("ropsten", {
    alchemy: process.env.ALCHEMY_API_KEY,


import { ethers } from "ethers";
import { env } from "./env";
import { getProvider } from "./provider";

export function getWallet(): ethers.Wallet {
  return new ethers.Wallet(env("ETH_PRIVATE_KEY"), getProvider());

Step 4: Create tests

Make these files in your test directory. Please take note that these tests are not exhaustive. They are designed to give you the building blocks to develop more thorough tests by only testing a small portion of the OpenZeppelin library’s ERC721 capabilities.

test/MyNFT.spec.ts (unit tests)

import { ethers, waffle } from "hardhat";
import { Contract, Wallet } from "ethers";
import { expect } from "chai";
import { TransactionResponse } from "@ethersproject/abstract-provider";
import sinon from "sinon";
import { deployTestContract } from "./test-helper";
import * as provider from "../lib/provider";

describe("MyNFT", () => {
  const TOKEN_URI = "";
  let deployedContract: Contract;
  let wallet: Wallet;

  beforeEach(async () => {
    sinon.stub(provider, "getProvider").returns(waffle.provider);
    [wallet] = waffle.provider.getWallets();
    deployedContract = await deployTestContract("MyNFT");

  async function mintNftDefault(): Promise {
    return deployedContract.mintNFT(wallet.address, TOKEN_URI);

  describe("mintNft", async () => {
    it("emits the Transfer event", async () => {
      await expect(mintNftDefault())
        .to.emit(deployedContract, "Transfer")
        .withArgs(ethers.constants.AddressZero, wallet.address, "1");

    it("returns the new item ID", async () => {
      await expect(
        await deployedContract.callStatic.mintNFT(wallet.address, TOKEN_URI)

    it("increments the item ID", async () => {
      const STARTING_NEW_ITEM_ID = "1";
      const NEXT_NEW_ITEM_ID = "2";

      await expect(mintNftDefault())
        .to.emit(deployedContract, "Transfer")

      await expect(mintNftDefault())
        .to.emit(deployedContract, "Transfer")

    it("cannot mint to address zero", async () => {
      const TX = deployedContract.mintNFT(
      await expect(TX)"ERC721: mint to the zero address");

  describe("balanceOf", () => {
    it("gets the count of NFTs for this address", async () => {
      await expect(await deployedContract.balanceOf(wallet.address)).to.eq("0");

      await mintNftDefault();

      expect(await deployedContract.balanceOf(wallet.address)).to.eq("1");

tasks.spec.ts (integration specs)

import { deployTestContract, getTestWallet } from "./test-helper";
import { waffle, run } from "hardhat";
import { expect } from "chai";
import sinon from "sinon";
import * as provider from "../lib/provider";

describe("tasks", () => {
  beforeEach(async () => {
    sinon.stub(provider, "getProvider").returns(waffle.provider);
    const wallet = getTestWallet();
    sinon.stub(process, "env").value({
      ETH_PUBLIC_KEY: wallet.address,
      ETH_PRIVATE_KEY: wallet.privateKey,

  describe("deploy-contract", () => {
    it("calls through and returns the transaction object", async () => {
      sinon.stub(process.stdout, "write");

      await run("deploy-contract");

      await expect(process.stdout.write).to.have.been.calledWith(
        "Contract address: 0x610178dA211FEF7D417bC0e6FeD39F05609AD788"

  describe("mint-nft", () => {
    beforeEach(async () => {
      const deployedContract = await deployTestContract("MyNFT");
      process.env.NFT_CONTRACT_ADDRESS = deployedContract.address;

    it("calls through and returns the transaction object", async () => {
      sinon.stub(process.stdout, "write");

      await run("mint-nft", { tokenUri: "" });

      await expect(process.stdout.write).to.have.been.calledWith(
        "TX hash: 0xd1e60d34f92b18796080a7fcbcd8c2b2c009687daec12f8bb325ded6a81f5eed"

test-helpers.ts Note this requires the NPM libraries imported, including Sinon, chai, and Sinon-chai. The sinon.restore() call is necessary due to the use of stubbing.

import sinon from "sinon";
import chai from "chai";
import sinonChai from "sinon-chai";
import { ethers as hardhatEthers, waffle } from "hardhat";
import { Contract, Wallet } from "ethers";


afterEach(() => {

export function deployTestContract(name: string): Promise {
  return hardhatEthers
    .getContractFactory(name, getTestWallet())
    .then((contractFactory) => contractFactory.deploy());

export function getTestWallet(): Wallet {
  return waffle.provider.getWallets()[0];

Step 5: Configuration

Here’s our fairly bare bones hardhat.config.ts.

import dotenv from "dotenv";
// You need to export an object to set up your config
// Go to to learn more

const argv = JSON.parse(env("npm_config_argv"));
if (argv.original !== ["hardhat", "test"]) {


import { HardhatUserConfig } from "hardhat/config";

const config: HardhatUserConfig = {
  solidity: "0.8.6",

export default config;

Note the conditional to only invoke dotenv if we’re not running tests. You might not want to run this in production, but rest assured that dotenv will silently ignore it if the .env file isn’t present.

Running Our Tasks

Now that we’ve put these files in place, we can run hardhat to see our tasks (excluding the built-in tasks for brevity).


  deploy-contract    Deploy NFT contract
  mint-nft      Mint an NFT

Forget the arguments to your task? No problem.

$ hardhat help deploy-contract

Usage: hardhat [GLOBAL OPTIONS] deploy-contract

deploy-contract: Deploy NFT contract

Running Our Tests

To run our tests, we run hardhat test.

    ✓ calls through and returns the transaction object (60ms)

      ✓ emits the Transfer event (60ms)
      ✓ returns the new item ID
      ✓ increments the item ID (57ms)
      ✓ cannot mint to address zero
      ✓ gets the count of NFTs for this address

  6 passing (2s)

✨  Done in 5.66s.

In this tutorial, we’ve created a firm foundation for a well-tested NFT infrastructure based on Solidity. The wallet is provided by waffle.provider.getWallets() links to a local fake Hardhat Network account that conveniently comes preloaded with an eth balance that we can use to fund our test transactions.

How to Set a Price on an NFT

You’ve just created an NFT and you want to sell it to your fellow NFT enthusiasts. To do this, we have to put a price on the NFT, and there are two primary ways to attach a price:

  1. Within the smart contract (this guide)
  2. Listing the NFT on an NFT marketplace or platform (a more popular approach)

Setting an NFT Price In-Contract

Require a Fee Upon Minting

Since the fee mechanism is integrated into the minting process itself and occurs in contract, this fee pattern is totally decentralized. You must modify your smart contract to reflect this behavior in order to place a price on minting. An NFT minting fee can be implemented by making the mint function pay-to-use and forcing the user to deposit a certain amount of ETH before the NFT is transferred to the buyer.

Here’s a sample piece of code for this type of minting process:

function mintToken(address to, uint256 tokenId, string uri) public virtual payable {

  require(msg.value >= 10, "Not enough ETH sent; check price!");

  mint(to, tokenId);
  _setTokenURI(tokenId, uri);

function mintToken(address to, uint256 tokenId, string uri) public virtual payable

  • We need to make this function payable and public so that users can pay ETH to mint an NFT. Internally or through messages, public functions can be used by anyone to interact with them. (We don’t want the owner of the contract to be the only one who can call this function; otherwise, potential buyers would not be able to use it.)

require(msg.value >= 10, “Not enough ETH sent; check price!”);

  • This require statement requires that the payable function receive at least 10 wei, else the function will fail and revert. The msg.value parameter is the ETH value of amount sent in alongside the mint function.

mint(to, tokenId);

  • This calls the mint function included in OpenZepplin’s ERC721 contract file and  instantiates/transfers the selected NFT to the buyer.

_setTokenURI(tokenId, uri);

  • This calls the _setTokenURIfunction included in OpenZepplin’s ERC721 contract file and sets the NFT URI to a particular endpoint.  

‌There are many different variants for implementing fees into minting contracts.  The one listed above is one of the most simple but many protocols also use fee patterns that are significantly more complex.

Setting an NFT Price via Auction Platforms

List the NFT on OpenSea or Another NFT Auction Platform

A non-coding alternative would be to simply list your newly minted NFT on OpenSea or another NFT auction website which would allow you to place a price on it. OpenSea’s UI layer running on top of the NFT allows you to place prices, accept bids, or have other more complex auction methods and handles all the logic for you.

For Ethereum mainnet, use:

For a testnet, use:

NOTE: NFT auction platforms typically charge for listing and handling the auction process. Keep to date with different platforms to find competitive rates and maximize your NFT sales. Zora and SuperRare are two alternative platforms that also offer similar services to OpenSea.

How to Build a Full-Stack NFT dApp

In this tutorial, you’ll build an NFT minter and learn how to create a full stack dApp by connecting your smart contract to a React frontend using Metamask and Web3 tools.

One of the greatest challenges for developers coming from a Web2 background is figuring out how to connect your smart contact to a frontend project and interact with it.

By building an NFT minter—a simple UI where you can input a link to your digital asset, a title,  and a description —you’ll learn how to:

  • Connect to Metamask via your frontend project
  • Call smart contract methods from your frontend
  • Sign transactions using Metamask

In this tutorial, we will be using React as our frontend framework. Because this tutorial is primarily focused on Web3 development, we won’t be spending much time breaking down React fundamentals. Instead, we’ll be focusing on bringing functionality to our project

As a prerequisite, you should have a beginner-level understanding of React—know how components, props, useState/useEffect, and basic function calling works. If you’ve never heard of any of those terms before, you may want to check out this Intro to React tutorial. For the more visual learners, we highly recommend this excellent Full Modern React Tutorial video series by Net Ninja.

Without further ado, let’s get started!


In order to build a full stack NFT minting dapp and be successful in this guide, you must have the following:

  • Node.js installed on your machine
  • Metamask wallet extension installed as a browser extension.

New to all this, learn here to set up your MetaMask account.


About the project: Build a full stack NFT minting dapp

Going forward be will build a full stack NFT minting dapp using SolidityHardhatethers.jsNext.js, and TailwindCSS.

build full stack NFT minting dapp
  • To view the final source code for this project, visit this repo
  • To view the deployed site visit this website

Project setup

To get started we need to create a hardhat project. To do so, open your terminal. Create or change into a new empty directory and run the following command:

npm install ethers hardhat @nomiclabs/hardhat-waffle \
ethereum-waffle chai @nomiclabs/hardhat-ethers \
@openzeppelin/contracts dotenv

This will install the dependencies for setting up a hardhat project and some other dependencies for the project.

Next, initialize a new Hardhat development environment from the root of your project. To do so, run the following command in your terminal:

npx hardhat

The output will be similar to what is shown below. Select Create a basic sample project to create a new hardhat project in your directory.

What do you want to do? … 
Create a basic sample project
Create an advanced sample project
. . .

Now you should see the following files and folders created for you in your root directory:

hardhat.config.js – The entirety of your Hardhat setup (i.e. your config, plugins, and custom tasks) is contained in this file.

scripts – A folder containing a script named sample-script.js that will deploy your smart contract when executed.

test – A folder containing an example testing script.

contracts – A folder holding an example Solidity smart contract.

Now, we need to create a new Next.js project for the frontend of the dapp. To do so, run the following command in your terminal:

npx create-next-app -e with-tailwindcss client

This will create a new Next project using tailwindcss for styling in a folder ‘client’.

After this install dependencies for the frontend inside the client folder. To do this run the following command in your terminal:

cd client

npm install axios ethers react-loader-spinner

Creating an Ethereum API key using Alchemy

Alchemy is a platform for blockchain developers that aims to make blockchain development simple. To make creating and running blockchain apps simple, they have created a set of developer tools, improved APIs, and superior node infrastructure.

To create an API key follow the video below. Things to note:

  • Select the network as rinkeby.
  • Copy the HTTP key after the creation of the app on alchemy.

Next, create a .env file to store your Alchemy key and your Account Private Key


Important: Do not push the .env file to GitHub as it contains your private data.

Updating hardhat.config.js

After this, update the configuration at hardhat.config.js with the following:


module.exports = {
    solidity: '0.8.3',
    networks: {
        rinkeby: {
            url: process.env.ALCHEMY_RINKEBY_URL,
            accounts: [process.env.ACCOUNT_KEY],

Creating Smart Contract logic

Next, we’ll create our smart contracts! We’ll create an NFT contract for the creation of NFT assets. Create a new file in the contracts directory named EternalNFT.sol. Here, add the following code:

You can view the gist at EternalNFT.sol

//SPDX-License-Identifier: MIT
pragma solidity 0.8.3;

import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import { Base64 } from "./libraries/Base64.sol";

contract EternalNFT is ERC721URIStorage {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenId;

    string public collectionName;
    string public collectionSymbol;

    string baseSvg = "

"; string[] element = [ 'Fire', 'Wind', 'Wave', 'Earth', 'Thunder', 'Space', 'Time' ]; string[] weapon = [ 'Sword', 'Spear', 'Shield', 'Hammer', 'Saber', 'Axe', 'Bow' ]; string[] rank = [ 'Lord', 'King', 'Emperor', 'Venerable', 'Ancestor', 'Saint', 'God' ]; constructor() ERC721("EternalNFT", "ENFT") { collectionName = name(); collectionSymbol = symbol(); } function random(string memory _input) internal pure returns(uint256) { return uint256(keccak256(abi.encodePacked(_input))); } function pickFirstWord(uint256 tokenId) public view returns(string memory) { uint256 rand = random(string(abi.encodePacked("element", Strings.toString(tokenId)))); rand = rand % element.length; return element[rand]; } function pickSecondWord(uint256 tokenId) public view returns(string memory) { uint256 rand = random(string(abi.encodePacked("weapon", Strings.toString(tokenId)))); rand = rand % weapon.length; return weapon[rand]; } function pickThirdWord(uint256 tokenId) public view returns(string memory) { uint256 rand = random(string(abi.encodePacked("rank", Strings.toString(tokenId)))); rand = rand % rank.length; return rank[rand]; } function createEternalNFT() public returns(uint256) { uint256 newItemId = _tokenId.current(); string memory first = pickFirstWord(newItemId); string memory second = pickSecondWord(newItemId); string memory third = pickThirdWord(newItemId); string memory combinedWord = string(abi.encodePacked(first,second,third)); string memory finalSvg = string(abi.encodePacked(baseSvg, first, second, third, "")); string memory json = Base64.encode( bytes( string( abi.encodePacked( '{"name": "', combinedWord, '", "description": "A highly acclaimed collection Eternal Warriors", "image": "data:image/svg+xml;base64,', Base64.encode(bytes(finalSvg)), '"}' ) ) ) ); string memory finalTokenURI = string(abi.encodePacked( "data:application/json;base64,", json )); _safeMint(msg.sender, newItemId); _setTokenURI(newItemId, finalTokenURI); _tokenId.increment(); return newItemId; } } 

In this contract, we are inheriting from the ERC721ERC721URIStorage.sol and Counters.sol implemented by OpenZeppelin

For the Base64 library that is inherited by the contract, create a libraries folder inside the contracts folder. Inside the libraries, folder create a Base64.sol file add the following code:

You can view the gist at Base64.sol

 *Submitted for verification at on 2021-09-05

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <>
library Base64 {
    bytes internal constant TABLE =

    /// @notice Encodes some bytes to the base64 representation
    function encode(bytes memory data) internal pure returns (string memory) {
        uint256 len = data.length;
        if (len == 0) return "";

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((len + 2) / 3);

        // Add some extra buffer at the end
        bytes memory result = new bytes(encodedLen + 32);

        bytes memory table = TABLE;

        assembly {
            let tablePtr := add(table, 1)
            let resultPtr := add(result, 32)

            for {
                let i := 0
            } lt(i, len) {

            } {
                i := add(i, 3)
                let input := and(mload(add(data, i)), 0xffffff)

                let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
                out := shl(8, out)
                out := add(
                    and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF)
                out := shl(8, out)
                out := add(
                    and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF)
                out := shl(8, out)
                out := add(
                    and(mload(add(tablePtr, and(input, 0x3F))), 0xFF)
                out := shl(224, out)

                mstore(resultPtr, out)

                resultPtr := add(resultPtr, 4)

            switch mod(len, 3)
            case 1 {
                mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
            case 2 {
                mstore(sub(resultPtr, 1), shl(248, 0x3d))

            mstore(result, encodedLen)

        return string(result);

Testing the Smart Contracts

Now the smart contract code and environment are complete and we can try testing it out.

To do so, we can create a local test to run through much of the functionality, like checking for the name, symbol, and address of the token, minting a token, etc.

To create the test, open test/sample-test.js and update it with the following code:

You can view the gist at sample-test.js

const { assert } = require('chai')

describe('EternalNFT Contract', async () => {
    let nft
    let nftContractAddress
    let tokenId

    // Deploys the EternalNFT contract and the EternalMarket contract before each test
    beforeEach('Setup Contract', async () => {
        const EternalNFT = await ethers.getContractFactory('EternalNFT')
        nft = await EternalNFT.deploy()
        await nft.deployed()
        nftContractAddress = await nft.address

    // Tests address for the EternalNFT contract
    it('Should have an address', async () => {
        assert.notEqual(nftContractAddress, 0x0)
        assert.notEqual(nftContractAddress, '')
        assert.notEqual(nftContractAddress, null)
        assert.notEqual(nftContractAddress, undefined)

    // Tests name for the token of EternalNFT contract
    it('Should have a name', async () => {
        // Returns the name of the token
        const name = await nft.collectionName()

        assert.equal(name, 'EternalNFT')

    // Tests symbol for the token of EternalNFT contract
    it('Should have a symbol', async () => {
        // Returns the symbol of the token
        const symbol = await nft.collectionSymbol()

        assert.equal(symbol, 'ENFT')

    // Tests for NFT minting function of EternalNFT contract using tokenID of the minted NFT
    it('Should be able to mint NFT', async () => {
        // Mints a NFT
        let txn = await nft.createEternalNFT()
        let tx = await txn.wait()

        // tokenID of the minted NFT
        let event =[0]
        let value = event.args[2]
        tokenId = value.toNumber()

        assert.equal(tokenId, 0)

        // Mints another NFT
        txn = await nft.createEternalNFT()
        tx = await txn.wait()

        // tokenID of the minted NFT
        event =[0]
        value = event.args[2]
        tokenId = value.toNumber()

        assert.equal(tokenId, 1)

To run the test, run the following command from your terminal at the root of your project:

npx hardhat test

Deploying the contracts to the Rinkeby Network

When we created the project, Hardhat created an example deployment script at scripts/sample-script.js.

To make the purpose of this script clear, delete scripts/sample-script.js and create scripts/deploy.js.

To deploy the contracts add the following code inside deploy.js:

const main = async () => {
    const nftContractFactory = await ethers.getContractFactory('EternalNFT')
    const nftContract = await nftContractFactory.deploy()
    await nftContract.deployed()
    console.log('Contract deployed to:', nftContract.address)

const runMain = async () => {
    try {
        await main()
    } catch (error) {


To deploy the contract to the rinkeby network run the following command in your terminal:

npx hardhat run scripts/deploy.js --network rinkeby

This will deploy the contract to the rinkeby network and output the address at which the contract is deployed in the terminal.

Building the frontend

Now that the smart contract is working and ready to go, we can start building out the UI.

First, we need to connect the frontend to the smart contract, so it can interact with the data from the blockchain using the functions in the smart contracts.

For this we need to do the following:

  • Create a utils folder inside the client folder and copy and paste the artifacts/contracts/EternalNFT.sol/EternalNFT.json file inside the utils folder.
  • Create a config.js file inside the client folder and add the following code inside it.
export const nftContractAddress = "DEPLOYED_CONTRACT_ADDRES"

Replace the DEPLOYED_CONTRACT_ADDRES with the deployed contract address from the terminal when deploying the smart contract.

Next, to set up the frontend go to client/pages/index.js and update it with the following code:

You can view the gist at index.js

import { useState, useEffect } from 'react'
import { nftContractAddress } from '../config.js'
import { ethers } from 'ethers'
import axios from 'axios'

import Loader from 'react-loader-spinner'

import NFT from '../utils/EternalNFT.json'

const mint = () => {
    const [mintedNFT, setMintedNFT] = useState(null)
    const [miningStatus, setMiningStatus] = useState(null)
    const [loadingState, setLoadingState] = useState(0)
    const [txError, setTxError] = useState(null)
    const [currentAccount, setCurrentAccount] = useState('')
    const [correctNetwork, setCorrectNetwork] = useState(false)

    // Checks if wallet is connected
    const checkIfWalletIsConnected = async () => {
        const { ethereum } = window
        if (ethereum) {
            console.log('Got the ethereum obejct: ', ethereum)
        } else {
            console.log('No Wallet found. Connect Wallet')

        const accounts = await ethereum.request({ method: 'eth_accounts' })

        if (accounts.length !== 0) {
            console.log('Found authorized Account: ', accounts[0])
        } else {
            console.log('No authorized account found')

    // Calls Metamask to connect wallet on clicking Connect Wallet button
    const connectWallet = async () => {
        try {
            const { ethereum } = window

            if (!ethereum) {
                console.log('Metamask not detected')
            let chainId = await ethereum.request({ method: 'eth_chainId' })
            console.log('Connected to chain:' + chainId)

            const rinkebyChainId = '0x4'

            const devChainId = 1337
            const localhostChainId = `0x${Number(devChainId).toString(16)}`

            if (chainId !== rinkebyChainId && chainId !== localhostChainId) {
                alert('You are not connected to the Rinkeby Testnet!')

            const accounts = await ethereum.request({ method: 'eth_requestAccounts' })

            console.log('Found account', accounts[0])
        } catch (error) {
            console.log('Error connecting to metamask', error)

    // Checks if wallet is connected to the correct network
    const checkCorrectNetwork = async () => {
        const { ethereum } = window
        let chainId = await ethereum.request({ method: 'eth_chainId' })
        console.log('Connected to chain:' + chainId)

        const rinkebyChainId = '0x4'

        const devChainId = 1337
        const localhostChainId = `0x${Number(devChainId).toString(16)}`

        if (chainId !== rinkebyChainId && chainId !== localhostChainId) {
        } else {

    useEffect(() => {
    }, [])

    // Creates transaction to mint NFT on clicking Mint Character button
    const mintCharacter = async () => {
        try {
            const { ethereum } = window

            if (ethereum) {
                const provider = new ethers.providers.Web3Provider(ethereum)
                const signer = provider.getSigner()
                const nftContract = new ethers.Contract(

                let nftTx = await nftContract.createEternalNFT()
                console.log('Mining....', nftTx.hash)

                let tx = await nftTx.wait()
                console.log('Mined!', tx)
                let event =[0]
                let value = event.args[2]
                let tokenId = value.toNumber()

                    `Mined, see transaction:${nftTx.hash}`

            } else {
                console.log("Ethereum object doesn't exist!")
        } catch (error) {
            console.log('Error minting character', error)

    // Gets the minted NFT data
    const getMintedNFT = async (tokenId) => {
        try {
            const { ethereum } = window

            if (ethereum) {
                const provider = new ethers.providers.Web3Provider(ethereum)
                const signer = provider.getSigner()
                const nftContract = new ethers.Contract(

                let tokenUri = await nftContract.tokenURI(tokenId)
                let data = await axios.get(tokenUri)
                let meta =

            } else {
                console.log("Ethereum object doesn't exist!")
        } catch (error) {

    return (

Mint your Eternal Domain NFT!

{currentAccount === ” ? ( ) : correctNetwork ? ( ) : (

Please connect to the Rinkeby Testnet
and reload the page


{loadingState === 0 ? ( miningStatus === 0 ? ( txError === null ? (

Processing your transaction

) : (


) ) : (

) ) : (

Your Eternal Domain Character



export default mint

Let’s discuss the code we have added to the index.js file

The code contains the following functions:

  • checkIfWalletIsConnected: This function checks if the wallet is connected to the app when it loads.
  • connectWallet: This function connects the wallet to the app when the user clicks the Connect Wallet button on the front.
  • checkCorrectNetwork: This function checks if the wallet is connected to the rinkeby network. If not the frontend asks the user to connect to the rinkeby network and reload the page.
  • mintCharacter: This function creates the transaction to mint a new NFT when the user clicks on the Mint Character button.
  • getMintedNFT: This function retrieves the data of the newly minted NFT to display it in the frontend.

To test the app in the browser, run the following command in your terminal:

cd client

npm run dev

Next steps?

Congratulations! Here’s how to build a Full Stack NFT minting Dapp using Hardhat, ethers.js, Next.js, and TailwindCSS. You most likely have deployed a full-stack NFT minting app to Ethereum by now.

After successfully deploying the app, you can host it on services like vertical or netlify.

Building a Successful NFT Project

In a nutshell, NFTs enable digital scarcity. We know real-world objects are scarce in their nature to have value. NFTs enable objects and data on the internet to be valuable.

It is not enough to create a number of works of art and then wait for a buyer to come along. It all depends on how involved and supportive the community is. To create a good NFT project, you must fully comprehend the procedures below. There are no absolute laws; rather, they are more like regulations that you can abide by.

Step 1: Write Down Your Story

This suggestion may seem like a no-brainer, but it is the most important one. The simplest suggestions are the most difficult to pull off. But you can make it easy by knowing you’re why. So, write it down. Answer the below questions on a piece of paper or type it out on a word document.

  • Why are you making your NFT project?
  • What is the purpose of your NFT project?
  • Why do you want to tell people about it?
  • What type of value is it going to provide to your community?
  • Why is your NFT project important?

This phase is covered by the last query. After all, why are you acting in the way that you are? Don’t undervalue the importance of this query. Thus, you’re mistaken if you believe that successful NFT enterprises are represented by images on the blockchain. The most effective NFT initiatives make clear why they exist. They clearly communicate their value to the people in their neighborhood. They express their goals clearly and with heart and humor. For your project, you must take the same action.

So it’s time to put your thinking cap on. Your NFT story has to be compelling. Successful NFT projects have clear answers in the form of a narrative and vision like world-class companies. At the end of the day, it’s the story that captures the attention and the wallets of people.

Step 2: Choose the Blockchain and Marketplace

Ethereum is the most popular blockchain out there. The Ethereum community has been at the forefront of NFTs, Defi, and DAOs. As a result, you have options. There are other blockchains on which you can launch your project on. Some of them include Binance Smart Chain, Cosmos, Polkadot, Avalanche, Solana, Fantom, etc.

You can also specify which markets you want customers to use to purchase your NFT collection. NFTically, MakersPlace, and others are some of the well-known ones. You may really launch your NFT collection integrated with several marketplaces and blockchains at once using marketplaces like NFTically. You can receive a portion of all upcoming secondary sales in the form of royalties thanks to smart contracts.

Step 3: Decide what kind of features and utilities your NFTs will have

While you can take the help of marketplaces to help you understand how to navigate through these, it is better if you decide for yourself. Ask yourself the following questions.

  • Do you want the NFTs to live on or off-chain?
  • How much should be the maximum mint amount?
  • Who will mint the NFTs? You or the public?
  • How will features like randomness, rarity, and voting rights work?
  • What’re the utilities you can provide? Anything special or exciting?

Always remember that features like mint amount, rarity, and royalty percentages are fixed after the NFTs are minted. As for the other features, make sure to specify them right at the start. Either in the smart contract or the whitepaper.

Step 4: Build your Community

Every NFT project is a story at the end of the day. A story that your community deeply believes in. So make sure you adhere to the following points.

  • Social media is your friend. Twitter, Discord, Instagram, Telegram, etc. Learn social media marketing or find someone who does. This is the place to talk to people and get to know them
  • Build a world-class website. Keep it clean, simple, and SEO friendly.
  • Create videos, photos, and written content
  • Do frequent AMAs and communicate the vision of your NFT project
  • Reach out to social media influencers and convince them to help you market your project

Always remember that successful NFT projects are not made overnight. But that does not mean you cannot start your online community right now! If you’ve an idea or a vision, start right now.

Step 5: Continue Innovating and Create as much value as possible

Every successful NFT project ensures that its community members continue to benefit above and beyond what was promised. This is because the NFT world is very dynamic. Although NFTs as a phenomenon is here to stay, remember that your NFT project will become successful when lots of different people see value in them.

Value can be both subjective and objective. If the point was not made clear, go back to step one and return to this page. Numerous NFT ventures are popular for a short period of time thanks to viral marketing, but they eventually fail because not enough people could connect with them personally or in their communities. Create an NFT project with a unique tale as a consequence. However, you should also make sure to occasionally innovate the story as needed. Your community’s ideals are always subject to change.

Building an NFT project is advantageous for numerous reasons. One of them is the fact that NFTs are now widely used and are about to overtake other markets and industries in terms of market share. Therefore, this is the ideal time to debut. Make careful, nevertheless, that the project does not become one of the numerous others that never materialize because their true reason for being was never discovered.

How to View Your NFT in Your Mobile Wallet

This tutorial describes how to view an existing NFT on your Mobile Metamask wallet.

Congrats! You’ve made it to the shortest and simplest part of our NFT tutorial series:  how to view your freshly minted NFT in your virtual wallet. We’ll be using Metamask for this example since it is what we used in the previous two parts.

As a prerequisite, you should already have Metamask on mobile installed, and it should include the account to which you minted your NFT — you can get the app for free on iOS, or Android .

Step 1: Set your network to Ropsten

At the top of the app, press the “Wallet” button, after which you’ll be prompted to select a network. As our NFT was minted on the Ropsten network, you’ll want to select Ropsten as your network.

Step 2: Add your collectible to Metamask

Once you’re on the Ropsten network, select the “Collectibles” tab on the right and add the NFT smart contract address and the ID of your NFT— which you should be able to find on Etherscan based on the transaction hash from your NFT minted in Part II of our tutorial.

You may need to refresh a couple times to view your NFT —but it will be there! ????

Congrats! You can now view your NFT in your wallet! We can’t wait to see how you’ll take the NFT world by storm! ????????????????????

Additional Resources

Congratulations on building your first NFT project! How did you like the track? 

There are a ton more resources that can guide you to learn more about NFT smart contract development. In particular, we’d recommend checking out the following tools: 

Thanks for reading and we’d love to see any NFT projects you’re developing: leave any feedback or progress you might have for us in the comment section.


Similar Posts

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *