diff --git a/tests/core/contracts/test_contract_caller_interface.py b/tests/core/contracts/test_contract_caller_interface.py index dc714e3503..78733a413f 100644 --- a/tests/core/contracts/test_contract_caller_interface.py +++ b/tests/core/contracts/test_contract_caller_interface.py @@ -149,7 +149,7 @@ def test_caller_with_args_and_no_transaction_keyword( add_result = contract.add(3, 5) assert add_result == 8 - + @pytest.mark.parametrize( "method_input, expected, type_str, namedtuple_repr", @@ -207,12 +207,13 @@ def test_caller_with_args_and_no_transaction_keyword( ), ) def test_tuple_contract_caller_with_decode_tuples( - tuple_contract_with_decode_tuples, method_input, expected, type_str, namedtuple_repr, transaction_dict + tuple_contract_with_decode_tuples, + method_input, + expected, + type_str, + namedtuple_repr, ): - # result = tuple_contract_with_decode_tuples.caller(transaction=transaction_dict).method(method_input) - result = tuple_contract_with_decode_tuples.caller(decode_tuples=True).method(method_input) - caller = tuple_contract_with_decode_tuples.caller - breakpoint() + result = tuple_contract_with_decode_tuples.caller.method(method_input) assert result == expected assert str(type(result)) == type_str assert result.__repr__() == namedtuple_repr @@ -221,7 +222,6 @@ def test_tuple_contract_caller_with_decode_tuples( assert str(type(result)) == type_str assert result.__repr__() == namedtuple_repr - # --- async --- # @@ -369,3 +369,76 @@ async def test_async_caller_with_args_and_no_transaction_keyword( add_result = await contract.add(3, 5) assert add_result == 8 + + +@pytest.mark.parametrize( + "method_input, expected, type_str, namedtuple_repr", + ( + ( + { + "a": 123, + "b": [1, 2], + "c": [ + { + "x": 234, + "y": [True, False], + "z": [ + "0x4AD7E79d88650B01EEA2B1f069f01EE9db343d5c", + "0xfdF1946A9b40245224488F1a36f4A9ed4844a523", + "0xfdF1946A9b40245224488F1a36f4A9ed4844a523", + ], + }, + { + "x": 345, + "y": [False, False], + "z": [ + "0xefd1FF70c185A1C0b125939815225199079096Ee", + "0xf35C0784794F3Cd935F5754d3a0EbcE95bEf851e", + ], + }, + ], + }, + ( + 123, + [1, 2], + [ + ( + 234, + [True, False], + [ + "0x4AD7E79d88650B01EEA2B1f069f01EE9db343d5c", + "0xfdF1946A9b40245224488F1a36f4A9ed4844a523", + "0xfdF1946A9b40245224488F1a36f4A9ed4844a523", + ], + ), + ( + 345, + [False, False], + [ + "0xefd1FF70c185A1C0b125939815225199079096Ee", + "0xf35C0784794F3Cd935F5754d3a0EbcE95bEf851e", + ], + ), + ], + ), + ".ABIDecodedNamedTuple'>", # noqa: E501 + "ABIDecodedNamedTuple(a=123, b=[1, 2], c=[ABIDecodedNamedTuple(x=234, y=[True, False], z=['0x4AD7E79d88650B01EEA2B1f069f01EE9db343d5c', '0xfdF1946A9b40245224488F1a36f4A9ed4844a523', '0xfdF1946A9b40245224488F1a36f4A9ed4844a523']), ABIDecodedNamedTuple(x=345, y=[False, False], z=['0xefd1FF70c185A1C0b125939815225199079096Ee', '0xf35C0784794F3Cd935F5754d3a0EbcE95bEf851e'])])", # noqa: E501 + ), + ), +) +@pytest.mark.asyncio +async def test_async_tuple_contract_caller_with_decode_tuples( + async_tuple_contract_with_decode_tuples, + method_input, + expected, + type_str, + namedtuple_repr, +): + result = await async_tuple_contract_with_decode_tuples.caller.method(method_input) + assert result == expected + assert str(type(result)) == type_str + assert result.__repr__() == namedtuple_repr + result = await async_tuple_contract_with_decode_tuples.caller().method(method_input) + assert result == expected + assert str(type(result)) == type_str + assert result.__repr__() == namedtuple_repr diff --git a/tests/core/contracts/test_contract_example.py b/tests/core/contracts/test_contract_example.py index 973197b86a..b3d5ffac90 100644 --- a/tests/core/contracts/test_contract_example.py +++ b/tests/core/contracts/test_contract_example.py @@ -83,9 +83,7 @@ def test_initial_greeting(foo_contract): def test_can_update_greeting(w3, foo_contract): # send transaction that updates the greeting - tx_hash = foo_contract.functions.setBar( - "testing contracts is easy", - ).transact( + tx_hash = foo_contract.functions.setBar("testing contracts is easy",).transact( { "from": w3.eth.accounts[1], } @@ -99,9 +97,7 @@ def test_can_update_greeting(w3, foo_contract): def test_updating_greeting_emits_event(w3, foo_contract): # send transaction that updates the greeting - tx_hash = foo_contract.functions.setBar( - "testing contracts is easy", - ).transact( + tx_hash = foo_contract.functions.setBar("testing contracts is easy",).transact( { "from": w3.eth.accounts[1], } diff --git a/web3/contract/async_contract.py b/web3/contract/async_contract.py index 1621c44b4e..592397c43b 100644 --- a/web3/contract/async_contract.py +++ b/web3/contract/async_contract.py @@ -117,9 +117,11 @@ def __init__(self, address: Optional[ChecksumAddress] = None) -> None: "The address argument is required to instantiate a contract." ) self.functions = AsyncContractFunctions( - self.abi, self.w3, self.address, self.decode_tuples + self.abi, self.w3, self.address, decode_tuples=self.decode_tuples + ) + self.caller = AsyncContractCaller( + self.abi, self.w3, self.address, decode_tuples=self.decode_tuples ) - self.caller = AsyncContractCaller(self.abi, self.w3, self.address) self.events = AsyncContractEvents(self.abi, self.w3, self.address) self.fallback = AsyncContract.get_fallback_function( self.abi, self.w3, AsyncContractFunction, self.address @@ -151,10 +153,13 @@ def factory( ), ) contract.functions = AsyncContractFunctions( - contract.abi, contract.w3, contract.decode_tuples + contract.abi, contract.w3, decode_tuples=contract.decode_tuples ) contract.caller = AsyncContractCaller( - contract.abi, contract.w3, contract.address + contract.abi, + contract.w3, + contract.address, + decode_tuples=contract.decode_tuples, ) contract.events = AsyncContractEvents(contract.abi, contract.w3) contract.fallback = AsyncContract.get_fallback_function( @@ -254,6 +259,7 @@ async def call( block_identifier: BlockIdentifier = "latest", state_override: Optional[CallOverride] = None, ccip_read_enabled: Optional[bool] = None, + decode_tuples: Optional[bool] = None, ) -> Any: """ Execute a contract function call using the `eth_call` interface. @@ -294,7 +300,7 @@ async def call( self.abi, state_override, ccip_read_enabled, - self.decode_tuples, + decode_tuples, *self.args, **self.kwargs, ) @@ -502,4 +508,5 @@ def __call__( transaction=transaction, block_identifier=block_identifier, ccip_read_enabled=ccip_read_enabled, + decode_tuples=self.decode_tuples, ) diff --git a/web3/contract/base_contract.py b/web3/contract/base_contract.py index c1561b0868..fe99e1c6e6 100644 --- a/web3/contract/base_contract.py +++ b/web3/contract/base_contract.py @@ -691,6 +691,7 @@ def call( block_identifier: BlockIdentifier = "latest", state_override: Optional[CallOverride] = None, ccip_read_enabled: Optional[bool] = None, + decode_tuples: Optional[bool] = False, ) -> Any: # This was needed for typing raise NotImplementedError( @@ -1092,7 +1093,6 @@ def __init__( ccip_read_enabled: Optional[bool] = None, decode_tuples: Optional[bool] = False, ) -> None: - print(decode_tuples) self.w3 = w3 self.address = address self.abi = abi @@ -1111,6 +1111,7 @@ def __init__( contract_abi=self.abi, address=self.address, function_identifier=func["name"], + decode_tuples=decode_tuples, ) block_id = parse_block_identifier(self.w3, block_identifier) @@ -1120,6 +1121,7 @@ def __init__( transaction=transaction, block_identifier=block_id, ccip_read_enabled=ccip_read_enabled, + decode_tuples=decode_tuples, ) setattr(self, func["name"], caller_method) @@ -1158,6 +1160,7 @@ def call_function( transaction: Optional[TxParams] = None, block_identifier: BlockIdentifier = "latest", ccip_read_enabled: Optional[bool] = None, + decode_tuples: Optional[bool] = False, **kwargs: Any, ) -> Any: if transaction is None: @@ -1166,4 +1169,5 @@ def call_function( transaction=transaction, block_identifier=block_identifier, ccip_read_enabled=ccip_read_enabled, + decode_tuples=decode_tuples, ) diff --git a/web3/contract/contract.py b/web3/contract/contract.py index 960f19a6bf..9ff5509d97 100644 --- a/web3/contract/contract.py +++ b/web3/contract/contract.py @@ -233,9 +233,11 @@ def __init__(self, address: Optional[ChecksumAddress] = None) -> None: ) self.functions = ContractFunctions( - self.abi, _w3, self.address, self.decode_tuples + self.abi, _w3, self.address, decode_tuples=self.decode_tuples + ) + self.caller = ContractCaller( + self.abi, _w3, self.address, decode_tuples=self.decode_tuples ) - self.caller = ContractCaller(self.abi, _w3, self.address, self.decode_tuples) self.events = ContractEvents(self.abi, _w3, self.address) self.fallback = Contract.get_fallback_function( self.abi, @@ -272,17 +274,15 @@ def factory( normalizers=normalizers, ), ) - # if contract.decode_tuples: - # breakpoint() - # else: - # print("passsing!", contract.all_functions()) - contract.functions = ContractFunctions( - contract.abi, contract.w3, contract.decode_tuples + contract.abi, contract.w3, decode_tuples=contract.decode_tuples + ) + contract.caller = ContractCaller( + contract.abi, + contract.w3, + contract.address, + decode_tuples=contract.decode_tuples, ) - contract.caller = ContractCaller(contract.abi, contract.w3, contract.address, contract.decode_tuples) - # if contract.decode_tuples: - # breakpoint() contract.events = ContractEvents(contract.abi, contract.w3) contract.fallback = Contract.get_fallback_function( contract.abi, @@ -376,6 +376,7 @@ def call( block_identifier: BlockIdentifier = "latest", state_override: Optional[CallOverride] = None, ccip_read_enabled: Optional[bool] = None, + decode_tuples: Optional[bool] = False, ) -> Any: """ Execute a contract function call using the `eth_call` interface. @@ -416,7 +417,7 @@ def call( self.abi, state_override, ccip_read_enabled, - self.decode_tuples, + decode_tuples, *self.args, **self.kwargs, ) @@ -477,7 +478,6 @@ def __init__( ccip_read_enabled: Optional[bool] = None, decode_tuples: Optional[bool] = False, ) -> None: - # breakpoint() super().__init__( abi=abi, w3=w3, @@ -493,12 +493,11 @@ def __call__( self, transaction: Optional[TxParams] = None, block_identifier: BlockIdentifier = "latest", - state_override: Optional[CallOverride] = None, ccip_read_enabled: Optional[bool] = None, - decode_tuples: Optional[bool] = False, ) -> "ContractCaller": if transaction is None: transaction = {} + return type(self)( self.abi, self.w3, @@ -506,5 +505,5 @@ def __call__( transaction=transaction, block_identifier=block_identifier, ccip_read_enabled=ccip_read_enabled, - decode_tuples=decode_tuples, + decode_tuples=self.decode_tuples, )