DEV Community

Cover image for How to create a motherf*cking NFT using JavaScript
Abdul Rauf
Abdul Rauf

Posted on • Updated on

How to create a motherf*cking NFT using JavaScript

This blog post is outdated as it is based on V1. Please use thirdweb V2 for your upcoming projects.

In my previous post, I explained how you can mint an NFT using Solidity. But what if you don't want to learn Solidity?

Ain't nobody got time for that b*tch.

You want to stick with your ol' pal JavaScript. Let me tell you that there's a way to do it. I present to you thirdweb - a library of smart contracts, SDK, and UI components that developers can use in their app.

How cool would it be if you could just call a mint function, give the token's metadata as an argument, and it mints an NFT for you? All without writing a single line of Solidity code. Let's see if that's possible.

Introduction to thirdweb

The first thing you need to learn about is the concept of projects and modules. In short, projects are smart contracts that act as containers for your modules. On the other hand, modules are packages that contain smart contracts and other functionalities. Head over to this link to learn more about them.

All the steps we need to take

The following are the steps we need to take to mint our NFT:

  1. Create a project using thirdweb
  2. Deploy an NFT module inside our project
  3. Mint our NFT

All of these steps will be done using just JavaScript. I will be separating these steps into 3 different .js files.

Setup

Before we start writing the code, we need to create a MetaMask wallet. Since we'll be deploying our contracts on the Rinkeby network, we'll also need some testnet ETH to approve the transactions. Here's a guide on how to create a MetaMask Wallet and get testnet ETH.

Now, head over to your thirdweb dashboard and create a project. Give it a name and a description of your choice. Make sure you've switched your network to Rinkeby.

Create project - thirdweb dashboard

We'll do everything else using code.

The code

Go ahead and create an empty project and install all the necessary packages:

  • @3rdweb/sdk - to use the smart contracts provided by thirdweb
  • ethers - to connect our MetaMask wallet
  • dotenv - to source sensitive data from a .env file
npm init -y
npm install @3rdweb/sdk ethers dotenv
Enter fullscreen mode Exit fullscreen mode

Let's create 3 separate files to code all the steps I mentioned above.

touch 1-init-sdk.js 2-deploy-collection.js 3-mint-nft.js
Enter fullscreen mode Exit fullscreen mode

1. Let's initialize the SDK

I like to show the entire code first before explaining it. Therefore, before further ado, here's the code for the first file i.e. 1-init-sdk.js

import { ThirdwebSDK } from '@3rdweb/sdk';
import ethers from 'ethers';

import dotenv from 'dotenv';
dotenv.config();

const sdk = new ThirdwebSDK(
  new ethers.Wallet(
    // Your wallet private key. ALWAYS KEEP THIS PRIVATE, DO NOT SHARE IT WITH ANYONE.
    // Add it to your .env file and do not commit that file to github!
    process.env.PRIVATE_KEY,
    // RPC URL, we'll use our Alchemy API URL from our .env file.
    ethers.getDefaultProvider('https://rinkeby-light.eth.linkpool.io/')
  )
);

(async () => {
  try {
    const apps = await sdk.getApps();
    console.log('Your app address is:', apps[0].address);
  } catch (err) {
    console.error('Failed to get apps from the sdk', err);
    process.exit(1);
  }
})();

// We are exporting the initialised thirdweb SDK so that we can use it in our other scripts
export default sdk;
Enter fullscreen mode Exit fullscreen mode

The code is really simple. We're importing thirdweb and then initializing the SDK. We're exporting it at the end so we can re-use it in the next script.

We're also running this:

(async () => {
  try {
    const apps = await sdk.getApps();
    // Get the address of the most recently created project
    console.log("Your app address is:", apps[0].address);
  } catch (err) {
    console.error("Failed to get apps from the sdk", err);
    process.exit(1);
  }
})(
Enter fullscreen mode Exit fullscreen mode

This code returns the address of your app or project. It's the address of the container that will hold all your modules. Remember, we created a project using our dashboard in the beginning? This will return its address.

Go ahead and run the following command in your terminal:

node 1-init-sdk.js
Enter fullscreen mode Exit fullscreen mode

Here's what I get when I run the script:

lilcoderman % node scripts/1-init-sdk.js
Your app address is: 0x25320e23DCd1813D11787aD836865a64CC69897A
Enter fullscreen mode Exit fullscreen mode

2. Deploying the NFT module

Now that we have our project/app, let's use the deployNftModule provided by thirdweb to deploy our collection. It is one of the methods available to the SDK we initialized in the first step.

We're not creating our NFT here, yet. This module will only help us create + deploy an ERC-721 collection to the Rinkeby testnet. We're just setting up the metadata of the collection itself. You know stuff like the name (e.g. Bored Ape Yacht Club), description, and image associated with the entire collection.

Go ahead and copy the following code to the 2-deploy-collection.js file:

import sdk from './1-init-sdk.js';
import { readFileSync } from 'fs';

import dotenv from 'dotenv';
dotenv.config();

const app = sdk.getAppModule('YOUR_APP_ADDRESS');

(async () => {
  try {
    const nftModule = await app.deployNftModule({
      // The collection's name, ex. CryptoPunks
      name: 'JavaScript NFTS',
      // A description for the collection.
      description:
        'How to mint an NFT using Javascript - a tutorial by @lilcoderman',
      // The image for the collection that will show up on OpenSea.
      image: readFileSync('assets/collection.png'),
      // The amount of royalty collected on all royalties represented as basis points. The default is 0 (no royalties).
      // 1 basis point = 0.01%
      // For example: if this value is 100, then the royalty is 1% of the total sales.
      sellerFeeBasisPoints: 0,
      // The address of the royalty recipient. All royalties will be sent to this address.
      feeRecipient: process.env.WALLET_ADDRESS,
      // The symbol for the NFT Collection
      symbol: 'JS',
    });

    console.log(
      '✅ Successfully deployed nft module, address:',
      nftModule.address
    );
  } catch (error) {
    console.log('failed to deploy nft module', error);
  }
})();
Enter fullscreen mode Exit fullscreen mode

The code is pretty self-explanatory. We're importing our SDK from the previous file and calling one of its methods. This method will deploy an NFT module (i.e collection) for us. We've also provided the necessary metadata as an argument to the deployNftModule function.

Once you run this script, it will return the collection's address. Here's what I get:

lilcoderman % node scripts/2-deploy-collection.js
✅ Successfully deployed nft module, address: 0x1C267DC8841999de9B9C4F33D63a8d6bC81b8e2D
Enter fullscreen mode Exit fullscreen mode

3. Time to mint our NFT

We're almost done now! It's time to mint our NFT, and we haven't even written a single line of Solidity. This is probably the simplest code we've written so far. Copy the following code to the final file 3-mint-nft.js:

import sdk from './1-init-sdk.js';
import { readFileSync } from 'fs';

const nft = sdk.getNFTModule('YOUR_NFT_MODULE_ADDRESS');

(async () => {
  try {
    await nft.mint({
      name: 'LCM',
      description: 'Follow me on twitter @lilcoderman',
      image: readFileSync('assets/nft.png'),
      properties: {},
    });
    console.log('✅ Successfully created a new NFT in the collection!');
  } catch (error) {
    console.error('failed to create the new NFT', error);
  }
})();
Enter fullscreen mode Exit fullscreen mode

Just like before, we're importing the SDK from the first file. However, we are using the module getNFTModule this time around. This module returns our ERC-721 contract.

Then, we can call the mint function from the contract to create an actual NFT! The mint function requires an object containing the metadata of the token. I've passed in the NFT's name, description, and image as arguments. You can also set its properties if you'd like.

Now, let's run it:

lilcoderman % node scripts/3-mint-nft.js
✅ Successfully created a new NFT in the collection!
Enter fullscreen mode Exit fullscreen mode

You can now view the NFT on your thirdweb dashboard.

NFT collection - thirdweb dashboard

We can also find our NFT on OpenSea by using its address. Go to this link to check mine.

That's it. You've now minted an NFT using JavaScript only. Pretty f*cking cool, won't you say?

Anyway, here's the Github repo with all the code: https://github.com/abdulrauf11/tutorial-thirdweb-nft

What next...

thirdweb can do much more than just minting an NFT collection. It has modules for creating a custom token, a marketplace for NFTs, and even a DAO! In the future, they also plan to support other chains like Solana and Flow.

We're using JavaScript to do all the steps, however, it is not a requirement. You can do all this manually using your dashboard. In my opinion, doing it with code just gives you more flexibility.

Keep in mind, if you're going to use thirdweb in production, they will take a minor 5% cut from your royalties. I think that's fair given how they're making our lives much easier with their product.


Don't leave me, take me with you

Like what you read? Follow me on social media to know more about NFTs, Web development, and shit-posting.

Twitter: @lilcoderman

Instagram: @lilcoderman

Oldest comments (15)

Collapse
 
azutech profile image
Azutech

This is incredible!!

Collapse
 
lilcoderman profile image
Abdul Rauf

Thank you! I'm glad you found this helpful 😁

Collapse
 
ranvirchoudhary profile image
RanvirChoudhary

does this mean after all this i cant sell my own NFTs?

Collapse
 
lilcoderman profile image
Abdul Rauf

On the contrary! You own the contract so you can sell them on any marketplace you want.

Collapse
 
toddpants profile image
todd

Hey, fascinating article and one that I'm trying to work with to help me test an NFT with js. So far I'm having problems getting test ETH through rinkeby faucet, it appears as though that well is dry, do you know any other ways to get test ETH?

Collapse
 
lilcoderman profile image
Abdul Rauf

Wow that’s so cool! 😍

Try this one: faucets.chain.link/rinkeby

Let me know if it works! Do share your project with me once you’re done. I would love to see it 😃

Collapse
 
toddpants profile image
todd

Thanks! Just tried it and it looks like it was confirmed, haven't seen it hit my metamask wallet yet but it might take a little while. Will definitely share my project when I'm done!

Thread Thread
 
lilcoderman profile image
Abdul Rauf

Perfect! This one almost always works.

Thread Thread
 
toddpants profile image
todd

This was awesome, thank you so much for posting. FYI I had to add "type":"module" to package.json to be able to run the node scripts. But I was able to create my first NFT!! I am still very new to this and have no idea how to list and/or share it with you though. Do you have any good references for that?

Thread Thread
 
lilcoderman profile image
Abdul Rauf

That’s awesome!

You can copy the address of your NFT and look it up on testnets.opensea.io/

Right now, your NFT is minted on the testnet and not the mainnet.

Let me know if this is what you were asking?

Thread Thread
 
toddpants profile image
todd

Ahhh I see, thank you, here is the link to the collection testnets.opensea.io/collection/rec... thanks again so much!

Thread Thread
 
lilcoderman profile image
Abdul Rauf

You’re welcome! You should be super proud of yourself 😃👏🎉

Collapse
 
gianpaj profile image
Gianfranco • Edited

For those who didn't know how to export your private key on Metatask, it's like this:

Account Details -> Export Private key


Collapse
 
lilcoderman profile image
Abdul Rauf

Thanks for helping out! 🙏

Collapse
 
dimamagunov profile image
Dmitry Magunov

Hey, great article!

Added a link to it to the "DIY NFT" Snapshot.

diy-nft.thenftsnapshot.com/