def __init__(self, event_abi, formatter=None): self.event_abi = event_abi self.formatter = formatter self.event_topic = initialize_event_topics(self.event_abi) self.args = AttributeDict( _build_argument_filters_from_event_abi(event_abi)) self._ordered_arg_names = tuple(arg['name'] for arg in event_abi['inputs'])
def test_attributedict_dict_in_list_in_dict(): data = {'instructions': [ 0, 1, 'neither shalt thou count, excepting that thou then proceedeth to three', {'if_naughty': 'snuff it'}, 'shalt thou not count', 'right out', ]} attrdict = AttributeDict.recursive(data) assert attrdict.instructions[3].if_naughty == 'snuff it'
def middleware(method, params): response = make_request(method, params) if 'result' in response: result = response['result'] if is_dict(result) and not isinstance(result, AttributeDict): return assoc(response, 'result', AttributeDict.recursive(result)) else: return response else: return response
class EventFilterBuilder: formatter = None _fromBlock = None _toBlock = None _address = None _immutable = False def __init__(self, event_abi, formatter=None): self.event_abi = event_abi self.formatter = formatter self.event_topic = initialize_event_topics(self.event_abi) self.args = AttributeDict( _build_argument_filters_from_event_abi(event_abi)) self._ordered_arg_names = tuple(arg['name'] for arg in event_abi['inputs']) @property def fromBlock(self): return self._fromBlock @fromBlock.setter def fromBlock(self, value): if self._fromBlock is None and not self._immutable: self._fromBlock = value else: raise ValueError( "fromBlock is already set to {0}. " "Resetting filter parameters is not permitted".format( self._fromBlock)) @property def toBlock(self): return self._toBlock @toBlock.setter def toBlock(self, value): if self._toBlock is None and not self._immutable: self._toBlock = value else: raise ValueError( "toBlock is already set to {0}. " "Resetting filter parameters is not permitted".format( self._toBlock)) @property def address(self): return self._address @address.setter def address(self, value): if self._address is None and not self._immutable: self._address = value else: raise ValueError( "address is already set to {0}. " "Resetting filter parameters is not permitted".format( self.address)) @property def ordered_args(self): return tuple(map(self.args.__getitem__, self._ordered_arg_names)) @property @to_tuple def indexed_args(self): return tuple(filter(is_indexed, self.ordered_args)) @property @to_tuple def data_args(self): return tuple(filter(is_not_indexed, self.ordered_args)) @property def topics(self): arg_topics = tuple(arg.match_values for arg in self.indexed_args) return normalize_topic_list(cons(to_hex(self.event_topic), arg_topics)) @property def data_argument_values(self): if self.data_args is not None: return tuple(arg.match_values for arg in self.data_args) else: return (None, ) @property def filter_params(self): params = { "topics": self.topics, "fromBlock": self.fromBlock, "toBlock": self.toBlock, "address": self.address } return valfilter(lambda x: x is not None, params) def deploy(self, w3): if not isinstance(w3, web3.Web3): raise ValueError("Invalid web3 argument: got: {0}".format( repr(w3))) for arg in self.args.values(): arg._immutable = True self._immutable = True log_filter = w3.eth.filter(self.filter_params) log_filter.filter_params = self.filter_params log_filter.set_data_filters(self.data_argument_values) log_filter.builder = self if self.formatter is not None: log_filter.log_entry_formatter = self.formatter return log_filter
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 stub_block(timestamp): return AttributeDict({ 'timestamp': timestamp, 'number': 123, })
('0x0', '0x0'), ('0x1', '0x1'), ('0x0001', '0x0001'), ('0x10', '0x10'), ('0xF', '0xf'), ('F', '0xf'), ), ) def test_to_hex_cleanup_only(val, expected): assert Web3.toHex(hexstr=val) == expected @pytest.mark.parametrize( 'val, expected', ( (AttributeDict({'one': HexBytes('0x1')}), '{"one": "0x01"}'), (AttributeDict({'two': HexBytes(2)}), '{"two": "0x02"}'), (AttributeDict({'three': AttributeDict({'four': 4}) }), '{"three": {"four": 4}}'), ({ 'three': 3 }, '{"three": 3}'), ), ) def test_to_json(val, expected): assert Web3.toJSON(val) == expected @pytest.mark.parametrize( 'tx, expected', (
def test_attributedict_recursive_dict(): w = AttributeDict.recursive({'x': {'y': {'z': 8}}}) assert w.x.y.z == 8
def test_attributedict_sequence_with_dict(sequence): data = sequence(['a', {'found': True}, 'c']) dict_in_sequence = AttributeDict.recursive(data) assert dict_in_sequence[1].found is True
def test_attributedict_equality(dict1, dict2): assert AttributeDict(dict1) == dict2 assert AttributeDict(dict1) == AttributeDict(dict2) assert dict1 == AttributeDict(dict2)
def test_attributedict_inequality(dict1, dict2): assert AttributeDict(dict1) != dict2 assert AttributeDict(dict1) != AttributeDict(dict2) assert dict1 != AttributeDict(dict2)
def test_attributedict_delitem_invalid(): container = AttributeDict({'a': 1}) with pytest.raises(TypeError): del container['a'] assert container['a'] == 1
def test_attributedict_setattr_invalid(): container = AttributeDict({'a': 1}) with pytest.raises(TypeError): container.a = 0 assert container.a == 1
def test_attributedict_repr(): dict1 = AttributeDict({'a': 1}) dict2 = eval(repr(dict1)) assert dict1 == dict2
def test_attributedict_access(): container = AttributeDict({'a': 1}) assert container.a == 1
def test_attributedict_set_in_recursive_dict(): data = {'mydict': {'myset': {'found'}}} attrdict = AttributeDict.recursive(data) assert 'found' in attrdict.mydict.myset