A common way of listening to what happened in a transaction is through events, also known as logs. These logs are emitted by the smart contract through the emit and event keywords and can be very important in a responsive frontend. Often, DApps will use toast elements to represent events in real-time, but for this DApp, we will use a simple table.
We created an event in our smart contract: event PurchaseOccurred(address minter, uint256 amount), so let's figure out how to display its information in the frontend.
Let's create a new component PurchaseOccurredEvents within a new file PurchaseOccurredEvents.js that reads the last five logs and displays them in a table:
import { useLogs, useBlockNumber } from '@usedapp/core';
import { utils } from 'ethers';
import {
Grid,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
} from '@mui/material';
export default function PurchaseOccurredEvents({ contract }) {
return (
<Grid item xs={12} marginTop={5}>
<TableContainer >
<Table>
<TableHead>
<TableRow>
<TableCell>Minter</TableCell>
<TableCell align='right'>Amount</TableCell>
</TableRow>
</TableHead>
<TableBody>
{/* This is where we have to inject data from our logs! */}
</TableBody>
</Table>
</TableContainer>
</Grid>
);
}
This component so far creates an empty table, so let's use two new hooks to read those logs:
export default function PurchaseOccurredEvents({ contract }) {
// Get block number to ensure that the useLogs doesn't search from 0, otherwise it will time out
const blockNumber = useBlockNumber();
// Create a filter & get the logs
const filter = { args: [null, null], contract, event: 'PurchaseOccurred' };
const logs = useLogs(filter, { fromBlock: blockNumber - 10000 });
const parsedLogs = logs?.value.slice(-5).map(log => log.data);
// ...
}
Here's what happens in this code:
The block number is received from the useBlockNumber hook, similar to using the JSON-RPC method eth_blockNumber
A filter is created to filter for all events with any arguments on the contract injected into the component with the event name PurchaseOccurred
Logs are queried for via the useLogs hook, similar to using the eth_getLogs JSON-RPC method. Note that we're only querying the last 10,000 blocks because otherwise the entire history of the blockchain would be queried and the RPC would timeout
The resultant logs are parsed, and the most recent five are selected
And, if you've done any transactions, you'll see that they'll pop up!
Now you've implemented three main components of DApp frontends: reading from storage, sending transactions, and reading logs. With these building blocks as well as the knowledge you gained with smart contracts and nodes, you should be able to cover 80% of DApps.