Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

fangjun
fangjun

Posted on • Edited on

     

Web3 Tutorial: build DApp with Web3-React and SWR

In "Tutorial: Build DAPP with hardhat, React and Ethers.js", we connect to and interact with the blockchain usingEthers.js directly. It is ok, but there are tedious processes needed to be done by ourselves.

We would rather use handy frameworks to help us in three aspects:

  1. maintain context and connect with blockchain.

  2. connect to different kinds of blockchain providers.

  3. query blockchain more efficiently.

Web3-React, a connecting framework for React and Ethereum, can help us with job 1 & 2. (We will focus on job 1.) Web3-React is an open source framework developed by Uniswap engineering Lead Noah Zinsmeister. You can also tryWAGMI: React Hooks for Ethereum.

SWR can help us to query blockchains efficiently. SWR (stale-while-revalidate) is a library of react hooks for data fetching. I learned how to use SWR with blockchain from Lorenzo Sicilia's tutorialHow to Fetch and Update Data From Ethereum with React and SWR.

I am still trying to find an efficient way to deal with Event. The Graph (sub-graph) is one of the good choices.The Graph Protocol and sub-graph are widely used by DeFi applications. In Nader Dabit's tutorial "The Complete Guide to Full Stack Web3 Development", he gives us a clear guide on how to use sub-graph.

Special thanks to Lorenzo Sicilia and his tutorial. I adapted the SWR flow and some code snippets from him.

You can find the code repos for this tutorial:
Hardhat project:https://github.com/fjun99/chain-tutorial-hardhat-starter
Webapp project:https://github.com/fjun99/web3app-tutrial-using-web3react

Let's start building our DApp using Web3-React.


Task #1

Task 1: Prepare webapp project and smart contract

The first half of Task 1 is the same as the ones in "Tutorial: build DApp with Hardhat, React and Ethers.js". Please refer to that tutorial.

Tutorial: build DApp with Hardhat, React and Ethers.js

https://dev.to/yakult/a-tutorial-build-dapp-with-hardhat-react-and-ethersjs-1gmi

Task 1: setup development environment

Task 1.1 Install Hardhat and init a Hardhat project

Task 1.2 Development Circle in Hardhat

Task 1.3 MetaMask Switch Local testnet

Task 1.4 Create webapp with Next.js and Chakra UI

Task 1.5 Edit webapp - header, layout, _app.tsx, index.tsx

We choose to download the webapp scaffold code fromour github repo.

First, we make ahhproject/ directory for our project (hhproject/chain/ for hardhat project,hhproject/webapp/ for React/Node.js webapp):

mkdir hhproject && cd hhproject
Enter fullscreen modeExit fullscreen mode

Project directory structure:

- hhproject  - chain (working dir for hardhat)    - contracts    - test    - scripts  - webapp (working dir for NextJS app)    - src      - pages      - components
Enter fullscreen modeExit fullscreen mode

Download an empty webapp scaffold:

git clone https://github.com/fjun99/webapp-tutorial-scaffold.git webappcd webappyarn installyarn dev
Enter fullscreen modeExit fullscreen mode

We also need to prepare an ERC20 token ClassToken for our webapp to interact with. This is the second half of Task 1.

This job can be done same as Task 3 of "Tutorial: build DApp with Hardhat, React and Ethers.js"

Task 3: Build ERC20 smart contract using OpenZeppelin

Task 3.1 Write ERC20 smart contract

Task 3.2 Compile smart contract

Task 3.3 Add unit test script

Task 3.4 Add deploy script

Task 3.5 Run stand-alone testnet again and deploy to it

Task 3.6 Interact with ClassToken in hardhat console

Task 3.7 Add token to MetaMask

Again, we choose to download the hardhat chain starter project fromgithub repo.In yourhhproject/ directory:

git clone git@github.com:fjun99/chain-tutorial-hardhat-starter.git chaincd chainyarn install
Enter fullscreen modeExit fullscreen mode

Let's run "compile, test, deploy" circle of smart contract development.

In another terminal, run command line inhhproject/chain/ directory to start a stand-alone Hardhat Network (local testnet) :

yarn hardhat node
Enter fullscreen modeExit fullscreen mode

Then compile, test and deploy smart contract:

yarn hardhat compileyarn hardhat test test/ClassToken.test.tsyarn hardhat run scripts/deploy_classtoken.ts --network localhost// ClassToken deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3// ✨  Done in 4.04s.
Enter fullscreen modeExit fullscreen mode

Now we have ClassToken deployed to local testnet:0x5FbDB2315678afecb367f032d93F642f64180aa3


Task #2

Task 2: Add Web3-React to our webapp - Connect button

Task 2.1: Understanding Web3-React

Web3-react explained

From my point of view, Web3-React is a web3 blockchainconnecting framework which provides three features we need:

  • Web3ReactProvder, a react context we can access throughout our web app.

  • useWeb3React, handy react hook to interact with blockchain.

  • Connectors of several kinds of blockchain providers, such as MetaMask (browser extension), RPC connector(Alchemy and Infura), QR code connector(WalletConnect), Hardware connector (Ledger/Trezor).

Currently Web3-React hasstable V6 andbeta V8. We will use V6 in our tutorial.

Task 2.2: InstallWeb3-React,Ethers.js and addWeb3ReactProvder

STEP 1: install dependencies

In thewebapp directory, run:

yarn add @web3-react/coreyarn add @web3-react/injected-connectoryarn add ethersyarn add swr
Enter fullscreen modeExit fullscreen mode

We will useswr later.

STEP 2: editpages/_app.tsx:

// src/pages/_app.tsximport{ChakraProvider}from'@chakra-ui/react'importtype{AppProps}from'next/app'import{Layout}from'components/layout'import{Web3ReactProvider}from'@web3-react/core'import{Web3Provider}from'@ethersproject/providers'functiongetLibrary(provider:any):Web3Provider{constlibrary=newWeb3Provider(provider)returnlibrary}functionMyApp({Component,pageProps}:AppProps){return(<Web3ReactProvidergetLibrary={getLibrary}><ChakraProvider><Layout><Component{...pageProps}/></Layout></ChakraProvider></Web3ReactProvider>)}exportdefaultMyApp
Enter fullscreen modeExit fullscreen mode

Explanations:

  • We add areact context providerWeb3ReactProvider in_app.tsx.

  • Blockchain provider (library) is an Ethers.jsWeb3Provider which we can add connector and activate later using hooks.

Task 2.3: Add an empty ConnectMetamask component

connector, provider, signer

The relationship between connector, provider and signer inEthers.js is illustrated in the graph.

In this sub-task we will add an empty ConnectMetamask component.

  • STEP 1: Addsrc/components/ConnectMetamask.tsx:
import{useEffect}from'react'import{useWeb3React}from'@web3-react/core'import{Web3Provider}from'@ethersproject/providers'import{Box,Button,Text}from'@chakra-ui/react'import{injected}from'utils/connectors'import{UserRejectedRequestError}from'@web3-react/injected-connector'import{formatAddress}from'utils/helpers'constConnectMetamask=()=>{const{chainId,account,activate,deactivate,setError,active,library,connector}=useWeb3React<Web3Provider>()constonClickConnect=()=>{activate(injected,(error)=>{if(errorinstanceofUserRejectedRequestError){// ignore user rejected errorconsole.log("user refused")}else{setError(error)}},false)}constonClickDisconnect=()=>{deactivate()}useEffect(()=>{console.log(chainId,account,active,library,connector)})return(<div>{active&&typeofaccount==='string'?(<Box><Buttontype="button"w='100%'onClick={onClickDisconnect}>Account:{formatAddress(account,4)}</Button><TextfontSize="sm"w='100%'my='2'align='center'>ChainID:{chainId}connected</Text></Box>):(<Box><Buttontype="button"w='100%'onClick={onClickConnect}>ConnectMetaMask</Button><TextfontSize="sm"w='100%'my='2'align='center'>notconnected</Text></Box>)}</div>)}exportdefaultConnectMetamask
Enter fullscreen modeExit fullscreen mode

STEP 2: define ainjected connector inuitls/connectors.tsx:

import{InjectedConnector}from"@web3-react/injected-connector";exportconstinjected=newInjectedConnector({supportedChainIds:[1,3,4,5,10,42,31337,42161]})
Enter fullscreen modeExit fullscreen mode

STEP 3: add a helper inutils/helpers.tsx

exportfunctionformatAddress(value:string,length:number=4){return`${value.substring(0,length+2)}...${value.substring(value.length-length)}`}
Enter fullscreen modeExit fullscreen mode

STEP 4: addConnectMetamask component toindex.tsx

importConnectMetamaskfrom'components/ConnectMetamask'...<ConnectMetamask/>
Enter fullscreen modeExit fullscreen mode

STEP 5: run web app by runningyarn dev

connect wallet

Explanation of what do we do here:

  • We get hooks fromuseWeb3React: chainId, account, activate,deactivate, setError, active,library ,connector

  • When a user clicks connect, we callactivate(injected).inject isInjectedConnector (mostly it means window.ethereum injected by MetaMask) that we can configure.

  • When user click disconnect, we calldecativate().

  • The library is the Ethers.js Web3Provider we can use.

Specifically, the library is anEthers.js provider which can be used to connect and read blockchain. If we want to send transaction to blockchain (write), we will need to getEthers.js signer by callprovider.getSigner().


Task #3

Task 3: Read from blockchain - ETHBalance

We will use Web3-React to read from smart contract.

Task 3.1: AddETHbalance.tsx (first attempt)

Add a component to get the ETH balance of your current account. Addcomponents/ETHBalance.tsx

import{useState,useEffect}from'react'import{useWeb3React}from'@web3-react/core'import{Web3Provider}from'@ethersproject/providers'import{Text}from'@chakra-ui/react'import{formatEther}from"@ethersproject/units"constETHBalance=()=>{const[ethBalance,setEthBalance]=useState<number|undefined>(undefined)const{account,active,library,chainId}=useWeb3React<Web3Provider>()constprovider=libraryuseEffect(()=>{if(active&&account){provider?.getBalance(account).then((result)=>{setEthBalance(Number(formatEther(result)))})}})return(<div>{active?(<TextfontSize="md"w='100%'my='2'align='left'>ETHinaccount:{ethBalance?.toFixed(3)}{chainId===31337?'Test':''}ETH</Text>):(<TextfontSize="md"w='100%'my='2'align='left'>ETHinaccount:</Text>)}</div>)}exportdefaultETHBalance
Enter fullscreen modeExit fullscreen mode

Editpages/index.tsx to display ETHBalance:

<Boxmb={0}p={4}w='100%'borderWidth="1px"borderRadius="lg"><Headingmy={4}fontSize='xl'>ETHBalance</Heading><ETHBalance/></Box>
Enter fullscreen modeExit fullscreen mode

The problem with this is how to constantly sync the results (ETH balance) with blockchain. Lorenzo Sicilia suggests to useSWR with events listening to get data more efficiently. TheSWR project homepage says:

SWR is a strategy to first return the data from cache (stale), then send the fetch request (revalidate), and finally come with the up-to-date data.

With SWR, components will get a stream of data updates constantly and automatically. The UI will always be fast and reactive.

Task 3.2: AddETHBalanceSWR.tsx (second attempt)

Addcomponents/ETHBalanceSWR.tsx

import{useState,useEffect}from'react'import{useWeb3React}from'@web3-react/core'import{Web3Provider}from'@ethersproject/providers'import{Text}from'@chakra-ui/react'import{formatEther}from"@ethersproject/units"importuseSWRfrom'swr'constfetcher=(library:any)=>(...args:any)=>{const[method,...params]=argsreturnlibrary[method](...params)}constETHBalanceSWR=()=>{const{account,active,library,chainId}=useWeb3React<Web3Provider>()const{data:balance,mutate}=useSWR(['getBalance',account,'latest'],{fetcher:fetcher(library),})console.log("ETHBalanceSWR",balance)useEffect(()=>{if(!library)return// listen for changes on an Ethereum addressconsole.log(`listening for blocks...`)library.on('block',()=>{console.log('update balance...')mutate(undefined,true)})// remove listener when the component is unmountedreturn()=>{library.removeAllListeners('block')}// trigger the effect only on component mount// ** changed to library prepared},[library])return(<div>{active&&balance?(<TextfontSize="md"w='100%'my='2'align='left'>ETHinaccount:{parseFloat(formatEther(balance)).toFixed(3)}{chainId===31337?'Test':''}ETH</Text>):(<TextfontSize="md"w='100%'my='2'align='left'>ETHinaccount:</Text>)}</div>)}exportdefaultETHBalanceSWR
Enter fullscreen modeExit fullscreen mode

AddETHBalanceSWR component toindex.tsx

<Boxmb={0}p={4}w='100%'borderWidth="1px"borderRadius="lg"><Headingmy={4}fontSize='xl'>ETHBalance<b>usingSWR</b></Heading><ETHBalanceSWR/></Box>
Enter fullscreen modeExit fullscreen mode

Explanations:

  • We use SWR to fetch data, which callsprovider.getBalance( address [ , blockTag = latest ] ) (Ethers docs link). Thelibrary is a web3 provider.
const{data:balance,mutate}=useSWR(['getBalance',account,'latest'],{fetcher:fetcher(library),})
Enter fullscreen modeExit fullscreen mode
  • The fetcher is constructed as:
constfetcher=(library:any)=>(...args:any)=>{const[method,...params]=argsreturnlibrary[method](...params)}
Enter fullscreen modeExit fullscreen mode
  • We getmutate of SWR to change its internal cache in the client. We mutate balance toundefined in every block, so SWR will query and update for us.
      library.on('block', () => {        console.log('update balance...')        mutate(undefined, true)      })
Enter fullscreen modeExit fullscreen mode
  • When library(provider) changes and we have a provider, the side effect (useEffect()) will add a listener to blockchain new block event. Block events are emitted on every block change.

Let's play with the webapp:

  • Send test ETH from Hardhat local testnet Account#0(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266) to Account#1(0x70997970C51812dc3A010C7d01b50e0d17dc79C8).

  • Check that the ETH balance of the current account (Account#0) changes accordingly.

More explanations about SWR can be found at:

  • Lorenzo Sicilia's blockchain tutorial:link

  • SWR documents:link


Image description

Task 4: Read / Listen - Interact with smart contract

In this task, we will read data using SWR from smart contract. We use smart contract event listening to get updates.

Task 4.1: AddERC20ABI.tsx

Addabi/ERC20ABI.tsx for standard ERC20.

exportconstERC20ABI=[// Read-Only Functions"function balanceOf(address owner) view returns (uint256)","function totalSupply() view returns (uint256)","function decimals() view returns (uint8)","function symbol() view returns (string)",// Authenticated Functions"function transfer(address to, uint amount) returns (bool)",// Events"event Transfer(address indexed from, address indexed to, uint amount)"];
Enter fullscreen modeExit fullscreen mode

Addcomponents/ReadERC20.tsx

importReact,{useEffect,useState}from'react';import{useWeb3React}from'@web3-react/core'import{Web3Provider}from'@ethersproject/providers'import{Contract}from"@ethersproject/contracts";import{formatEther}from"@ethersproject/units"import{Text}from'@chakra-ui/react'importuseSWRfrom'swr'import{ERC20ABIasabi}from"abi/ERC20ABI"interfaceProps{addressContract:string}constfetcher=(library:Web3Provider|undefined,abi:any)=>(...args:any)=>{if(!library)returnconst[arg1,arg2,...params]=argsconstaddress=arg1constmethod=arg2constcontract=newContract(address,abi,library)returncontract[method](...params)}exportdefaultfunctionReadERC20(props:Props){constaddressContract=props.addressContractconst[symbol,setSymbol]=useState<string>("")const[totalSupply,setTotalSupply]=useState<string>()const{account,active,library}=useWeb3React<Web3Provider>()const{data:balance,mutate}=useSWR([addressContract,'balanceOf',account],{fetcher:fetcher(library,abi),})useEffect(()=>{if(!(active&&account&&library))returnconsterc20:Contract=newContract(addressContract,abi,library);library.getCode(addressContract).then((result:string)=>{//check whether it is a contractif(result==='0x')returnerc20.symbol().then((result:string)=>{setSymbol(result)}).catch('error',console.error)erc20.totalSupply().then((result:string)=>{setTotalSupply(formatEther(result))}).catch('error',console.error);})//called only when changed to active},[active])useEffect(()=>{if(!(active&&account&&library))returnconsterc20:Contract=newContract(addressContract,abi,library)// listen for changes on an Ethereum addressconsole.log(`listening for Transfer...`)constfromMe=erc20.filters.Transfer(account,null)erc20.on(fromMe,(from,to,amount,event)=>{console.log('Transfer|sent',{from,to,amount,event})mutate(undefined,true)})consttoMe=erc20.filters.Transfer(null,account)erc20.on(toMe,(from,to,amount,event)=>{console.log('Transfer|received',{from,to,amount,event})mutate(undefined,true)})// remove listener when the component is unmountedreturn()=>{erc20.removeAllListeners(toMe)erc20.removeAllListeners(fromMe)}// trigger the effect only on component mount},[active,account])return(<div><Text>ERC20Contract:{addressContract}</Text><Text>tokentotalSupply:{totalSupply}{symbol}</Text><Textmy={4}>ClassTokenincurrentaccount:{balance?parseFloat(formatEther(balance)).toFixed(1):""}{symbol}</Text></div>)}
Enter fullscreen modeExit fullscreen mode

AddReadERC20 toindex.tsx:

constaddressContract='0x5fbdb2315678afecb367f032d93f642f64180aa3'...<Boxmy={4}p={4}w='100%'borderWidth="1px"borderRadius="lg"><Headingmy={4}fontSize='xl'>ClassToken:ERC20SmartContract</Heading><ReadERC20addressContract={addressContract}/></Box>
Enter fullscreen modeExit fullscreen mode

Some explanations:

  • We query data from blockchain and smart contract by callingcontract.balanceOf().
const{data:balance,mutate}=useSWR([addressContract,'balanceOf',account],{fetcher:fetcher(library,ERC20ABI),})
Enter fullscreen modeExit fullscreen mode
  • The fetcher is constructed as:
constfetcher=(library:Web3Provider|undefined,abi:any)=>(...args:any)=>{if(!library)returnconst[arg1,arg2,...params]=argsconstaddress=arg1constmethod=arg2constcontract=newContract(address,abi,library)returncontract[method](...params)}
Enter fullscreen modeExit fullscreen mode
  • When ethereum network connection is changed toactive, querysymbol() andtotalSupply. Since these two are non-changable constants, we only query them once.

  • Add listener when change toactive oraccount change. Two listeners are added: events transfer ERC20 token toaccount and fromaccount.

// listen for changes on an Ethereum addressconsole.log(`listening for Transfer...`)constfromMe=erc20.filters.Transfer(account,null)erc20.on(fromMe,(from,to,amount,event)=>{console.log('Transfer|sent',{from,to,amount,event})mutate(undefined,true)})consttoMe=erc20.filters.Transfer(null,account)erc20.on(toMe,(from,to,amount,event)=>{console.log('Transfer|received',{from,to,amount,event})mutate(undefined,true)})
Enter fullscreen modeExit fullscreen mode

Result:

display results


Task #5

Task 5: Write - Interact with smart contract

Task 5.1: Add a component for Transfer

In this task, we will addTransferERC20.tsx.

Editcomponents/TransferERC20.tsx

importReact,{useState}from'react';import{useWeb3React}from'@web3-react/core'import{Web3Provider}from'@ethersproject/providers'import{Contract}from"@ethersproject/contracts";import{parseEther}from"@ethersproject/units"import{Button,Input,NumberInput,NumberInputField,FormControl,FormLabel}from'@chakra-ui/react'import{ERC20ABI}from"abi/ERC20ABI"interfaceProps{addressContract:string}exportdefaultfunctionTransferERC20(props:Props){constaddressContract=props.addressContractconst[toAddress,setToAddress]=useState<string>("")const[amount,setAmount]=useState<string>('100')const{account,active,library}=useWeb3React<Web3Provider>()asyncfunctiontransfer(event:React.FormEvent){event.preventDefault()if(!(active&&account&&library))return// new contract instance with **signer**consterc20=newContract(addressContract,ERC20ABI,library.getSigner());erc20.transfer(toAddress,parseEther(amount)).catch('error',console.error)}consthandleChange=(value:string)=>setAmount(value)return(<div><formonSubmit={transfer}><FormControl><FormLabelhtmlFor='amount'>Amount:</FormLabel><NumberInputdefaultValue={amount}min={10}max={1000}onChange={handleChange}><NumberInputField/></NumberInput><FormLabelhtmlFor='toaddress'>Toaddress:</FormLabel><Inputid="toaddress"type="text"requiredonChange={(e)=>setToAddress(e.target.value)}my={3}/><Buttontype="submit"isDisabled={!account}>Transfer</Button></FormControl></form></div>)}
Enter fullscreen modeExit fullscreen mode

Task 5.2 Add transfer component toindex.tsx

AddTransferERC20 inindex.tsx:

<Boxmy={4}p={4}w='100%'borderWidth="1px"borderRadius="lg"><Headingmy={4}fontSize='xl'>TransferClassTokenERC20token</Heading><TransferERC20addressContract={addressContract}/></Box>
Enter fullscreen modeExit fullscreen mode

Let's go tohttp://localhost:3000/ in browse and play with our DApp:

Webapp


You can find that the webapp is structured well and simply by usingWeb3-React. Web3-React gives us context provider and hooks we can use easily.

From now on, you can begin to write your own DAPPs.


Tutorial List:

1. A Concise Hardhat Tutorial(3 parts)

https://dev.to/yakult/a-concise-hardhat-tutorial-part-1-7eo

2. Understanding Blockchain withEthers.js(5 parts)

https://dev.to/yakult/01-understanding-blockchain-with-ethersjs-4-tasks-of-basics-and-transfer-5d17

3. Tutorial : build your first DAPP with Remix and Etherscan (7 Tasks)

https://dev.to/yakult/tutorial-build-your-first-dapp-with-remix-and-etherscan-52kf

4. Tutorial: build DApp with Hardhat, React and Ethers.js (6 Tasks)

https://dev.to/yakult/a-tutorial-build-dapp-with-hardhat-react-and-ethersjs-1gmi

5. Tutorial: build DAPP with Web3-React and SWR

https://dev.to/yakult/tutorial-build-dapp-with-web3-react-and-swr-1fb0

6. Tutorial: write upgradeable smart contract (proxy) using OpenZeppelin(7 Tasks)

https://dev.to/yakult/tutorial-write-upgradeable-smart-contract-proxy-contract-with-openzeppelin-1916

7. Tutorial: Build an NFT marketplace DApp like Opensea(5 Tasks)

https://dev.to/yakult/tutorial-build-a-nft-marketplace-dapp-like-opensea-3ng9


If you find this tutorial helpful, follow me at Twitter@fjun99

Top comments(12)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
wenthebondsfail profile image
ThetaKing
  • Joined

Hi fangjun,

Thanks a lot for the detailed tutorial. It finally allowed me to do some progress in my DApp after spending hours trying to deal with truffle suite dependencies and errors. I managed to successfully follow all steps and what I have learned is very useful for what I am currently working with. I still am struggling with a point however, that this tutorial did not address: how can I retrieve the values of functions that are public view on Solidity? For example if I am doing a simple storage DApp like the one given in Remix as an example:

contract Storage {
uint256 number;
function store(uint256 num) public {
number = num;
}
function retrieve() public view returns (uint256){
return number;
}
}

where my intent is to fill a number in a form and click a button and have this number shown to me. How can I accomplish that? I have tried multiple alternatives but nothing works. Could you please address this case in the next tutorial?

Thank you

CollapseExpand
 
yakult profile image
fangjun
blockchain and web3 developer, author of several books including "Introduction to Blockchain", "Introduction to Metaverse", "Platform Era".
  • Joined

a quick reply:

using ethers.js to call contract.retrieve()

value = await contract.retrieve()

CollapseExpand
 
wenthebondsfail profile image
ThetaKing
  • Joined
• Edited on• Edited

Thanks for the reply. I tried but it still fails to show the value. I want to avoid turning your article into a stackoverflow thread, but would you be able to point what is missing here? The storage function works and I can verify that the contract has stored the number using Remix IDE. I don't get any error, but {Retrieve} comes out blank. Thanks

import React, { useState } from 'react';
import { useWeb3React } from '@web3-react/core'
import { Web3Provider } from '@ethersproject/providers'
import {Contract} from "@ethersproject/contracts";
import { ethers } from "ethers";
import { parseEther}from "@ethersproject/units"
import { Button, Input , NumberInput, NumberInputField, FormControl, FormLabel } from '@chakra-ui/react'
import {STORAGE} from "abi/STORAGE"
import Web3 from "web3"

const web3 = new Web3("localhost:8545")

interface Props {
numberStored: string
addressContract: string
}

export default function StoringNumber(props:Props){

const addressContract = props.addressContract
const numberStored = props.numberStored
const [toAddress, setToAddress]=useState("")
const [amount,setAmount]=useState('0.00001')

const [number, setNewNumber] = useState();
const { account, active, library} = useWeb3React()

async function Store(event:React.FormEvent) {
event.preventDefault()
if(!(active && account && library)) return
const storing = new Contract(addressContract, STORAGE, library.getSigner());
storing.store(amount).catch('error', console.error)
}

async function Retrieve(event:React.FormEvent) {
const retrieving = new ethers.Contract(addressContract, STORAGE)
await retrieving.retrieve()
}

const handleChange = (value:string) => setAmount(value)

return (

//storing form erased to save space

    <form onSubmit={Retrieve}>      <FormControl>      <FormLabel htmlFor='amount'>Number that was stored: {Retrieve}</FormLabel>        <NumberInput defaultValue={Retrieve} min={0} max={1000} onChange={handleChange}>          <NumberInputField />        </NumberInput>        <Button type="submit">Retrieve</Button>      </FormControl>    </form></div>
Enter fullscreen modeExit fullscreen mode

)
}

Thread Thread
 
yakult profile image
fangjun
blockchain and web3 developer, author of several books including "Introduction to Blockchain", "Introduction to Metaverse", "Platform Era".
  • Joined

you can console.log to see the output:

add a line :
console.log(await retrieving.retrieve())

Thread Thread
 
wenthebondsfail profile image
ThetaKing
  • Joined

Oh I see. It is giving me:

"Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead."

will try to find out what can be done (if you know and can answer, will be very grateful). Thanks a lot!

Thread Thread
 
yakult profile image
fangjun
blockchain and web3 developer, author of several books including "Introduction to Blockchain", "Introduction to Metaverse", "Platform Era".
  • Joined
• Edited on• Edited

good direction.

a suggestion: try to decouple two kind of jobs

  • interact with smart contract (just as a traditional restful API) to get/set data correctly
  • render react page and components with data
CollapseExpand
 
t_p profile image
t_p
  • Joined

@yakul curious, would usingwagmi lib suffice and replace the need forweb3-react andSWR ? sincewagmi hooks have cache and watch that allow to refetch data from the blockchain? Wondering since it seems using one library would be simpler. Have you tiredwagmi and still prefer using the libs from the tutorial?

CollapseExpand
 
yakult profile image
fangjun
blockchain and web3 developer, author of several books including "Introduction to Blockchain", "Introduction to Metaverse", "Platform Era".
  • Joined

using wagmi these days, the hooks are simpler.

I haven't used the cache of wagmi yet. Will take a look at this feature. Thank you.

CollapseExpand
 
ombayoeco11 profile image
ombayoeco11
  • Joined
• Edited on• Edited

hi fangjun, i was trying to interact with my NFT Contract using web3-react with ReactJS. my BIGGEST problem is ABI part. it's always gave me the same error"Uncaught SyntaxError: Unexpected non-whitespace character after JSON at position 1"
when i inspect it, it just point at ** abi = JSON.parse(fragments)**; in interface,js (i'm using Google Chrome). can you point any solution for this?

*edit: my bad, i misplaced the abi with contract address. But then a new problem arise. i still can't interact with my contract. i'm using React Js and i haven't got any example on using web3-react with contract interaction.

CollapseExpand
 
toolkituse profile image
toolkituse
ToolkitUse is a commonly used toolkit designed specifically for front-end developers, aiming to provide convenient and efficient solutions and tools to accelerate the front-end project development pro

nice

CollapseExpand
 
okokokokokhygt profile image
Jokoko
  • Education
    Toulouse school of economics
  • Work
    Economist European Central Bank
  • Joined

Hi,

Amazing post!
I am currently looking for a web3 dev yo develop a dapp. Please contact me if interested.

CollapseExpand
 
hamza_albaba_d6d2fd7e072 profile image
Hamza Al baba
  • Joined

Hello Can you help me make my dapp i Will pay you for helping me

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

blockchain and web3 developer, author of several books including "Introduction to Blockchain", "Introduction to Metaverse", "Platform Era".
  • Joined

More fromfangjun

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp