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!
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
- In the identical listing the place you put in Hardhat run:
npx hardhat
- 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
npm set up @openzeppelin/contracts
-
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 nametokenOfOwnerByIndex
andbalanceOf
strategies, we are able to create an interface forCryptoDevs contract
with solely these two features.This manner we’d savegasoline
as we’d not must inherit and deploy the wholeCryptoDevs Contract
however solely part of it. -
Create a brand new file contained in the
contracts
listing and name itICryptoDevs.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);
}
- Create a brand new file contained in the
contracts
listing and name itCryptoDevToken.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 {}
}
- 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
- Now create a
.env
file within thehardhat-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"
-
Lets deploy the contract to
rinkeby
community. Create a brand new file nameddeploy.js
below thescripts
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);
});
- You’ll see that the
deploy.js
file requires a relentless. Let’s create aconstants
folder belowhardhat-tutorial
folder. -
Contained in the
constants
folder create a brand new file namedindex.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 };
- Change “address-of-the-nft-contract” with the handle of the
-
Now open the
hardhat.config.js
file, we’d add therinkeby
community right here in order that we are able to deploy our contract to rinkeby. Change all of the traces within thehardhat.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],
},
},
};
- Compile the contract, open up a terminal pointing at
hardhat-tutorial
listing and execute this command
npx hardhat compile
- To deploy, open up a terminal pointing at
hardhat-tutorial
listing and execute this command
npx hardhat run scripts/deploy.js --network rinkeby
- 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
- To create this
my-app
, within the terminal level to ICO folder and kind
npx create-next-app@newest
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
-
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
- In the identical terminal additionally set up
ethers.js
npm i ethers
.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;
}
}
- 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 ❤ by Crypto Devs
</footer>
</div>
);
}
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";
- Now in your terminal which is pointing to
my-app
folder, execute
npm run dev
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 toRoot Listing
and set it tomy-app
-
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 π
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.