Smart Contract Frontend — FundMe dApp
A lightweight vanilla JavaScript frontend that connects the MetaMask wallet to a FundMe smart contract deployed on a local Hardhat node. Built to learn the Web3 frontend stack end-to-end: wallet integration, contract interaction, and transaction confirmation handling — with no build tools, no framework, no npm deps.
What this project does
This is the frontend half of a Fund Me / Crowdfunding dApp. Users connect their
MetaMask wallet, fund a smart contract with ETH, check the contract balance,
and the owner withdraws the collected funds. The contract enforces a minimum
USD contribution (via a Chainlink price feed) through the FundMe.sol contract.
| Button | Action |
|---|---|
| Connect | Requests MetaMask accounts (eth_requestAccounts) |
| Fund | Sends ETH to the contract's fund() function |
| getBalance | Reads the contract's ETH balance |
| Withdraw | Owner calls withdraw() to pull collected funds |
The index.html page has zero build step — just open it and the ES-module scripts
load the bundled ethers.js from ./ethers-5.6.esm.min.js.
What I learned building this
This project was my hands-on introduction to building decentralized app frontends. Key concepts I worked through:
- Connecting a wallet — using
window.ethereumandeth_requestAccountsto let MetaMask handle accounts / signing / gas. - Provider, Signer & Contract — the core ethers.js objects:
Web3Provider= connection to the blockchainSigner= the wallet that pays gasContract= the on-chain program you call
- ABI & contract address — feeding the compiled
FundMe.jsonABI and the deployed address (fromartifacts/contracts/FundMe.sol/FundMe.json) into ethers. - Sending transactions —
fund()with{ value: parseEther(amount) }. - Reading state —
getBalance()withformatEther. - Transaction confirmation — listening via
provider.once(hash, cb)instead of justwait(), so the UI knows when a tx is mined. - MetaMask quirk handling — resetting the account when a localhost Hardhat node restarts and the nonce resets to 0.
- ES modules over CDN-free bundles — both
ethers-5.6(used here) andethers-6.13.2are included for experimentation.
Companion repo: the Solidity / Hardhat backend for this contract (FundMe.sol, Chainlink price feed, deploy scripts) lives in my Hardhat learning repo.
Getting started
Requires a local Hardhat node running the FundMe contract, and the MetaMask extension in Google Chrome.
1. Run the local node
yarn hardhat node # prints private keys for test accounts
yarn hardhat deploy # prints the FundMe contract address
2. Point the frontend at your contract
Update the address + ABI in constants.js:
export const contractAddress = "0x..."; // from hardhat deploy
export const abi = [ /* from artifacts/contracts/FundMe.sol/FundMe.json (abi only) */ ];
3. Set up MetaMask
- Add the localhost network
- Settings → Networks → Add a network
- RPC URL:
http://127.0.0.1:8545/ - Chain ID:
31337(default Hardhat chain) - Currency symbol:
ETH
- Import a test account via the private key printed by
yarn hardhat node. - Open
index.htmland click Connect, then Fund.
Troubleshooting
- MetaMask prompt / nonce errors → Reset account in MetaMask. When the localhost node restarts, the nonce resets to 0, so MetaMask must forget the old one too.
- Buttons show "Please install MetaMask" → MetaMask isn't injected into this tab.
Project structure
├── index.html # UI (vanilla HTML + buttons)
├── index.js # wallet connect, fund, withdraw, balance logic (ES module)
├── constants.js # deployed contract address + ABI
├── ethers-5.6.esm.min.js # bundled ethers.js v5 (ESM)
├── ethers-6.13.2.min.js # bundled ethers.js v6 (for comparison / upgrades)
├── package.json # prettier only — no runtime deps
└── yarn.lock
Tech stack
- ethers.js 5.6 — Web3Provider / Signer / Contract / utils
- MetaMask — browser wallet provider (
window.ethereum) - Hardhat — local blockchain for testing (companion repo)
- Vanilla JS ES modules — no build step, no framework
About me / Open to work
I'm Hoelee, a hands-on developer transitioning from traditional Web2 development (PHP / CodeIgniter, Java / Spring, WordPress, JS) into Web3 / blockchain development. I'm working through the full stack — Solidity, ERC-20 / ERC-721, upgradeable contracts, OpenZeppelin, Hardhat & Foundry, Chainlink oracles, ethers.js / web3.js — and building real projects like this one to prove it.
This is a learning repository, so the code is intentionally simple, readable, and well-commented rather than production-hardened — it reflects what I learned while building it.
I'm open to remote opportunities in blockchain / full-stack web development. Let's talk:
- 🌐 Portfolio: hoelee.com
- ✉️ Email: me@hoelee.com
- 💬 WhatsApp: +60 12-797 2969
Built while following the Smart Contract Engineer learning path. Frontend for the FundMe contract — send ETH to support a project, and the owner withdraws when ready.