Launch an ICO on Ethereum using Solidity, Next.js, ethers.js, Web3Modal. Airdrop free tokens to NFT holders.

Now its time so that you can launch a token for Crypto Devs. Let’s name the token Crypto Dev Token.




Favor a Video?

Should you would moderately be taught from a video, now we have a recording accessible of this tutorial on our YouTube. Watch the video by clicking on the screenshot beneath, or go forward and skim the tutorial!
ICO dApp Part-1
ICO dApp Part-2



Construct



Necessities

  • There must be a max of 10,000 CD tokens.
  • Each Crypto Dev NFT holder ought to get 10 tokens without cost however they must pay the gasoline charges.
  • The worth of 1 CD on the time of ICO must be 0.001 ether
  • There must be an internet site which customers can go to for the ICO.

Let’s begin constructing πŸš€



Stipulations



Idea

  • What’s an ERC20?
    • ERC-20 is a technical customary; it’s used for all sensible contracts on the Ethereum blockchain for token implementation and offers a listing of guidelines that each one Ethereum-based tokens should observe.
    • Please take a look at all of the ERC20 functions earlier than transferring forward



Construct



Good Contract

To construct the sensible contract we’d be utilizing Hardhat.Hardhat is an Ethereum growth setting and framework designed for full stack growth in Solidity. In easy phrases you’ll be able to write your sensible contract, deploy them, run assessments, and debug your code.

  • To setup a Hardhat challenge, Open up a terminal and execute these instructions
  mkdir hardhat-tutorial
  cd hardhat-tutorial
  npm init --yes
  npm set up --save-dev hardhat
Enter fullscreen mode

Exit fullscreen mode

  • In the identical listing the place you put in Hardhat run:
  npx hardhat
Enter fullscreen mode

Exit fullscreen mode

  • Choose Create a primary pattern challenge
  • Press enter for the already specified Hardhat Challenge root
  • Press enter for the query on if you wish to add a .gitignore
  • Press enter for Do you wish to set up this pattern challenge's dependencies with npm (@nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers)?

Now you may have a hardhat challenge able to go!

In case you are not on mac, please do that additional step and set up these libraries as properly πŸ™‚

npm set up --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers
Enter fullscreen mode

Exit fullscreen mode

  npm set up @openzeppelin/contracts
Enter fullscreen mode

Exit fullscreen mode

  • We might want to name the CryptoDevs Contract that you simply deployed to your earlier degree to test for homeowners of CryptoDev NFT’s. As we solely must name tokenOfOwnerByIndex and balanceOf strategies, we are able to create an interface for CryptoDevs contract with solely these two features.This manner we’d save gasoline as we’d not must inherit and deploy the whole CryptoDevs Contract however solely part of it.

  • Create a brand new file contained in the contracts listing and name it ICryptoDevs.sol and add the next traces

  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.10;

  interface ICryptoDevs {
      /**
       * @dev Returns a token ID owned by `proprietor` at a given `index` of its token checklist.
       * Use together with {balanceOf} to enumerate all of ``proprietor``'s tokens.
       */
      perform tokenOfOwnerByIndex(handle proprietor, uint256 index)
          exterior
          view
          returns (uint256 tokenId);

      /**
       * @dev Returns the variety of tokens in ``proprietor``'s account.
       */
      perform balanceOf(handle proprietor) exterior view returns (uint256 stability);
  }

Enter fullscreen mode

Exit fullscreen mode

  • Create a brand new file contained in the contracts listing and name it CryptoDevToken.sol and add the next traces
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.10;

    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    import "@openzeppelin/contracts/entry/Ownable.sol";
    import "./ICryptoDevs.sol";

    contract CryptoDevToken is ERC20, Ownable {
        // Value of 1 Crypto Dev token
        uint256 public fixed tokenPrice = 0.001 ether;
        // Every NFT would give the person 10 tokens
        // It must be represented as 10 * (10 ** 18) as ERC20 tokens are represented by the smallest denomination attainable for the token
        // By default, ERC20 tokens have the smallest denomination of 10^(-18). This implies, having a stability of (1)
        // is definitely equal to (10 ^ -18) tokens.
        // Proudly owning 1 full token is equal to proudly owning (10^18) tokens if you account for the decimal locations.
        // Extra data on this may be discovered within the Freshman Monitor Cryptocurrency tutorial.
        uint256 public fixed tokensPerNFT = 10 * 10**18;
        // the max complete provide is 10000 for Crypto Dev Tokens
        uint256 public fixed maxTotalSupply = 10000 * 10**18;
        // CryptoDevsNFT contract occasion
        ICryptoDevs CryptoDevsNFT;
        // Mapping to maintain monitor of which tokenIds have been claimed
        mapping(uint256 => bool) public tokenIdsClaimed;

        constructor(handle _cryptoDevsContract) ERC20("Crypto Dev Token", "CD") {
            CryptoDevsNFT = ICryptoDevs(_cryptoDevsContract);
        }

        /**
         * @dev Mints `quantity` variety of CryptoDevTokens
         * Necessities:
         * - `msg.worth` must be equal or better than the tokenPrice * quantity
         */
        perform mint(uint256 quantity) public payable {
            // the worth of ether that must be equal or better than tokenPrice * quantity;
            uint256 _requiredAmount = tokenPrice * quantity;
            require(msg.worth >= _requiredAmount, "Ether despatched is inaccurate");
            // complete tokens + quantity <= 10000, in any other case revert the transaction
            uint256 amountWithDecimals = quantity * 10**18;
            require(
                (totalSupply() + amountWithDecimals) <= maxTotalSupply,
                "Exceeds the max complete provide accessible."
            );
            // name the inner perform from Openzeppelin's ERC20 contract
            _mint(msg.sender, amountWithDecimals);
        }

        /**
         * @dev Mints tokens based mostly on the variety of NFT's held by the sender
         * Necessities:
         * stability of Crypto Dev NFT's owned by the sender must be better than 0
         * Tokens ought to haven't been claimed for all of the NFTs owned by the sender
         */
        perform declare() public {
            handle sender = msg.sender;
            // Get the variety of CryptoDev NFT's held by a given sender handle
            uint256 stability = CryptoDevsNFT.balanceOf(sender);
            // If the stability is zero, revert the transaction
            require(stability > 0, "You dont personal any Crypto Dev NFT's");
            // quantity retains monitor of variety of unclaimed tokenIds
            uint256 quantity = 0;
            // loop over the stability and get the token ID owned by `sender` at a given `index` of its token checklist.
            for (uint256 i = 0; i < stability; i++) {
                uint256 tokenId = CryptoDevsNFT.tokenOfOwnerByIndex(sender, i);
                // if the tokenId has not been claimed, enhance the quantity
                if (!tokenIdsClaimed[tokenId]) {
                    quantity += 1;
                    tokenIdsClaimed[tokenId] = true;
                }
            }
            // If all of the token Ids have been claimed, revert the transaction;
            require(quantity > 0, "You've already claimed all of the tokens");
            // name the inner perform from Openzeppelin's ERC20 contract
            // Mint (quantity * 10) tokens for every NFT
            _mint(msg.sender, quantity * tokensPerNFT);
        }

        // Perform to obtain Ether. msg.knowledge should be empty
        obtain() exterior payable {}

        // Fallback perform is known as when msg.knowledge isn't empty
        fallback() exterior payable {}
    }

Enter fullscreen mode

Exit fullscreen mode

  • Now we’d set up dotenv package deal to have the ability to import the env file and use it in our config. Open up a terminal pointing athardhat-tutorial listing and execute this command
  npm set up dotenv
Enter fullscreen mode

Exit fullscreen mode

  • Now create a .env file within the hardhat-tutorial folder and add the next traces, use the directions within the feedback to get your Alchemy API Key URL and RINKEBY Non-public Key. Ensure that the account from which you get your rinkeby non-public secret’s funded with Rinkeby Ether.

  // Go to https://www.alchemyapi.io, join, create
  // a brand new App in its dashboard and choose the community as Rinkeby, and exchange "add-the-alchemy-key-url-here" with its key url
  ALCHEMY_API_KEY_URL="add-the-alchemy-key-url-here"

  // Change this non-public key together with your RINKEBY account non-public key
  // To export your non-public key from Metamask, open Metamask and
  // go to Account Particulars > Export Non-public Key
  // Concentrate on NEVER placing actual Ether into testing accounts
  RINKEBY_PRIVATE_KEY="add-the-rinkeby-private-key-here"
Enter fullscreen mode

Exit fullscreen mode

  • Lets deploy the contract to rinkeby community. Create a brand new file named deploy.js below the scripts folder

  • Now we’d write some code to deploy the contract in deploy.js file.

  const { ethers } = require("hardhat");
  require("dotenv").config({ path: ".env" });
  const { CRYPTO_DEVS_NFT_CONTRACT_ADDRESS } = require("../constants");

  async perform important() {
    // Handle of the Crypto Devs NFT contract that you simply deployed within the earlier module
    const cryptoDevsNFTContract = CRYPTO_DEVS_NFT_CONTRACT_ADDRESS;

    /*
      A ContractFactory in ethers.js is an abstraction used to deploy new sensible contracts,
      so cryptoDevsTokenContract here's a manufacturing facility for cases of our CryptoDevToken contract.
      */
    const cryptoDevsTokenContract = await ethers.getContractFactory(
      "CryptoDevToken"
    );

    // deploy the contract
    const deployedCryptoDevsTokenContract = await cryptoDevsTokenContract.deploy(
      cryptoDevsNFTContract
    );

    // print the handle of the deployed contract
    console.log(
      "Crypto Devs Token Contract Handle:",
      deployedCryptoDevsTokenContract.handle
    );
  }

  // Name the principle perform and catch if there's any error
  important()
    .then(() => course of.exit(0))
    .catch((error) => {
      console.error(error);
      course of.exit(1);
    });
Enter fullscreen mode

Exit fullscreen mode

  • You’ll see that the deploy.js file requires a relentless. Let’s create a constants folder below hardhat-tutorial folder.
  • Contained in the constants folder create a brand new file named index.js and add the next traces to it.

    • Change “address-of-the-nft-contract” with the handle of the CryptoDevs.sol that you simply deployed within the earlier module(NFT-Assortment)
    // Handle of the NFT Contract that you simply deployed
    const CRYPTO_DEVS_NFT_CONTRACT_ADDRESS = "address-of-the-nft-contract";
    
    module.exports = { CRYPTO_DEVS_NFT_CONTRACT_ADDRESS };
    
  • Now open the hardhat.config.js file, we’d add the rinkeby community right here in order that we are able to deploy our contract to rinkeby. Change all of the traces within the hardhat.config.js file with the given beneath traces

  require("@nomiclabs/hardhat-waffle");
  require("dotenv").config({ path: ".env" });

  const ALCHEMY_API_KEY_URL = course of.env.ALCHEMY_API_KEY_URL;

  const RINKEBY_PRIVATE_KEY = course of.env.RINKEBY_PRIVATE_KEY;

  module.exports = {
    solidity: "0.8.10",
    networks: {
      rinkeby: {
        url: ALCHEMY_API_KEY_URL,
        accounts: [RINKEBY_PRIVATE_KEY],
      },
    },
  };
Enter fullscreen mode

Exit fullscreen mode

  • Compile the contract, open up a terminal pointing athardhat-tutorial listing and execute this command
     npx hardhat compile
Enter fullscreen mode

Exit fullscreen mode

  • To deploy, open up a terminal pointing athardhat-tutorial listing and execute this command
    npx hardhat run scripts/deploy.js --network rinkeby
Enter fullscreen mode

Exit fullscreen mode

  • Save the CryptoDevToken Contract Handle that was printed in your terminal in your notepad, you would want it futher down within the tutorial.



Web site

  • To develop the web site we’d be utilizing React and Next Js. React is a javascript framework which is used to make web sites and Subsequent Js is constructed on high of React.
  • First, You would want to create a brand new subsequent app. Your folder construction ought to look one thing like
     - ICO
         - hardhat-tutorial
         - my-app
Enter fullscreen mode

Exit fullscreen mode

  • To create this my-app, within the terminal level to ICO folder and kind
      npx create-next-app@newest
Enter fullscreen mode

Exit fullscreen mode

and press enter for all of the questions

  • Now to run the app, execute these instructions within the terminal
  cd my-app
  npm run dev
Enter fullscreen mode

Exit fullscreen mode

  • Now go to http://localhost:3000, your app must be working 🀘

  • Now lets set up Web3Modal library(https://github.com/Web3Modal/web3modal). Web3Modal is an easy-to-use library to assist builders add assist for a number of suppliers of their apps with a easy customizable configuration. By default Web3Modal Library helps injected suppliers like (Metamask, Dapper, Gnosis Secure, Body, Web3 Browsers, and so forth), You can too simply configure the library to assist Portis, Fortmatic, Squarelink, Torus, Authereum, D’CENT Pockets and Arkane.
    Open up a terminal pointing atmy-app listing and execute this command

    npm set up web3modal
Enter fullscreen mode

Exit fullscreen mode

  • In the identical terminal additionally set up ethers.js
  npm i ethers
Enter fullscreen mode

Exit fullscreen mode

  .important {
    min-height: 90vh;
    show: flex;
    flex-direction: row;
    justify-content: heart;
    align-items: heart;
    font-family: "Courier New", Courier, monospace;
  }

  .footer {
    show: flex;
    padding: 2rem 0;
    border-top: 1px strong #eaeaea;
    justify-content: heart;
    align-items: heart;
  }

  .picture {
    width: 70%;
    top: 50%;
    margin-left: 20%;
  }

  .enter {
    width: 200px;
    top: 100%;
    padding: 1%;
    margin-bottom: 2%;
    box-shadow: 0 0 15px 4px rgba(0, 0, 0, 0.06);
    border-radius: 10px;
  }

  .title {
    font-size: 2rem;
    margin: 2rem 0;
  }

  .description {
    line-height: 1;
    margin: 2rem 0;
    font-size: 1.2rem;
  }

  .button {
    border-radius: 4px;
    background-color: blue;
    border: none;
    colour: #ffffff;
    font-size: 15px;
    padding: 5px;
    width: 100px;
    cursor: pointer;
    margin-bottom: 2%;
  }
  @media (max-width: 1000px) {
    .important {
      width: 100%;
      flex-direction: column;
      justify-content: heart;
      align-items: heart;
    }
  }
Enter fullscreen mode

Exit fullscreen mode

  • Open you index.js file below the pages folder and paste the next code, clarification of the code might be discovered within the feedback.
import { BigNumber, Contract, suppliers, utils } from "ethers";
import Head from "subsequent/head";
import React, { useEffect, useRef, useState } from "react";
import Web3Modal from "web3modal";
import {
  NFT_CONTRACT_ABI,
  NFT_CONTRACT_ADDRESS,
  TOKEN_CONTRACT_ABI,
  TOKEN_CONTRACT_ADDRESS,
} from "../constants";
import types from "../types/Dwelling.module.css";

export default perform Dwelling() {
  // Create a BigNumber `0`
  const zero = BigNumber.from(0);
  // walletConnected retains monitor of whether or not the person's pockets is related or not
  const [walletConnected, setWalletConnected] = useState(false);
  // loading is about to true once we are ready for a transaction to get mined
  const [loading, setLoading] = useState(false);
  // tokensToBeClaimed retains monitor of the variety of tokens that may be claimed
  // based mostly on the Crypto Dev NFT's held by the person for which they havent claimed the tokens
  const [tokensToBeClaimed, setTokensToBeClaimed] = useState(zero);
  // balanceOfCryptoDevTokens retains monitor of variety of Crypto Dev tokens owned by an handle
  const [balanceOfCryptoDevTokens, setBalanceOfCryptoDevTokens] = useState(
    zero
  );
  // quantity of the tokens that the person desires to mint
  const [tokenAmount, setTokenAmount] = useState(zero);
  // tokensMinted is the overall variety of tokens which have been minted until now out of 10000(max complete provide)
  const [tokensMinted, setTokensMinted] = useState(zero);
  // Create a reference to the Web3 Modal (used for connecting to Metamask) which persists so long as the web page is open
  const web3ModalRef = useRef();

  /**
   * getTokensToBeClaimed: checks the stability of tokens that may be claimed by the person
   */
  const getTokensToBeClaimed = async () => {
    strive {
      // Get the supplier from web3Modal, which in our case is MetaMask
      // No want for the Signer right here, as we're solely studying state from the blockchain
      const supplier = await getProviderOrSigner();
      // Create an occasion of NFT Contract
      const nftContract = new Contract(
        NFT_CONTRACT_ADDRESS,
        NFT_CONTRACT_ABI,
        supplier
      );
      // Create an occasion of tokenContract
      const tokenContract = new Contract(
        TOKEN_CONTRACT_ADDRESS,
        TOKEN_CONTRACT_ABI,
        supplier
      );
      // We'll get the signer now to extract the handle of the presently related MetaMask account
      const signer = await getProviderOrSigner(true);
      // Get the handle related to the signer which is related to  MetaMask
      const handle = await signer.getAddress();
      // name the balanceOf from the NFT contract to get the variety of NFT's held by the person
      const stability = await nftContract.balanceOf(handle);
      // stability is a Huge quantity and thus we'd evaluate it with Huge quantity `zero`
      if (stability === zero) {
        setTokensToBeClaimed(zero);
      } else {
        // quantity retains monitor of the variety of unclaimed tokens
        var quantity = 0;
        // For all of the NFT's, test if the tokens have already been claimed
        // Solely enhance the quantity if the tokens haven't been claimed
        // for a an NFT(for a given tokenId)
        for (var i = 0; i < stability; i++) {
          const tokenId = await nftContract.tokenOfOwnerByIndex(handle, i);
          const claimed = await tokenContract.tokenIdsClaimed(tokenId);
          if (!claimed) {
            quantity++;
          }
        }
        //tokensToBeClaimed has been initialized to a Huge Quantity, thus we'd convert quantity
        // to a giant quantity after which set its worth
        setTokensToBeClaimed(BigNumber.from(quantity));
      }
    } catch (err) {
      console.error(err);
      setTokensToBeClaimed(zero);
    }
  };

  /**
   * getBalanceOfCryptoDevTokens: checks the stability of Crypto Dev Tokens's held by an handle
   */
  const getBalanceOfCryptoDevTokens = async () => {
    strive {
      // Get the supplier from web3Modal, which in our case is MetaMask
      // No want for the Signer right here, as we're solely studying state from the blockchain
      const supplier = await getProviderOrSigner();
      // Create an instace of token contract
      const tokenContract = new Contract(
        TOKEN_CONTRACT_ADDRESS,
        TOKEN_CONTRACT_ABI,
        supplier
      );
      // We'll get the signer now to extract the handle of the presently related MetaMask account
      const signer = await getProviderOrSigner(true);
      // Get the handle related to the signer which is related to  MetaMask
      const handle = await signer.getAddress();
      // name the balanceOf from the token contract to get the variety of tokens held by the person
      const stability = await tokenContract.balanceOf(handle);
      // stability is already a giant quantity, so we dont must convert it earlier than setting it
      setBalanceOfCryptoDevTokens(stability);
    } catch (err) {
      console.error(err);
      setBalanceOfCryptoDevTokens(zero);
    }
  };

  /**
   * mintCryptoDevToken: mints `quantity` variety of tokens to a given handle
   */
  const mintCryptoDevToken = async (quantity) => {
    strive {
      // We'd like a Signer right here since it is a 'write' transaction.
      // Create an occasion of tokenContract
      const signer = await getProviderOrSigner(true);
      // Create an occasion of tokenContract
      const tokenContract = new Contract(
        TOKEN_CONTRACT_ADDRESS,
        TOKEN_CONTRACT_ABI,
        signer
      );
      // Every token is of `0.001 ether`. The worth we have to ship is `0.001 * quantity`
      const worth = 0.001 * quantity;
      const tx = await tokenContract.mint(quantity, {
        // worth signifies the price of one crypto dev token which is "0.001" eth.
        // We're parsing `0.001` string to ether utilizing the utils library from ethers.js
        worth: utils.parseEther(worth.toString()),
      });
      setLoading(true);
      // anticipate the transaction to get mined
      await tx.wait();
      setLoading(false);
      window.alert("Sucessfully minted Crypto Dev Tokens");
      await getBalanceOfCryptoDevTokens();
      await getTotalTokensMinted();
      await getTokensToBeClaimed();
    } catch (err) {
      console.error(err);
    }
  };

  /**
   * claimCryptoDevTokens: Helps the person declare Crypto Dev Tokens
   */
  const claimCryptoDevTokens = async () => {
    strive {
      // We'd like a Signer right here since it is a 'write' transaction.
      // Create an occasion of tokenContract
      const signer = await getProviderOrSigner(true);
      // Create an occasion of tokenContract
      const tokenContract = new Contract(
        TOKEN_CONTRACT_ADDRESS,
        TOKEN_CONTRACT_ABI,
        signer
      );
      const tx = await tokenContract.declare();
      setLoading(true);
      // anticipate the transaction to get mined
      await tx.wait();
      setLoading(false);
      window.alert("Sucessfully claimed Crypto Dev Tokens");
      await getBalanceOfCryptoDevTokens();
      await getTotalTokensMinted();
      await getTokensToBeClaimed();
    } catch (err) {
      console.error(err);
    }
  };

  /**
   * getTotalTokensMinted: Retrieves what number of tokens have been minted until now
   * out of the overall provide
   */
  const getTotalTokensMinted = async () => {
    strive {
      // Get the supplier from web3Modal, which in our case is MetaMask
      // No want for the Signer right here, as we're solely studying state from the blockchain
      const supplier = await getProviderOrSigner();
      // Create an occasion of token contract
      const tokenContract = new Contract(
        TOKEN_CONTRACT_ADDRESS,
        TOKEN_CONTRACT_ABI,
        supplier
      );
      // Get all of the tokens which have been minted
      const _tokensMinted = await tokenContract.totalSupply();
      setTokensMinted(_tokensMinted);
    } catch (err) {
      console.error(err);
    }
  };
  /**
   * Returns a Supplier or Signer object representing the Ethereum RPC with or with out the
   * signing capabilities of metamask connected
   *
   * A `Supplier` is required to work together with the blockchain - studying transactions, studying balances, studying state, and so forth.
   *
   * A `Signer` is a particular sort of Supplier utilized in case a `write` transaction must be made to the blockchain, which includes the related account
   * needing to make a digital signature to authorize the transaction being despatched. Metamask exposes a Signer API to permit your web site to
   * request signatures from the person utilizing Signer features.
   *
   * @param {*} needSigner - True in the event you want the signer, default false in any other case
   */
  const getProviderOrSigner = async (needSigner = false) => {
    // Hook up with Metamask
    // Since we retailer `web3Modal` as a reference, we have to entry the `present` worth to get entry to the underlying object
    const supplier = await web3ModalRef.present.join();
    const web3Provider = new suppliers.Web3Provider(supplier);

    // If person isn't related to the Rinkeby community, allow them to know and throw an error
    const { chainId } = await web3Provider.getNetwork();
    if (chainId !== 4) {
      window.alert("Change the community to Rinkeby");
      throw new Error("Change community to Rinkeby");
    }

    if (needSigner) {
      const signer = web3Provider.getSigner();
      return signer;
    }
    return web3Provider;
  };

  /*
        connectWallet: Connects the MetaMask pockets
      */
  const connectWallet = async () => {
    strive {
      // Get the supplier from web3Modal, which in our case is MetaMask
      // When used for the primary time, it prompts the person to attach their pockets
      await getProviderOrSigner();
      setWalletConnected(true);
    } catch (err) {
      console.error(err);
    }
  };

  // useEffects are used to react to modifications in state of the web site
  // The array on the finish of perform name represents what state modifications will set off this impact
  // On this case, each time the worth of `walletConnected` modifications - this impact shall be known as
  useEffect(() => {
    // if pockets isn't related, create a brand new occasion of Web3Modal and join the MetaMask pockets
    if (!walletConnected) {
      // Assign the Web3Modal class to the reference object by setting it is `present` worth
      // The `present` worth is persevered all through so long as this web page is open
      web3ModalRef.present = new Web3Modal({
        community: "rinkeby",
        providerOptions: {},
        disableInjectedProvider: false,
      });
      connectWallet();
      getTotalTokensMinted();
      getBalanceOfCryptoDevTokens();
      getTokensToBeClaimed();
    }
  }, [walletConnected]);

  /*
        renderButton: Returns a button based mostly on the state of the dapp
      */
  const renderButton = () => {
    // If we're presently ready for one thing, return a loading button
    if (loading) {
      return (
        <div>
          <button className={types.button}>Loading...</button>
        </div>
      );
    }
    // If tokens to be claimed are better than 0, Return a declare button
    if (tokensToBeClaimed > 0) {
      return (
        <div>
          <div className={types.description}>
            {tokensToBeClaimed * 10} Tokens can be claimed!
          </div>
          <button className={types.button} onClick={claimCryptoDevTokens}>
            Declare Tokens
          </button>
        </div>
      );
    }
    // If person would not have any tokens to assert, present the mint button
    return (
      <div type={{ show: "flex-col" }}>
        <div>
          <enter
            sort="quantity"
            placeholder="Quantity of Tokens"
            // BigNumber.from converts the `e.goal.worth` to a BigNumber
            onChange={(e) => setTokenAmount(BigNumber.from(e.goal.worth))}
            className={types.enter}
          />
        </div>

        <button
          className={types.button}
          disabled={!(tokenAmount > 0)}
          onClick={() => mintCryptoDevToken(tokenAmount)}
        >
          Mint Tokens
        </button>
      </div>
    );
  };

  return (
    <div>
      <Head>
        <title>Crypto Devs</title>
        <meta identify="description" content material="ICO-Dapp" />
        <hyperlink rel="icon" href="/favicon.ico" />
      </Head>
      <div className={types.important}>
        <div>
          <h1 className={types.title}>Welcome to Crypto Devs ICO!</h1>
          <div className={types.description}>
            You can declare or mint Crypto Dev tokens right here
          </div>
          {walletConnected ? (
            <div>
              <div className={types.description}>
                {/* Format Ether helps us in changing a BigNumber to string */}
                You have minted {utils.formatEther(balanceOfCryptoDevTokens)} Crypto
                Dev Tokens
              </div>
              <div className={types.description}>
                {/* Format Ether helps us in changing a BigNumber to string */}
                Total {utils.formatEther(tokensMinted)}/10000 have been minted!!!
              </div>
              {renderButton()}
            </div>
          ) : (
            <button onClick={connectWallet} className={types.button}>
              Join your pockets
            </button>
          )}
        </div>
        <div>
          <img className={types.picture} src="./0.svg" />
        </div>
      </div>

      <footer className={types.footer}>
        Made with &#10084; by Crypto Devs
      </footer>
    </div>
  );
}
Enter fullscreen mode

Exit fullscreen mode

  export const NFT_CONTRACT_ABI = "abi-of-your-nft-contract";
  export const NFT_CONTRACT_ADDRESS = "address-of-your-nft-contract";
  export const TOKEN_CONTRACT_ABI = "abi-of-your-token-contract";
  export const TOKEN_CONTRACT_ADDRESS = "address-of-your-token-contract";
Enter fullscreen mode

Exit fullscreen mode

  • Now in your terminal which is pointing to my-app folder, execute
  npm run dev
Enter fullscreen mode

Exit fullscreen mode

Your ICO dapp ought to now work with out errors πŸš€




Push to Github

Be certain to push all this code to Github before proceeding to the next step.




Deploying your dApp

We’ll now deploy your dApp, so that everybody can see your web site and you may share it with all your LearnWeb3 DAO pals.

  • Go to https://vercel.com/ and check in together with your GitHub
  • Then click on on New Challenge button after which choose your ICO dApp repo
  • When configuring your new challenge, Vercel will help you customise your Root Listing
  • Click on Edit subsequent to Root Listing and set it to my-app
  • Choose the Framework Preset as Subsequent.js

  • Click on Deploy

  • Now you’ll be able to see your deployed web site by going to your dashboard, choosing your challenge, and copying the URL from there!



CONGRATULATIONS! You are all completed!

Hopefully you loved this tutorial. Remember to share your ICO web site within the #showcase channel on Discord πŸ˜€


Image description

This text is delivered to you by LearnWeb3 DAO. A free, complete A to Z blockchain coaching program for builders throughout the globe.

Every thing from “What’s a Blockchain” to “Hacking sensible contracts”β€Š-β€Šand all the things in between, but additionally way more!
Be part of us now to start out buidling with 25,000+ builders.

Website
Discord
Twitter



Add a Comment

Your email address will not be published. Required fields are marked *