How to bulk upload 10,000+ NFTs to OpenSea
Published: 2022-05-01 12:04:19

I am assuming that you have got 10,000 graphic images ready and now you want them to be listed on *OpenSea*, though you can choose any of platform but here I am gonna tell you about OpenSea as it is more popular and more flexible NFT marketplace we have currently!

Now, there are several ways to list your art on OpenSea, I am listing down all possible ways down below and then we will choose best of all, that should have minimum gas fee and convenient for all. There could be several factors upon which we can differentiate them, here I am differentiating them on the bases of Using Smart Contract and Without Smart Contract.

**Bulk uploading without Smart Contracts**

 1. Upload your NFTs one by one to OpenSea and mint them to Ethereum Blockchain.

![Minting a NFT with Ethereum Blockchain](https://cdn-images-1.medium.com/max/2722/1*Pet5cmJo_Pc-qYqd3nCtDg.png)

But this costs lots of gas fee on minting as well as on storing images and metadata.

2. Upload your NFTs one by one to OpenSea and mint them to Polygon Blockchain.

![Minting a NFT with Polygon Blockchain](https://cdn-images-1.medium.com/max/2732/1*LOkA917rD0KE8ZWlNk1cHQ.png)

The reason behind choosing Polygon Blockchain here is it has no gas fee.

The problem here is we can only mint one by one NFT, not the bulk uploading, so that causes lots of time for uploading 10,000 NFTs. Now, there are two solutions to it, either we choose Smart Contract or we simply automate this process, as this section is for without Smart Contract I will explain how to automate the process, while in the other section we will be using Bulk Uploading through Smart Contracts.

So to automate this process we will be using *Mini Mouse Macro* tool [https://sourceforge.net/projects/minimousemacro/, ](https://sourceforge.net/projects/minimousemacro/)that simply copies our actions while uploading single NFT and then it repeats those actions on loop, to do so simply set the loop for 10,000 and it will automatically upload all the images to opensea.

![Bulk uploading using Mini Mouse Macro](https://cdn-images-1.medium.com/max/2000/1*T7IjT682Xv_A6yOA7RAeAQ.png)

Now I will not be explaining its complete working here, you can check out this video to understand how it works [https://youtu.be/-P20u-D--vA](https://youtu.be/-P20u-D--vA) . The problem with this method is, it also takes alot of time and it requires that all the programs running in your laptop should be at certain positions, if any popup or warning showed up, the macro gets distracted and you have to repeat your bulk uploading process all again.

So to answer this problem, we have another method that auto uploads NFTs, but I will not be writing it here now, I will write separate article on that.

**Bulk uploading using Smart Contracts**

The other way of bulk uploading is using Smart Contracts, now here also we have two ways to do it, either we deploy our smart contract online through *remix — Ethereum IDE* or we write the code offline and migrate the contract through *Truffle *and *Ganache*. One thing to note here is we have to pay gas fee on deploying any type of Smart Contract, no matter we are deploying it on Ethereum Blockchain or Polygon. **[**https://medium.com/scrappy-squirrels/estimating-smart-contract-costs-f65acf818c26](https://medium.com/scrappy-squirrels/estimating-smart-contract-costs-f65acf818c26) Here you can read further about what is Gas fee, why we have to pay it and can estimate the cost for deploying your smart contract, either you are choosing Ethereum or any side chain such as Polygon .

**Writing the contract offline and migrating it to mainnet or testnet**

While deploying contract through remix —Ethereum IDE, its very flexible as it provides everything in there, but when we are writing code offline and then migrating it to mainnet or testnet it requires lots of third party tools.

First you need to install Ganache and Truffle, then create your account on Pinata, then upload your images to IPFS using [https://github.com/HashLips/generative-art-node](https://github.com/HashLips/generative-art-node) this repository, that will return back the hash of images, you need update that hash to the metadata file and then upload the medatadata file to pinata that returns you the hash of metadata and then you have to go to the network you selected for your NFTs, like Polygon or Ethereum and paste the link there and it renders your NFTs on OpenSea. I will not be using this method here as it requires lots of third parties and you have to update the hashes each time and also need to manually add that link to render images on OpenSea, instead we will be using some advance version of this method.

**Writing a smart contract on Remix — Ethereum IDE and deploying on OpenSea**

Before moving ahead, lets discuss some dependencies we will be using for this method:

**IPFS**

IPFS is a distributed system for storing and accessing files, websites, applications, and data. When you add a file to IPFS, your file is split into smaller chunks, crypto-graphically hashed and given a unique fingerprint called content Identifier(CID), this CID acts as a permanent record of your file. When other nodes lookup your file, they ask their peer nodes who’s storing the content referenced by the file’s CID. When they view or download your file, they cache a copy and become another provider of your content until their cache is cleared. Average lifespan of a web page is 100 days, before its gone, but IPFS can store every version of your file by mirroring data. Nodes on IPFS network can automatically cache resources they download and keep those resources available for other nodes. Storage is finite so nodes need to clear out some of their previously cached resources to make room for new resources. This process Is called garbage collection. To ensure data persists on IPFS and not deleted during garbage collection, data can be pinned to one or more IPFS nodes.

**Pinata**

Billed as a simple way to upload files onto the IPFS, or InterPlanetary File System, Pinata is essentially a platform for moving and securing data through blockchains. To ensure someone can claim legitimate ownership of a digital file requires the verification and transfer of a particular non-fungible token.

**Lets start…**

 1. First of all place your all images in one folder and metadata in another.

 2. Create your account on Pinata [https://app.pinata.cloud/register](https://app.pinata.cloud/register)

 3. Once your account is created, sign-in to that and upload the images to Pinata

![Uploading Images to Pinata](https://cdn-images-1.medium.com/max/2730/1*wMMDs8SezxFNPW7YEpgOpg.png)

Simply click on upload and choose images folder, it will ask you name it, give the name and hit enter.

4. Once folder gets uploaded successfully Pinata generates the CID of that, copy that CID and update it to metadata file, for image

![](https://cdn-images-1.medium.com/max/2000/1*acPllr9IZuaLgrRmBlQg2w.png)

For each of image attribute add the CID of images folder/image_number. Here the CID is pointing the folder stored on IPFS and image_number is pointing that image in folder.

5. Go to Pinata and upload the metadata folder

6. Copy the CID of metadata folder

![CID of Metadata](https://cdn-images-1.medium.com/max/2732/1*eNjGA1Zrr41-Z54nG1ddkA.png)

7. Open remix — IDE

![Remix — IDE Ethereum](https://cdn-images-1.medium.com/max/2732/1*fnfr9jyjYtspNGMpiuYnpw.png)

Under the artifacts folder, create a file with extension sol and paste the blow code to it.

    pragma solidity >=0.7.0 <0.9.0;

    import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";

    import "@openzeppelin/contracts/access/Ownable.sol";

    contract NFT is ERC721Enumerable, Ownable {

    using Strings for uint256;

    string public baseURI;

    string public baseExtension = ".json";

    uint256 public cost = 0.05 ether;

    uint256 public maxSupply = 10000;

    uint256 public maxMintAmount = 10000;

    bool public paused = false;

    mapping(address => bool) public whitelisted;

    constructor(

    string memory _name,

    string memory _symbol,

    string memory _initBaseURI

    ) ERC721(_name, _symbol) {

    setBaseURI(_initBaseURI);

    mint(msg.sender, 10);

    }

    // internal

    function _baseURI() internal view virtual override returns (string memory) {

    return baseURI;

    }

    // public

    function mint(address _to, uint256 _mintAmount) public payable {

    uint256 supply = totalSupply();

    require(!paused);

    require(_mintAmount > 0);

    require(_mintAmount <= maxMintAmount);

    require(supply + _mintAmount <= maxSupply);

    if (msg.sender != owner()) {

    if(whitelisted[msg.sender] != true) {

    require(msg.value >= cost * _mintAmount);

    }

    }

    for (uint256 i = 1; i <= _mintAmount; i++) {

    _safeMint(_to, supply + i);

    }

    }

    function walletOfOwner(address _owner)

    public

    view

    returns (uint256[] memory)

    {

    uint256 ownerTokenCount = balanceOf(_owner);

    uint256[] memory tokenIds = new uint256[](ownerTokenCount);

    for (uint256 i; i < ownerTokenCount; i++) {

    tokenIds[i] = tokenOfOwnerByIndex(_owner, i);

    }

    return tokenIds;

    }

    function tokenURI(uint256 tokenId)

    public

    view

    virtual

    override

    returns (string memory)

    {

    require(

    _exists(tokenId),

    "ERC721Metadata: URI query for nonexistent token"

    );

    string memory currentBaseURI = _baseURI();

    return bytes(currentBaseURI).length > 0

    ? string(abi.encodePacked(currentBaseURI, tokenId.toString(), baseExtension))

    : "";

    }

    //only owner

    function setCost(uint256 _newCost) public onlyOwner {

    cost = _newCost;

    }

    function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner {

    maxMintAmount = _newmaxMintAmount;

    }

    function setBaseURI(string memory _newBaseURI) public onlyOwner {

    baseURI = _newBaseURI;

    }

    function setBaseExtension(string memory _newBaseExtension) public onlyOwner {

    baseExtension = _newBaseExtension;

    }

    function pause(bool _state) public onlyOwner {

    paused = _state;

    }

    function whitelistUser(address _user) public onlyOwner {

    whitelisted[_user] = true;

    }

    function removeWhitelistUser(address _user) public onlyOwner {

    whitelisted[_user] = false;

    }

    function withdraw() public payable onlyOwner {

    // This will pay HashLips 5% of the initial sale.

    // You can remove this if you want, or keep it in to support HashLips and his channel.

    // =============================================================================

    (bool hs, ) = payable(0x943590A42C27D08e3744202c4Ae5eD55c2dE240D).call{value: address(this).balance * 5 / 100}("");

    require(hs);

    // =============================================================================

    // This will payout the owner 95% of the contract balance.

    // Do not remove this otherwise you will not be able to withdraw the funds.

    // =============================================================================

    (bool os, ) = payable(owner()).call{value: address(this).balance}("");

    require(os);

    // =============================================================================

    }

    }

Instead of 10,000 if you want to upload 1000 or any number or more than 10,000 then simply change the value of

    uint256 public maxSupply = total_no_of_nfts;

    uint256 public maxMintAmount = nfts_you_want_to_upload;

8. From environment select Injected Web3

![](https://cdn-images-1.medium.com/max/2000/1*-IE495EYil7cHeUgf6n8xA.png)

If you want to deploy on testnet, go to Metamask and choose testnet account and then from environment choose Injected Web3, if you want to choose Ethereum Mainnet, choose the network from metamask and apply web3, same goes for Polygon, currently I have selected Polygon, you can see its chain ID 137. Also make sure to choose compiler between 0.7.0 <0.9.0

9. From contract option, select the .sol file you just created

![](https://cdn-images-1.medium.com/max/2000/1*zyS9reyEOKExdqm5LGYH7g.png)

In deploy add name of your nft project and symbol, in the baseuri paste the CID of your metadata folder from Pinata and add the like, ipfs://Metadata_CID/ Don’t forget to add / in the last, it will go like /1,/2 …/10000.

10. You are good to go, simply click on transact option, a popup will appear from metamask to confirm the transaction. You need to have some currency in your account, now it varies from network to network, you can read about it in detail on above provided article regarding cost of deploying on different networks.

![](https://cdn-images-1.medium.com/max/2000/1*wYVUF1T9qpptYcRqQObOmA.png)

Here I am using the Rinkeby testnet, simply click on Confirm to allow the transaction.

11. Go to [https://opensea.io](https://opensea.io) and go to the account option and then collection to view your collection, incase if you have deployed it on testnet then go to [https://testnets.opensea.io/](https://testnets.opensea.io/) and then collection, respectively.

![](https://cdn-images-1.medium.com/max/2000/1*j0a-G2fLQwFbwIPckUVBrQ.png)

Happy Hacking!…