예제 #1
0
    def get_eth2_deposits(
            self,
            from_ts: Optional[Timestamp] = None,
            to_ts: Optional[Timestamp] = None,
            address: Optional[ChecksumEthAddress] = None,
    ) -> List[Eth2Deposit]:
        """Returns a list of Eth2Deposit filtered by time and address"""
        cursor = self.db.conn.cursor()
        query = (
            'SELECT '
            'tx_hash, '
            'tx_index, '
            'from_address, '
            'timestamp, '
            'pubkey, '
            'withdrawal_credentials, '
            'amount, '
            'usd_value '
            'FROM eth2_deposits '
        )
        # Timestamp filters are omitted, done via `form_query_to_filter_timestamps`
        filters = []
        if address is not None:
            filters.append(f'from_address="{address}" ')

        if filters:
            query += 'WHERE '
            query += 'AND '.join(filters)

        query, bindings = form_query_to_filter_timestamps(query, 'timestamp', from_ts, to_ts)
        results = cursor.execute(query, bindings)

        return [Eth2Deposit.deserialize_from_db(deposit_tuple) for deposit_tuple in results]
예제 #2
0
def test_eth2_deposits_serialization():
    addr1 = make_ethereum_address()
    addr2 = make_ethereum_address()
    deposits = [
        Eth2Deposit(
            from_address=addr1,
            pubkey='0xb016e31f633a21fbe42a015152399361184f1e2c0803d89823c224994af74a561c4ad8cfc94b18781d589d03e952cd5b',  # noqa: E501
            withdrawal_credentials='0x004c7691c2085648f394ffaef851f3b1d51b95f7263114bc923fc5338f5fc499',  # noqa: E501
            value=Balance(FVal(32), FVal(64)),
            deposit_index=9,
            tx_hash='0xd9eca1c2a0c5ff2f25071713432b21cc4d0ff2e8963edc63a48478e395e08db1',
            log_index=22,
            timestamp=Timestamp(int(1604506685)),
        ), Eth2Deposit(
            from_address=addr2,
            pubkey='0xa8ff5fc88412d080a297683c25a791ef77eb52d75b265fabab1f2c2591bb927c35818ac6289bc6680ab252787d0ebab3',  # noqa: E501
            withdrawal_credentials='0x00cfe1c10347d642a8b8daf86d23bcb368076972691445de2cf517ff43765817',  # noqa: E501
            value=Balance(FVal(32), FVal(64)),
            deposit_index=1650,
            tx_hash='0x6905f4d1843fb8c003c1fbbc2c8e6c5f9792f4f44ddb1122553412ee0b128da7',
            log_index=221,
            timestamp=Timestamp(int(1605043544)),
        ),
    ]

    serialized = process_result_list(deposits)
    assert serialized == [
        {
            'from_address': addr1,
            'pubkey': '0xb016e31f633a21fbe42a015152399361184f1e2c0803d89823c224994af74a561c4ad8cfc94b18781d589d03e952cd5b',  # noqa: E501
            'withdrawal_credentials': '0x004c7691c2085648f394ffaef851f3b1d51b95f7263114bc923fc5338f5fc499',  # noqa: E501
            'value': {'amount': '32', 'usd_value': '64'},
            'deposit_index': 9,
            'tx_hash': '0xd9eca1c2a0c5ff2f25071713432b21cc4d0ff2e8963edc63a48478e395e08db1',
            'log_index': 22,
            'timestamp': 1604506685,
        }, {
            'from_address': addr2,
            'pubkey': '0xa8ff5fc88412d080a297683c25a791ef77eb52d75b265fabab1f2c2591bb927c35818ac6289bc6680ab252787d0ebab3',  # noqa: E501
            'withdrawal_credentials': '0x00cfe1c10347d642a8b8daf86d23bcb368076972691445de2cf517ff43765817',  # noqa: E501
            'value': {'amount': '32', 'usd_value': '64'},
            'deposit_index': 1650,
            'tx_hash': '0x6905f4d1843fb8c003c1fbbc2c8e6c5f9792f4f44ddb1122553412ee0b128da7',
            'log_index': 221,
            'timestamp': 1605043544,
        },
    ]
예제 #3
0
    def get_validator_deposits(
        self,
        indices_or_pubkeys: Union[List[int], List[Eth2PubKey]],
    ) -> List[Eth2Deposit]:
        """Get the deposits of all the validators given from the list of indices or pubkeys

        Queries in chunks of 100 due to api limitations

        May raise:
        - RemoteError due to problems querying beaconcha.in API
        """
        chunks = _calculate_query_chunks(indices_or_pubkeys)
        data = []
        for chunk in chunks:
            result = self._query(
                module='validator',
                endpoint='deposits',
                encoded_args=','.join(str(x) for x in chunk),
            )
            if isinstance(result, list):
                data.extend(result)
            else:
                data.append(result)

        deposits = []
        for entry in data:
            try:
                amount = from_gwei(FVal(entry['amount']))
                timestamp = entry['block_ts']
                usd_price = query_usd_price_zero_if_error(
                    asset=A_ETH,
                    time=timestamp,
                    location=f'Eth2 staking deposit at time {timestamp}',
                    msg_aggregator=self.msg_aggregator,
                )
                deposits.append(
                    Eth2Deposit(
                        from_address=deserialize_ethereum_address(
                            entry['from_address']),
                        pubkey=entry['publickey'],
                        withdrawal_credentials=entry['withdrawal_credentials'],
                        value=Balance(
                            amount=amount,
                            usd_value=amount * usd_price,
                        ),
                        tx_hash=hexstring_to_bytes(entry['tx_hash']),
                        tx_index=entry['tx_index'],
                        timestamp=entry['block_ts'],
                    ))
            except (DeserializationError, KeyError) as e:
                msg = str(e)
                if isinstance(e, KeyError):
                    msg = f'Missing key entry for {msg}.'
                raise RemoteError(
                    f'Beaconchai.in deposits response processing error. {msg}',
                ) from e

        return deposits
예제 #4
0
파일: eth2.py 프로젝트: paultbarrett/rotki
def _get_eth2_staking_deposits_onchain(
    ethereum: 'EthereumManager',
    addresses: List[ChecksumEthAddress],
    msg_aggregator: MessagesAggregator,
    from_ts: Timestamp,
    to_ts: Timestamp,
) -> List[Eth2Deposit]:
    events = ETH2_DEPOSIT.get_logs(
        ethereum=ethereum,
        event_name='DepositEvent',
        argument_filters={},
        from_block=ETH2_DEPOSIT.deployed_block,
        to_block='latest',
    )
    transactions = ethereum.transactions.query(
        addresses=addresses,
        from_ts=from_ts,
        to_ts=to_ts,
        with_limit=False,
        recent_first=False,
    )
    deposits: List[Eth2Deposit] = []
    for transaction in transactions:
        if transaction.to_address != ETH2_DEPOSIT.address:
            continue

        tx_hash = '0x' + transaction.tx_hash.hex()
        for event in events:
            # Now find the corresponding event. If no event is found the transaction
            # probably failed or was something other than a deposit
            if event['transactionHash'] == tx_hash:
                decoded_data = decode_event_data(event['data'], EVENT_ABI)
                # all pylint ignores below due to https://github.com/PyCQA/pylint/issues/4114
                amount = int.from_bytes(decoded_data[2], byteorder='little')  # pylint: disable=unsubscriptable-object  # noqa: E501
                usd_price = query_usd_price_zero_if_error(
                    asset=A_ETH,
                    time=transaction.timestamp,
                    location='Eth2 staking query',
                    msg_aggregator=msg_aggregator,
                )
                normalized_amount = from_gwei(FVal(amount))
                deposits.append(
                    Eth2Deposit(
                        from_address=transaction.from_address,
                        pubkey='0x' + decoded_data[0].hex(),  # pylint: disable=unsubscriptable-object  # noqa: E501
                        withdrawal_credentials='0x' + decoded_data[1].hex(),  # pylint: disable=unsubscriptable-object  # noqa: E501
                        value=Balance(normalized_amount,
                                      usd_price * normalized_amount),
                        deposit_index=int.from_bytes(decoded_data[4],
                                                     byteorder='little'),  # pylint: disable=unsubscriptable-object  # noqa: E501
                        tx_hash=tx_hash,
                        log_index=event['logIndex'],
                        timestamp=Timestamp(transaction.timestamp),
                    ))
                break

    return deposits
예제 #5
0
파일: test_eth2.py 프로젝트: zalam003/rotki
    '0xfeF0E7635281eF8E3B705e9C5B86e1d3B0eAb397')
ADDR2 = deserialize_ethereum_address(
    '0x00F8a0D8EE1c21151BCcB416bCa1C152f9952D19')
ADDR3 = deserialize_ethereum_address(
    '0x3266F3546a1e5Dc6A15588f3324741A0E20a3B6c')

# List of ADDR1, ADDR2 and ADDR3 deposit events from 1604506685 to 1605044577
# sorted by (timestamp, log_index).
EXPECTED_DEPOSITS = [
    Eth2Deposit(
        from_address=ADDR1,
        pubkey=
        '0xb016e31f633a21fbe42a015152399361184f1e2c0803d89823c224994af74a561c4ad8cfc94b18781d589d03e952cd5b',  # noqa: E501
        withdrawal_credentials=
        '0x004c7691c2085648f394ffaef851f3b1d51b95f7263114bc923fc5338f5fc499',  # noqa: E501
        value=Balance(FVal(32), FVal(64)),
        deposit_index=9,
        tx_hash=
        '0xd9eca1c2a0c5ff2f25071713432b21cc4d0ff2e8963edc63a48478e395e08db1',
        log_index=22,
        timestamp=Timestamp(int(1604506685)),
    ),
    Eth2Deposit(
        from_address=ADDR3,
        pubkey=
        '0x90b2f65cb43d9cdb2279af9f76010d667b9d8d72e908f2515497a7102820ce6bb15302fe2b8dc082fce9718569344ad8',  # noqa: E501
        withdrawal_credentials=
        '0x00a257d19e1650dec1ab59fc9e1cb9a9fc2fe7265b0f27e7d79ff61aeff0a1f0',  # noqa: E501
        value=Balance(FVal(32), FVal(64)),
        deposit_index=993,
        tx_hash=