def call_contract_function(contract, function_name, transaction, *args, **kwargs): """ Helper function for interacting with a contract function using the `eth_call` API. """ call_transaction = contract._prepare_transaction( fn_name=function_name, fn_args=args, fn_kwargs=kwargs, transaction=transaction, ) return_data = contract.web3.eth.call(call_transaction) function_abi = contract._find_matching_fn_abi(function_name, args, kwargs) output_types = get_abi_output_types(function_abi) output_data = decode_abi(output_types, return_data) normalized_data = [ normalize_return_type(data_type, data_value) for data_type, data_value in zip(output_types, output_data) ] if len(normalized_data) == 1: return normalized_data[0] else: return normalized_data
def call_contract_function(contract, function_name, transaction, *args, **kwargs): """ Helper function for interacting with a contract function using the `eth_call` API. """ call_transaction = contract._prepare_transaction( fn_name=function_name, fn_args=args, fn_kwargs=kwargs, transaction=transaction, ) return_data = contract.web3.eth.call(call_transaction) function_abi = contract._find_matching_fn_abi(function_name, args, kwargs) output_types = get_abi_output_types(function_abi) try: output_data = decode_abi(output_types, return_data) except DecodingError as e: # Provide a more helpful error message than the one provided by # eth-abi-utils is_missing_code_error = ( return_data in ACCEPTABLE_EMPTY_STRINGS and contract.web3.eth.getCode(contract.address) in ACCEPTABLE_EMPTY_STRINGS ) if is_missing_code_error: msg = ( "Could not transact with/call contract function, is contract " "deployed correctly and chain synced?" ) else: msg = ( "Could not decode contract function call {} return data {} for " "output_types {}".format( function_name, return_data, output_types ) ) raise BadFunctionCallOutput(msg) from e normalizers = itertools.chain( BASE_RETURN_NORMALIZERS, contract._return_data_normalizers, ) normalized_data = map_abi_data(normalizers, output_types, output_data) if len(normalized_data) == 1: return normalized_data[0] else: return normalized_data
def call(self, *args, **kwargs): kwargs.pop('private_key', None) from_address = None if len(args) == 1: from_address = args[0].pop('from', None) tx = self._call.buildTransaction(*args, **kwargs) if from_address is not None: tx['from'] = from_address output_types = get_abi_output_types(self._call.abi) return_data = self._call.web3.eth.call(tx) decoded = decode_abi(output_types, return_data) return decoded[0] if len(decoded) == 1 else decoded
def call_contract_function(contract, function_name, transaction, *args, **kwargs): """ Helper function for interacting with a contract function using the `eth_call` API. """ call_transaction = contract._prepare_transaction( fn_name=function_name, fn_args=args, fn_kwargs=kwargs, transaction=transaction, ) return_data = contract.web3.eth.call(call_transaction) function_abi = contract._find_matching_fn_abi(function_name, args, kwargs) output_types = get_abi_output_types(function_abi) try: output_data = decode_abi(output_types, return_data) except DecodingError as e: # Provide a more helpful error message than the one provided by # eth-abi-utils msg = ( "Could not decode contract function call {} return data {} for " "output_types {}".format( function_name, return_data, output_types ) ) raise_from(BadFunctionCallOutput(msg), e) normalized_data = [ normalize_return_type(data_type, data_value) for data_type, data_value in zip(output_types, output_data) ] if len(normalized_data) == 1: return normalized_data[0] else: return normalized_data
def call_contract_function(contract, function_name, transaction, *args, **kwargs): """Calls a contract constant or function. The function must not have state changing effects. For those see :func:`transact_with_contract_function` For usual cases, you do not want to call this directly, but interact with your contract through :meth:`Contract.call` method. :param contract: :class:`web3.contract.Contract` object instance :param function_name: Contract function name to call :param transaction: Transaction parameters to pass to underlying ``web3.eth.call`` :param *arguments: Arguments to be passed to contract function. Automatically encoded :return: Function call results, encoded to Python object """ if transaction is None: call_transaction = {} else: call_transaction = dict(**transaction) function_abi = contract.find_matching_fn_abi(function_name, args, kwargs) function_selector = function_abi_to_4byte_selector(function_abi) arguments = merge_args_and_kwargs(function_abi, args, kwargs) call_transaction['data'] = contract.encodeABI( function_name, arguments, data=function_selector, ) return_data = contract.web3.eth.call(call_transaction) output_types = get_abi_output_types(function_abi) output_data = decode_abi(output_types, return_data) normalized_data = [ normalize_return_type(data_type, data_value) for data_type, data_value in zip(output_types, output_data) ] if len(normalized_data) == 1: return normalized_data[0] else: return normalized_data
def call(self, function_name: str, *args, **kargs): self._check_function_name_and_kargs(function_name, kargs) data = self.get_transaction_data(self.abi, function_name, args) res = self.call_function(sender=self.sender, to=self.contract_address, value=kargs.pop('value', 0), data=decode_hex(data), **kargs) if res: fn_abi = find_matching_fn_abi(self.abi, function_name, args) output_types = get_abi_output_types(fn_abi) res = decode_abi(output_types, res) if len(res) == 1: res = res[0] return res
def call_contract_function(contract=None, function_name=None, transaction=None, *arguments): if not arguments: arguments = [] function_abi = contract.find_matching_abi(function_name, arguments) function_selector = function_abi_to_4byte_selector(function_abi) transaction['data'] = contract.encodeABI( function_name, arguments, data=function_selector, ) return_data = contract.web3.eth.call(transaction) output_types = get_abi_output_types(function_abi) output_data = decode_abi(output_types, return_data) if len(output_data) == 1: return output_data[0] else: return output_data