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

abigen doesn't generate interfaces for Caller/Transactor/Filterer #28278

Open
samlaf opened this issue Oct 8, 2023 · 4 comments
Open

abigen doesn't generate interfaces for Caller/Transactor/Filterer #28278

samlaf opened this issue Oct 8, 2023 · 4 comments

Comments

@samlaf
Copy link
Contributor

samlaf commented Oct 8, 2023

Rationale

abigen should generate interfaces for the structs it creates, to facilitate test doubles and other implementations.

Here is one example in Optimism's codebase of them having to define their own Caller interface and keep it updated.

// MinimalDisputeGameFactoryCaller is a minimal interface around [bindings.DisputeGameFactoryCaller].
// This needs to be updated if the [bindings.DisputeGameFactoryCaller] interface changes.
type MinimalDisputeGameFactoryCaller interface {
	GameCount(opts *bind.CallOpts) (*big.Int, error)
	GameAtIndex(opts *bind.CallOpts, _index *big.Int) (struct {
		GameType  uint8
		Timestamp uint64
		Proxy     common.Address
	}, error)
}

Implementation

Will submit a PR shortly.

@karalabe
Copy link
Member

Could you give an example of exactly what you're trying to test and how and why you need these interfaces? Would help figure out the code a bit better.

@samlaf
Copy link
Contributor Author

samlaf commented Oct 16, 2023

Could you give an example of exactly what you're trying to test and how and why you need these interfaces? Would help figure out the code a bit better.

I might be completely missing something here regarding how people generally use these abigen structs for testing. The only way I've found is to use an actual chain, or a simulated client (as described in https://medium.com/@m.vanderwijden1/intro-to-web3-go-part-4-5a21bc71fddc).

But for some unit tests, even a simulated client is painful to work with. If I'm only interacting with one or a few contracts, I might want to create a fake/mock of those contracts in golang directly, and interact with those. Having the interfaces for those contracts is necessary to implement these fake/mocks isn't it?

Currently in the eigensdk we're developing we're using these chainClients structs which basically just wrap the bindings and expose their methods via this hand-written interface. But then if we change the contracts or add another contract, we need to update these manually etc. If abigen generated the interfaces directly all of this would be taken care of automatically. This, at least, is my current thinking. Let me know if I'm misunderstanding how to use these or if there's a better way to go about this!

@samlaf
Copy link
Contributor Author

samlaf commented Dec 5, 2023

@karalabe any updates or thoughts on this? I'm integrating this approach into our eigensdk. See for eg Layr-Labs/eigensdk-go#73 and https://github.com/Layr-Labs/eigensdk-go/blob/3d14cf3a2662924a57d01e098c987bd33ce8efcf/chainio/clients/elcontracts/reader.go#L71

If I'm using this wrong or there's a better way to do this I'd like to know.

@arora-anmol
Copy link

@karalabe @samlaf following up on this, this feature is relevant for us as well to generate mocks for on chain calls. If interfaces are not relevant for everyone, maybe we can have another arg in abigen as an option? Open to discussion and building this as necessary. Currently we are using @samlaf 's PR here -- #28279

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

No branches or pull requests

3 participants