Beispiel #1
0
def get_filter_args_for_specific_event_from_channel(
    token_network_address: Address,
    channel_identifier: ChannelID,
    event_name: str,
    from_block: BlockSpecification = 0,
    to_block: BlockSpecification = 'latest',
):
    """ Return the filter params for a specific event of a given channel. """
    if not event_name:
        raise ValueError('Event name must be given')

    contract_manager = ContractManager(CONTRACTS_PRECOMPILED_PATH)
    event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK,
                                               event_name)

    # Here the topics for a specific event are created
    # The first entry of the topics list is the event name, then the first parameter is encoded,
    # in the case of a token network, the first parameter is always the channel identifier
    _, event_filter_params = construct_event_filter_params(
        event_abi=event_abi,
        contract_address=to_checksum_address(token_network_address),
        argument_filters={
            'channel_identifier': channel_identifier,
        },
        fromBlock=from_block,
        toBlock=to_block,
    )

    return event_filter_params
Beispiel #2
0
    def get_logs(self,
                 event_name,
                 from_block=0,
                 to_block='latest',
                 filters=None):
        filter_kwargs = {
            'fromBlock': from_block,
            'toBlock': to_block,
            'address': self.contract_addr
        }
        event_abi = [
            i for i in self.auction_contract.abi
            if i['type'] == 'event' and i['name'] == event_name
        ][0]
        assert event_abi
        filters = filters if filters else {}
        filter_ = construct_event_filter_params(event_abi,
                                                argument_filters=filters,
                                                **filter_kwargs)[1]
        filter_params = input_filter_params_formatter(filter_)
        response = self.chain.web3._requestManager.request_blocking(
            'eth_getLogs', [filter_params])

        logs = log_array_formatter(response)
        logs = [dict(log) for log in logs]
        for log in logs:
            log['args'] = get_event_data(event_abi, log)['args']
        return logs
Beispiel #3
0
def create_event_filter(
        web3: Web3,
        event_name: str,
        event_abi: Dict,
        filter_params: Dict = {}
) -> LogFilter:
    """Create filter object that tracks events emitted.

    Args:
        web3: A web3 client
        event_name: The name of the event to track
        event_abi: The ABI of the event to track
        filter_params: Other parameters to limit the events

    Returns:
        A LogFilter instance"""
    filter_meta_params = dict(filter_params)

    data_filter_set, event_filter_params = construct_event_filter_params(
        event_abi,
        **filter_meta_params
    )

    log_data_extract_fn = functools.partial(get_event_data, event_abi)

    log_filter = web3.eth.filter(event_filter_params)

    log_filter.set_data_filters(data_filter_set)
    log_filter.log_entry_formatter = log_data_extract_fn
    log_filter.filter_params = event_filter_params

    return log_filter
Beispiel #4
0
def get_logs(
        contract: Contract,
        event_name: str,
        from_block: Union[int, str] = 0,
        to_block: Union[int, str] = 'pending',
        argument_filters: Dict[str, Any] = None
):
    event_abi = [
        abi_element for abi_element in contract.abi
        if abi_element['type'] == 'event' and abi_element['name'] == event_name
    ]
    assert len(event_abi) == 1, 'No event found matching name {}.'.format(event_name)
    event_abi = event_abi[0]

    if argument_filters is None:
        argument_filters = {}

    filter_params = input_filter_params_formatter(construct_event_filter_params(
        event_abi,
        argument_filters=argument_filters,
        address=contract.address,
        fromBlock=from_block,
        toBlock=to_block
    )[1])

    response = _get_logs_raw(contract, filter_params)

    logs = log_array_formatter(response)
    logs = [dict(log) for log in logs]
    for log in logs:
        log['args'] = get_event_data(event_abi, log)['args']
    return logs
Beispiel #5
0
    def __init__(self,
                 web3,
                 abi,
                 address,
                 event_name,
                 from_block=0,
                 to_block='latest',
                 filters=None,
                 callback=None):
        self.web3 = web3
        filter_kwargs = {
            'fromBlock': from_block,
            'toBlock': to_block,
            'address': address
        }
        self.event_abi = [
            i for i in abi if i['type'] == 'event' and i['name'] == event_name
        ][0]
        assert self.event_abi
        filters = filters if filters else {}
        self.filter = construct_event_filter_params(self.event_abi,
                                                    argument_filters=filters,
                                                    **filter_kwargs)[1]
        filter_params = input_filter_params_formatter(self.filter)

        self.filter = web3.eth.filter(filter_params)

        for log in self.get_logs():
            callback(log)

        self.watch_logs(callback)
Beispiel #6
0
def get_filter_args_for_channel_from_token_network(
    token_network_address: Address,
    channel_identifier: ChannelID,
    from_block: BlockSpecification = 0,
    to_block: BlockSpecification = 'latest',
) -> Dict:
    event_abi = CONTRACT_MANAGER.get_event_abi(CONTRACT_TOKEN_NETWORK,
                                               EVENT_CHANNEL_OPENED)

    # Here the topics for a specific event are created
    # The first entry of the topics list is the event name, then the first parameter is encoded,
    # in the case of a token network, the first parameter is always the channel identifier
    data_filter_set, event_filter_params = construct_event_filter_params(
        event_abi=event_abi,
        contract_address=to_checksum_address(token_network_address),
        argument_filters={
            'channel_identifier': channel_identifier,
        },
        fromBlock=from_block,
        toBlock=to_block,
    )

    # As we want to get all events for a certain channel we remove the event specific code here
    # and filter just for the channel identifier
    # We also have to remove the trailing topics to get all filters
    event_filter_params['topics'] = [None, event_filter_params['topics'][1]]

    return event_filter_params
Beispiel #7
0
    def on(self, event_name, filter_params=None, *callbacks):
        """
        register a callback to be triggered on the appropriate events.
        """
        if filter_params is None:
            filter_params = {}

        argument_filters = filter_params.pop('filter', {})
        argument_filter_names = list(argument_filters.keys())
        event_abi = self._find_matching_event_abi(
            event_name,
            argument_filter_names,
        )

        data_filter_set, event_filter_params = construct_event_filter_params(
            event_abi,
            contract_address=self.address,
            argument_filters=argument_filters,
            **filter_params
        )

        log_data_extract_fn = functools.partial(get_event_data, event_abi)

        log_filter = self.web3.eth.filter(event_filter_params)

        log_filter.set_data_filters(data_filter_set)
        log_filter.log_entry_formatter = log_data_extract_fn
        log_filter.filter_params = event_filter_params

        if callbacks:
            log_filter.watch(*callbacks)

        return log_filter
Beispiel #8
0
    def __init__(self,
        web3,
        abi,
        address,
        event_name,
        from_block=0,
        to_block='latest',
        filters=None,
        callback=None):
        self.web3 = web3
        self.event_name = event_name

        # Callback for every registered log
        self.callback = callback

        filter_kwargs = {
            'fromBlock': from_block,
            'toBlock': to_block,
            'address': address
        }

        event_abi = [i for i in abi if i['type'] == 'event' and i['name'] == event_name]
        if len(event_abi) == 0:
            return None

        self.event_abi = event_abi[0]
        assert self.event_abi

        filters = filters if filters else {}
        self.filter = construct_event_filter_params(
            self.event_abi,
            argument_filters=filters,
            **filter_kwargs)[1]
        filter_params = input_filter_params_formatter(self.filter)
        self.filter = web3.eth.filter(filter_params)
Beispiel #9
0
def get_filter_args_for_specific_event_from_channel(
        token_network_address: TokenNetworkAddress,
        channel_identifier: ChannelID,
        event_name: str,
        contract_manager: ContractManager,
        from_block: BlockSpecification = GENESIS_BLOCK_NUMBER,
        to_block: BlockSpecification = 'latest',
):
    """ Return the filter params for a specific event of a given channel. """
    if not event_name:
        raise ValueError('Event name must be given')

    event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK, event_name)

    # Here the topics for a specific event are created
    # The first entry of the topics list is the event name, then the first parameter is encoded,
    # in the case of a token network, the first parameter is always the channel identifier
    _, event_filter_params = construct_event_filter_params(
        event_abi=event_abi,
        contract_address=to_checksum_address(token_network_address),
        argument_filters={
            'channel_identifier': channel_identifier,
        },
        fromBlock=from_block,
        toBlock=to_block,
    )

    return event_filter_params
Beispiel #10
0
    def on(self, event_name, filter_params=None, *callbacks):
        """
        Register a callback to be triggered on the appropriate events.
        """
        if filter_params is None:
            filter_params = {}

        argument_filters = filter_params.pop('filter', {})
        argument_filter_names = list(argument_filters.keys())
        event_abi = self._find_matching_event_abi(
            event_name,
            argument_filter_names,
        )

        data_filter_set, event_filter_params = construct_event_filter_params(
            event_abi,
            contract_address=self.address,
            argument_filters=argument_filters,
            **filter_params)

        log_data_extract_fn = functools.partial(get_event_data, event_abi)

        log_filter = self.web3.eth.filter(event_filter_params)

        log_filter.set_data_filters(data_filter_set)
        log_filter.log_entry_formatter = log_data_extract_fn
        log_filter.filter_params = event_filter_params

        if callbacks:
            log_filter.watch(*callbacks)

        return log_filter
Beispiel #11
0
def get_filter_args_for_specific_event_from_channel(
    token_network_address: TokenNetworkAddress,
    channel_identifier: ChannelID,
    event_name: str,
    contract_manager: ContractManager,
    from_block: BlockSpecification = GENESIS_BLOCK_NUMBER,
    to_block: BlockSpecification = "latest",
):
    """ Return the filter params for a specific event of a given channel. """
    if not event_name:
        raise ValueError("Event name must be given")

    event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK,
                                               event_name)

    # Here the topics for a specific event are created
    # The first entry of the topics list is the event name, then the first parameter is encoded,
    # in the case of a token network, the first parameter is always the channel identifier
    _, event_filter_params = construct_event_filter_params(
        event_abi=event_abi,
        contract_address=to_checksum_address(token_network_address),
        argument_filters={"channel_identifier": channel_identifier},
        fromBlock=from_block,
        toBlock=to_block,
    )

    return event_filter_params
Beispiel #12
0
    def eventFilter(self, event_name, filter_params={}):
        """
        Create filter object that tracks events emitted by this contract.
        :param event_name: the name of the event to track
        :param filter_params: other parameters to limit the events
        """
        filter_meta_params = dict(filter_params)
        argument_filters = filter_meta_params.pop('filter', {})

        argument_filter_names = list(argument_filters.keys())
        event_abi = self._find_matching_event_abi(
            event_name,
            argument_filter_names,
        )

        data_filter_set, event_filter_params = construct_event_filter_params(
            event_abi,
            contract_address=self.address,
            argument_filters=argument_filters,
            **filter_meta_params
        )

        log_data_extract_fn = functools.partial(get_event_data, event_abi)

        log_filter = self.web3.eth.filter(event_filter_params)

        log_filter.set_data_filters(data_filter_set)
        log_filter.log_entry_formatter = log_data_extract_fn
        log_filter.filter_params = event_filter_params

        return log_filter
Beispiel #13
0
    def eventFilter(self, event_name, filter_params={}):
        """
        Create filter object that tracks events emitted by this contract.
        :param event_name: the name of the event to track
        :param filter_params: other parameters to limit the events
        """
        filter_meta_params = dict(filter_params)
        argument_filters = filter_meta_params.pop('filter', {})

        argument_filter_names = list(argument_filters.keys())
        event_abi = self._find_matching_event_abi(
            event_name,
            argument_filter_names,
        )

        data_filter_set, event_filter_params = construct_event_filter_params(
            event_abi,
            contract_address=self.address,
            argument_filters=argument_filters,
            **filter_meta_params)

        log_data_extract_fn = functools.partial(get_event_data, event_abi)

        log_filter = self.web3.eth.filter(event_filter_params)

        log_filter.set_data_filters(data_filter_set)
        log_filter.log_entry_formatter = log_data_extract_fn
        log_filter.filter_params = event_filter_params

        return log_filter
Beispiel #14
0
def make_filter(web3, event_abi, filters={}, **filter_kwargs):
    assert event_abi != []
    log_data_extract_fn = functools.partial(get_event_data, event_abi)
    data_filter_set, filter_params = construct_event_filter_params(
        event_abi, argument_filters=filters, **filter_kwargs)

    event_filter = web3.eth.filter(filter_params)
    event_filter.log_entry_formatter = log_data_extract_fn
    event_filter.set_data_filters(data_filter_set)
    event_filter.filter_params = filter_params
    return event_filter
Beispiel #15
0
def getLogs(self,
            argument_filters=None,
            fromBlock=None,
            toBlock="latest",
            address=None,
            topics=None):
    """Get events using eth_getLogs API.

    This is a stateless method, as opposite to createFilter.
    It can be safely called against nodes which do not provide eth_newFilter API, like Infura.

    :param argument_filters:
    :param fromBlock:
    :param toBlock:
    :param address:
    :param topics:
    :return:
    """

    if fromBlock is None:
        raise TypeError(
            "Missing mandatory keyword argument to getLogs: fromBlock")

    abi = self._get_event_abi()

    argument_filters = dict()

    _filters = dict(**argument_filters)

    # Construct JSON-RPC raw filter presentation based on human readable Python descriptions
    # Namely, convert event names to their keccak signatures
    data_filter_set, event_filter_params = construct_event_filter_params(
        abi,
        abi_codec=self.web3.codec,
        contract_address=self.address,
        argument_filters=_filters,
        fromBlock=fromBlock,
        toBlock=toBlock,
        address=address,
        topics=topics,
    )

    # Call JSON-RPC API
    logs = self.web3.eth.getLogs(event_filter_params)

    # Convert raw binary data to Python proxy objects as described by ABI
    for entry in logs:
        yield get_event_data(self.web3.codec, abi, entry)
Beispiel #16
0
def get_event_logs(
    web3: Web3, contract_abi: Dict, event_name: str, from_block: int = 0, to_block: int = None
):
    """Helper function to get all event logs in a given range"""
    abi = find_matching_event_abi(contract_abi, event_name)
    log_data_extract_fn = functools.partial(get_event_data, abi)
    data_filter_set, filter_params = construct_event_filter_params(
        abi, argument_filters=None, fromBlock=from_block, toBlock=to_block
    )

    event_filter = web3.eth.filter(filter_params)
    event_filter.log_entry_formatter = log_data_extract_fn
    event_filter.set_data_filters(data_filter_set)
    event_filter.filter_params = filter_params
    entries = event_filter.get_all_entries()
    web3.eth.uninstallFilter(event_filter.filter_id)
    return entries
Beispiel #17
0
    def createFilter(
            self,
            *,  # PEP 3102
            argument_filters=None,
            fromBlock=None,
            toBlock="latest",
            address=None,
            topics=None):
        """
        Create filter object that tracks logs emitted by this contract event.
        :param filter_params: other parameters to limit the events
        """
        if fromBlock is None:
            raise TypeError(
                "Missing mandatory keyword argument to createFilter: fromBlock"
            )

        if argument_filters is None:
            argument_filters = dict()

        if not address:
            address = self.address

        _filters = dict(**argument_filters)

        data_filter_set, event_filter_params = construct_event_filter_params(
            self._get_event_abi(),
            contract_address=self.address,
            argument_filters=_filters,
            fromBlock=fromBlock,
            toBlock=toBlock,
            address=address,
            topics=topics,
        )

        log_data_extract_fn = functools.partial(get_event_data,
                                                self._get_event_abi())

        log_filter = self.web3.eth.filter(event_filter_params)

        log_filter.set_data_filters(data_filter_set)
        log_filter.log_entry_formatter = log_data_extract_fn
        log_filter.filter_params = event_filter_params

        return log_filter
 def get_logs(  # pylint: disable=too-many-arguments
         self, contract, event_name: str, args, from_block: Union[int, str],
         to_block: Union[int, str]):
     event_abi = list(
         filter(
             lambda e: e['type'] == 'event' and e['name'] == event_name,
             contract.abi,
         ))[0]
     for name in args:
         assert any(name == event['name'] for event in event_abi['inputs'])
     _, filter_args = construct_event_filter_params(
         event_abi,
         contract_address=contract.address,
         argument_filters=args,
         fromBlock=from_block,
         toBlock=to_block,
     )
     return self.web3.eth.getLogs(filter_args)
Beispiel #19
0
    def __init__(
        self,
        web3: Web3,
        abi: List[Any],
        address: HexAddress,
        event_name: str,
        from_block: int = 0,
        to_block: Union[int, str] = "latest",
        filters: Any = None,
        callback: Optional[Callable[..., Any]] = None,
    ):
        self.web3 = web3
        self.event_name = event_name

        # Callback for every registered log
        self.callback = callback

        filter_kwargs = {
            "fromBlock": from_block,
            "toBlock": to_block,
            "address": address
        }

        event_abi = [
            i for i in abi if i["type"] == "event" and i["name"] == event_name
        ]
        if len(event_abi) == 0:
            raise ValueError(f"Event of name {event_name} not found")

        self.event_abi = event_abi[0]
        assert self.event_abi

        filters = filters if filters else {}

        data_filter_set, filter_params = construct_event_filter_params(
            event_abi=self.event_abi,
            argument_filters=filters,
            **filter_kwargs)
        log_data_extract_fn = functools.partial(get_event_data, event_abi)

        self.filter = web3.eth.filter(filter_params)
        self.filter.set_data_filters(data_filter_set)
        self.filter.log_entry_formatter = log_data_extract_fn
        self.filter.filter_params = filter_params
    async def get_new_entries_from_logs(
            self, event_name: str,
            block_hashes: List[HexBytes]) -> List[AttributeDict]:
        event_abi: Dict[str, any] = self._event_abi_map.get(event_name, None)
        if event_abi is None:
            event_abi = find_matching_event_abi(self._contract_abi,
                                                event_name=event_name)
            self._event_abi_map[event_name] = event_abi

        _, event_filter_params = construct_event_filter_params(
            event_abi, contract_address=self._address)
        tasks = []
        for block_hash in block_hashes:
            event_filter_params["blockHash"] = block_hash.hex()
            tasks.append(self._get_logs(event_filter_params))

        raw_logs = await asyncio.gather(*tasks, return_exceptions=True)
        logs: List[any] = list(cytoolz.concat(raw_logs))
        new_entries = []
        for log in logs:
            event_data: AttributeDict = get_event_data(event_abi, log)
            event_data_block_number: int = event_data["blockNumber"]
            event_data_tx_hash: HexBytes = event_data["transactionHash"]
            if event_data_tx_hash not in self._event_cache:
                if event_data_block_number not in self._block_events:
                    self._block_events[event_data_block_number] = [
                        event_data_tx_hash
                    ]
                else:
                    self._block_events[event_data_block_number].append(
                        event_data_tx_hash)
                self._event_cache.add(event_data_tx_hash)
                new_entries.append(event_data)
            else:
                self.logger().debug(
                    f"Duplicate event transaction hash found - '{event_data_tx_hash.hex()}'."
                )

        while len(self._block_events) > self._block_events_window_size:
            tx_hashes: List[HexBytes] = self._block_events.popitem(
                last=False)[1]
            for tx_hash in tx_hashes:
                self._event_cache.remove(tx_hash)
        return new_entries
Beispiel #21
0
    def __init__(self,
                 web3,
                 abi,
                 address,
                 event_name,
                 from_block=0,
                 to_block='latest',
                 filters=None,
                 callback=None):
        self.web3 = web3
        self.event_name = event_name

        # Callback for every registered log
        self.callback = callback

        filter_kwargs = {
            'fromBlock': from_block,
            'toBlock': to_block,
            'address': address,
        }

        event_abi = [
            i for i in abi if i['type'] == 'event' and i['name'] == event_name
        ]
        if len(event_abi) == 0:
            return None

        self.event_abi = event_abi[0]
        assert self.event_abi

        filters = filters if filters else {}

        data_filter_set, filter_params = construct_event_filter_params(
            self.event_abi,
            argument_filters=filters,
            **filter_kwargs,
        )
        log_data_extract_fn = functools.partial(get_event_data, event_abi)

        self.filter = web3.eth.filter(filter_params)
        self.filter.set_data_filters(data_filter_set)
        self.filter.log_entry_formatter = log_data_extract_fn
        self.filter.filter_params = filter_params
        def decorator(handler_func):
            event_abi = self.contract._find_matching_event_abi(event_name, {})
            _, event_filter_params = construct_event_filter_params(
                event_abi, contract_address=self.contract.address)

            if iscoroutinefunction(handler_func):

                async def decorated(payload):
                    event_data = get_event_data(event_abi, payload)
                    return await handler_func(event_name, event_data)
            else:

                def decorated(payload):
                    event_data = get_event_data(event_abi, payload)
                    return handler_func(event_name, event_data)

            self.topic_filters.append(event_filter_params)
            self.handlers[event_filter_params["topics"][0]] = decorated

            return decorated
Beispiel #23
0
    def __init__(self,
                 web3,
                 abi,
                 address,
                 event_name,
                 from_block=0,
                 to_block='latest',
                 filters=None,
                 callback=None):
        self.web3 = web3
        self.event_name = event_name

        # Callback for every registered log
        self.callback = callback

        filter_kwargs = {
            'fromBlock': from_block,
            'toBlock': to_block,
            'address': address
        }

        event_abi = [i for i in abi if i['type'] == 'event' and i['name'] == event_name]
        if len(event_abi) == 0:
            return None

        self.event_abi = event_abi[0]
        assert self.event_abi

        filters = filters if filters else {}

        data_filter_set, filter_params = construct_event_filter_params(
            self.event_abi,
            argument_filters=filters,
            **filter_kwargs
        )
        log_data_extract_fn = functools.partial(get_event_data, event_abi)

        self.filter = web3.eth.filter(filter_params)
        self.filter.set_data_filters(data_filter_set)
        self.filter.log_entry_formatter = log_data_extract_fn
        self.filter.filter_params = filter_params
def test_construct_event_filter_params_for_data_filters(event_abi, fn_kwargs,
                                                        expected):
    actual, _ = construct_event_filter_params(event_abi, **fn_kwargs)
    assert actual == expected
def test_construct_event_filter_params(event_abi, fn_kwargs, expected):
    _, actual = construct_event_filter_params(event_abi, **fn_kwargs)
    assert actual == expected
Beispiel #26
0
    def getLogs(
        self,
        event,
        web3,
        argument_filters: Optional[Dict[str, Any]] = None,
        fromBlock: Optional[BlockIdentifier] = None,
        toBlock: Optional[BlockIdentifier] = None,
        blockHash: Optional[HexBytes] = None,
    ):
        """Get events for this contract instance using eth_getLogs API.

        This is a stateless method, as opposed to createFilter.
        It can be safely called against nodes which do not provide
        eth_newFilter API, like Infura nodes.
        If there are many events,
        like ``Transfer`` events for a popular token,
        the Ethereum node might be overloaded and timeout
        on the underlying JSON-RPC call.
        Example - how to get all ERC-20 token transactions
        for the latest 10 blocks:
        .. code-block:: python
            from = max(mycontract.web3.eth.blockNumber - 10, 1)
            to = mycontract.web3.eth.blockNumber
            events = mycontract.events.Transfer.getLogs(fromBlock=from, toBlock=to)
            for e in events:
                print(e["args"]["from"],
                    e["args"]["to"],
                    e["args"]["value"])
        The returned processed log values will look like:
        .. code-block:: python
            (
                AttributeDict({
                 'args': AttributeDict({}),
                 'event': 'LogNoArguments',
                 'logIndex': 0,
                 'transactionIndex': 0,
                 'transactionHash': HexBytes('...'),
                 'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
                 'blockHash': HexBytes('...'),
                 'blockNumber': 3
                }),
                AttributeDict(...),
                ...
            )
        See also: :func:`web3.middleware.filter.local_filter_middleware`.
        :param argument_filters:
        :param fromBlock: block number or "latest", defaults to "latest"
        :param toBlock: block number or "latest". Defaults to "latest"
        :param blockHash: block hash. blockHash cannot be set at the
          same time as fromBlock or toBlock
        :yield: Tuple of :class:`AttributeDict` instances
        """
        if not self.address:
            raise TypeError(
                "This method can be only called on "
                "an instated contract with an address"
            )

        abi = event._get_event_abi()

        if argument_filters is None:
            argument_filters = dict()

        _filters = dict(**argument_filters)

        blkhash_set = blockHash is not None
        blknum_set = fromBlock is not None or toBlock is not None
        if blkhash_set and blknum_set:
            raise ValidationError(
                "blockHash cannot be set at the same" " time as fromBlock or toBlock"
            )

        # Construct JSON-RPC raw filter presentation based on human readable Python descriptions
        # Namely, convert event names to their keccak signatures
        _, event_filter_params = construct_event_filter_params(
            abi,
            contract_address=self.address,
            argument_filters=_filters,
            fromBlock=fromBlock,
            toBlock=toBlock,
        )

        if blockHash is not None:
            event_filter_params["blockHash"] = blockHash

        # Call JSON-RPC API
        logs = web3.eth.getLogs(event_filter_params)

        # Convert raw binary data to Python proxy objects as described by ABI
        return tuple(get_event_data(abi, entry) for entry in logs)
def test_construct_event_filter_params_for_data_filters(
        event_abi, fn_kwargs, expected):
    actual, _ = construct_event_filter_params(event_abi, **fn_kwargs)
    assert actual == expected
def test_construct_event_filter_params(event_abi, fn_kwargs, expected):
    _, actual = construct_event_filter_params(event_abi, **fn_kwargs)
    assert actual == expected