def test_hexstr_if_str_on_invalid_hex(val): try: is_hexstr = (is_hex(val) or val == '') except ValueError: is_hexstr = False if not is_hexstr: with pytest.raises(ValueError): hexstr_if_str(Mock(), val)
def abi_int_to_hex( abi_type: BasicType, type_str: TypeStr, data: Any ) -> Optional[Tuple[TypeStr, HexStr]]: if abi_type.base == 'uint' and not abi_type.is_array: # double check? return type_str, hexstr_if_str(to_hex, data) return None
def decode_event_data(data: str, event_abi: Dict[str, Any]) -> Tuple: """Decode the data of an event according to the event's abi entry""" log_data = hexstr_if_str(to_bytes, data) log_data_abi = exclude_indexed_event_inputs(event_abi) # type: ignore log_data_normalized_inputs = normalize_event_input_types(log_data_abi) log_data_types = get_event_abi_types_for_decoding(log_data_normalized_inputs) decoded_log_data = ABI_CODEC.decode_abi(log_data_types, log_data) return decoded_log_data
def abi_bytes_to_hex(abi_type, type_str, data): if abi_type.base != 'bytes' or abi_type.is_array: return bytes_data = hexstr_if_str(to_bytes, data) if abi_type.sub is None: return type_str, to_hex(bytes_data) num_bytes = abi_type.sub if len(bytes_data) > num_bytes: raise ValueError( "This value was expected to be at most %d bytes, but instead was %d: %r" % ((num_bytes, len(bytes_data), data))) padded = bytes_data.ljust(num_bytes, b'\0') return type_str, to_hex(padded)
def abi_bytes_to_hex(abi_type: BasicType, type_str: TypeStr, data: Any) -> Optional[Tuple[TypeStr, HexStr]]: if abi_type.base != 'bytes' or abi_type.is_array: return None bytes_data = hexstr_if_str(to_bytes, data) if abi_type.sub is None: return type_str, to_hex(bytes_data) num_bytes = abi_type.sub if len(bytes_data) > num_bytes: raise ValueError( f"This value was expected to be at most {num_bytes} bytes, " f"but instead was {len(bytes_data)}: {data!r}") padded = bytes_data.ljust(num_bytes, b'\0') return type_str, to_hex(padded)
def abi_bytes_to_hex(abi_type, data): base, sub, arrlist = process_type(abi_type) if base == 'bytes' and not arrlist: bytes_data = hexstr_if_str(to_bytes, data) if not sub: return abi_type, to_hex(bytes_data) else: num_bytes = int(sub) if len(bytes_data) <= num_bytes: padded = bytes_data.ljust(num_bytes, b'\0') return abi_type, to_hex(padded) else: raise ValueError( "This value was expected to be at most %d bytes, but instead was %d: %r" % ( (num_bytes, len(bytes_data), data) ) )
def abi_bytes_to_bytes(abi_type, type_str, data): if abi_type.base == 'bytes' and not abi_type.is_array: return type_str, hexstr_if_str(to_bytes, data)
def abi_int_to_hex(abi_type, type_str, data): if abi_type.base == 'uint' and not abi_type.is_array: return abi_type, hexstr_if_str(to_hex, data)
def test_hexstr_if_str_on_valid_hex(val): to_type = Mock(return_value='zoot') assert hexstr_if_str(to_type, val) == 'zoot' assert to_type.call_args == ((None, ), {'hexstr': val})
def test_hexstr_if_str_curried(): converter = hexstr_if_str(to_hex) assert converter(255) == '0xff'
def test_hexstr_if_str_passthrough(val): to_type = Mock(return_value='zoot') assert hexstr_if_str(to_type, val) == 'zoot' assert to_type.call_args == ((val, ), {'hexstr': None})
def abi_int_to_hex(abi_type, data): base, _sub, arrlist = process_type(abi_type) if base == 'uint' and not arrlist: return abi_type, hexstr_if_str(to_hex, data)
def get_event_data(event_abi, log_entry): """ Given an event ABI and a log entry for that event, return the decoded event data """ if event_abi['anonymous']: log_topics = log_entry['topics'] elif not log_entry['topics']: raise MismatchedABI("Expected non-anonymous event to have 1 or more topics") elif event_abi_to_log_topic(event_abi) != log_entry['topics'][0]: raise MismatchedABI("The event signature did not match the provided ABI") else: log_topics = log_entry['topics'][1:] log_topics_abi = get_indexed_event_inputs(event_abi) log_topic_normalized_inputs = normalize_event_input_types(log_topics_abi) log_topic_types = get_event_abi_types_for_decoding(log_topic_normalized_inputs) log_topic_names = get_abi_input_names({'inputs': log_topics_abi}) if len(log_topics) != len(log_topic_types): raise ValueError("Expected {0} log topics. Got {1}".format( len(log_topic_types), len(log_topics), )) log_data = hexstr_if_str(to_bytes, log_entry['data']) log_data_abi = exclude_indexed_event_inputs(event_abi) log_data_normalized_inputs = normalize_event_input_types(log_data_abi) log_data_types = get_event_abi_types_for_decoding(log_data_normalized_inputs) log_data_names = get_abi_input_names({'inputs': log_data_abi}) # sanity check that there are not name intersections between the topic # names and the data argument names. duplicate_names = set(log_topic_names).intersection(log_data_names) if duplicate_names: raise ValueError( "Invalid Event ABI: The following argument names are duplicated " "between event inputs: '{0}'".format(', '.join(duplicate_names)) ) decoded_log_data = decode_abi(log_data_types, log_data) normalized_log_data = map_abi_data( BASE_RETURN_NORMALIZERS, log_data_types, decoded_log_data ) decoded_topic_data = [ decode_single(topic_type, topic_data) for topic_type, topic_data in zip(log_topic_types, log_topics) ] normalized_topic_data = map_abi_data( BASE_RETURN_NORMALIZERS, log_topic_types, decoded_topic_data ) event_args = dict(itertools.chain( zip(log_topic_names, normalized_topic_data), zip(log_data_names, normalized_log_data), )) event_data = { 'args': event_args, 'event': event_abi['name'], 'logIndex': log_entry['logIndex'], 'transactionIndex': log_entry['transactionIndex'], 'transactionHash': log_entry['transactionHash'], 'address': log_entry['address'], 'blockHash': log_entry['blockHash'], 'blockNumber': log_entry['blockNumber'], } return AttributeDict.recursive(event_data)
def abi_bytes_to_bytes(abi_type: BasicType, type_str: TypeStr, data: Any) -> Optional[Tuple[TypeStr, HexStr]]: if abi_type.base == 'bytes' and not abi_type.is_array: return type_str, hexstr_if_str(to_bytes, data) return None
def abi_bytes_to_bytes(abi_type, data): base, sub, arrlist = process_type(abi_type) if base == 'bytes' and not arrlist: return abi_type, hexstr_if_str(to_bytes, data)
def get_event_data(abi_codec: ABICodec, event_abi: ABIEvent, log_entry: LogReceipt) -> EventData: """ Given an event ABI and a log entry for that event, return the decoded event data """ if event_abi['anonymous']: log_topics = log_entry['topics'] elif not log_entry['topics']: raise MismatchedABI("Expected non-anonymous event to have 1 or more topics") # type ignored b/c event_abi_to_log_topic(event_abi: Dict[str, Any]) elif event_abi_to_log_topic(event_abi) != log_entry['topics'][0]: # type: ignore raise MismatchedABI("The event signature did not match the provided ABI") else: log_topics = log_entry['topics'][1:] log_topics_abi = get_indexed_event_inputs(event_abi) log_topic_normalized_inputs = normalize_event_input_types(log_topics_abi) log_topic_types = get_event_abi_types_for_decoding(log_topic_normalized_inputs) log_topic_names = get_abi_input_names(ABIEvent({'inputs': log_topics_abi})) if len(log_topics) != len(log_topic_types): raise LogTopicError("Expected {0} log topics. Got {1}".format( len(log_topic_types), len(log_topics), )) log_data = hexstr_if_str(to_bytes, log_entry['data']) log_data_abi = exclude_indexed_event_inputs(event_abi) log_data_normalized_inputs = normalize_event_input_types(log_data_abi) log_data_types = get_event_abi_types_for_decoding(log_data_normalized_inputs) log_data_names = get_abi_input_names(ABIEvent({'inputs': log_data_abi})) # sanity check that there are not name intersections between the topic # names and the data argument names. duplicate_names = set(log_topic_names).intersection(log_data_names) if duplicate_names: raise InvalidEventABI( "The following argument names are duplicated " f"between event inputs: '{', '.join(duplicate_names)}'" ) decoded_log_data = abi_codec.decode_abi(log_data_types, log_data) normalized_log_data = map_abi_data( BASE_RETURN_NORMALIZERS, log_data_types, decoded_log_data ) decoded_topic_data = [ abi_codec.decode_single(topic_type, topic_data) for topic_type, topic_data in zip(log_topic_types, log_topics) ] normalized_topic_data = map_abi_data( BASE_RETURN_NORMALIZERS, log_topic_types, decoded_topic_data ) event_args = dict(itertools.chain( zip(log_topic_names, normalized_topic_data), zip(log_data_names, normalized_log_data), )) event_data = { 'args': event_args, 'event': event_abi['name'], 'logIndex': log_entry['logIndex'], 'transactionIndex': log_entry['transactionIndex'], 'transactionHash': log_entry['transactionHash'], 'address': log_entry['address'], 'blockHash': log_entry['blockHash'], 'blockNumber': log_entry['blockNumber'], } return cast(EventData, AttributeDict.recursive(event_data))
)), RPC.eth_estimateGas: apply_one_of_formatters(( (is_length(1), estimate_gas_without_block_id), (is_length(2), estimate_gas_with_block_id), )), RPC.eth_sendTransaction: apply_formatter_at_index(transaction_param_formatter, 0), RPC.eth_signTransaction: apply_formatter_at_index(transaction_param_formatter, 0), RPC.eth_getProof: apply_formatter_at_index(to_hex_if_integer, 2), # personal RPC.personal_importRawKey: apply_formatter_at_index( compose(remove_0x_prefix, hexstr_if_str(to_hex)), 0, ), RPC.personal_sign: apply_formatter_at_index(text_if_str(to_hex), 0), RPC.personal_ecRecover: apply_formatter_at_index(text_if_str(to_hex), 0), RPC.personal_sendTransaction: apply_formatter_at_index(transaction_param_formatter, 0), # Snapshot and Revert RPC.evm_revert: apply_formatter_at_index(integer_to_hex, 0), RPC.trace_replayBlockTransactions: apply_formatter_at_index(to_hex_if_integer, 0), RPC.trace_block: apply_formatter_at_index(to_hex_if_integer, 0),
), 'eth_getUncleByBlockHashAndIndex': apply_formatter_at_index(integer_to_hex, 1), 'eth_newFilter': apply_formatter_at_index(filter_params_formatter, 0), 'eth_getLogs': apply_formatter_at_index(filter_params_formatter, 0), 'eth_call': combine_argument_formatters( transaction_param_formatter, block_number_formatter, ), 'eth_estimateGas': apply_one_of_formatters(( (estimate_gas_without_block_id, is_length(1)), (estimate_gas_with_block_id, is_length(2)), )), 'eth_sendTransaction': apply_formatter_at_index(transaction_param_formatter, 0), # personal 'personal_importRawKey': apply_formatter_at_index( compose(remove_0x_prefix, hexstr_if_str(to_hex)), 0, ), 'personal_sign': apply_formatter_at_index(text_if_str(to_hex), 0), 'personal_ecRecover': apply_formatter_at_index(text_if_str(to_hex), 0), 'personal_sendTransaction': apply_formatter_at_index(transaction_param_formatter, 0), # Snapshot and Revert 'evm_revert': apply_formatter_at_index(integer_to_hex, 0), 'trace_replayBlockTransactions': apply_formatter_at_index(block_number_formatter, 0), 'trace_block': apply_formatter_at_index(block_number_formatter, 0), 'trace_call': compose( apply_formatter_at_index(transaction_param_formatter, 0), apply_formatter_at_index(block_number_formatter, 2) ), }, result_formatters={