"use strict";(self.webpackChunkstatus_network_docs=self.webpackChunkstatus_network_docs||[]).push([[313],{6939:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var r=t(4848),s=t(8453);const i={},a="Interacting with Smart Contracts Using ethers.js",o={id:"tutorials/ethers-tutorial",title:"Interacting with Smart Contracts Using ethers.js",description:"Learn how to interact with smart contracts deployed on Status Network from a frontend using ethers.js.",source:"@site/docs/tutorials/ethers-tutorial.md",sourceDirName:"tutorials",slug:"/tutorials/ethers-tutorial",permalink:"/tutorials/ethers-tutorial",draft:!1,unlisted:!1,editUrl:"https://github.com/status-im/status-network-docs/tree/main/docs/tutorials/ethers-tutorial.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"\ud83d\udda5\ufe0f Node Operators",permalink:"/tools/node-operators"},next:{title:"\ud83c\udfa9 Using Hardhat",permalink:"/tutorials/deploying-contracts/using-hardhat"}},d={},c=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Set Up Status Network Testnet",id:"set-up-status-network-testnet",level:3},{value:"Smart Contract Deployment on Status Network",id:"smart-contract-deployment-on-status-network",level:2},{value:"BidBoard Smart Contract",id:"bidboard-smart-contract",level:3},{value:"Deploying the Contract",id:"deploying-the-contract",level:3},{value:"Setting Up the Frontend Application",id:"setting-up-the-frontend-application",level:2},{value:"Step 1: Create a React App",id:"step-1-create-a-react-app",level:3},{value:"Step 2: Install ethers.js",id:"step-2-install-ethersjs",level:3},{value:"Building the Main Application Component",id:"building-the-main-application-component",level:2},{value:"Import Required Libraries",id:"import-required-libraries",level:3},{value:"Setting Up the Provider",id:"setting-up-the-provider",level:3},{value:"Fetch Current Advertisement Data",id:"fetch-current-advertisement-data",level:3},{value:"Submit a New Bid",id:"submit-a-new-bid",level:3},{value:"Listen to Contract Events",id:"listen-to-contract-events",level:3},{value:"Creating the User Interface",id:"creating-the-user-interface",level:2},{value:"Styling the Application",id:"styling-the-application",level:2},{value:"Running the Application",id:"running-the-application",level:2},{value:"Testing the Application",id:"testing-the-application",level:2},{value:"Conclusion",id:"conclusion",level:2},{value:"Next Steps",id:"next-steps",level:2},{value:"Resources",id:"resources",level:2}];function l(e){const n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"interacting-with-smart-contracts-using-ethersjs",children:"Interacting with Smart Contracts Using ethers.js"})}),"\n",(0,r.jsxs)(n.p,{children:["Learn how to interact with smart contracts deployed on ",(0,r.jsx)(n.strong,{children:"Status Network"})," from a frontend using ",(0,r.jsx)(n.strong,{children:"ethers.js"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["In this tutorial, we'll walk through setting up a basic web application, deploying a smart contract on the ",(0,r.jsx)(n.strong,{children:"Status Network Testnet"}),", and interacting with it using ",(0,r.jsx)(n.strong,{children:"ethers.js"}),"."]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,r.jsx)(n.p,{children:"Before you begin, ensure you have the following:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"MetaMask"})," installed in your browser."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Node.js"})," and ",(0,r.jsx)(n.strong,{children:"npm"})," installed on your computer."]}),"\n",(0,r.jsxs)(n.li,{children:["Basic understanding of ",(0,r.jsx)(n.strong,{children:"React.js"})," and how ",(0,r.jsx)(n.strong,{children:"blockchains"})," work."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"set-up-status-network-testnet",children:"Set Up Status Network Testnet"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Add Status Network Testnet to MetaMask"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Follow the guide ",(0,r.jsx)(n.a,{href:"/general-info/add-status-network",children:"Adding Status Network to MetaMask"})," to add the testnet network to your wallet."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Obtain Test ETH"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Use the ",(0,r.jsx)(n.a,{href:"/tools/testnet-faucets",children:"Status Network Testnet Faucet"})," to get test ETH for deploying and interacting with contracts."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Bridge Assets (Optional)"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["If needed, bridge assets to the Status Network Testnet using the ",(0,r.jsx)(n.a,{href:"/general-info/bridge/bridging-testnet",children:"Testnet Bridge"}),"."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"smart-contract-deployment-on-status-network",children:"Smart Contract Deployment on Status Network"}),"\n",(0,r.jsxs)(n.p,{children:["We'll use a simple smart contract called ",(0,r.jsx)(n.strong,{children:"BidBoard"})," for this tutorial. The contract allows advertisers to bid for space on an advertising board."]}),"\n",(0,r.jsx)(n.h3,{id:"bidboard-smart-contract",children:"BidBoard Smart Contract"}),"\n",(0,r.jsxs)(n.p,{children:["Here's the ",(0,r.jsx)(n.code,{children:"BidBoard.sol"})," contract code:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-solidity",children:'// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ncontract BidBoard {\n string public currentAd;\n address public advertiser;\n uint256 public currentBid;\n\n event AdUpdated(string newAd, address newAdvertiser, uint256 newBid);\n\n constructor() {\n currentAd = "Welcome to Status Network!";\n advertiser = msg.sender;\n currentBid = 0;\n }\n\n function updateAd(string memory newAd) public payable {\n require(msg.value > currentBid, "Bid must be higher than current bid");\n currentAd = newAd;\n advertiser = msg.sender;\n currentBid = msg.value;\n emit AdUpdated(newAd, msg.sender, msg.value);\n }\n\n function getCurrentAd() public view returns (string memory, address, uint256) {\n return (currentAd, advertiser, currentBid);\n }\n}\n'})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Note:"})," You can use your own smart contract if you prefer."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"deploying-the-contract",children:"Deploying the Contract"}),"\n",(0,r.jsxs)(n.p,{children:["Follow the guide ",(0,r.jsx)(n.a,{href:"/tutorials/deploying-contracts/using-remix",children:"Deploying a Smart Contract Using Remix"})," to deploy the ",(0,r.jsx)(n.code,{children:"BidBoard.sol"})," contract to the Status Network Testnet."]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"setting-up-the-frontend-application",children:"Setting Up the Frontend Application"}),"\n",(0,r.jsx)(n.p,{children:"We'll create a React.js application to interact with the deployed smart contract."}),"\n",(0,r.jsx)(n.h3,{id:"step-1-create-a-react-app",children:"Step 1: Create a React App"}),"\n",(0,r.jsx)(n.p,{children:"Open your terminal and run:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"npx create-react-app bidboard-ui\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This command creates a new React application named ",(0,r.jsx)(n.code,{children:"bidboard-ui"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"step-2-install-ethersjs",children:"Step 2: Install ethers.js"}),"\n",(0,r.jsxs)(n.p,{children:["Navigate to the project directory and install ",(0,r.jsx)(n.strong,{children:"ethers.js"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"cd bidboard-ui\nnpm install ethers\n"})}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"building-the-main-application-component",children:"Building the Main Application Component"}),"\n",(0,r.jsxs)(n.p,{children:["Open the project in your code editor and navigate to ",(0,r.jsx)(n.code,{children:"src/App.js"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"import-required-libraries",children:"Import Required Libraries"}),"\n",(0,r.jsxs)(n.p,{children:["Replace the content of ",(0,r.jsx)(n.code,{children:"App.js"})," with the following code:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:'import React, { useState, useEffect } from "react";\nimport { ethers } from "ethers";\nimport "./App.css";\n\nconst App = () => {\n // Contract details\n const contractAddress = "YOUR_CONTRACT_ADDRESS";\n const abi = [/* ABI JSON CODE */];\n\n // State variables\n const [currentAd, setCurrentAd] = useState("");\n const [currentBid, setCurrentBid] = useState(0);\n const [advertiser, setAdvertiser] = useState("");\n const [newAd, setNewAd] = useState("");\n const [bidAmount, setBidAmount] = useState("");\n const [provider, setProvider] = useState(null);\n const [status, setStatus] = useState("");\n\n // Rest of the code...\n};\n\nexport default App;\n'})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Important:"})," Replace ",(0,r.jsx)(n.code,{children:'"YOUR_CONTRACT_ADDRESS"'})," with the address of your deployed ",(0,r.jsx)(n.code,{children:"BidBoard"})," contract. Paste the ABI of your contract in the ",(0,r.jsx)(n.code,{children:"abi"})," array."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"setting-up-the-provider",children:"Setting Up the Provider"}),"\n",(0,r.jsxs)(n.p,{children:["Add the following code inside the ",(0,r.jsx)(n.code,{children:"App"})," component to set up the provider:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:'useEffect(() => {\n if (typeof window.ethereum !== "undefined") {\n const newProvider = new ethers.providers.Web3Provider(window.ethereum);\n setProvider(newProvider);\n } else {\n console.error("Please install MetaMask!");\n }\n}, []);\n'})}),"\n",(0,r.jsx)(n.h3,{id:"fetch-current-advertisement-data",children:"Fetch Current Advertisement Data"}),"\n",(0,r.jsx)(n.p,{children:"Add a function to fetch the current advertisement data:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:'const fetchCurrentAd = async () => {\n try {\n const contract = new ethers.Contract(contractAddress, abi, provider);\n const adData = await contract.getCurrentAd();\n setCurrentAd(adData[0]);\n setAdvertiser(adData[1]);\n setCurrentBid(ethers.utils.formatEther(adData[2]));\n } catch (error) {\n console.error("Error fetching current ad:", error);\n }\n};\n\nuseEffect(() => {\n if (provider) {\n fetchCurrentAd();\n }\n}, [provider]);\n'})}),"\n",(0,r.jsx)(n.h3,{id:"submit-a-new-bid",children:"Submit a New Bid"}),"\n",(0,r.jsx)(n.p,{children:"Add a function to submit a new bid:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:'const submitBid = async () => {\n if (!newAd || !bidAmount) {\n setStatus("Please enter an ad message and bid amount.");\n return;\n }\n\n try {\n const signer = provider.getSigner();\n const contract = new ethers.Contract(contractAddress, abi, signer);\n const tx = await contract.updateAd(newAd, {\n value: ethers.utils.parseEther(bidAmount),\n });\n setStatus("Transaction sent, waiting for confirmation...");\n await tx.wait();\n setStatus("Transaction confirmed!");\n setNewAd("");\n setBidAmount("");\n fetchCurrentAd();\n } catch (err) {\n console.error(err);\n setStatus("Error: " + err.message);\n }\n};\n'})}),"\n",(0,r.jsx)(n.h3,{id:"listen-to-contract-events",children:"Listen to Contract Events"}),"\n",(0,r.jsxs)(n.p,{children:["Add code to listen to the ",(0,r.jsx)(n.code,{children:"AdUpdated"})," event:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:'useEffect(() => {\n let contract;\n\n const setupEventListener = async () => {\n if (provider) {\n contract = new ethers.Contract(contractAddress, abi, provider);\n contract.on("AdUpdated", (newAd, newAdvertiser, newBid) => {\n setCurrentAd(newAd);\n setAdvertiser(newAdvertiser);\n setCurrentBid(ethers.utils.formatEther(newBid));\n });\n }\n };\n\n setupEventListener();\n\n return () => {\n if (contract) {\n contract.removeAllListeners("AdUpdated");\n }\n };\n}, [provider]);\n'})}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"creating-the-user-interface",children:"Creating the User Interface"}),"\n",(0,r.jsxs)(n.p,{children:["Update the ",(0,r.jsx)(n.code,{children:"return"})," statement in the ",(0,r.jsx)(n.code,{children:"App"})," component:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:'return (\n
Status: {status}
\n"{currentAd}"
\n\n Advertiser: {advertiser}\n
\n\n Current Bid: {currentBid} ETH\n
\n