DEV Community

Emanuel Ferreira
Emanuel Ferreira

Posted on • Updated on

How to mint 10000 NFTs on Opensea

Minting to Opensea

After creating all your NFTs the more hardest step is to mint so many NFTs to Opensea mostly in large quantities without a contract.

Gif from process

To do it I'll share my repository that uses puppeteer to automate the process of minting the NFTs, you just need an images folder file and the images name to mint all. I'll teach you how to use the repository below.

If you want to add another property on the mint time send me an email we can discuss it oi@manel.dev.

Install the packages

To start we go to install the packages to run the script, on your project run:

yarn add @chainsafe/dappeteer puppeteer esbuild esbuild-register
Enter fullscreen mode Exit fullscreen mode

The @chainsafe/dappeteer serves to automate the metamask connect to mint the NFTs.

The puppeteer we will use to upload the images and fill the inputs.

And we are going to use the esbuild and esbuild-register to run our script.

Create the script

Let's start creating a file called script.ts file doing the first imports and adding your first variables.

script.ts

import puppeteer, { Page } from 'puppeteer';
import dappeteer from '@chainsafe/dappeteer';
import fs from 'fs';

const collectionName = "Your Collection Name"
const collectionURL = `https://opensea.io/collection/${collectionName}/assets/create`
const openseaDescription = `Your description here`
const lockedContent = `Locked content text here`
Enter fullscreen mode Exit fullscreen mode

Connect Wallet Function

So to select the Metamask wallet when our script opens the Browser, let's create a function to click on the Metamask button and connect to the wallet.

script.ts

const connectWallet = async (page: Page, metamask) => {
  const button = await page.$('button.dBFmez:first-child');
  await button.click();

  await metamask.approve();

  return;
}
Enter fullscreen mode Exit fullscreen mode

Create the Upload Image function

Now to upload the image on create NFT page let's create the function which receives the page and the file then takes the input element in the HTML and uploads the image to it.

script.ts

const uploadImage = async (page: Page, file: string) => {
  const elementHandle = await page.$("#media");
  await elementHandle.uploadFile(`images/${file}`);

  return;
}
Enter fullscreen mode Exit fullscreen mode

Create the page timeout function

This function is to give time for our script to perform the filling or clicks in the application.

script.ts

const pageTimeout = async (time: number, page: Page) => {
  await page.waitForTimeout(time)
  return;
}
Enter fullscreen mode Exit fullscreen mode

Create the fill fields function

this is the function where we are going to get each field from the create NFT page and fill it.

the steps this function takes
1- Fill in the field name
2 - Fill in the field input.
3 - Turn on the unlockable content and fill the unlockable content text.
4 - Select the Polygon chain

script.ts


const fillFields = async (page: Page, fileName: string) => {

// Get and fill in the input name
  await page.focus('#name')
  await page.keyboard.type(fileName)

  await pageTimeout(1000, page)

//Get and fill in the input name
  await page.$eval('#description', (el, value) => el.value = value, openseaDescription);
  await page.focus('#description')
  await page.keyboard.type(' ')

  await pageTimeout(1000, page)

// Click on the unlockable content checkbox
  await page.evaluate(() => {
    document.querySelector("#unlockable-content-toggle").parentElement.click();
  });

  await pageTimeout(1000, page)

// Fill in the unlockable content text
  await page.$eval('textarea[placeholder="Enter content (access key, code to redeem, link to a file, etc.)"]', (el, value) => el.value = value, lockedContent);
  await page.focus('textarea[placeholder="Enter content (access key, code to redeem, link to a file, etc.)"]')
  await page.keyboard.type(' ')

// Open the select chain input
  const input = await page.$("#chain")
  input.click()

  await pageTimeout(1000, page)

// Select the polygon chain
  await page.click('img[src="/static/images/logos/polygon.svg"]')

  return;
}
Enter fullscreen mode Exit fullscreen mode

Creating the Main Function

In this function we go to create all the main functions to run our scripts the steps are:

1 - Run the dappeteer to set up the Metamask on Opensea.
2 - Get our files from the images folder file.
3 - Remove the first file(.DS_Store) - just for macOS.
4 - Open the create asset page of the collection.
5 - Run the connect wallet function
6 - Run a loop for each image on the images folder (to create the asset one by one)

See the code below step-by-step:

script.ts

(async () => { // Async function because we need promises to do it
  const browser = await dappeteer.launch(puppeteer, { metamaskVersion: 'v10.1.1' }); // Launch the browser with metamask
  const metamask = await dappeteer.setupMetamask(browser, { seed: "Secret phase here"}); // Add your secret phase here to metamask connect with your account
  const files = await fs.promises.readdir("images/"); // Get an List with all images on images folder
  files.shift() // WARN: just on macOS: remove the first file .DS_Store 

// Open the create assets url of the  collection
  const page = await browser.newPage();
  await page.goto(collectionURL);

// Get the tabs and close the first tab openned by the dappeteer
  const firstTabs = await browser.pages()
  await firstTabs[0].close()

  await pageTimeout(2000, page)

// Run our function to click on the Metamask button in the Opensea
  await connectWallet(page, metamask)

// Start the loop on each image of images folder
  for (let i = 0; i <= files.length ; i++) {
    const tabs = await browser.pages() // Get the tabs on each loop
    const data = {
      name: `Your Asset name here #${1 + i}`, // Add your NFT name (the count start on 1 and stop on the quantity of the files)
    }

// At the first time on loop you need to do an sign to create the assets 
    if(i === 0) {
      await tabs[1].bringToFront() // Move one tab
      await tabs[1].goto(collectionURL) // Change the page to collection url again

      await pageTimeout(2000, page)

      await metamask.sign() // Use the metamask to do the transaction
      await metamask.page.waitForTimeout(2000) // wait for the transaction
    }

// Now if not the first time, after creating the first NFT just open the create assets page again to create the second NFT and so sequentially.
    if(i === 0) {
      await tabs[1].bringToFront()
      await tabs[1].goto(collectionURL)
    } else {
      await tabs[1].bringToFront()
      await tabs[1].goto(collectionURL)
    }

    await pageTimeout(2000, page)

// Upload the current image file
    await uploadImage(page, files[i]);

// Fill the fields using the asset name with the count
    await fillFields(page, data.name);

// Click on create asset button
    const button = await page.$('.AssetForm--action button');
    await button.click()

    await pageTimeout(4000, page)

// Rename the image name to know if already is completed
    fs.renameSync(`images/${files[i]}`, `images/completed-${files[i]}`)

    console.log({ message: `Mint the NFT: ${data.name}`, fileName: files[i]})
    console.log(`Mint the NFT: ${data.name}`)
  }

  console.log('Minted all NFTs with success')
})();
Enter fullscreen mode Exit fullscreen mode

Ready!! now Let's config our package.json to run the script with one line

package.json

{
  "name": "node",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "@chainsafe/dappeteer": "^2.2.0",
    "dappeteer": "^1.0.0",
    "esbuild": "^0.13.10",
    "esbuild-register": "^3.0.0",
    "puppeteer": "^10.4.0"
  },
  "scripts": {
    "es": "node -r esbuild-register"
  }
}
Enter fullscreen mode Exit fullscreen mode

Now to run your script just run on the CLI:

yarn es ./src/script.ts
Enter fullscreen mode Exit fullscreen mode

Download the Repository

First, you need to download my repository here that contains the script to mint the NFTs.

Star my repository here

It's done, now the puppeteer will create all your NFTs one by one and so much fast.

That's it!!

Follow me on Twitter
My Github

Discussion (23)

Collapse
bikramgyawali profile image
Bikram Gyawali

Hello emanuel . This is a great content ever.
But i am stucked on uploadfile function the error is

TypeError: Cannot read property 'uploadFile' of null

const uploadImage = async (page: Page, file: string) => {
const elementHandle = await page.$("#media");
await elementHandle.uploadFile(images/${file});

return;
};

what do you think the error is ?
Are the api endpoints are changed ?

Collapse
emanuelferreira profile image
Emanuel Ferreira Author

Hello Bikram, maybe the upload image selector was updated , so he dont find the file input, you can try use the dev tools to see the new upload image selector

Collapse
bikramgyawali profile image
Bikram Gyawali

Thankyou Emanuel I came to the next error that is not included in this tutorial maybe you can help
so the thing i am doing is to sign the wallet signature of metamask , this step is not included here , So what I did is just made new instance of the metamask sign page

const newpage = await browser.newPage();
await newpage.goto(`chrome-extension://${extensionID}/${extensionEndURL}`);
await pageTimeout(4000, page);

const button = await page.$("body:nth-child(2)"); // problematic selector
await button.click();
Enter fullscreen mode Exit fullscreen mode

Here the second child is the sign button on clicking that our item gets added to the Collection.
I need your help here and this is the only one tutorial all over the internet i can get.Thanks for that also followed you on github.
your help is greatly appreciated

Thread Thread
bikramgyawali profile image
Bikram Gyawali

problem solved hahahh my blunder mistake . Thankyou Emanuel for this content
now i will be doing all the selling automation with likes hahahhaha.
I might be back here again for those coming errors hehe.

Collapse
iih39354895 profile image
I H • Edited on

Hey @emanuelferreira. Thank you very much for the excellent explanation and effective solution.

After I upload/minting the items in to Openea with your scrpt how do I enter the price for them and listing them for sale. Maybe I missed something.

And if the idea is to do it on the interface of Opensea.
Do you know if there an option to list all the items at once (say 10K items)
i checked and i can't find an option like this.
thanks for the help!

Collapse
iih39354895 profile image
I H

:) U gave 'like' but what should i do? hhh

Collapse
emanuelferreira profile image
Emanuel Ferreira Author

Sorry, I forgot to send the answer hahaha

I'm searching for time to update the script to put the items to sell automatically and update the post teaching how to do it, you can call me in Twitter and I show to you how to adapt the script to put to sell

twitter.com/manelferreira_

Collapse
milanic profile image
Frank Stangenberger

Hi @emanuelferreira ,
All works fine, until a few days ago. Then the sign of login to opensea doesn't work any longer. But I could click myself the sign button.
But now, after all properties are inserted and clicking the 'create' button I get only the error from opensea: [401] Not authorized contract editor.

Can you confirm this. Is there a way to fix this?
Maybe they doesn't support test environments? Puppeteer always starts a browser with the hint 'Chrome is being controlled by automated test software'

Kind regards
Frank

Collapse
emanuelferreira profile image
Emanuel Ferreira Author

Hey Frank can you verify if the url to create the collection is right? opensea.io/assets/collectionName/c... or opensea.io/asset/collectionName/cr...

Collapse
milanic profile image
Frank Stangenberger

Shame on me. I've removed my secret phrase for git push and forget to add it again. I'm so sorry!

Collapse
milanic profile image
Frank Stangenberger

Yes. The url opensea.io/collection/${collection... is right. It works for a few weeks. :)

Collapse
arshinnef profile image
Arshin nefasati

Hi @emanuelferreira. Thank you very much for the explanation and great solution.
I am facing some issues with the script, please can you take a look at the attached screen and kindly let me know what am I missing or doing wrong? dev-to-uploads.s3.amazonaws.com/up...

Collapse
emanuelferreira profile image
Emanuel Ferreira Author

Hi @arshinnef, before run the yarn es you run the yarn install to install the packages?

Collapse
arshinnef profile image
Arshin nefasati • Edited on

dev-to-uploads.s3.amazonaws.com/up...
dev-to-uploads.s3.amazonaws.com/up...
Thank you for your reply, Yes I installed the package but still i get this error. Can you help to fix the issue please, I'll appreciate your help.

Thread Thread
emanuelferreira profile image
Emanuel Ferreira Author

Hi Arshin, you change the variable collectionName to happyapesub, so only need to back to collectionName

Collapse
arbeltal profile image
ArbelTal

Hi, why do i need to enter my phrase? there's no other way?
metamask allready connectend in my pc.

thank you.

Collapse
emanuelferreira profile image
Emanuel Ferreira Author

Hey, it's because in this flow the script need to join on your account in a new browser, so your account is not connected.

You can try to update the script to use your browser which is already logged in Metamask.

Collapse
arbeltal profile image
ArbelTal

Hi, thanks for the reply.

I'm new to programing where can i start with solving it?.

Collapse
megaevolutionto profile image
mega evolution

i need mint and sell nft its possible?

Collapse
emanuelferreira profile image
Emanuel Ferreira Author

Yeah, you need to adapt the script for this

Collapse
anhnpt profile image
AnhNPT

Hi there, can you add the function "add properties on opensea"?
I think you forget that :D

Collapse
arshinnef profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Arshin nefasati • Edited on

Hi @emanuelferreira. Thank you very much for the explanation and this great solution.
I am facing some issues with the script, please can you take a look at the attached screen and kindly let me know what am I missing or doing wrong? dev-to-uploads.s3.amazonaws.com/up...