def encode_abi(web3, abi, arguments, data=None): argument_types = get_abi_input_types(abi) if not check_if_arguments_can_be_encoded(abi, arguments, {}): raise TypeError( "One or more arguments could not be encoded to the necessary " "ABI type. Expected types are: {0}".format( ', '.join(argument_types), )) try: normalizers = [ abi_ens_resolver(web3), abi_address_to_hex, abi_bytes_to_bytes, abi_string_to_text, ] normalized_arguments = map_abi_data( normalizers, argument_types, arguments, ) encoded_arguments = eth_abi_encode_abi( argument_types, normalized_arguments, ) except EncodingError as e: raise TypeError( "One or more arguments could not be encoded to the necessary " "ABI type: {0}".format(str(e))) if data: return to_hex(HexBytes(data) + encoded_arguments) else: return encode_hex(encoded_arguments)
def pack_data(*args: Tuple[Any, str]) -> bytes: """Normalize data and pack them into a byte array""" values, abi_types = zip(*args) normalized_values = map_abi_data([abi_address_to_hex], abi_types, values) return decode_hex("".join( remove_0x_prefix(hex_encode_abi_type(abi_type, value)) for abi_type, value in zip(abi_types, normalized_values)))
def abi_request_formatters(normalizers, abis): for method, abi_types in abis.items(): if isinstance(abi_types, list): yield method, map_abi_data(normalizers, abi_types) elif isinstance(abi_types, dict): single_dict_formatter = apply_abi_formatters_to_dict(normalizers, abi_types) yield method, apply_formatter_at_index(single_dict_formatter, 0) else: raise TypeError("ABI definitions must be a list or dictionary, got %r" % abi_types)
def apply_abi_formatters_to_dict(normalizers, abi_dict, data): fields = list(set(abi_dict.keys()) & set(data.keys())) formatted_values = map_abi_data( normalizers, [abi_dict[field] for field in fields], [data[field] for field in fields], ) formatted_dict = dict(zip(fields, formatted_values)) return dict(data, **formatted_dict)
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 soliditySha256(self, abi_types, values): normalized_values = map_abi_data([abi_ens_resolver(Web3)], abi_types, values) #print(normalized_values) hex_string = add_0x_prefix(''.join( remove_0x_prefix(hex_encode_abi_type(abi_type, value)) for abi_type, value in zip(abi_types, normalized_values))) #print(hex_string) hash_object = hashlib.sha256(Web3.toBytes(hexstr=hex_string)) return hash_object.hexdigest()
def pack_data(abi_types, values) -> bytes: """Normalize data and pack them into a byte array""" if len(abi_types) != len(values): raise ValueError( "Length mismatch between provided abi types and values. Got " "{0} types and {1} values.".format(len(abi_types), len(values))) normalized_values = map_abi_data([abi_address_to_hex], abi_types, values) return decode_hex("".join( remove_0x_prefix(hex_encode_abi_type(abi_type, value)) for abi_type, value in zip(abi_types, normalized_values)))
def apply_abi_formatters_to_dict(abi_dict, data): formatters = [ abi_bytes_to_hex, abi_int_to_hex, abi_string_to_hex, abi_address_to_hex, ] fields = list(set(abi_dict.keys()) & set(data.keys())) formatted_values = map_abi_data( formatters, [abi_dict[field] for field in fields], [data[field] for field in fields], ) formatted_dict = dict(zip(fields, formatted_values)) return dict(data, **formatted_dict)
def pack_data(abi_types, values) -> bytes: """Normalize data and pack them into a byte array""" warnings.warn( 'eth_recover from raiden-libs is deprecated. ' 'Function is now moved in the raiden client', DeprecationWarning, ) if len(abi_types) != len(values): raise ValueError( "Length mismatch between provided abi types and values. Got " "{0} types and {1} values.".format(len(abi_types), len(values)), ) normalized_values = map_abi_data([abi_address_to_hex], abi_types, values) return decode_hex(''.join( remove_0x_prefix(hex_encode_abi_type(abi_type, value)) for abi_type, value in zip(abi_types, normalized_values)))
def get_request_bytes_representation(payee_id_addresses, amounts, payer, ipfs_hash=None): """ Return the bytes representation of the given Request data. The JS version uses lower-cased addresses but web3.py expects checksum addresses. To work around this the encoded result is converted to lowercase. address(creator) address(payer) uint8(number_of_payees) [ address(main_payee_address) int256(main_payee_expected_amount) address(second_payee_address) int256(second_payee_expected_amount) ... ] uint8(data_string_size) size(data) :return: """ ipfs_hash = ipfs_hash if ipfs_hash else '' payer = payer if payer else EMPTY_BYTES_20 parts = [(payee_id_addresses[0], 'address'), (payer, 'address'), (len(payee_id_addresses), 'uint8')] for i in range(0, len(payee_id_addresses)): parts.append((payee_id_addresses[i], 'address')) parts.append((amounts[i], 'int256')) parts.append((len(ipfs_hash), 'uint8')) parts.append((ipfs_hash, 'string')) values, abi_types = zip(*parts) # Taken from `Web3.soliditySha3` normalized_values = map_abi_data([abi_ens_resolver(w3)], abi_types, values) return add_0x_prefix(''.join( remove_0x_prefix(hex_encode_abi_type(abi_type, value)) for abi_type, value in zip(abi_types, normalized_values))).lower()
def _encode_abi(cls, abi, arguments, data=None): argument_types = get_abi_input_types(abi) if not check_if_arguments_can_be_encoded(abi, arguments, {}): raise TypeError( "One or more arguments could not be encoded to the necessary " "ABI type. Expected types are: {0}".format( ', '.join(argument_types), ) ) try: normalizers = [ abi_ens_resolver(cls.web3), abi_address_to_hex, abi_bytes_to_hex, abi_string_to_hex, hexstrs_to_bytes, ] normalized_arguments = map_abi_data( normalizers, argument_types, arguments, ) encoded_arguments = encode_abi( argument_types, normalized_arguments, ) except EncodingError as e: raise TypeError( "One or more arguments could not be encoded to the necessary " "ABI type: {0}".format(str(e)) ) if data: return to_hex(HexBytes(data) + encoded_arguments) else: return encode_hex(encoded_arguments)
def soliditySha3(cls, abi_types, values): """ Executes sha3 (keccak256) exactly as Solidity does. Takes list of abi_types as inputs -- `[uint24, int8[], bool]` and list of corresponding values -- `[20, [-1, 5, 0], True]` """ if len(abi_types) != len(values): raise ValueError( "Length mismatch between provided abi types and values. Got " "{0} types and {1} values.".format(len(abi_types), len(values))) if isinstance(cls, type): w3 = None else: w3 = cls normalized_values = map_abi_data([abi_ens_resolver(w3)], abi_types, values) hex_string = add_0x_prefix(''.join( remove_0x_prefix(hex_encode_abi_type(abi_type, value)) for abi_type, value in zip(abi_types, normalized_values))) return cls.sha3(hexstr=hex_string)
def soliditySha3(cls, abi_types, values): """ Executes sha3 (keccak256) exactly as Solidity does. Takes list of abi_types as inputs -- `[uint24, int8[], bool]` and list of corresponding values -- `[20, [-1, 5, 0], True]` """ if len(abi_types) != len(values): raise ValueError( "Length mismatch between provided abi types and values. Got " "{0} types and {1} values.".format(len(abi_types), len(values)) ) if isinstance(cls, type): w3 = None else: w3 = cls normalized_values = map_abi_data([abi_ens_resolver(w3)], abi_types, values) hex_string = add_0x_prefix(''.join( remove_0x_prefix(hex_encode_abi_type(abi_type, value)) for abi_type, value in zip(abi_types, normalized_values) )) return cls.sha3(hexstr=hex_string)
def is_array_of_strings(value): if not is_list_like(value): return False return all((is_string(item) for item in value)) filter_result_formatter = apply_one_of_formatters(( (apply_formatter_to_array(log_entry_formatter), is_array_of_dicts), (apply_formatter_to_array(to_ascii_if_bytes), is_array_of_strings), )) format_abi_parameters = map_abi_data([ abi_bytes_to_hex, abi_int_to_hex, abi_string_to_hex, abi_address_to_hex, ]) pythonic_middleware = construct_formatting_middleware( request_formatters={ # Eth 'eth_call': apply_formatter_at_index(transaction_params_formatter, 0), 'eth_getBalance': compose( format_abi_parameters(['address', None]), apply_formatter_at_index(block_number_formatter, 1), ), 'eth_getBlockByHash': format_abi_parameters(['bytes32', 'bool']),
def test_map_abi_data(types, data, funcs, expected): assert map_abi_data(funcs, types, data) == expected
return all((is_dict(item) for item in value)) def is_array_of_strings(value): if not is_list_like(value): return False return all((is_string(item) for item in value)) filter_result_formatter = apply_one_of_formatters(( (apply_formatter_to_array(log_entry_formatter), is_array_of_dicts), (apply_formatter_to_array(to_ascii_if_bytes), is_array_of_strings), )) format_abi_parameters = map_abi_data([ abi_bytes_to_hex, abi_int_to_hex, ]) pythonic_middleware = construct_formatting_middleware( request_formatters={ # Eth 'eth_call': apply_formatter_at_index(transaction_params_formatter, 0), 'eth_getBalance': apply_formatter_at_index(block_number_formatter, 1), 'eth_getBlockByHash': format_abi_parameters(['bytes32', 'bool']), 'eth_getBlockByNumber': apply_formatter_at_index(block_number_formatter, 0), 'eth_getBlockTransactionCountByNumber': apply_formatter_at_index(