Ethers.js: Add convenience method to TransactionReceipt for parsing events

Created on 14 Jun 2020  Â·  5Comments  Â·  Source: ethers-io/ethers.js

API:

receipt.parseEvents(objectOrString) ⇒ Result<LogDescription>

Use:

const tokenAmount = ethers.utils.parseEther('10')
const wallet = new ethers.Contract(address , abi , signer)

const receipt = await (await wallet.deposit(tokenAmount)).wait()
const transferEvents = receipt.parseEvents('transfer(address to, uint amount)')
assert(tokenAmount.eq(transferEvents[0].amount))

This would allow for validating events are properly triggered on external contracts in 3 lines of code. (Or potentially a single line for the crazy people out there)

assert(tokenAmount.eq((await (await wallet.deposit(tokenAmount)).wait()).parseEvents('transfer(address to, uint amount)')[0].amount))

Most helpful comment

Please note that contractInterface.parseLog(log) will throw if the event doesn't not exist in the contractInterface. This is possible if contract makes a call to another contract (for e.g. ERC20 contract) that triggers an event from that contract.

All 5 comments

@ricmoo Any plans on implementing this?

In the meantime, here is a simple helper which achieves this functionality:

const parseEvents = (receipt, interface, eventName) =>
  receipt.logs
    .map((log) => interface.parseLog(log))
    .filter((log) => log.name === eventName);

for the typescript folks, you'll want to use this

import { Interface } from 'ethers/lib/utils'
import { TransactionReceipt } from '@ethersproject/providers'

const parseEvents = (
  receipt: TransactionReceipt,
  contractInterface: Interface,
  eventName: string,
) =>
  receipt.logs
    .map((log) => contractInterface.parseLog(log))
    .filter((log) => log.name === eventName)

Please note that contractInterface.parseLog(log) will throw if the event doesn't not exist in the contractInterface. This is possible if contract makes a call to another contract (for e.g. ERC20 contract) that triggers an event from that contract.

Not sure how I missed this issue before, but I'm trying to clean up the issues a bit and stumbled across it.

You can already accomplish this. The method is already available on the contract.interface object (see decodingEventLog or parseLog), but the events will already have been decoded for you, so you should be able to use receipt.events.filter((e) => (e.name === "transfer")) to pull all the transfer events out of a Contract's TransactionReceipt.

Does that work for you?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cloudonshore picture cloudonshore  Â·  25Comments

Tomix3D picture Tomix3D  Â·  39Comments

MicahZoltu picture MicahZoltu  Â·  24Comments

subramanianv picture subramanianv  Â·  34Comments

fjrojasgarcia picture fjrojasgarcia  Â·  28Comments