Zero to One Full-Stack DApp Ethereum Development based on Foundry, NextJS, Typescript - 6 Deploying DApp to the world

Zero to One Full-Stack DApp Ethereum Development based on Foundry, NextJS, Typescript - 6 Deploying DApp to the world

Deploying it to the World

So, we have it working great locally, how do we get it out to the world?

Deploying smart contract to Goerli test network

Get some test GoEth

I really recommend this faucet https://goerli-faucet.pk910.de/. It doesn’t register any account. It is easy.

Get the goerli RPC url

sign up the https://infura.io and you can find it.

It looks like this:
https://goerli.infura.io/v3/YOUR_API_KEY

Get the etherscan api key to verify

https://etherscan.io/myapikey here find your api key.

The smart contract deploys to Goerli test network

1
2
3
// on ./DApp-Demo
cd chain_end
forge create --rpc-url https://goerli.infura.io/v3/YOUR_API_KEY --private-key YOUR_PRIVATE_KEY src/Counter.sol:Counter --etherscan-api-key YOUR_ETHERSCAN_API_KEY --verify

Output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[⠆] Compiling...
No files changed, compilation skipped
Deployer: 0x858F72b2919d5A5794bE7b93ce4e603f8FFB8792
Deployed to: 0x4B54941BB18D54dD78D9bA598bc799a759c671c9
Transaction hash: 0x736ac18b04092b9acf3d4140ae49d7e93e450a49f14fe96081ed5e4fe26f38cc
Starting contract verification...
Waiting for etherscan to detect contract deployment...

Submitting verification for [src/Counter.sol:Counter] "0x4B54941BB18D54dD78D9bA598bc799a759c671c9".

Submitting verification for [src/Counter.sol:Counter] "0x4B54941BB18D54dD78D9bA598bc799a759c671c9".

Submitting verification for [src/Counter.sol:Counter] "0x4B54941BB18D54dD78D9bA598bc799a759c671c9".

Submitting verification for [src/Counter.sol:Counter] "0x4B54941BB18D54dD78D9bA598bc799a759c671c9".

Submitting verification for [src/Counter.sol:Counter] "0x4B54941BB18D54dD78D9bA598bc799a759c671c9".
Submitted contract for verification:
Response: `OK`
GUID: `ukrqjb5n3rmrxbns2jf91a2nbbmiqkjv8vticjhti3t4dzw6jf`
URL:
https://goerli.etherscan.io/address/0x4b54941bb18d54dd78d9ba598bc799a759c671c9
Waiting for verification result...
Contract successfully verified

Please remember this is deployed to value. It is your smart contract address.

Checks it on Etherscan

Our code was verified. Nice!

image.png

Deploying website to IPFS

Update our front-end code

We need to do two things:

  1. replace StaticJsonRpcProvider with InfuraProvider
  2. Uses the correct smart contract address. replace const COUNTER_ADDRESS value.

We changed our front_end/pages/index.tsx file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
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,
Alert,
} 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 = '0x4B54941BB18D54dD78D9bA598bc799a759c671c9'

useEffect(() => {
const interval = setInterval(() => setTime(Date.now()), 5000)
return () => {
clearInterval(interval)
}
}, [])

useEffect(() => {
const provider = new ethers.providers.InfuraProvider('goerli')
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.InfuraProvider('goerli')
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>

<Alert
color="warning"
additionalContent={
<>
<a
href={`https://goerli.etherscan.io/address/${COUNTER_ADDRESS}`}
className="mr-2 inline-flex items-center rounded-lg bg-yellow-700 px-3 py-1.5 text-center text-xs font-medium text-white hover:bg-yellow-800 focus:ring-4 focus:ring-yellow-300 dark:bg-yellow-800 dark:hover:bg-yellow-900"
>
View more
</a>
</>
}
>
<div className="flex w-full justify-between flex-row space-x-5">
<div>
<span className="font-medium">Alert!</span> This smart contract runs
on the Goerli testnet.
</div>
</div>
</Alert>

<div className="min-w-screen min-h-full mx-auto mt-8">
<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

Update front end project config

  1. Open package.json and add the following scripts
1
2
3
4
5
6
7
8
...
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"export": "next export"
}
...
  1. Open next.config.js and add two lines of code.
1
2
3
4
5
6
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
exportTrailingSlash: true,
assetPrefix: './',
}

Deploys front end project to IPFS

We will use the fleek to help us to deploy our front end project.

The fleek likes vercel. They are the same and easy to use. Just the fleek pushes the file to IPFS.

So First we sign up the fleek or sign in if you already have an account.

Then,

  1. Create a new site

image.png

  1. Connect to Github

  2. Pick a repository

image.png

  1. Deploy location

image.png

  1. Build options, and deploy!

Framework selects Next.JS

image.png

Build command
npm install && npm run build && npm run export
changes to

cd front_end && npm install && npm run build && npm run export

Publish directory
out
changes to
front_end/out

image.png

All right. Wait a few minutes.

You will see like:
image.png

We can click Verify on IPFS to verify our website on IPFS.

This is url likes https://ipfs.fleek.co/ipfs/QmcNoHXxrpaxyxKhLhpUoFDzzycvx7o2fUh9mXiG83Xph4/

The QmcNoHXxrpaxyxKhLhpUoFDzzycvx7o2fUh9mXiG83Xph4 is your unique token.

We can replace the URL to https://ipfs.io/ipfs/QmcNoHXxrpaxyxKhLhpUoFDzzycvx7o2fUh9mXiG83Xph4/ for 100% verification on IPFS.

Everything looks great.

Summary

So exciting, We build a real 100% decentralized application from 0 to 1.

We used all modern tech stack:

  1. NextJS
  2. TailwindCSS
  3. Solidity
  4. Foundry
  5. IPFS

We deploy a smart contract on Goerli test network and deploy a website on IPFS.

You can find the code on github and visit the website on custom domain or IPFS domain

image.png

P.S.

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://blog.fleek.co/posts/fleek-nextJS

https://github.com/Velenir/nextjs-ipfs-example

Zero to One Full-Stack DApp Ethereum Development based on Foundry, NextJS, Typescript - 6 Deploying DApp to the world

https://iiiyu.com/2022/10/23/Zero-to-One-Full-Stack-DApp-Ethereum-Development-based-on-Foundry-NextJS-Typescript-6-Deploying-DApp-to-the-world/

Author

Ewan Xiao

Posted on

October 23rd 2022

Updated on

September 28th 2023

Licensed under

Comments