├── style.css
├── README.md
├── mint-usdc.html
├── script
├── mint-usdc.js
├── app.js
└── transfer-usdc.js
├── .gitignore
└── index.html
/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | padding: 0;
3 | margin: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: 'Nunito Sans', sans-serif;
9 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Building Dapps With Ethers.js
2 |
3 | > Learn how to build your first Dapp with Ethers.js
4 | > https://blog.logrocket.com/building-dapp-ethers-js/
5 |
6 | ## Info
7 |
8 | Repo include the source-code for a dapp built with ethers.js, with the following functionalities:
9 | - Connect to Metamask or other ETH based wallet
10 | - Read USDC balance
11 | - Transfer USDC to other accounts
12 |
13 | ## Setup
14 |
15 | ```bash
16 | $ git clone https://github.com/AsaoluElijah/first-dapp.git
17 | $ cd first-dapp
18 | # switch to front-end branch
19 | $ git switch front-end
20 | $ code . # open with vscode
21 | ```
22 | ## Screenshot
23 |
24 | 
25 |
--------------------------------------------------------------------------------
/mint-usdc.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Mint USDC
8 |
14 |
15 |
16 |
17 |
Mint USDC
18 |
Click the button below to mint usdc
19 |
20 |
21 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/script/mint-usdc.js:
--------------------------------------------------------------------------------
1 | const provider = new ethers.providers.Web3Provider(window.ethereum, "any");
2 |
3 | const usdc = {
4 | address: "0x68ec573C119826db2eaEA1Efbfc2970cDaC869c4",
5 | abi: [
6 | "function name() view returns (string)",
7 | "function symbol() view returns (string)",
8 | "function gimmeSome() external",
9 | "function balanceOf(address _owner) public view returns (uint256 balance)",
10 | "function transfer(address _to, uint256 _value) public returns (bool success)",
11 | ],
12 | };
13 |
14 | async function mintUsdc() {
15 | await provider.send("eth_requestAccounts", []);
16 | const signer = provider.getSigner();
17 | let userAddress = await signer.getAddress();
18 | const usdcContract = new ethers.Contract(usdc.address, usdc.abi, signer);
19 |
20 | const tx = await usdcContract.gimmeSome({ gasPrice: 20e9 });
21 | console.log(`Transaction hash: ${tx.hash}`);
22 |
23 | const receipt = await tx.wait();
24 | console.log(`Transaction confirmed in block ${receipt.blockNumber}`);
25 | console.log(`Gas used: ${receipt.gasUsed.toString()}`);
26 | }
27 |
--------------------------------------------------------------------------------
/script/app.js:
--------------------------------------------------------------------------------
1 | const provider = new ethers.providers.Web3Provider(window.ethereum, "any");
2 |
3 | const usdc = {
4 | address: "0x68ec573C119826db2eaEA1Efbfc2970cDaC869c4",
5 | abi: [
6 | "function name() view returns (string)",
7 | "function symbol() view returns (string)",
8 | "function gimmeSome() external",
9 | "function balanceOf(address _owner) public view returns (uint256 balance)",
10 | "function transfer(address _to, uint256 _value) public returns (bool success)",
11 | ],
12 | };
13 |
14 | async function main() {
15 | /*=======
16 | CONNECT TO METAMASK
17 | =======*/
18 | await provider.send("eth_requestAccounts", []);
19 | const signer = provider.getSigner();
20 | let userAddress = await signer.getAddress();
21 | document.getElementById("userAddress").innerText =
22 | userAddress.slice(0, 8) + "...";
23 |
24 | /*======
25 | INITIALIZING CONTRACT
26 | ======*/
27 | const usdcContract = new ethers.Contract(usdc.address, usdc.abi, signer);
28 |
29 | let contractName = await usdcContract.name();
30 | // document.getElementById("contractName").innerText = contractName;
31 | let usdcBalance = await usdcContract.balanceOf(userAddress);
32 | usdcBalance = ethers.utils.formatUnits(usdcBalance, 6);
33 | document.getElementById("usdcBalance").innerText = usdcBalance;
34 | }
35 | main();
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
--------------------------------------------------------------------------------
/script/transfer-usdc.js:
--------------------------------------------------------------------------------
1 | async function transferUsdc() {
2 | let receiver = document.getElementById("receiver").value;
3 | let amount = document.getElementById("amount").value;
4 | let response;
5 |
6 | await provider.send("eth_requestAccounts", []);
7 | const signer = provider.getSigner();
8 | let userAddress = await signer.getAddress();
9 |
10 | const usdcContract = new ethers.Contract(usdc.address, usdc.abi, signer);
11 |
12 | try {
13 | receiver = ethers.utils.getAddress(receiver);
14 | } catch {
15 | response = `Invalid address: ${receiver}`;
16 | document.getElementById("transferResponse").innerText = response;
17 | document.getElementById("transferResponse").style.display = "block";
18 | }
19 |
20 | try {
21 | amount = ethers.utils.parseUnits(amount, 6);
22 | if (amount.isNegative()) {
23 | throw new Error();
24 | }
25 | } catch {
26 | console.error(`Invalid amount: ${amount}`);
27 | response = `Invalid amount: ${amount}`;
28 | document.getElementById("transferResponse").innerText = response;
29 | document.getElementById("transferResponse").style.display = "block";
30 | }
31 |
32 | const balance = await usdcContract.balanceOf(userAddress);
33 |
34 | if (balance.lt(amount)) {
35 | let amountFormatted = ethers.utils.formatUnits(amount, 6);
36 | let balanceFormatted = ethers.utils.formatUnits(balance, 6);
37 | console.error(
38 | `Insufficient balance receiver send ${amountFormatted} (You have ${balanceFormatted})`
39 | );
40 |
41 | response = `Insufficient balance receiver send ${amountFormatted} (You have ${balanceFormatted})`;
42 | document.getElementById("transferResponse").innerText = response;
43 | document.getElementById("transferResponse").style.display = "block";
44 | }
45 | let amountFormatted = ethers.utils.formatUnits(amount, 6);
46 |
47 | console.log(`Transferring ${amountFormatted} USDC receiver ${receiver}...`);
48 |
49 | response = `Transferring ${amountFormatted} USDC receiver ${receiver.slice(
50 | 0,
51 | 6
52 | )}...`;
53 | document.getElementById("transferResponse").innerText = response;
54 | document.getElementById("transferResponse").style.display = "block";
55 |
56 | const tx = await usdcContract.transfer(receiver, amount, { gasPrice: 20e9 });
57 | console.log(`Transaction hash: ${tx.hash}`);
58 | document.getElementById(
59 | "transferResponse"
60 | ).innerText += `Transaction hash: ${tx.hash}`;
61 |
62 | const receipt = await tx.wait();
63 | console.log(`Transaction confirmed in block ${receipt.blockNumber}`);
64 | document.getElementById(
65 | "transferResponse"
66 | ).innerText += `Transaction confirmed in block ${receipt.blockNumber}`;
67 | }
68 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | My First Dapp
8 |
9 |
10 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
You have:
29 |
30 |
0.00
31 | USDC
34 |
35 |
36 | 0x..add-here
47 |
48 |
49 |
50 | visit here to mint usdc
51 |
52 |
53 |
54 |
Transfer Usdt
55 |
60 | Lorem ipsum dolor sit amet.
61 |
62 |
86 |
87 |
88 |
89 |
90 |
91 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------