Пример #1
0
def match_fn(codec: ABICodec, match_values_and_abi: Collection[Tuple[str,
                                                                     Any]],
             data: Any) -> bool:
    """Match function used for filtering non-indexed event arguments.

    Values provided through the match_values_and_abi parameter are
    compared to the abi decoded log data.
    """
    abi_types, all_match_values = zip(*match_values_and_abi)

    decoded_values = codec.decode_abi(abi_types, HexBytes(data))
    for data_value, match_values, abi_type in zip(decoded_values,
                                                  all_match_values, abi_types):
        if match_values is None:
            continue
        normalized_data = normalize_data_values(abi_type, data_value)
        for value in match_values:
            if not codec.is_encodable(abi_type, value):
                raise ValueError(f"Value {value} is of the wrong abi type. "
                                 f"Expected {abi_type} typed value.")
            if value == normalized_data:
                break
        else:
            return False

    return True
Пример #2
0
    def __init__(self, receipt):
        self.raw_receipt = receipt
        self.transaction_hash = receipt['transactionHash']
        self.gas_used = receipt['gasUsed']
        self.transfers = []
        self.result = None

        receipt_logs = receipt['logs']
        if (receipt_logs is not None) and (len(receipt_logs) > 0):
            self.successful = True
            for receipt_log in receipt_logs:
                if len(receipt_log['topics']) > 0:
                    # $ seth keccak $(seth --from-ascii "Transfer(address,address,uint256)")
                    # 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
                    if receipt_log['topics'][0] == HexBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'):
                        from pymaker.token import ERC20Token
                        transfer_abi = [abi for abi in ERC20Token.abi if abi.get('name') == 'Transfer'][0]
                        codec = ABICodec(default_registry)
                        event_data = get_event_data(codec, transfer_abi, receipt_log)
                        self.transfers.append(Transfer(token_address=Address(event_data['address']),
                                                       from_address=Address(event_data['args']['from']),
                                                       to_address=Address(event_data['args']['to']),
                                                       value=Wad(event_data['args']['value'])))

                    # $ seth keccak $(seth --from-ascii "Mint(address,uint256)")
                    # 0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885
                    if receipt_log['topics'][0] == HexBytes('0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885'):
                        from pymaker.token import DSToken
                        transfer_abi = [abi for abi in DSToken.abi if abi.get('name') == 'Mint'][0]
                        codec = ABICodec(default_registry)
                        event_data = get_event_data(codec, transfer_abi, receipt_log)
                        self.transfers.append(Transfer(token_address=Address(event_data['address']),
                                                       from_address=Address('0x0000000000000000000000000000000000000000'),
                                                       to_address=Address(event_data['args']['guy']),
                                                       value=Wad(event_data['args']['wad'])))

                    # $ seth keccak $(seth --from-ascii "Burn(address,uint256)")
                    # 0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5
                    if receipt_log['topics'][0] == HexBytes('0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5'):
                        from pymaker.token import DSToken
                        transfer_abi = [abi for abi in DSToken.abi if abi.get('name') == 'Burn'][0]
                        codec = ABICodec(default_registry)
                        event_data = get_event_data(codec, transfer_abi, receipt_log)
                        self.transfers.append(Transfer(token_address=Address(event_data['address']),
                                                       from_address=Address(event_data['args']['guy']),
                                                       to_address=Address('0x0000000000000000000000000000000000000000'),
                                                       value=Wad(event_data['args']['wad'])))

        else:
            self.successful = False
Пример #3
0
    def __init__(self,
                 provider=None,
                 middlewares=None,
                 modules=None,
                 ens=empty):
        self.manager = self.RequestManager(self, provider, middlewares)

        if modules is None:
            modules = get_default_modules()

        attach_modules(self, modules)

        self.codec = ABICodec(build_default_registry())

        self.ens = ens
Пример #4
0
    def __init__(
        self,
        provider: Optional[BaseProvider] = None,
        middlewares: Optional[Sequence[Any]] = None,
        modules: Optional[Dict[str, Sequence[Any]]] = None,
        ens: ENS = cast(ENS, empty)
    ) -> None:
        self.manager = self.RequestManager(self, provider, middlewares)

        if modules is None:
            modules = get_default_modules()

        attach_modules(self, modules)

        self.codec = ABICodec(build_default_registry())

        self.ens = ens
Пример #5
0
 def parse_event(self, event):
     signature = Web3.toHex(event['topics'][0])
     codec = ABICodec(default_registry)
     if signature == "0xc84ce3a1172f0dec3173f04caaa6005151a4bfe40d4c9f3ea28dba5f719b2a7a":
         event_data = get_event_data(codec, self.kick_abi, event)
         return Flipper.KickLog(event_data)
     else:
         event_data = get_event_data(codec, self.log_note_abi, event)
         return LogNote(event_data)
Пример #6
0
 def parse_event(self, event):
     signature = Web3.toHex(event['topics'][0])
     codec = ABICodec(default_registry)
     if signature == "0x7e8881001566f9f89aedb9c5dc3d856a2b81e5235a8196413ed484be91cc0df6":
         event_data = get_event_data(codec, self.kick_abi, event)
         return Flopper.KickLog(event_data)
     else:
         event_data = get_event_data(codec, self.log_note_abi, event)
         return LogNote(event_data)
Пример #7
0
    def __init__(
        self,
        provider: Optional[BaseProvider] = None,
        middlewares: Optional[Sequence[Any]] = None,
        modules: Optional[Dict[str, Sequence[Any]]] = None,
        ens: ENS = cast(ENS, empty)
    ) -> None:
        self.manager = self.RequestManager(self, provider, middlewares)
        # this codec gets used in the module initialization,
        # so it needs to come before attach_modules
        self.codec = ABICodec(build_default_registry())

        if modules is None:
            modules = get_default_modules()

        attach_modules(self, modules)

        self.ens = ens
Пример #8
0
 def parse_event(self, event):
     signature = Web3.toHex(event['topics'][0])
     codec = ABICodec(default_registry)
     if signature == "0xe6dde59cbc017becba89714a037778d234a84ce7f0a137487142a007e580d609":
         event_data = get_event_data(codec, self.kick_abi, event)
         return Flapper.KickLog(event_data)
     else:
         event_data = get_event_data(codec, self.log_note_abi, event)
         return LogNote(event_data)
Пример #9
0
    def from_event(cls, event: dict):
        assert(isinstance(event, dict))

        topics = event.get('topics')
        if topics and topics[0] == HexBytes('0x3383e3357c77fd2e3a4b30deea81179bc70a795d053d14d5b7f2f01d0fd4596f'):
            log_take_abi = [abi for abi in SimpleMarket.abi if abi.get('name') == 'LogTake'][0]
            codec = ABICodec(default_registry)
            event_data = get_event_data(codec, log_take_abi, event)

            return LogTake(event_data)
Пример #10
0
    def from_receipt(cls, receipt: Receipt):
        assert(isinstance(receipt, Receipt))

        if receipt.logs is not None:
            for log in receipt.logs:
                if len(log['topics']) > 0 and log['topics'][0] == HexBytes('0x773ff502687307abfa024ac9f62f9752a0d210dac2ffd9a29e38e12e2ea82c82'):
                    log_make_abi = [abi for abi in SimpleMarket.abi if abi.get('name') == 'LogMake'][0]
                    codec = ABICodec(default_registry)
                    event_data = get_event_data(codec, log_make_abi, log)

                    yield LogMake(event_data)
Пример #11
0
    def from_event(cls, event: AttributeDict, contract_abi: list):
        assert isinstance(event, AttributeDict)
        assert isinstance(contract_abi, list)

        log_note_abi = [abi for abi in contract_abi if abi.get('name') == 'LogNote'][0]
        try:
            codec = ABICodec(default_registry)
            event_data = get_event_data(codec, log_note_abi, event)
            return LogNote(event_data)
        except ValueError:
            # event is not a LogNote
            return None
Пример #12
0
        def from_event(cls, event: dict):
            assert isinstance(event, dict)

            topics = event.get('topics')
            if topics and topics[0] == HexBytes('0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8'):
                log_bite_abi = [abi for abi in Cat.abi if abi.get('name') == 'Bite'][0]
                codec = ABICodec(default_registry)
                event_data = get_event_data(codec, log_bite_abi, event)

                return Cat.LogBite(event_data)
            else:
                logging.warning(f'[from_event] Invalid topic in {event}')
    async def poll_zeroex_logs_loop(self):
        while True:
            try:
                new_blocks: List[
                    AttributeDict] = await self._new_blocks_queue.get()

                for block in new_blocks:
                    block_bloom_filter = BloomFilter(
                        int.from_bytes(block["logsBloom"], byteorder='big'))
                    if FILL_EVENT_TOPIC in block_bloom_filter:
                        # Potentially a Fill for an order hash we are interested in
                        order_hashes: List[str] = []
                        for order_hash in self._watch_order_hashes:
                            if bytes.fromhex(order_hash) in block_bloom_filter:
                                order_hashes.append("0x" + order_hash)
                        if len(order_hashes) > 0:
                            fill_entries = await self._get_logs({
                                'topics': [
                                    "0x6869791f0a34781b29882982cc39e882768cf2c96995c2a110c577c53bc932d5",
                                    None, None, order_hashes
                                ],
                                'blockhash':
                                block["hash"].hex()
                            })

                            for fill_entry in fill_entries:
                                event_data: AttributeDict = get_event_data(
                                    ABICodec(registry), self._event_abi,
                                    fill_entry)
                                event_data_tx_hash: HexBytes = event_data[
                                    "transactionHash"]
                                # Skip any duplicates
                                if event_data_tx_hash not in self._event_cache:
                                    await self._handle_event_data(event_data)

                            # Mark all of these as processed now, since each tx may contain multiple Fill logs
                            for fill_entry in fill_entries:
                                event_data_tx_hash: HexBytes = fill_entry[
                                    "transactionHash"]
                                if event_data_tx_hash not in self._event_cache:
                                    self._event_cache.add(event_data_tx_hash)

            except asyncio.CancelledError:
                raise
            except asyncio.TimeoutError:
                continue
            except Exception:
                self.logger().network(
                    "Unknown error trying to fetch new events for ZeroEx fills.",
                    exc_info=True,
                    app_warning_msg=
                    "Unknown error trying to fetch new events for ZeroEx fills. "
                    "Check wallet network connection")
Пример #14
0
 def parse_event(self, event):
     signature = Web3.toHex(event['topics'][0])
     codec = ABICodec(default_registry)
     if signature == "0x9102bd0b66dcb83f469f1122a583dc797657b114141460c59230fc1b41f48229":
         event_data = get_event_data(codec, self.start_auction_abi, event)
         return DebtAuctionHouse.StartAuctionLog(event_data)
     elif signature == "0x8c63feacc784a7f735e454365ba433f17d17293b02c57d98dad113977dbf0f13":
         event_data = get_event_data(codec, self.decrease_sold_amount_abi,
                                     event)
         return DebtAuctionHouse.DecreaseSoldAmountLog(event_data)
     elif signature == "0xef063949eb6ef5abef19139d9c75a558424ffa759302cfe445f8d2d327376fe4":
         event_data = get_event_data(codec, self.settle_auction_abi, event)
         return DebtAuctionHouse.SettleAuctionLog(event_data)
Пример #15
0
    def from_event(cls, event: dict):
        assert (isinstance(event, dict))

        topics = event.get('topics')
        if topics and topics[0] == HexBytes(
                '0x0bcc4c97732e47d9946f229edb95f5b6323f601300e4690de719993f3c371129'
        ):
            log_fill_abi = [
                abi for abi in ZrxExchangeV2.abi if abi.get('name') == 'Fill'
            ][0]
            codec = ABICodec(default_registry)
            event_data = get_event_data(codec, log_fill_abi, event)

            return LogFill(event_data)
Пример #16
0
 def parse_event(self, event):
     signature = Web3.toHex(event['topics'][0])
     codec = ABICodec(default_registry)
     if signature == "0x7c5bfdc0a5e8192f6cd4972f382cec69116862fb62e6abff8003874c58e064b8":
         event_data = get_event_data(codec, self.kick_abi, event)
         return Clipper.KickLog(event_data)
     elif signature == "0x05e309fd6ce72f2ab888a20056bb4210df08daed86f21f95053deb19964d86b1":
         event_data = get_event_data(codec, self.take_abi, event)
         self._get_sender_for_eventlog(event_data)
         return Clipper.TakeLog(event_data, self._get_sender_for_eventlog(event_data))
     elif signature == "0x275de7ecdd375b5e8049319f8b350686131c219dd4dc450a08e9cf83b03c865f":
         event_data = get_event_data(codec, self.redo_abi, event)
         return Clipper.RedoLog(event_data)
     else:
         logger.debug(f"Found event signature {signature}")
Пример #17
0
 def parse_event(self, event):
     signature = Web3.toHex(event['topics'][0])
     codec = ABICodec(default_registry)
     if signature == "0xdf7b5cd0ee6547c7389d2ac00ee0c1cd3439542399d6c8c520cc69c7409c0990":
         event_data = get_event_data(codec, self.start_auction_abi, event)
         return FixedDiscountCollateralAuctionHouse.StartAuctionLog(
             event_data)
     elif signature == "0xa4a1133e32fac37643a1fe1db4631daadb462c8662ae16004e67f0b8bb608383":
         event_data = get_event_data(codec, self.buy_collateral_abi, event)
         return FixedDiscountCollateralAuctionHouse.BuyCollateralLog(
             event_data)
     elif signature == "0xef063949eb6ef5abef19139d9c75a558424ffa759302cfe445f8d2d327376fe4":
         event_data = get_event_data(codec, self.settle_auction_abi, event)
         return FixedDiscountCollateralAuctionHouse.SettleAuctionLog(
             event_data)
Пример #18
0
 def parse_event(self, event):
     signature = Web3.toHex(event['topics'][0])
     codec = ABICodec(default_registry)
     if signature == "0xa4863af70e77aecfe2769e0569806782ba7c6f86fc9a307290a3816fb8a563e5":
         event_data = get_event_data(codec, self.start_auction_abi, event)
         return PreSettlementSurplusAuctionHouse.StartAuctionLog(event_data)
     elif signature == "0xd87c815d5a67c2e130ad04b714d87a6fb69d5a6df0dbb0f1639cd9fe292201f9":
         event_data = get_event_data(codec, self.increase_bid_size_abi,
                                     event)
         return PreSettlementSurplusAuctionHouse.IncreaseBidSizeLog(
             event_data)
     elif signature == "0x03af424b0e12d91ea31fe7f2c199fc02c9ede38f9aa1bdc019a8087b41445f7a":
         event_data = get_event_data(codec, self.settle_auction_abi, event)
         return PreSettlementSurplusAuctionHouse.SettleAuctionLog(
             event_data)
Пример #19
0
    def from_event(cls, event: dict):
        assert (isinstance(event, dict))

        topics = event.get('topics')
        if topics and topics[0] == HexBytes(
                '0x259b30ca39885c6d801a0b5dbc988640f3c25e2f37531fe138c5c5af8955d41b'
        ):
            log_created_abi = [
                abi for abi in DSProxyFactory.abi
                if abi.get('name') == 'Created'
            ][0]
            codec = ABICodec(default_registry)
            event_data = get_event_data(codec, log_created_abi, event)

            return LogCreated(event_data)
        else:
            raise Exception(f'[from_event] Invalid topic in {event}')
Пример #20
0
 def parse_event(self, event):
     signature = Web3.toHex(event['topics'][0])
     codec = ABICodec(default_registry)
     if signature == "0xdf7b5cd0ee6547c7389d2ac00ee0c1cd3439542399d6c8c520cc69c7409c0990":
         event_data = get_event_data(codec, self.start_auction_abi, event)
         return EnglishCollateralAuctionHouse.StartAuctionLog(event_data)
     elif signature == "0xd87c815d5a67c2e130ad04b714d87a6fb69d5a6df0dbb0f1639cd9fe292201f9":
         event_data = get_event_data(codec, self.increase_bid_size_abi,
                                     event)
         return EnglishCollateralAuctionHouse.IncreaseBidSizeLog(event_data)
     elif signature == "0x8c63feacc784a7f735e454365ba433f17d17293b02c57d98dad113977dbf0f13":
         event_data = get_event_data(codec, self.decrease_sold_amount_abi,
                                     event)
         return EnglishCollateralAuctionHouse.DecreaseSoldAmountLog(
             event_data)
     elif signature == "0x03af424b0e12d91ea31fe7f2c199fc02c9ede38f9aa1bdc019a8087b41445f7a":
         event_data = get_event_data(codec, self.settle_auction_abi, event)
         return EnglishCollateralAuctionHouse.SettleAuctionLog(event_data)
Пример #21
0
def construct_event_data_set(
    event_abi: ABIEvent, abi_codec: ABICodec,
    arguments: Optional[Union[Sequence[Any], Dict[str, Any]]] = None
) -> List[List[Optional[HexStr]]]:
    if arguments is None:
        arguments = {}
    if isinstance(arguments, (list, tuple)):
        if len(arguments) != len(event_abi['inputs']):
            raise ValueError(
                "When passing an argument list, the number of arguments must "
                "match the event constructor."
            )
        arguments = {
            arg['name']: [arg_value]
            for arg, arg_value
            in zip(event_abi['inputs'], arguments)
        }

    normalized_args = {
        key: value if is_list_like(value) else [value]
        # type ignored b/c at this point arguments is always a dict
        for key, value in arguments.items()  # type: ignore
    }

    non_indexed_args = exclude_indexed_event_inputs(event_abi)
    zipped_abi_and_args = [
        (arg, normalized_args.get(arg['name'], [None]))
        for arg in non_indexed_args
    ]
    encoded_args = [
        [
            None if option is None else encode_hex(abi_codec.encode_single(arg['type'], option))
            for option in arg_options]
        for arg, arg_options in zipped_abi_and_args
    ]

    data = [
        list(permutation)
        if any(value is not None for value in permutation)
        else []
        for permutation in itertools.product(*encoded_args)
    ]
    return data
Пример #22
0
def construct_event_topic_set(
    event_abi: ABIEvent, abi_codec: ABICodec,
    arguments: Optional[Union[Sequence[Any], Dict[str, Any]]] = None
) -> List[HexStr]:
    if arguments is None:
        arguments = {}
    if isinstance(arguments, (list, tuple)):
        if len(arguments) != len(event_abi['inputs']):
            raise ValueError(
                "When passing an argument list, the number of arguments must "
                "match the event constructor."
            )
        arguments = {
            arg['name']: [arg_value]
            for arg, arg_value
            in zip(event_abi['inputs'], arguments)
        }

    normalized_args = {
        key: value if is_list_like(value) else [value]
        # type ignored b/c arguments is always a dict at this point
        for key, value in arguments.items()  # type: ignore
    }

    # typed dict cannot be used w/ a normal Dict
    # https://github.com/python/mypy/issues/4976
    event_topic = encode_hex(event_abi_to_log_topic(event_abi))  # type: ignore
    indexed_args = get_indexed_event_inputs(event_abi)
    zipped_abi_and_args = [
        (arg, normalized_args.get(arg['name'], [None]))
        for arg in indexed_args
    ]
    encoded_args = [
        [
            None if option is None else encode_hex(abi_codec.encode_single(arg['type'], option))
            for option in arg_options]
        for arg, arg_options in zipped_abi_and_args
    ]

    topics = list(normalize_topic_list([event_topic] + encoded_args))  # type: ignore
    return topics
Пример #23
0
    def from_receipt(cls, contract_abi: List, receipt: Receipt):
        assert (isinstance(contract_abi, List))
        assert (isinstance(receipt, Receipt))

        mint_logs = []

        if receipt.logs is not None:
            for log in receipt.logs:
                if len(log['topics']) > 0 and log['topics'][0] == HexBytes(
                        '0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde'
                ):
                    log_mint_abi = [
                        abi for abi in contract_abi
                        if abi.get('name') == 'Mint'
                    ][0]
                    codec = ABICodec(default_registry)
                    event_data = get_event_data(codec, log_mint_abi, log)

                    mint_logs.append(LogMint(event_data))

        return mint_logs
Пример #24
0
    def from_receipt(cls, contract_abi: List, receipt: Receipt):
        assert (isinstance(contract_abi, List))
        assert (isinstance(receipt, Receipt))

        initialize_logs = []

        if receipt.logs is not None:
            for log in receipt.logs:
                if len(log['topics']) > 0 and log['topics'][0] == HexBytes(
                        '0x98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c95'
                ):
                    log_initialize_abi = [
                        abi for abi in contract_abi
                        if abi.get('name') == 'Initialize'
                    ][0]
                    codec = ABICodec(default_registry)
                    event_data = get_event_data(codec, log_initialize_abi, log)

                    initialize_logs.append(LogInitialize(event_data))

        return initialize_logs
Пример #25
0
    def from_receipt(cls, contract_abi: List, receipt: Receipt):
        assert (isinstance(contract_abi, List))
        assert (isinstance(receipt, Receipt))

        swap_logs = []

        if receipt.logs is not None:
            for log in receipt.logs:
                if len(log['topics']) > 0 and log['topics'][0] == HexBytes(
                        '0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67'
                ):
                    log_swap_abi = [
                        abi for abi in contract_abi
                        if abi.get('name') == 'Swap'
                    ][0]
                    codec = ABICodec(default_registry)
                    event_data = get_event_data(codec, log_swap_abi, log)

                    swap_logs.append(LogSwap(event_data))

        return swap_logs
Пример #26
0
    def from_receipt(cls, contract_abi: List, receipt: Receipt):
        assert (isinstance(contract_abi, List))
        assert (isinstance(receipt, Receipt))

        liquidity_logs = []

        if receipt.logs is not None:
            for log in receipt.logs:
                if len(log['topics']) > 0 and log['topics'][0] == HexBytes(
                        '0x40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f01'
                ):
                    log_collect_abi = [
                        abi for abi in contract_abi
                        if abi.get('name') == 'Collect'
                    ][0]
                    codec = ABICodec(default_registry)
                    event_data = get_event_data(codec, log_collect_abi, log)

                    liquidity_logs.append(LogCollect(event_data))

        return liquidity_logs
Пример #27
0
    def from_receipt(cls, contract_abi: List, receipt: Receipt):
        assert (isinstance(contract_abi, List))
        assert (isinstance(receipt, Receipt))

        liquidity_logs = []

        if receipt.logs is not None:
            for log in receipt.logs:
                if len(log['topics']) > 0 and log['topics'][0] == HexBytes(
                        '0x26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b4'
                ):
                    log_decrease_liquidity_abi = [
                        abi for abi in contract_abi
                        if abi.get('name') == 'DecreaseLiquidity'
                    ][0]
                    codec = ABICodec(default_registry)
                    event_data = get_event_data(codec,
                                                log_decrease_liquidity_abi,
                                                log)

                    liquidity_logs.append(LogDecreaseLiquidity(event_data))

        return liquidity_logs
Пример #28
0
    def from_receipt(cls, contract_abi: List, receipt: Receipt):
        assert (isinstance(contract_abi, List))
        assert (isinstance(receipt, Receipt))

        liquidity_logs = []

        if receipt.logs is not None:
            for log in receipt.logs:
                if len(log['topics']) > 0 and log['topics'][0] == HexBytes(
                        '0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f'
                ):
                    log_increase_liquidity_abi = [
                        abi for abi in contract_abi
                        if abi.get('name') == 'IncreaseLiquidity'
                    ][0]
                    codec = ABICodec(default_registry)
                    event_data = get_event_data(codec,
                                                log_increase_liquidity_abi,
                                                log)

                    liquidity_logs.append(LogIncreaseLiquidity(event_data))

        return liquidity_logs
Пример #29
0
from eth_abi.codec import (
    ABICodec,
)
from eth_abi.registry import (
    registry,
)

default_codec = ABICodec(registry)

encode = default_codec.encode
decode = default_codec.decode
is_encodable = default_codec.is_encodable
is_encodable_type = default_codec.is_encodable_type
Пример #30
0
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))