π Hello world! This is Santhosh Reddy, a web3 developer and the solo developer of NFTJS . I keep building projects on blockchain like Dapps and smart contracts which reflect the real world use cases and the NFT.JS is a part of it. Today, I'm launching NFTJS 2.0 which is the next level of NFT.JS
Intro... πββοΈ
Have you heard of NFT.JS ? Okay! Let me repeat it once again. NFTJS is a Javascript library to implement NFTs in your Dapps. You can read more about it here
Hope you are now aware of NFT.JS and how its initial version is.
Today I'm launching NFT.JS 2.0 which is the next level of NFT.JS β¨
What improvisation has been done to NFT.JS? Let's jump into it.
What has been improved..β
As said in the previous article, the only future plans I have as a developer is to break the limitations of NFT.JS.
The major improvisations that are made to NFT.JS are...
1. Lot more EVM based networks added : NFT.JS used to support only Ethereum mainnet and testnets. But now, it also supports other EVM based networks like Polygon, BSC and Avalanche.
2. Also supports ERC1155 : NFT.JS not only supports ERC721 as earlier, but also supports ERC1155 in this version.
3. Integrated minting fee & transfer charges : In this version, NFT.JS helps you add a minting fee (must specify while deploying) which is transferred to the collection's contract when someone mints a token and the owner/deployer can withdraw them later. Remember that lazy minting doesn't work if the minting fee is added (>0).
You can also charge your users at token transfers. For this, you need to specify the admin's address to which the transfer charges get transferred as well as the percentage of the price at the transfer which is the transfer charge while deploying the contract. Remember that the transferCharge must be a pure integer and not a float.
Always be aware that, whenever I'm saying "price", it is the value of the native crypto currency of the network that you had set in the NFTJS.start()
function.
4. Published to NPM : Installing NFT.JS is a bit old till date. But now, NFT.JS 2.0 is an upgraded version and it can be installed easily using NPM.
Cool..! NFT.JS is now lot more powerful with lot more features
Alright. NFT.JS has been upgraded right ? So, its methods and usage also changes right ? Right, right... Now let's discuss the new methods and the new ways of usage.
Before moving on, I have a small request. If you found NFT.JS 2.0 interesting and useful please consider upvoting it on Product Hunt
Visit : NFT.JS
Implementation and Usage π
Now let's jump into a deep talk on how to use NFT.JS 2.0 by exploring its usage and implementations.
Install NFT.JS
The first thing you need to do to get started with NFT.JS is to install.
You can install NFT.JS easily by the given NPM command
npm install nftjs-lib
and import it like this.
import NFTJS from "nftjs-lib"
Note : When using typescript, you will probably get an error warning like Could not find a declaration file for module 'nftjs-lib'
. The only solution to this is to add "noImplicitAny": false
to your tsconfig.json
or just ignore it and it'll definitely work fine.
Alternatively, you can do it by adding a simple script tag in the <head>
section of your index.html file.
<script src="https://nft-js.web.app/nft.js" type="text/javascript" />`
Initialize it...
After installing NFT.JS you need to initialize the NFT.JS by providing the network (eth/rinkeby or polygon/mumbai...) and the user's wallet address as strings in the following way.
NFTJS.start("eth/rinkeby", accounts[0])
It supports the following networks' string values
eth/mainnet
eth/ropsten
eth/rinkeby
eth/goerli
eth/kovan
polygon/mainnet
polygon/mumbai
bsc/mainnet
bsc/testnet
avalanche/mainnet
avalanche/testnet
If you want to change the network or user's wallet address in any instance, you can easily do it by calling the same function again with different parameters.
NFTJS.start("polygon/mumbai", accounts[1])
Deploying a ERC721 collection contract
The ERC721 contract is created using Solidity with all the required functions and compiled already. By calling the createERC721
function, you can deploy it to the network that you have set in NFTJS.start()
.
The required parameters are name
of the collections as a string, SYMBOL
of the collection as a string, publicMintable
as string ("true"/"false"), maxSupply
as an integer, admin
as the string of the address to which the transferCharges has to be transferred in the lazyMintNFT and buyTransfer functions, mintFee
as the integer which is the fee that the contract receives and the owner can withdraw using the withdraw function later and transferCharge
as the integer which is the percentage of the transfer "price" amount that the admin receives.
Remember that transferCharge shouldn't be a float value and if the mintFee exists/greater than 0, lazyMint function doesn't work. publicMintable is a parameter that defines if you would like to allow others (other than owner) to mint NFTs in the collection and default value is false and it's always false unless you give "true" as the parameter value.
await NFTJS.createERC721(
"Nftify",
"NFY",
"true",
10000,
"0xb3h45......f3d",
0.01,
2
)
After the transaction receipt gives the deployed contractAddress, you can get it by calling a simple function like this.
var address = NFTJS.deployed()
This only gives the address of the collection that is most recently deployed in that web session. If either the page is reloaded or a new contract is deployed, the address of the past contract becomes unavailable.
Deploying a ERC1155 collection contract
The ERC1155 contract is created using Solidity with all the required functions and compiled already. By calling the createERC1155
function, you can deploy it to the network that you have set in NFTJS.start()
.
The required parameters are name
of the collections as a string, SYMBOL
of the collection as a string, publicMintable
as string ("true"/"false"), admin
as the string of the address to which the transferCharges has to be transferred in the lazyMintNFT and buyTransfer functions, transferCharge
as the integer which is the percentage of the transfer "price" amount that the admin receives and metadata
as an object for the collection's URI at last.
Remember that transferCharge shouldn't be a float value. publicMintable is a parameter that defines if you would like to allow others (other than owner) to create NFTs or mint tokens in the collection and default value is "false" and it's always false unless you give "true" as the parameter value.
await NFTJS.createERC1155("Nftify", "NFY", "true", "0xb3d....f3d", 2, {
name : "kingdom",
description : "heaven on the earth",
image : inputElement.files[0]
})
After the transaction receipt gives the deployed contractAddress, you can get it by calling a simple function like this.
var address = NFTJS.deployed()
Initiating a ERC721 collection
Initiating a collection requires the address of that contract and must be deployed to the network that you have provided in the NFTJS.start()
var collection = new NFTJS.ERC721(address)
Initiating a ERC1155 collection
Initiating a collection requires the address of that contract and must be deployed to the network that you have provided in the NFTJS.start()
var collection = new NFTJS.ERC1155(address)
Functions of a ERC721 collection
Now let's see how to interact with an ERC721's collection contract by sending and calling the data.
1. mintNFT : Minting an NFT requires the metadata object which contains the details like name, description, image and others.
Let's discuss the role of IPFS here. The first thing that the minNFT function does is, it checks if an item in the top level items of the object is a file. It uploads all the files to the IPFS and replaces the file values with the file URL. It will take some to complete the whole process.
Note that, if a file input's value is given in metadata and the user doesn't upload a file, the function fails.
After uploading the files in metadata, it uploads the final metadata object to the IPFS and then sends the transaction to the metamask wallet.
await collection.mintNFT(minter, {
name : "king",
description : "king of the kingdom",
image : inputElement.files[0]
})
2. lazyMintNFT : This is a function which is similar to mintNFT but is needed if you want to provide your users a gas free minting experience.
The required parameters are minter, price and metadata. Here, the buyer of the NFT is the user who is willing to buy the NFT and calling the function and the minter is the one who minted the NFT off-chain. The price is the amount of ETH the buyer needs to pay the minter.
The metadata of the NFT stored off-chain while minting should be given as the parameter. Dealing with metadata and IPFS is the same as in the mintNFT function.
As soon as the transaction is completed, the NFT data moves on-chain by directly minting it to the buyer and the ETH gets transferred to the minter address.
await collection.lazyMintNFT(
nft.minter,
nft.price,
nft.metadataObj
)
3. updateNFT : This is a crucial function to update the NFT's metadata. This function requires the ID of the NFT that needs to be updated and the new metadata that needs to replace the old one.
Here, the user must be the owner of the NFT.
Dealing with metadata and IPFS is the same as in the mintNFT function.
await collection.updateNFT(id, {
name : "king1",
description : "king1 of the kingdom1",
image : inputElement.files[0]
})
4. burnNFT : This function is used to burn or delete the NFT. This function requires the ID of the NFT that has to be burned and the user must be the owner of the NFT.
await collection.burnNFT(id)
5. approve : This function is used to give the transfer approval to the collection contract. This function requires the ID of the NFT that has to be approved and the user must be the owner of the NFT.
await collection.approve(id)
6. setApprovalForAll : This function allows the user to give or revoke approval on all his NFTs to the collection contract. The parameter that you need to give is a string form of the boolean ("true"/"false").
The default value is "true" and is always the same unless you give a parameter like "false".
await collection.setApprovalForAll(bool)
7. buyTransfer : This function is basically a buy function. The required parameters are from, to, price and id. As this transfer is made by the collection contract, the from/owner must give the approval to the contract before calling this function.
Usually, this function should be called by the "to". This function transfers the NFT of the given ID from "from" to the "to" and transfers the ETH of "price" from "to" to the "from". As said, it's a buy function and msg.value must be > 0.
await collection.buyTransfer(from, to, price, id)
8. transfer : This function is used when a user wants to transfer his/her NFT to anyone he/she wishes. The required parameters are "to" which is an address to which he/she wants to transfer and the ID of the NFT.
await collection.transfer(to, id)
9. transferFrom : This function is similar to the buyTransfer
function but it's not a payable function and is needed if a transferFrom should be called without any ETH transaction.
await collection.transferFrom(from, to, id)
10. details : This function returns the object that includes the details of the collection like, name, symbol, owner, maxSupply, publucMintable and totalSupply. Here, totalSupply also includes the burned NFTs.
var details = await collection.details()
11. getApproved : This function takes the ID of a NFT and returns the address to which the owner has given approval of that NFT id.
Usually, it returns the address(0) if not approved and returns the address of the collection if approved.
var address = await collection.getApproved(id)
12. isApprovedForAll : This function requires the address of the userand returns the boolean value. This boolean is equal to the value given in the setApprovalForAll function.
var bool = await collection.isApprovedForAll()
13. ownerOf : This function returns the owner's address of the given NFT id.
var owner = await collection.ownerOf(id)
14. balanceOf : This function returns the no.of NFTs holding of the given user's address.
var balance = await collection.balanceOf(address)
15. tokenURI : This function returns the URL of the specified token's metadata.
var url = await collection.tokenURI(id)
16. withdraw & balance: This function can be called only by the owner of the collection contract to withdraw some ETH from the contract which is transferred as the mintFee in the mintNFT function if the mintFee is greater than 0.
await collection.withdraw(amount)
You can simply read the current balance of the contract using the following function.
var balance = await collection.balance()
Functions of a ERC1155 collection
Now let's see how to interact with an ERC1155's collection contract by sending and calling the data.
1. setURI : This is a crucial function to update the ERC1155 collection's metadata. This function requires the new metadata to replace the old one.
Here, the user must be the owner/deployer of the collection contract.
Dealing with metadata and IPFS is the same as in the createNFT function discussed below.
await collection.setURI({
name : "kingdom",
description : "heaven on the earth",
image : inputElement.files[0]
})
2. createNFT : Minting an NFT requires the initialSupply which will be get minted to the NFT creator, maxSupply of that NFT, fee which is the mintFee that the contract receives and the owner can withdraw using withdraw
function later and the metadata object which contains the details like name, description, image and others.
Let's discuss the role of IPFS here. The first thing that the minNFT function does is, it checks if an item in the top level items of the object is a file. It uploads all the files to the IPFS and replaces the file values with the file URL. It will take some to complete the whole process.
Note that, if a file input's value is given in metadata and the user doesn't upload a file, the function fails.
After uploading the files in metadata, it uploads the final metadata object to the IPFS and then sends the transaction to the metamask wallet.
await collection.createNFT(initialSupply, maxSupply, fee, {
name : "king",
description : "king of the kingdom",
image : inputElement.files[0]
})
3. updateNFT : This is a crucial function to update the NFT's metadata. This function requires the ID of the NFT that needs to be updated and the new metadata, maxSupply and fee that needs to replace the old ones.
Here, the user must be the creator of the NFT.
Dealing with metadata and IPFS is the same as in the createNFT function.
await collection.updateNFT(id, maxSupply, fee, {
name : "king",
description : "king of the kingdom",
image : inputElement.files[0]
})
4. mint : This function is used to mint the tokens of an NFT. This function requires the ID of the NFT that has to be minted and the amount of tokens to be minted. This function has the transaction value of the token's mintFee*amount by default.
await collection.mint(id, amount)
5. lazyMint : This is a function which is similar to mint but is needed if you want to provide your users a gas free minting experience.
The required parameters are minter, id, amount and price. Here, the buyer of the NFT is the user who is calling the function and the minter is the one who minted the NFT off-chain. The price*amount is the amount of ETH the buyer needs to pay the minter.
As soon as the transaction is completed, the NFT data moves on-chain by directly minting the specified amount of the tokens to the buyer and the ETH gets transferred to the minter address.
await collection.lazyMint(
nft.minter,
nft.id,
nft.amount,
nft.price
)
6. burn : This function is used to burn or delete the tokens of an NFT. This function requires the ID of the NFT that has to be burned and the amount of tokens to be burned. The user's balance of that NFT must be >= amount.
await collection.burn(id, amount)
7. setApprovalForAll : This function allows the user to give or revoke approval on all his NFTs to the collection contract. The parameter that you need to give is a string form of the boolean ("true"/"false").
The default value is "true" and is always the same unless you give a parameter like "false".
await collection.setApprovalForAll(bool)
8. buyTransfer : This function is basically a buy function. The required parameters are from, to, price, id and amount. As this transfer is made by the collection contract, the from/owner must give the approval to the contract before calling this function.
Usually, this function should be called by the "to". This function transfers the "amount" of NFTs of the given ID from "from" to the "to" and transfers the ETH of "price*amount" from "to" to the "from". As said, it's a buy function and msg.value must be > 0.
await collection.buyTransfer(from, to, id, amount, price)
9. transfer : This function is used when a user wants to transfer his/her NFTs to anyone he/she wishes. The required parameters are "to" which is an address to which he/she wants to transfer, the "id" of the NFT and the "amount" of tokens.
await collection.transfer(to, id, amount)
10. transferFrom : This function is similar to the buyTransfer function but it's not a payable function and is needed if a transferFrom should be called without any ETH transaction.
await collection.transferFrom(from, to, id, amount)
11. collectionDetails : This function returns an object of all the details of the collection. This object contains the owner, name, symbol, uri, publicMintable and totalSupply of the collection.
var details = await collection.collectionDetails()
12. tokenDetails : This function returns an object of all the details of the specified NFT by ID. This object contains the creator, uri, totalSupply and maxSupply of the NFT.
var details = await collection.tokenDetails(id)
13. isApprovedForAll : This function returns the boolean value. This boolean is equal to the value given in the setApproveAll function.
var bool = await collection.isApprovedForAll(user)
14. balanceOf : This function returns the no.of tokens holding of the given user's address in a specified NFT id.
var balance = await collection.balanceOf(user, id)
15. withdraw & balance: This function can be called only by the owner of the collection contract to withdraw some ETH from the contract which is transferred as the mintFee in the mintNFT function if the mintFee is greater than 0.
await collection.withdraw(amount)
You can simply read the current balance of the contract using the following function.
var balance = await collection.balance()
Hope you understand how to use NFT.JS to implement NFTs in your projects in a low-code way and save your valuable time & energy.
If you have any doubts, found any bugs or want to give a suggestion or feedback on NFT.JS you can comment down below or can reach out to me on twitter
Final Thoughts... π
Finally completed my mission of upgrading NFT.JS by solving a few bugs and adding many more features. Hope you love it and save your valuable time and energy by using NFT.JS 2.0 to implement NFTs in your Dapps in a highly efficient manner.
Uhhh...
So, if you are about to build a web3 project or a Dapp that requires the implementation of NFTs, consider using NFT.JS to build fast and scalable Dapps.
Taking a leave for now...π Bye!