If you are into building DApps, it is crucial to know how to integrate your application with smart contracts. Because most of the time your smart contract will be the heart of your DApp where the logic is written. Which makes your app decentralized. In this post, I will show you how to do it.
Prerequisite for DApp
I assume you have successfully deployed your smart contract in one of the Testnet or locally in the personal blockchain. Also, you have some basic knowledge of React web app development.
Create DApp using React
Let’s create of DApp using react. You can use the following command to create a basic single-page application using it.
npx create-react-app nft-gallery
cd nft-gallery
npm start
You should be able to see your react web application inside the browser at http://localhost:3000. Do the necessary clean-up of the application and make sure you have blank space as output inside the browser.
Integrate Metamask Wallet with our Application
Let’s connect the Metamask wallet with our application. For that, we will make use of ethersjs library. You can install the ethersjs using the command given below.
npm install ethers
You can connect with the Metamask wallet using ethersjs as given below.
Modify the App.js file as given below. I have added the useEffect() hook to connect with the Metamask wallet.
import "./App.css";
import { useEffect, useState } from "react";
import { ethers } from "ethers";
function App() {
const [address, setAddress] = useState("");
const [provider, setProvider] = useState(null);
//To connect with the metamask wallet
useEffect(() => {
const connectWallet = async () => {
if (window.ethereum == null) {
alert("Metamask not found");
console.log("Metamask not found");
} else {
//You can use this providerInstance to just perform read operations
const providerInstance = new ethers.BrowserProvider(window.ethereum);
try {
//You can use the signer to perform both read and write operations
const signer = await providerInstance.getSigner();
setProvider(signer);
setAddress(await signer.getAddress());
} catch (error) {
console.log(error);
}
}
};
connectWallet();
//Listen for accounts changed event
window.ethereum.on("accountsChanged", (accounts) => {
console.log(accounts);
setAddress(accounts[0]); //current active account address will be at index 0
});
//Listen for network changed event
window.ethereum.on("chainChanged", (chainId) => {
console.log(chainId);
connectWallet();
});
}, []);
return (
<div className="App">
<p>Wallet Address: {address ? address : "wallet not connected"} </p>
</div>
);
}
export default App;
This is how your package.json file should look like.
{
"name": "nft-gallery",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"ethers": "^6.13.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
There are two event listeners. It listens to account changes and network changes with the Metamask wallet. Whenever it happens I rerender my application with the updated wallet information.
Connect Application with Smart Contract on Blockchain
Finally, let’s connect our application with the smart contract that we have deployed. You can use the contract address “0xCa2eb4eE46063E3Fc7454D31d4dA674C5B8C24Ce”. It is a simple NFT smart contract developed using Openzeppelin ERC721 smart contract. Otherwise, you can use your smart contract address. The above smart contract is deployed into Sepolia Testnet.
The entire NFT project can be found at https://github.com/sumukus/gcit-nft-collection inside the main branch. In this post, I focus on how to connect the smart contract with our application. So I will explain how you can do it. Please refer to the code given below for it. There are two methods to get the name of the NFT collection and symbol with the method name() and symbol(). So we will make use of it to check whether the integration of the smart contract with the application is successful or not. You should see the name value as “Gcit NFT Collection” and the symbol value as “GCITNFT”. If you see it, your application can communicate with the smart contract in the Blockchain.
Modify the App.js file as given below. We have added two more useEffect() hooks to handle the smart contract connection and fetch data from the smart contract.
import "./App.css";
import { useEffect, useState } from "react";
import { ethers } from "ethers";
//Import ABI file and smart contract address
const smartContractABI = require("./contracts/SmartContractABI.json"); //Replace this with your own
const smartContractAddress = "0xCa2eb4eE46063E3Fc7454D31d4dA674C5B8C24Ce"; //Replace this with your own
function App() {
const [address, setAddress] = useState(null);
const [provider, setProvider] = useState(null);
const [smartContractAPI, setSmartContractAPI] = useState(null);
const [nftName, setNFTName] = useState(null);
const [nftSymbol, setNFTSymbol] = useState(null);
//To connect with the metamask wallet
useEffect(() => {
const connectWallet = async () => {
if (window.ethereum == null) {
alert("Metamask not found");
console.log("Metamask not found");
} else {
//You can use this providerInstance to just perform read operations
const providerInstance = new ethers.BrowserProvider(window.ethereum);
try {
//You can use the signer to perform both read and write operations
const signer = await providerInstance.getSigner();
setProvider(signer);
setAddress(await signer.getAddress());
} catch (error) {
console.log(error);
}
}
};
connectWallet();
//Listen for accounts changed event
window.ethereum.on("accountsChanged", (accounts) => {
console.log(accounts);
setAddress(accounts[0]); //current active account address will be at index 0
});
//Listen for network changed event
window.ethereum.on("chainChanged", (chainId) => {
console.log(chainId);
// To refetch the details when network changes
connectWallet();
setNFTName(null);
setNFTSymbol(null);
});
}, []);
//Connect with the smart contract
useEffect(() => {
if (provider) {
try {
setSmartContractAPI(
new ethers.Contract(
smartContractAddress,
smartContractABI.abi, //If JSON file only contains ABI section, then you can directly use it
provider
)
);
} catch (error) {
console.log(error);
}
}
}, [provider]);
//Lets fetch the NFT contract name and symbol
useEffect(() => {
const fetchNFTDetails = async () => {
try {
if (smartContractAPI) {
setNFTName(await smartContractAPI.name());
setNFTSymbol(await smartContractAPI.symbol());
}
} catch (error) {
console.log(error);
}
};
fetchNFTDetails();
}, [smartContractAPI]);
return (
<div className="App">
<p>Wallet Address: {address ? address : "wallet not connected"} </p>
<br />
<p>NFT Name: {nftName ? nftName : "Couldn't fetch NFT name"}</p>
<p>NFT Symbol: {nftSymbol ? nftSymbol : "Couldn't fetch NFT symbol"}</p>
</div>
);
}
export default App;
This JSON file is generated using the Truffle suite. The JSON file contains more than ABI content. We can access the ABI using the “abi” key with the JSON file. If you want you can import the ABI section only. The JSON file can be found here. Create the “contracts” directory inside the “src” folder. Then create the “SmartContractABI.json” file and put the content of the JSON file[access here] inside this file. Otherwise, you can use your own smart contract JSON file. Only use the one I provided if you are using the above-given contract address(i.e.“0xCa2eb4eE46063E3Fc7454D31d4dA674C5B8C24Ce”).
Congratulations!… You have successfully created your first DApp using React, EthersJS, and Metamask wallet. But remember the auto-complete features for smart contracts methods are not enabled. Therefore, you have to know the names of the methods that are inside your smart contract to communicate with it.
Conclusion
To conclude, I showed how to make Dapp using React, EtherJS, and Metamask wallet. The core idea behind the DApp is powered by the Blockchain’s decentralized nature and the smart contract feature it provides. I hope this took you one step further in the work of DApp and web3 developer. If you have any questions, drop in the comment section. Change the network inside the Metamask wallet and observe the output.
I am an enthusiastic tech guy. Ever ready to learn new technology. I love building software solutions that can help mankind to solve problems.
You can support us by:
Becoming a patron at https://www.patreon.com/drukinfotech
Buy me coffee at https://www.buymeacoffee.com/drukinfotech