def __call_by_default(self, args): # If function is constant in ABI, then call by default, else transact function_abi = find_matching_fn_abi(self._function.contract_abi, fn_name=self._function.method_name, args=args) return function_abi['constant'] if 'constant' in function_abi.keys( ) else False
def get_transaction_data(abi: Dict, function_name: str, args: Any = None, kwargs: Any = None): """Get encoded transaction data""" args = args or list() fn_abi = find_matching_fn_abi(abi, function_name, args=args, kwargs=kwargs) return encode_transaction_data( None, function_name, contract_abi=abi, fn_abi=fn_abi, args=args, kwargs=kwargs )
def get_transaction_data(abi: Dict, function_name: str, args: List = list()): """Get encoded transaction data""" fn_abi = find_matching_fn_abi(abi, function_name, args) args = ContractProxy.sanitize_args(fn_abi, args) return encode_transaction_data(abi, None, function_name, args)
def extract_secret_from_redeem_transaction(self, tx_address: str) -> str: ''' Extracting secret from redeem transaction. Args: tx_address (str): address of the redeem transaction Returns: str,: Secret string Raises: ValueError: When given transaction was not a redeem type transaction Example: >>> from clove.network import EthereumTestnet >>> network = EthereumTestnet() >>> network.extract_secret_from_redeem_transaction('0x9e41847c3cc780e4cb59902cf55657f0ee92642d9dee4145e090cbf206d4748f') # noqa: E501 b2eefaadbbefeb9d9467092b612464db7c6724f71b5c1d70c85853845728f0e9 ''' tx_dict = self.get_transaction(tx_address) method_id = self.extract_method_id(tx_dict['input']) if method_id != self.redeem: logger.debug('Not a redeem transaction.') raise ValueError('Not a redeem transaction.') method_name = self.get_method_name(method_id) input_types = get_abi_input_types( find_matching_fn_abi(self.abi, fn_identifier=method_name)) input_values = decode_abi(input_types, Web3.toBytes(hexstr=tx_dict['input'][10:])) return input_values[0].hex()
def __call_by_default(self, args): function_abi = find_matching_fn_abi( self._function.contract_abi, fn_identifier=self._function.function_identifier, args=args) return function_abi['constant'] if 'constant' in function_abi.keys( ) else False
def __init__(self, network, tx_dict): self.network = network self.tx_dict = tx_dict self.method_id = self.network.extract_method_id(tx_dict['input']) self.type = self.network.get_method_name(self.method_id) self.token = None if not self.is_initiate: logger.warning('Not a contract transaction.') raise ValueError('Not a contract transaction.') if self.is_token_contract: self.abi = self.network.token_abi else: self.abi = self.network.abi input_types = get_abi_input_types( find_matching_fn_abi(self.abi, fn_identifier=self.type)) input_names = get_abi_input_names( find_matching_fn_abi(self.abi, fn_identifier=self.type)) input_values = decode_abi( input_types, Web3.toBytes(hexstr=self.tx_dict['input'][10:])) self.inputs = dict(zip(input_names, input_values)) self.locktime = datetime.utcfromtimestamp(self.inputs['_expiration']) self.recipient_address = Web3.toChecksumAddress( self.inputs['_participant']) self.refund_address = self.tx_dict['from'] self.secret_hash = self.inputs['_hash'].hex() self.contract_address = Web3.toChecksumAddress(self.tx_dict['to']) self.confirmations = self.network.latest_block - self.tx_dict[ 'blockNumber'] if self.is_token_contract: self.value_base_units = self.inputs['_value'] self.token_address = Web3.toChecksumAddress(self.inputs['_token']) self.token = self.network.get_token_by_address(self.token_address) self.value = self.token.value_from_base_units( self.value_base_units) self.symbol = self.token.symbol else: self.value_base_units = self.tx_dict['value'] self.value = self.network.value_from_base_units( self.value_base_units) self.symbol = self.network.default_symbol
def extract_secret_from_redeem_transaction(self, tx_address: str) -> str: tx_dict = self.get_transaction(tx_address) method_id = self.extract_method_id(tx_dict['input']) if method_id != self.redeem: logger.debug('Not a redeem transaction.') raise ValueError('Not a redeem transaction.') method_name = self.get_method_name(method_id) input_types = get_abi_input_types(find_matching_fn_abi(self.abi, fn_identifier=method_name)) input_values = decode_abi(input_types, Web3.toBytes(hexstr=tx_dict['input'][10:])) return input_values[0].hex()
def call_contract_function(abi, web3, address, normalizers, function_name, transaction, *args, **kwargs): """ Helper function for interacting with a contract function using the `eth_call` API. """ call_transaction = prepare_transaction( abi, address, web3, fn_name=function_name, fn_args=args, fn_kwargs=kwargs, transaction=transaction, ) return_data = web3.eth.call(call_transaction) function_abi = find_matching_fn_abi(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 web3.eth.getCode(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, 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 _set_function_info(self): self.abi = find_matching_fn_abi(self.contract_abi, self.function_identifier, self.args, self.kwargs) if self.function_identifier is FallbackFn: self.selector = encode_hex(b'') elif is_text(self.function_identifier): self.selector = encode_hex(function_abi_to_4byte_selector(self.abi)) else: raise TypeError("Unsupported function identifier") self.arguments = merge_args_and_kwargs(self.abi, self.args, self.kwargs)
def get_transaction_data(abi: Dict, function_name: str, args: List = None): """Get encoded transaction data""" args = args or list() fn_abi = find_matching_fn_abi( abi, function_name, args, ) args = ContractProxy.sanitize_args(fn_abi, args) return encode_transaction_data( None, function_name, contract_abi=abi, fn_abi=fn_abi, args=args, )
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 encode_function_call(abi: Dict, function: str, args: List = list()): fn_abi = find_matching_fn_abi(abi, function, args) fn_types = get_abi_input_types(fn_abi) return encode_abi(fn_types, args)
def _find_matching_fn_abi(cls, fn_identifier=None, args=None, kwargs=None): return find_matching_fn_abi(cls.abi, fn_identifier=fn_identifier, args=args, kwargs=kwargs)
def __call_by_default(self, args): function_abi = find_matching_fn_abi(self._function.contract_abi, fn_identifier=self._function.function_identifier, args=args) return function_abi['constant'] if 'constant' in function_abi.keys() else False
def call_contract_function(abi, web3, address, normalizers, function_name, transaction, *args, **kwargs): """ Helper function for interacting with a contract function using the `eth_call` API. """ call_transaction = prepare_transaction( abi, address, web3, fn_name=function_name, fn_args=args, fn_kwargs=kwargs, transaction=transaction, ) return_data = web3.eth.call(call_transaction) function_abi = find_matching_fn_abi(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 web3.eth.getCode(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, 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 _set_function_info(self): self.abi = find_matching_fn_abi(self.contract_abi, self.fn_name, self.args, self.kwargs) self.selector = encode_hex(function_abi_to_4byte_selector(self.abi)) self.arguments = merge_args_and_kwargs(self.abi, self.args, self.kwargs)
def __call_by_default(self, args): # If function is constant in ABI, then call by default, else transact function_abi = find_matching_fn_abi(self._function.contract_abi, fn_name=self._function.function_name, args=args) return function_abi['constant'] if 'constant' in function_abi.keys() else False
def _find_matching_fn_abi(cls, fn_name=None, args=None, kwargs=None): return find_matching_fn_abi(cls.abi, fn_name=fn_name, args=args, kwargs=kwargs)