Zero to One Full-Stack DApp Ethereum Development based on Foundry, NextJS, Types...
source link: https://iiiyu.com/2022/10/17/zero-to-one-full-stack-dapp-ethereum-development-based-on-foundry-nextjs-typescript-5-building-front-end-then-using-it-to-call-smart-contract/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Zero to One Full-Stack DApp Ethereum Development based on Foundry, NextJS, Typescript - 5 Building front-end then using it to call smart contract
In the beginning, we quickly build our home page’s layout on the front-end project.
We use below code to replace front_end/pages/index.tsx
file
import type { NextPage } from "next";
import { Navbar, Footer, Button } from "flowbite-react";
const Home: NextPage = () => {
const handleConnectWallet = () => {};
return (
<div className="">
<Navbar fluid={true} rounded={true}>
<Navbar.Brand href="/">
<img
src="https://flowbite.com/docs/images/logo.svg"
className="mr-3 h-6 sm:h-9"
alt="Flowbite Logo"
/>
<span className="self-center whitespace-nowrap text-xl font-semibold dark:text-white">
DApp Demo
</span>
</Navbar.Brand>
<Navbar.Toggle />
<Navbar.Collapse>
<Button onClick={handleConnectWallet}>Connect Wallet</Button>
</Navbar.Collapse>
</Navbar>
<div className="min-w-full min-h-full">
<div className="container flex flex-col justify-center items-center space-y-5"></div>
</div>
<Footer container={true}>
<Footer.Copyright
href="#"
by="OhMyApps™"
year={new Date().getFullYear()}
/>
<Footer.LinkGroup>
<Footer.Link href="#">About</Footer.Link>
<Footer.Link href="#">Privacy Policy</Footer.Link>
<Footer.Link href="#">Licensing</Footer.Link>
<Footer.Link href="#">Contact</Footer.Link>
</Footer.LinkGroup>
</Footer>
</div>
);
};
export default Home;
Let’s try to build the first feature with ethers.js
Install ethers.js
The ethers.js library is interacting with Ethereum. So we choose it.
Now, We install it.
// on ./DApp-Demo
cd front_end
yarn add ethers
We will build a button that connects our wallet.
We will use metamask to connect to our website. Looks like
We study the ethersjs document,
We changed our front_end/pages/index.tsx
file.
import { useState } from 'react'
import type { NextPage } from 'next'
import { Navbar, Footer, Button } from 'flowbite-react'
import { ethers } from 'ethers'
declare let window: any
const Home: NextPage = () => {
const [address, setAddress] = useState<string>()
const [balance, setBalance] = useState<string>()
const handleConnectWallet = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum)
await provider.send('eth_requestAccounts', [])
const signer = provider.getSigner()
setAddress(await signer.getAddress())
setBalance(ethers.utils.formatEther(await signer.getBalance()))
}
return (
<div className="">
<Navbar fluid={true} rounded={true}>
<Navbar.Brand href="/">
<img
src="https://flowbite.com/docs/images/logo.svg"
className="mr-3 h-6 sm:h-9"
alt="Flowbite Logo"
/>
<span className="self-center whitespace-nowrap text-xl font-semibold dark:text-white">
DApp Demo
</span>
</Navbar.Brand>
<Navbar.Toggle />
<Navbar.Collapse>
{address ? (
<>
<div>{address}</div>
<div>{balance}</div>
</>
) : (
<Button onClick={handleConnectWallet}>Connect Wallet</Button>
)}
</Navbar.Collapse>
</Navbar>
<div className="min-w-full min-h-full">
<div className="container flex flex-col justify-center items-center space-y-5"></div>
</div>
<Footer container={true}>
<Footer.Copyright
href="#"
by="OhMyApps™"
year={new Date().getFullYear()}
/>
<Footer.LinkGroup>
<Footer.Link href="#">About</Footer.Link>
<Footer.Link href="#">Privacy Policy</Footer.Link>
<Footer.Link href="#">Licensing</Footer.Link>
<Footer.Link href="#">Contact</Footer.Link>
</Footer.LinkGroup>
</Footer>
</div>
)
}
export default Home
We built the first feature with ethersjs.
Now we want to call our smart contract.
Integrating the Front-End
Generate Typescript code from ABI
Because we use typescript, so we can’t like javascript to directly call ABI.
Recommend TypeChain library. It helps us to create typescript code from Ethereum smart contract.
Install TypeChain
// on ./DApp-Demo
cd front_end
yarn add typechain @typechain/ethers-v5 -D
Use TypeChain
// on ./DApp-Demo/front_end
// Keep you already built the smart contract before.
npx typechain --target ethers-v5 --out-dir generated/contract-types '../chain_end/out/Counter.sol/Counter.json'
Output: Successfully generated 5 typings!
Now, we finished from the JSON ABI files to the typescript module.
Update the homepage
We changed our front_end/pages/index.tsx
file.
Only one important thing is COUNTER_ADDRESS
value. It muse be your smart contract deployed address.
import type { NextPage } from 'next'
import React from 'react'
import { useState, useEffect } from 'react'
import { ethers } from 'ethers'
import { Counter__factory } from '../generated/contract-types'
import { Navbar, Footer, Card, Label, TextInput, Button } from 'flowbite-react'
declare let window: any
const Home: NextPage = () => {
const [address, setAddress] = useState<string>()
const [balance, setBalance] = useState<string>()
const [count, setCount] = useState<number>(0)
const [number, setNumber] = useState<number>(0)
const [time, setTime] = useState(Date.now())
const COUNTER_ADDRESS = '0x4D32EEaee44e11cBD3fDE99F38f0885D0F735dE3'
useEffect(() => {
const interval = setInterval(() => setTime(Date.now()), 5000)
return () => {
clearInterval(interval)
}
}, [])
useEffect(() => {
const provider = new ethers.providers.StaticJsonRpcProvider()
const counter = Counter__factory.connect(COUNTER_ADDRESS, provider)
if (counter) {
counter.number().then((count) => {
setCount(count.toNumber())
})
}
}, [time])
const handleConnectWallet = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum)
await provider.send('eth_requestAccounts', [])
const signer = provider.getSigner()
setAddress(await signer.getAddress())
setBalance(ethers.utils.formatEther(await signer.getBalance()))
}
const handleRefresh = async () => {
const provider = new ethers.providers.StaticJsonRpcProvider()
const counter = Counter__factory.connect(COUNTER_ADDRESS, provider)
const n = await counter.number()
setCount(n.toNumber())
}
const handleIncrement = async () => {
console.log('increment')
const provider = new ethers.providers.Web3Provider(window.ethereum)
const signer = await provider.getSigner()
const counter = Counter__factory.connect(COUNTER_ADDRESS, signer)
await counter.increment()
}
const handleSetNumber = async () => {
console.log('set number')
const provider = new ethers.providers.Web3Provider(window.ethereum)
const signer = await provider.getSigner()
const contract = Counter__factory.connect(COUNTER_ADDRESS, signer)
await contract.setNumber(number)
}
return (
<div className="">
<Navbar fluid={true} rounded={true}>
<Navbar.Brand href="/">
<img
src="https://flowbite.com/docs/images/logo.svg"
className="mr-3 h-6 sm:h-9"
alt="Flowbite Logo"
/>
<span className="self-center whitespace-nowrap text-xl font-semibold dark:text-white">
DApp Demo
</span>
</Navbar.Brand>
<Navbar.Toggle />
<Navbar.Collapse>
{address ? (
<>
<div>{address}</div>
<div>{balance}</div>
</>
) : (
<Button onClick={handleConnectWallet}>Connect Wallet</Button>
)}
</Navbar.Collapse>
</Navbar>
<div className="min-w-full min-h-full">
<div className="container flex flex-col justify-center items-center space-y-5">
<div className="text-3xl font-bold">Counter {count}</div>
<Button color="light" onClick={handleRefresh}>
Refresh Counter
</Button>
<Card>
<Button onClick={handleIncrement}>Increment Counter</Button>
</Card>
<Card>
<div>
<div className="mb-2 block">
<Label htmlFor="number" value="Set Number" />
</div>
<TextInput
id="number"
type="number"
placeholder="Enter number"
value={number}
required={true}
onChange={(e) => setNumber(parseInt(e.target.value))}
/>
</div>
<Button type="submit" onClick={handleSetNumber}>
Submit
</Button>
</Card>
</div>
</div>
<Footer container={true}>
<Footer.Copyright
href="#"
by="OhMyApps™"
year={new Date().getFullYear()}
/>
<Footer.LinkGroup>
<Footer.Link href="#">About</Footer.Link>
<Footer.Link href="#">Privacy Policy</Footer.Link>
<Footer.Link href="#">Licensing</Footer.Link>
<Footer.Link href="#">Contact</Footer.Link>
</Footer.LinkGroup>
</Footer>
</div>
)
}
export default Home
Complete
This article is very subjective. If you do not feel comfortable viewing it, please close it as soon as possible.
If you think my article can help you, you can subscribe to this site by using RSS.
Referrals
Photo by GuerrillaBuzz Crypto PR on Unsplash
https://docs.scaffoldeth.io/scaffold-eth/toolkit/how-tos-and-troubleshooting/providers
https://docs.ethers.io/v5/api/providers/
https://docs.ethers.io/v5/api/signer/
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK