"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
\n {/* Header */}\n
\n

BidBoard

\n

Status: {status}

\n
\n\n {/* Current Advertisement */}\n
\n

Current Advertisement

\n

"{currentAd}"

\n

\n Advertiser: {advertiser}\n

\n

\n Current Bid: {currentBid} ETH\n

\n
\n\n {/* Submit a New Bid */}\n
\n

Submit a New Bid

\n setNewAd(e.target.value)}\n placeholder="Your Ad Message"\n />\n setBidAmount(e.target.value)}\n placeholder="Bid Amount in ETH"\n />\n \n
\n\n {/* Footer */}\n \n
\n);\n'})}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"styling-the-application",children:"Styling the Application"}),"\n",(0,r.jsxs)(n.p,{children:["Create a ",(0,r.jsx)(n.code,{children:"App.css"})," file in the ",(0,r.jsx)(n.code,{children:"src"})," directory and add your preferred styles. Here's a basic example:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-css",children:".app {\n text-align: center;\n font-family: Arial, sans-serif;\n}\n\nheader {\n background-color: #282c34;\n padding: 20px;\n color: white;\n}\n\nsection {\n margin: 20px;\n}\n\ninput {\n margin: 5px;\n padding: 10px;\n width: 200px;\n}\n\nbutton {\n padding: 10px 20px;\n}\n\nfooter {\n margin-top: 40px;\n}\n"})}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"running-the-application",children:"Running the Application"}),"\n",(0,r.jsx)(n.p,{children:"In your terminal, navigate to your project directory and run:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"npm start\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This command starts the development server. Open ",(0,r.jsx)(n.a,{href:"http://localhost:3000",children:"http://localhost:3000"})," in your browser to view the application."]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"testing-the-application",children:"Testing the Application"}),"\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:"View Current Advertisement"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The application should display the current ad message, advertiser address, and current bid."}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Submit a New Bid"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Enter a new ad message and a bid amount higher than the current bid."}),"\n",(0,r.jsxs)(n.li,{children:["Click ",(0,r.jsx)(n.strong,{children:'"Submit Bid"'}),"."]}),"\n",(0,r.jsx)(n.li,{children:"MetaMask will prompt you to confirm the transaction."}),"\n",(0,r.jsx)(n.li,{children:"Wait for the transaction to be confirmed."}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Observe Real-Time Updates"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Upon confirmation, the application should automatically update with the new ad, advertiser, and bid amount."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,r.jsxs)(n.p,{children:["You've successfully created a web application that interacts with a smart contract deployed on the Status Network Testnet using ",(0,r.jsx)(n.strong,{children:"ethers.js"}),". This tutorial covered:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Setting up a React application."}),"\n",(0,r.jsx)(n.li,{children:"Deploying a smart contract to the Status Network."}),"\n",(0,r.jsx)(n.li,{children:"Connecting the frontend to the smart contract using ethers.js."}),"\n",(0,r.jsx)(n.li,{children:"Handling user interactions and real-time updates via events."}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"next-steps",children:"Next Steps"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Explore More Tutorials"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Check out other tutorials in the ",(0,r.jsx)(n.a,{href:"/tutorials/ethers-tutorial",children:"Status Network Documentation"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Enhance the Application"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Add error handling for edge cases."}),"\n",(0,r.jsx)(n.li,{children:"Improve the UI/UX design."}),"\n",(0,r.jsx)(n.li,{children:"Implement additional features like user authentication."}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Deploy to Production"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Learn how to deploy your application for production use."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"resources",children:"Resources"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://status.network/",children:"Status Network Official Website"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://docs.status.network/",children:"Status Network Documentation"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://docs.ethers.io/",children:"ethers.js Documentation"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://reactjs.org/",children:"React.js Documentation"})}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Happy Coding!"})})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>o});var r=t(6540);const s={},i=r.createContext(s);function a(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]);