Introduction
Decentralized applications (dApps) run on blockchain networks, enabling trustless, transparent, and censorship-resistant functionality. In this guide, we’ll build a dApp using React, Solidity, and MetaMask, integrating Web3.js and Ethers.js for blockchain interactions.
What You'll Learn:
✔ Writing smart contracts in Solidity
✔ Deploying contracts on Ethereum testnet
✔ Connecting a dApp to MetaMask using Web3.js & Ethers.js
✔ Executing blockchain transactions from React
- Setting Up the Development Environment
Prerequisites
Ensure you have the following installed:
Node.js (v16 or later)
MetaMask browser extension
Hardhat (Ethereum development environment)
Step 1: Initialize a Hardhat Project
mkdir my-dapp && cd my-dapp npm init -y npm install --save-dev hardhat npx hardhat
Select “Create a basic sample project” and install dependencies when prompted.
- Writing a Smart Contract in Solidity
Step 1: Create a Solidity Contract
Inside contracts/, create a file named MyContract.sol:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; contract MyContract { uint256 public counter; function increment() public { counter++; } }
Step 2: Compile the Contract
npx hardhat compile
Step 3: Deploy the Contract
Modify scripts/deploy.js:
const hre = require("hardhat"); async function main() { const Contract = await hre.ethers.getContractFactory("MyContract"); const contract = await Contract.deploy(); await contract.deployed(); console.log("Contract deployed to:", contract.address); } main().catch((error) => { console.error(error); process.exit(1); });
Run the deployment script:
npx hardhat run
scripts/deploy.js --network localhost
- Connecting the dApp to MetaMask with Web3.js & Ethers.js
Step 1: Install Web3.js & Ethers.js
npm install web3 ethers
Step 2: Connect React to MetaMask
In App.js, set up MetaMask connection:
import { useState } from "react"; import { ethers } from "ethers"; function App() { const [account, setAccount] = useState(""); async function connectWallet() { if (window.ethereum) { const provider = new ethers.providers.Web3Provider(window.ethereum); const accounts = await provider.send("eth_requestAccounts", []); setAccount(accounts[0]); } else { alert("MetaMask not found"); } } return ( <div> <button onClick={connectWallet}>Connect Wallet</button> <p>Connected Account: {account}</p> </div> ); } export default App;
- Interacting with the Smart Contract
Step 1: Load the Contract in React
Create contractABI.js with ABI (after deployment, copy from artifacts/contracts/MyContract.json):
const contractABI = [ { "inputs": [], "name": "increment", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "counter", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function" } ]; export default contractABI;
Step 2: Fetch Contract Data in React
Modify App.js:
import { useState, useEffect } from "react"; import { ethers } from "ethers"; import contractABI from "./contractABI"; const contractAddress = "YOUR_DEPLOYED_CONTRACT_ADDRESS"; function App() { const [account, setAccount] = useState(""); const [contract, setContract] = useState(null); const [counter, setCounter] = useState(0); async function connectWallet() { if (window.ethereum) { const provider = new ethers.providers.Web3Provider(window.ethereum); const signer = provider.getSigner(); const accounts = await provider.send("eth_requestAccounts", []); setAccount(accounts[0]); const contractInstance = new ethers.Contract(contractAddress, contractABI, signer); setContract(contractInstance); fetchCounter(contractInstance); } else { alert("MetaMask not found"); } } async function fetchCounter(contractInstance) { const count = await contractInstance.counter(); setCounter(count.toNumber()); } async function incrementCounter() { if (contract) { const tx = await contract.increment(); await tx.wait(); fetchCounter(contract); } } useEffect(() => { if (contract) fetchCounter(contract); }, [contract]); return ( <div> <button onClick={connectWallet}>Connect Wallet</button> <p>Connected Account: {account}</p> <p>Counter Value: {counter}</p> <button onClick={incrementCounter}>Increment Counter</button> </div> ); }
export default App;
- Testing the dApp on a Testnet
Step 1: Get Testnet Funds
Open MetaMask.
Switch to Goerli or Sepolia Testnet.
Get test ETH from a faucet (https://goerlifaucet.com).
Step 2: Deploy to Testnet
Modify hardhat.config.js:
module.exports = { solidity: "0.8.19", networks: { goerli: { url: "https://eth-goerli.alchemyapi.io/v2/YOUR_ALCHEMY_API_KEY", accounts: ["YOUR_PRIVATE_KEY"] } } };
Deploy:
npx hardhat run scripts/deploy.js --network goerli
- Enhancing the dApp
✔ Use IPFS or Arweave for decentralized file storage.
✔ Add WalletConnect to support multiple wallets.
✔ Use Moralis API for indexing blockchain data.
✔ Deploy front-end on Vercel or Netlify for easy hosting.
Conclusion
In this guide, we built a React + Solidity dApp that connects to MetaMask, interacts with smart contracts, and runs transactions on Ethereum.
✔ Wrote and deployed a Solidity contract
✔ Connected React with MetaMask using Ethers.js
✔ Interacted with smart contracts from the front end
I am open to collaboration on projects and work. Let's transform ideas into digital reality.
Top comments (0)