Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ethers-v6): TypedContractEvent should extend EventLog #811

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

songkeys
Copy link

This is to align with v5:

import type { Event } from "ethers";

export interface TypedEvent<
  TArgsArray extends Array<any> = any,
  TArgsObject = any
> extends Event {
  args: TArgsArray & TArgsObject;
}

so that we can type the event log with it.

@changeset-bot
Copy link

changeset-bot bot commented Feb 24, 2023

⚠️ No Changeset found

Latest commit: f36855b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@zemse
Copy link
Contributor

zemse commented Feb 25, 2023

There is a TypedEventLog in the same file, which is the return type for queryFilter. The TypedEvent in v5 is similar to TypedEventLog in v6.

However, TypedContractEvent is a different thing, it is a proxy function that can be used to generate a filter. Maybe we can change its name if it's not the best.

I don't think extending EventLog here would not be appropriate, are you facing any type issues?

Types in ethers v6 without typechain:

contract.filters.Transfer // ContractEvent
contract.getEvent('Transfer') // ContractEvent

contract.filters.Transfer('0x123') // DeferredTopicFilter

contract.queryFilter(contract.filters.Transfer) // EventLog

with typechain:

import {ERC20} from '../typechain'

contract.filters.Transfer // ERC20.TransferEvent.Event
contract.getEvent('Transfer') // ERC20.TransferEvent.Event

contract.filters.Transfer('0x123') // TypedDeferredTopicFilter<ERC20.TransferEvent.Event>;

contract.queryFilter(contract.filters.Transfer) // TypedEventLog<ERC20.TransferEvent.Event>

@songkeys
Copy link
Author

songkeys commented Feb 25, 2023

How do I type the event log?

In v5, I type them like this:

    import type { MintEvent } from '../Abi'


    const targetTopicHash = keccak256(toUtf8Bytes('Mint(uint256,uint256,uint256)')

    // txReceipt.logs
    const _logs = logs.filter((log) => log.topics[0] === targetTopicHash)

    if (_logs.length === 0) {
      throw new Error(`Log with topic ${filterTopic} not found`)
    }

    const log = _logs[0]

    return this.contract.interface.parseLog(log) as unknown as MintEvent

In v6, the MintEvent (XxxEvent) turns into an namespace which includes an Event type:

export namespace MintEvent {
  export type InputTuple = [
    to: BigNumberish,
    tokenId: BigNumberish,
    tokenNumber: BigNumberish
  ];
  export type OutputTuple = [to: bigint, tokenId: bigint, tokenNumber: bigint];
  export interface OutputObject {
    to: bigint;
    tokenId: bigint;
    tokenNumber: bigint;
  }
  export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
  export type Filter = TypedDeferredTopicFilter<Event>;
}

But the MintEvent.Event type (TypedContractEvent) doesn't extends EventLog to be compatible with LogDescription.

I tried using TypedEventLog<MintEvent.Event> but got this error:

type MintEvent.Event = TypedContractEvent<MintEvent.InputTuple, MintEvent.OutputTuple, MintEvent.OutputObject>
Type 'Event' does not satisfy the constraint 'TypedContractEvent<any, any, any>'.
  Types of parameters 'to' and 'args' are incompatible.
    Type 'Partial<any>' is not assignable to type '[to?: BigNumberish | undefined, tokenId?: BigNumberish | undefined, tokenNumber?: BigNumberish | undefined]'.ts(2344)

TypedEventLog<TransferEvent.Event> works fine actually.

Do you have any suggestions? thanks.


Edit: I should state the overall request: to type the logs of tx receipt. More specifically,

const tx = await abi.mint({ ... })
const receipt = await tx.wait()
const parsedLog = parseLog(receipt.logs, 'Mint(uint256,uint256,uint256)')
console.log(parsedLog.args.tokenId.toNumber())

I wrote the parseLog function manually in v5 and type the returned value as described above. But I have no clue to find the type in v6.

@zemse
Copy link
Contributor

zemse commented Feb 26, 2023

But the MintEvent.Event type (TypedContractEvent) doesn't extends EventLog to be compatible with LogDescription.

Yea, MintEvent.Event will not work but TypedEventLog<MintEvent.Event> should work since it extends EventLog. To prevent further confusion I think we should rename this to something else.

I tried using TypedEventLog<MintEvent.Event> but got this error
TypedEventLog<TransferEvent.Event> works fine actually.

Do you mean Transfer event works but Mint event gives type errors?

Can you try this once?

const parsedLog = parseLog(receipt.logs, 'Mint(uint256,uint256,uint256)') as unknown as TypedEventLog<MintEvent.Event>[]

You should be able to access .args since it is available in both EventLog and LogDescription. But for full compatibility (without requiring to cast into unknown), I can add a TypedLogDescription here.

@songkeys
Copy link
Author

songkeys commented Feb 27, 2023

Do you mean Transfer event works but Mint event gives type errors?

Yes. I pasted the error in the above comment. I paste here again:

The MintEvent generated for me is:

export namespace MintEvent {
  export type InputTuple = [
    to: BigNumberish,
    tokenId: BigNumberish,
    tokenNumber: BigNumberish
  ];
  export type OutputTuple = [to: bigint, tokenId: bigint, tokenNumber: bigint];
  export interface OutputObject {
    to: bigint;
    tokenId: bigint;
    tokenNumber: bigint;
  }
  export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
  export type Filter = TypedDeferredTopicFilter<Event>;
}

The error for TypedEventLog<MintEvent.Event> is:

type MintEvent.Event = TypedContractEvent<MintEvent.InputTuple, MintEvent.OutputTuple, MintEvent.OutputObject>
Type 'Event' does not satisfy the constraint 'TypedContractEvent<any, any, any>'.
  Types of parameters 'to' and 'args' are incompatible.
    Type 'Partial<any>' is not assignable to type '[to?: BigNumberish | undefined, tokenId?: BigNumberish | undefined, tokenNumber?: BigNumberish | undefined]'.ts(2344)

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants