Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
June 21, 2021 05:54 pm GMT

How to create NFTs with JavaScript

Written by Adebola Adeniran

In February 2021, Figma CEO Dylan Fields sold a piece of NFT art for $7.5 million. Similarly, Twitter co-founder Jack Dorsey sold his first tweet on Twitter as an NFT for $2,915,835.47.

Jack Dorsey First Tweet NFT

An NFT (non-fungible token) is a fascinating new technology that represents ownership of an asset digitally. In this tutorial, well cover some important background information, set up third-party services, and finally code and deploy our very own NFT to the Ropsten Testnet.

Lets get started!

Background information

Before creating our own NFT, lets take a look at the technologies and features that make NFTs work.

Fungible vs. non-fungible

Fungibility is essentially the ability to exchange an item for a similar item of the same value. Consider a five-dollar bill. It always equals the same amount anywhere in the world. You can exchange five one-dollar bills for a single five-dollar bill, and they are worth the same value all the time.

On the other hand, non-fungible items do not have the same value in comparison to each other. For example, an exact replica of the Mona Lisa is not equal in value to the original painting, despite being the same in every way. Non-fungible items are inherently unique and cannot be considered equivalent to any other item.

An item can be both fungible and non-fungible. For example, while two seats in economy class on a plane are worth the same price, one person may place sentimental value on a window seat, decreasing the value of every other seat for that person.

Blockchain

A blockchain is a public database or digital ledger that keeps track of transactions. It is replicated across several computer systems that are part of the chain. Well build our NFT on the Ethereum blockchain.

Minting ERC721 tokens

Minting is the process of creating something for the first time, or in our case, publishing a unique instance of our ERC721 token on the blockchain. ERC-721 is the standard for creating an NFT, and an ERC721 token is a unique representation of digital content published to the Ethereum blockchain. No two tokens are ever the same, so each time you mint a new token with the same block of code, a new address will be generated.

Smart contracts and NFTs

Smart contracts are simple programs that are deployed to the blockchain and run as-is, meaning theyre not controlled by a user. We can use a smart contract to create and track our tokens.

An NFT is a digital store of data that conforms to the ERC-721 standard and lives on a public blockchain. NFTs contain information or data about the asset they represent, which could be a digital item like a Tweet or a physical item like a hoodie.

A smart contract can be considered an NFT if it implements the ERC-721 standard, and an NFT is an instance of a smart contract. Each time we mint a new NFT, we use the smart contract code that has been deployed to the blockchain.

Public networks: Mainnet vs. Testnet

Ethereum uses multiple networks. The network used in production is usually referred to as Mainnet and the others, which are used for testing, are called Testnet. Well deploy the NFT we create to the Ropsten Testnet, a proof-of-work Testnet for Ethereum.

Note that when we eventually deploy our NFT, either to production or to the Mainnet, the transaction history and balances we have on the Ropsten Testnet will not carry over. Think of the Testnet as a public staging/development environment and the Mainnet as a production environment.

Private networks

A network is considered private if its nodes are not connected to the public blockchain. You can run the Ethereum blockchain on a private network, like your local machine, or on a group of machines, like consortium networks, that are not accessible on the Mainnet or Testnet.

Running the Ethereum blockchain on a group of machines like an intranet would require validating transactions with a node, an Ethereum software running on a client that verifies blocks and transaction data.

HardHat and Ganache are two examples of Ethereum blockchain development environments that you can run on your local machine to compile, test, deploy, and debug your smart contract application.

Well run our application on a public network so that it can be accessed by anyone connected to the network.

Faucets

To test our application, we need to get Ether (ETH), the Ethereum cryptocurrency, from a faucet. Faucets, like the Ropsten Faucet, are web apps that allow you to specify and send test ETH to an address, which you can then use to complete transactions on a Testnet.

The price of ETH on exchanges is determined by transactions occurring on the Mainnet at any given time. If you choose to run your Ethereum application on a private network, you don't need test ETH.

Nodes and clients

As previously mentioned, nodes verify blocks and transaction data. You can create your own node using clients like Geth and OpenEthereum and contribute to the Ethereum blockchain by validating transactions and blocks on the blockchain.

You can skip the process of creating your own node and instead use one hosted on the cloud with a node-as-a-service platform like Alchemy. We can quickly move from development to production and ensure that we get important metrics for our application.

Well be using the Alchemy API to deploy our application to the Ropsten blockchain. Alchemy has been described as the AWS for blockchains and provides developer tools that allow us to view insights into how our application is performing.

Building the NFT

Prerequisites

  • Node.js and npm
  • basic knowledge of JavaScript

I enjoy photography and take a lot of pictures on my mobile device. What better way to protect my work than to mint an NFT that I can transfer to anyone who loves my photos? They can then use the NFT data on either the Ropsten Testnet or the Mainnet to prove that they own the rights to the original image.

Well create an NFT that identifies the picture I took of the Osun River below, which is believed to have unique healing powers.

Osun River NFT Art

Create an Alchemy account

Well use Alchemy to code our NFT, allowing us to skip the process of running an Ethereum node on our local machine.

Navigate to the Alchemy dashboard where youll see a screen titled Create your first app. Ive used my name as the team name and named the app The Osun River NFT.

Select Ropsten as the test network for the application.

Create App Alchemy

Hit the Create App button to continue.

On the next screen, select the free plan. On the following screen, you can avoid entering payment information by hitting the Skip for now button, but you may choose to do that at a later time. On the last screen, select the Capped Capacity option.

Now, youll see our app listed on your dashboard.

Alchemy App Listed Dashboard

Create an Ethereum account

We need to create a wallet to hold an Ethereum account. To deploy our application to a network, well need to pay a fee denominated in ETH, known as gas fees. When testing our application, we can use dummy ETH to complete the process, which well retrieve from a faucet later.

Well create an Ethereum account using MetaMask, a virtual wallet thats available as a Chrome extension.

Once youve installed MetaMask and created an account, open the MetaMask extension in Chrome and select the Ropsten Test Network from the list of networks.

Metamask Extension Chrome

MetaMask will automatically generate a wallet address denominated in ETH. Simply click on Account 1 to copy your wallet address.

Getting ETH from a faucet

Lets send Ether to our new wallet using the Ropsten Faucet. First, enter your wallet address, which you can copy from above, and the site will send 1ETH to your wallet.

Ether Ropsten Faucet Site

You can confirm by checking your MetaMask wallet.

Metamask Wallet 1eth

Setting up our token

Lets start coding our NFT token! First, create a new directory for our project and initialize npm:

mkdir the-osun-river-nft && cd the-osun-river-nftnpm init -y

We need to set up Hardhat, a development environment for Ethereum that allows us to compile our application on our local machine and test functionality before deploying to the Ropsten Testnet.

To install Hardhat as a development dependency within our project, run:

npm install -D hardhat

Now, initialize Hardhat using the npx hardhat command:

Initialize Hardhat NPX Hardhat Command

Select Create an empty hardhat.config.js. Well use this file to set up configuration for our project later on. Now, well set up two new folders in our project: one will hold the code for our smart contract, and the other will hold the scripts that deploy and interact with the smart contract code:

mkdir contracts && mkdir scripts

Creating a smart contract

Smart contracts are simply applications that can be run on the Ethereum blockchain. They are written in a language called Solidity.

Our smart contract code will be based on the OpenZeppelin ERC721 implementation. ERC721 is the standard for representing ownership of NFTs, and the OpenZeppelin contracts provide us with some flexibility in using ERC721.

Install the OpenZeppelin contracts library:

npm i @openzeppelin/[email protected]

In your contracts directory, create an OsunRiverNFT.sol file using the code below. Ive left several comments that clarify each line:

//Contract based on https://docs.openzeppelin.com/contracts/3.x/erc721// SPDX-License-Identifier: MITpragma solidity ^0.7.3;// implements the ERC721 standardimport "@openzeppelin/contracts/token/ERC721/ERC721.sol";// keeps track of the number of tokens issuedimport "@openzeppelin/contracts/utils/Counters.sol";import "@openzeppelin/contracts/access/Ownable.sol";// Accessing the Ownable method ensures that only the creator of the smart contract can interact with itcontract TorNFT is ERC721, Ownable {    using Counters for Counters.Counter;    Counters.Counter private _tokenIds;    // the name and symbol for the NFT    constructor() public ERC721("TheOsunRiver", "TOR") {}    // Create a function to mint/create the NFT   // receiver takes a type of address. This is the wallet address of the user that should receive the NFT minted using the smart contract    // tokenURI takes a string that contains metadata about the NFT    function createNFT(address receiver, string memory tokenURI)        public onlyOwner        returns (uint256)    {        _tokenIds.increment();        uint256 newItemId = _tokenIds.current();        _mint(receiver, newItemId);        _setTokenURI(newItemId, tokenURI);        // returns the id for the newly created token        return newItemId;    }}

For our NFT to be a valid ERC721 token, it must meet all ERC721 standards. import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; ensures this by importing the ERC721 standards into our file.

Connecting MetaMask to the project

Now, well connect our MetaMask wallet to our project. Every transaction on a virtual wallet requires a private key to complete, so well need to grab our MetaMask private key.

In your Chrome browser, open up the MetaMask extension, click the three dots in the top right, and select theAccount Details option. Next, click the Export Private Key button. Enter your password to see your private key, then copy it.

Metamask Export Private Key Chrome Browser

Its important to keep our private key secured within our projects codebase to prevent it from being exposed when using version control platforms like GitHub. To keep our keys secure, we will install the dotenv package:

npm i dotenv

Create a .env file in the root of your project, then add your MetaMask private key from earlier to it. You'll also add your alchemy API_URL, which you can find by navigating to your Alchemy Dashboard, clicking the Apps dropdown, selecting the App you created earlier, then selecting the View Key button:

Alchemy Dashboard View Key

METAMASK_PRIVATE_KEY = "yourMetamaskPrivateKey"API_URL = "https://eth-ropsten.alchemyapi.io/v2/your-api-key"

Setting up Ether.js

Ether.js is a library that simplifies interacting with the Ethereum blockchain. Well use the Ether plugin for Hardhat:

npm i -D @nomiclabs/hardhat-ethers 'ethers@^5.0.0'

Head to the hardhat.config.js file we created earlier to add some of the new dependencies weve installed:

/*** @type import('hardhat/config').HardhatUserConfig*/require('dotenv').config();require("@nomiclabs/hardhat-ethers");const { API_URL, METAMASK_PRIVATE_KEY } = process.env;module.exports = {   solidity: "0.7.3",   defaultNetwork: "ropsten",   networks: {      hardhat: {},      ropsten: {         url: API_URL,         accounts: [`0x${METAMASK_PRIVATE_KEY}`]      }   },}

Lets walk through what we have in our configuration file:

  • dotenv package: lets us use environment variables within our Node.js application
  • require("@nomiclabs/hardhat-ethers"): runs the user-friendly methods provided by Ether in our deploy scripts
  • defaultNetwork: specifies which network Hardhat should use when deploying our application (Ropsten Testnet)
  • accounts : a private key generated by MetaMask that allows our application to connect to our MetaMask virtual wallet to complete a transaction
  • url: specifies the URL that our Node.js application is hosted on (Alchemy servers)

Well connect to the Ropsten Testnet via the nodes hosted at our URL. You can read more about configuration files in Hardhat.

Now, lets run the compiletask that Hardhat provides to check that everything works correctly:

npx hardhat compile

You should see a success message like the one below. You can ignore the warnings that appear in the terminal.

Hardhat Compile Task Success Message

Creating a deployment script

Now that weve wrapped up our smart contract code, lets write the necessary scripts to deploy our smart contract to the Ethereum blockchain.

In your scripts directory, create a new file called deploy.js:

async function main() {    const [deployer] = await ethers.getSigners();    console.log("Deploying contracts with the account:", deployer.address);    console.log("Account balance:", (await deployer.getBalance()).toString());    const TOR = await ethers.getContractFactory("TorNFT");    // Start deployment, returning a promise that resolves to a contract object    const tor = await TOR.deploy();    console.log("Contract deployed to address:", tor.address); } main()   .then(() => process.exit(0))   .catch(error => {     console.error(error);     process.exit(1);   });

Now, we can run the Hardhat deploy task:

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

We add the --network ropsten flag to tell Hardhat to connect to a specific network, in our case, Ropsten.

After a few seconds, well see that our smart contract has been successfully deployed to the Ropsten Testnet. From our terminal logs, we can see the newly created address for our smart contract.

Smart Contract Successful Address Display

Now, lets confirm that our smart contract is deployed to the blockchain. Head to the Ropsten Etherscan and paste your contract address into the search bar. You should see details about your contract within one minute.

Ropsten Etherscan Contract Details Display

If you check your Ethereum wallet on MetaMask, youll notice that the amount of ETH you have has been reduced on account of the gas fees required to process transactions. Now, weve successfully deployed our smart contract to the Ropsten Testnet!

Minting an NFT

Our smart contract code takes in two arguments: the receiver address and a tokenURI. The tokenURI links to data that we would like to attach our token to. To use the receiver address, simply pass it in the wallet address of the user youre giving the token to.

Data stored on the blockchain needs to be processed, verified, and replicated across multiple networks, making storing data on the blockchain very expensive. Uploading an entire image to the blockchain is not advisable, and you can store only the metadata for the NFT instead.

Although the URL for an NFT can be stored on the blockchain, the link may go offline at any time. Additionally, anyone who has access to the content at a URL may change it.

An example is when an NFT artist pulled the rugon NFTs he had sold on OpenSea, meaning he changed the original images that hed sold to buyers. The link to those images was still present on the blockchain, however, the original content had been completely altered.

Therefore, we need a way to store data thats affordable, persistent, decentralized, and immutable.

Using IPFS

IPFS is a distributed system for storing and accessing files that uses content addressing to tackle the problem above. Any piece of data that is uploaded to IPFS will be issued a unique content identifier (CID). Once a CID is generated for a piece of data, that CID will always represent that data, and the data cannot be changed.

Heres an example IPFS URI:

ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi

To generate an IPFS URI, you simply need to prefix the CID with ipfs://. In a browser, IPFS URIs follow the format:

https://ipfs.io/ipfs/{CID}

The URI will be resolved by your user agent (browser) to display the content. There are a few browsers able to resolve IPFS URIs, but we'll use Google Chrome browser version 90.

Setting up web3.js

Lets continue adding metadata to our NFT. Well install the Alchemy Web3 package:

npm install @alch/alchemy-web3

According to its docs, web3.js is a collection of libraries that allows you to interact with a local or remote Ethereum node using HTTP, IPC, or WebSocket.

Alchemy wraps around the Web3.js library, extending its functionality by offering automatic retries and robust WebSocket support.

Setting up scripts to mint NFTs

Now, its time to write the scripts to mint our NFT.

In your scriptsfolder, create a file called mint-nft.js. Then, add the following block of code:

require('dotenv').config();const API_URL = process.env.API_URL;const { createAlchemyWeb3 } = require("@alch/alchemy-web3");const alchemyWeb3 = createAlchemyWeb3(API_URL);const contract = require("../artifacts/contracts/OsunRiverNFT.sol/TorNFT.json"); 

Uploading NFT metadata to Pinata

Pinata is a platform for using IPFS protocol to store our NFTs metadata. If you havent already, create an account.

Once youre signed in, select the teal upload button, click File, then select your NFT image.

Upload NFT Metadata Pinata

Once the image is successfully uploaded, youll see it on your dashboard. Make sure to take note of the alphanumeric characters under the IPFS CID column above. Well use them later.

Now that weve uploaded our image to Pinata, lets create a JSON file to hold information about our NFT. We will store the URI on the blockchain when an NFT is minted.

In the root of your application, create a file called nft-metadata.json and add the following information. Remember to change the image value to use the CID that was generated when you uploaded your image to Pinata:

{    "description" : "An image of the Osun River captured on the suspended bridge at the Osogbo Sacred Grove.",    "image" : "https://ipfs.io/ipfs/Qmf1r8igsCAFTFjrQrK7jk6uD6YKVYo5dGu7cvm9TmPhJV",    "photographer" : "Adebola Adeniran"}

Notice that for the image attribute, we have added the IPFS CID from our Pinata dashboard with the prefix https://ipfs.io/ipfs/. Save the file, then head back to Pinata to upload the file.

Upload File Pinata

You should see both the image and JSON files on our dashboard.

Creating an instance of our contract

To mint the NFT, grab the contract address that was created when our smart contract was deployed to the Ropsten Testnet. You can see this in our terminal logs. Our contract address is 0x9436f34035a4885650C8311cA24e3E2DeD2FF0a2.

Create Instance Smart Contract

Head back into the scripts/mint-nft.jsfile and add the following code:

const contractAddress = "0x9436f34035a4885650C8311cA24e3E2DeD2FF0a2";const nftContract = new alchemyWeb3.eth.Contract(contract.abi, contractAddress);

Lets update our .envfile with our public Ethereum address, which is the same account address we copied earlier. Add the address to our .env file:

METAMASK_PRIVATE_KEY="Our metamask Private key"API_URL="Our alchemy API URL"METAMASK_PUBLIC_KEY="Our metamask public key"

Next, well need to create a transaction.

Add the following code into our mint-nft.jsfile. Ive added comments to explain what were doing at each step:

const METAMASK_PUBLIC_KEY = process.env.METAMASK_PUBLIC_KEY;const METAMASK_PRIVATE_KEY = process.env.METAMASK_PRIVATE_KEY;async function mintNFT(tokenURI) {    // get the nonce - nonce is needed for security reasons. It keeps track of the number of    // transactions sent from our address and prevents replay attacks.  const nonce = await alchemyWeb3.eth.getTransactionCount(METAMASK_PUBLIC_KEY, 'latest');  const tx = {    from: METAMASK_PUBLIC_KEY, // our MetaMask public key    to: contractAddress, // the smart contract address we want to interact with    nonce: nonce, // nonce with the no of transactions from our account    gas: 1000000, // fee estimate to complete the transaction    data: nftContract.methods      .createNFT("0x0d28235B6191a66A3410cc1e3CeBfE53602D7865", tokenURI)      .encodeABI(), // call the createNFT function from our OsunRiverNFT.sol file and pass the account that should receive the minted NFT.  };}

Ive created a new MetaMask wallet and passed the wallet address in tx.data above. You can also pass in our METAMASK_PUBLIC_KEY if you wish. In production, the wallet address passed here should be the wallet address of the NFTs recipient.

Now that the transaction is created, well need to sign off of the transaction using our METAMASK_PRIVATE_KEY.

Add the following block of code to the mint-nft.js file within the mintNFT function:

  const signPromise = alchemyWeb3.eth.accounts.signTransaction(    tx,    METAMASK_PRIVATE_KEY  );  signPromise    .then((signedTx) => {      alchemyWeb3.eth.sendSignedTransaction(        signedTx.rawTransaction,        function (err, hash) {          if (!err) {            console.log(              "The hash of our transaction is: ",              hash,              "
Check Alchemy's Mempool to view the status of our transaction!" ); } else { console.log( "Something went wrong when submitting our transaction:", err ); } } ); }) .catch((err) => { console.log(" Promise failed:", err); });

Finally, we need to copy the IPFS CID hash from the nft-metadata.json **file we uploaded to Pinata earlier and pass that into our mintNFT function when its called:

mintNFT("https://ipfs.io/ipfs/QmdZMtdApdeobM5iCRcWqAMByfG4No8tW4oheb7jQjKgTm") // pass the CID to the JSON file uploaded to Pinata

If you open the link above in our browser, you should see our nft-metadata.jsonfile with the CID above:

NFT Metadata JSON CID

Now, we can run node scripts/mint-nft.js in our terminal to mint our NFT. Wait a few seconds, and you should get a response like the image below in our terminal.

Mint NFT Terminal

Now, well go to the Alchemy Mempool, which tracks the status of all the transactions happening on our account without having to use Etherscan.

Alchemy Mempool NFT Data Dashboard

We can see information about our newly minted NFT on Etherscan, as well as the URL that links to our nft-metadata.json file on the Ethereum blockchain.

Newly Minted NFT Etherscan

Scroll down to input data, then click the decode input data button. You should see the data we passed to our createNFT function in the contracts/OsunRiverNFT.sol file: the receiving wallet address and the URL for the JSON file that holds our NFTs metadata.

Decode Input Data Etherscan

If you search for the contract address used to mint the NFT on Etherscan, youll see a record of all the NFTs that have been minted, or more accurately, all the transactions that have occurred using this smart contract.

Contract Address Etherscan NFT Record

Adding our NFT to our MetaMask wallet

  1. Check connection to the Ropsten Test Network
  2. Open MetaMask wallet extension
  3. Click the add token button
  4. Copy the contract address of your new token from Etherscan and paste it into MetaMask. MetaMask will automatically generate the tokens symbol.
  5. Click next to add the token to your wallet

Add NFT Metamask Wallet

Metamask Wallet Balance

Conclusion

And with that, weve learned how to:

  • Create and deploy a smart contract to the Ropsten Testnet
  • Mint NFTs by deploying the smart contract to a blockchain
  • Add metadata to our NFT using content addressing protocol in IPFS via Piata
  • View our NFT in our MetaMask wallet

Hopefully, you see why NFTs are causing such commotion. This is a fascinating technology that is likely to stick around a while.

In production, the steps are exactly the same as in this tutorial. The only difference is that youll now be interacting with the Mainnet rather than a Testnet.

You can see all the code for this project on my GitHub.

Are you adding new JS libraries to improve performance or build new features? What if theyre doing the opposite?

Theres no doubt that frontends are getting more complex. As you add new JavaScript libraries and other dependencies to your app, youll need more visibility to ensure your users dont run into unknown issues.

LogRocket is a frontend application monitoring solution that lets you replay JavaScript errors as if they happened in your own browser so you can react to bugs more effectively.

LogRocket Dashboard Free Trial Banner

LogRocket works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and ngrx/store. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your apps performance, reporting metrics like client CPU load, client memory usage, and more.

Build confidently start monitoring for free.


Original Link: https://dev.to/logrocket/how-to-create-nfts-with-javascript-58no

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To