diff --git a/newsfragments/3626.feature.rst b/newsfragments/3626.feature.rst new file mode 100644 index 0000000000..c3bbca51dd --- /dev/null +++ b/newsfragments/3626.feature.rst @@ -0,0 +1,2 @@ +Add abi properties stateMutability, type, inputs, outputs to the ``ContractFunction`` object as ``state_mutability``, ``type``, ``inputs``, ``outputs``. +Add abi properties type, anonymous, inputs to the ``ContractEvent`` object with the same name. diff --git a/tests/core/contracts/test_contract_example.py b/tests/core/contracts/test_contract_example.py index e47c9352d9..5326cde2fb 100644 --- a/tests/core/contracts/test_contract_example.py +++ b/tests/core/contracts/test_contract_example.py @@ -112,6 +112,34 @@ def test_updating_greeting_emits_event(w3, foo_contract): assert event.args._bar == "testing contracts is easy" +def test_functions_abi_state_mutability(w3, foo_contract): + assert foo_contract.functions.setBar.state_mutability == "nonpayable" + assert foo_contract.functions.bar.state_mutability == "view" + + +def test_functions_abi_type(w3, foo_contract): + assert foo_contract.functions.setBar.type == "function" + assert foo_contract.functions.bar.type == "function" + + +def test_functions_abi_inputs(w3, foo_contract): + assert foo_contract.functions.setBar.inputs == [{"name": "_bar", "type": "string"}] + assert foo_contract.functions.bar.inputs == [] + + +def test_functions_abi_outputs(w3, foo_contract): + assert foo_contract.functions.setBar.outputs == [] + assert foo_contract.functions.bar.outputs == [{"name": "", "type": "string"}] + + +def test_events_abi(w3, foo_contract): + assert foo_contract.events.barred.type == "event" + assert foo_contract.events.barred.anonymous is False + assert foo_contract.events.barred.inputs == [ + {"indexed": False, "name": "_bar", "type": "string"} + ] + + @pytest.fixture def async_eth_tester(): return AsyncEthereumTesterProvider().ethereum_tester diff --git a/web3/contract/base_contract.py b/web3/contract/base_contract.py index 6e9c3c9a04..537b3c2b77 100644 --- a/web3/contract/base_contract.py +++ b/web3/contract/base_contract.py @@ -22,6 +22,8 @@ ) from eth_typing import ( ABI, + ABIComponent, + ABIComponentIndexed, ABIElement, ABIEvent, ABIFunction, @@ -209,6 +211,18 @@ def topic(self) -> HexStr: self._topic = encode_hex(keccak(text=self.signature)) return self._topic + @property + def type(self) -> str: + return "event" + + @property + def anonymous(self) -> Optional[bool]: + return self.abi.get("anonymous") + + @property + def inputs(self) -> Optional[Sequence["ABIComponentIndexed"]]: + return self.abi.get("inputs") + @combomethod def _get_event_abi(cls) -> ABIEvent: if cls.abi: @@ -596,6 +610,22 @@ def __init__(self, abi: Optional[ABIFunction] = None) -> None: self.argument_names = tuple([input.get("name", None) for input in event_inputs]) self.argument_types = tuple([input["type"] for input in event_inputs]) + @property + def state_mutability(self) -> str: + return self.abi["stateMutability"] + + @property + def type(self) -> str: + return "function" + + @property + def inputs(self) -> Optional[Sequence["ABIComponent"]]: + return self.abi.get("inputs") + + @property + def outputs(self) -> Optional[Sequence["ABIComponent"]]: + return self.abi.get("outputs") + @combomethod def _get_abi(cls) -> ABIFunction: if not cls.args and not cls.kwargs: