Utilities for Contract ABIs
What was wrong?
Contract ABI utilities are useful for encoding and decoding contract transactions. Many utilities are implemented in web3.py as private methods.
Related to https://github.com/ethereum/web3.py/issues/3036
These changes will be utilized in web3.py function/event utils: https://github.com/ethereum/web3.py/pull/3408 https://github.com/ethereum/web3.py/pull/3401
How was it fixed?
Implements a public API for ABI utilities.
Todo:
-
[X] Clean up commit history
-
[X] Add or update documentation related to these changes
-
[X] Add entry to the release notes
Cute Animal Picture
Usage question - I pulled an ABI from web3 (extended_resolver.py), use get_all_function_abis to get function info, then take a name from that, say supportsInterface. From the description, I should be able to plug the abi and the function name into get_function_abi and get the same info back about that function, but I get:
MismatchedABI:
Could not identify the intended function with name `supportsInterface`, positional arguments with type(s) `` and keyword arguments with type(s) `{}`.
Found 1 function(s) with the name `supportsInterface`: ['supportsInterface(bytes4)']
Function invocation failed due to improper number of arguments.
Same for get_function_info.
Cleaned things up and addressed feedback, thanks!
@kclowes @fselmo this is ready for another look.
This is still a WIP. Keeping the ABI methods but codec utils will move into web3.utils.abi.
Cleaning up a few more items on this and I will request reviews when it's good to go!
I think all my concerns were addressed here. Will wait to approve once the eth-typing branch / version gets decided and updated rather than using the git commit hash for the branch.
I'm inclined to publish a major version for this then, with hexbytes being the new dependency. @fselmo @kclowes @pacrob
We can hold this until after eth-typing v5 is released and I can update the pin.
I could change these to be real fixtures...
Does this mean something like:
@pytest.fixture
def fn_abi_a():
return {"name": "tokenLaunched", "type": "function", "inputs": []}
If ^ is the way you were thinking, I wonder if we could just pass around the fixture sort of like you have it now, instead of the string of the fixture name. So something like:
def build_contract_abi(*abis):
...
Another thought that came to mind was reusing these fixtures across libs so that I can pull them in to tests in web3.py
I could see an eth-utils module that exported these ABIs. Although, if they're being tested here, does it add value to also test them in web3? The other thing to think about is that if they live in eth-utils, for example, to update the fixtures we'd have to make the change in eth-utils, release and then pull that release into web3.
Coupled releases would not be ideal, that's a good point. The only motivation for reusing these elements is so that the utilities are run through a wide range of cases. I dont mind having some duplication of these cases across libs.
I did mean use the @pytest.fixture as you outlined but I think the constant variables are fine too. I am planning to put them in a separate file at least, maybe just something like abi_data.py in tests/core/abi-utils alongside the tests.
So this is likely what I'll end up with:
ABI_FUNCTION_TOKEN_LAUNCHED = ABIFunction({"name": "tokenLaunched", "type": "function", "inputs": []})
So basically I'll just clean up what I have, splitting out the constant vars into a new file and making sure the tests are covered. I'll still use that build_contract_abi function as well. 👍
Cool, that sounds good to me!
Had trouble with pytest importing the variables from another file, I guess fixtures are the only way to do that. Given these arent being shared across tests within the library, I'll just keep them in the test file itself after all. This is good for another look now! @kclowes @fselmo @pacrob
@pacrob @fselmo @kclowes This is good for a final check, it's functioning as I'd expect with the ABI utils I added to web3.