Skip to main content

Exercise 2

In this exercise we'll learn how to read blockchain state using useDApp.

In the application we're building, go to the second tab. This tab has a small table in which WETH balances for specific addresses should be displayed. The first row is your own address, and the address for the second row was selected arbitrarily. In this exercise you'll need to modify the Exercise2.tsx file.

Let's start with something we already know how to do - getting the current account address. We'll use the useEthers hook to get the account variable.

const { account } = useEthers();

Now pass the account variable as props to the first row in the table:

- <TableBody>
- <BalancesTableRow address={secondAddress}/>
- <BalancesTableRow address={secondAddress}/>
- </TableBody>
+ <TableBody>
+ <BalancesTableRow address={account}/>
+ <BalancesTableRow address={secondAddress}/>
+ </TableBody>

Next let's implement the logic in BalancesTableRow component. We'll need the address of the WETH contract. But on different chains it may be different. As in this tutorial we only consider the case of two chains (Goerli and local), an object with the addresses is provided in the packages/frontend/src/shared directory.

import { weth10Addresses } from '../shared/weth10addresses';

Now create an ethers contract instance for the WETH10 contract. You'll need the WETH10ABI object from the @simple-dapp/contracts package (what's ABI?) and optionally the WETH10 contract type - this will allow you to get type hints for the contract methods.

import { WETH10ABI, WETH10 } from '@simple-dapp/contracts';
import { Contract, utils } from 'ethers';

And now in the BalancesTableRow component:

const { chainId } = useEthers();
const weth10Contract = chainId && new Contract(weth10Addresses[chainId], WETH10ABI.abi) as WETH10;

Now we're ready to make the first call to the blockchain. We'll use the useCall hook.

- import { useEthers } from '@usedapp/core';
+ import { useCall, useEthers } from '@usedapp/core';

In the BalancesTableRow component:

const balance = useCall(address && weth10Contract && {
contract: weth10Contract,
method: 'balanceOf',
args: [address],

The useCall hook accepts falsy values as well. In our case the call wouldn't make sense if weth10Contract or address were not defined, so we're using the && operator to make sure that the call is made only when both values are defined.

Now we can display the balance in the table.

- <TableRow>
- <TableCell>{address}</TableCell>
- <TableCell align="right">
- {undefined // TODO: if request is completed
- ?
- false // TODO: if there is an error
- ?
- <Box sx={{ color: 'error.main' }}> Error fetching balance </Box>
- :
- '0 ETH' // TODO: show properly formatted balance balance
- : 'Loading...'}
- </TableCell>
- </TableRow>
+ <TableRow>
+ <TableCell>{address}</TableCell>
+ <TableCell align="right">
+ {balance
+ ?
+ balance.error
+ ?
+ <Box sx={{ color: 'error.main' }}> Error fetching balance </Box>
+ :
+ utils.formatEther(balance.value[0])
+ : 'Loading...'}
+ </TableCell>
+ </TableRow>