Exemple #1
0
    def _get_liquidation_events(
        self,
        address: ChecksumEthAddress,
        from_ts: Timestamp,
        to_ts: Timestamp,
    ) -> List[CompoundEvent]:
        """https://compound.finance/docs/ctokens#liquidate-borrow"""
        param_types, param_values = get_common_params(from_ts, to_ts, address)
        result = self.graph.query(  # type: ignore
            querystr=
            """liquidationEvents (where: {blockTime_lte: $end_ts, blockTime_gte: $start_ts, from: $address}) {
    id
    amount
    from
    blockNumber
    blockTime
    cTokenSymbol
    underlyingSymbol
    underlyingRepayAmount
}}""",
            param_types=param_types,
            param_values=param_values,
        )

        events = []
        for entry in result['liquidationEvents']:
            ctoken_symbol = entry['cTokenSymbol']
            try:
                ctoken_asset = Asset(ctoken_symbol)
            except UnknownAsset:
                log.error(
                    f'Found unexpected cTokenSymbol {ctoken_symbol} during graph query. Skipping.'
                )
                continue
            underlying_symbol = entry['underlyingSymbol']
            try:
                underlying_asset = Asset(underlying_symbol)
            except UnknownAsset:
                log.error(
                    f'Found unexpected token symbol {underlying_symbol} during '
                    f'graph query. Skipping.', )
                continue
            timestamp = entry['blockTime']
            # Amount/value of underlying asset paid by liquidator
            # Essentially liquidator covers part of the debt of the user
            debt_amount = FVal(entry['underlyingRepayAmount'])
            underlying_usd_price = query_usd_price_zero_if_error(
                asset=underlying_asset,
                time=timestamp,
                location='compound liquidation underlying asset',
                msg_aggregator=self.msg_aggregator,
            )
            debt_usd_value = debt_amount * underlying_usd_price
            # Amount/value of ctoken_asset lost to the liquidator
            # This is what the liquidator gains at a discount
            liquidated_amount = FVal(entry['amount'])
            liquidated_usd_price = query_usd_price_zero_if_error(
                asset=ctoken_asset,
                time=timestamp,
                location='compound liquidation ctoken asset',
                msg_aggregator=self.msg_aggregator,
            )
            liquidated_usd_value = liquidated_amount * liquidated_usd_price
            parse_result = _get_txhash_and_logidx(entry['id'])
            if parse_result is None:
                log.error(
                    f'Found unprocessable liquidation id from the graph {entry["id"]}. Skipping',
                )
                continue

            gained_value = Balance(amount=debt_amount,
                                   usd_value=debt_usd_value)
            lost_value = Balance(amount=liquidated_amount,
                                 usd_value=liquidated_usd_value)
            events.append(
                CompoundEvent(
                    event_type='liquidation',
                    address=address,
                    block_number=entry['blockNumber'],
                    timestamp=timestamp,
                    asset=underlying_asset,
                    value=gained_value,
                    to_asset=ctoken_asset,
                    to_value=lost_value,
                    realized_pnl=None,
                    tx_hash=parse_result[0],
                    log_index=parse_result[1],
                ))

        return events
Exemple #2
0
    def _get_lend_events(
        self,
        event_type: Literal['mint', 'redeem'],
        address: ChecksumEthAddress,
        from_ts: Timestamp,
        to_ts: Timestamp,
    ) -> List[CompoundEvent]:
        param_types, param_values = get_common_params(from_ts, to_ts, address)
        if event_type == 'mint':
            graph_event_name = 'mintEvents'
            addr_position = 'to'
        elif event_type == 'redeem':
            graph_event_name = 'redeemEvents'
            addr_position = 'from'

        result = self.graph.query(  # type: ignore
            querystr=LEND_EVENTS_QUERY_PREFIX.format(
                graph_event_name=graph_event_name,
                addr_position=addr_position,
            ),
            param_types=param_types,
            param_values=param_values,
        )

        events = []
        for entry in result[graph_event_name]:
            ctoken_symbol = entry['cTokenSymbol']
            try:
                ctoken_asset = Asset(ctoken_symbol)
            except UnknownAsset:
                log.error(
                    f'Found unexpected cTokenSymbol {ctoken_symbol} during graph query. Skipping.'
                )
                continue

            underlying_symbol = ctoken_symbol[1:]
            try:
                underlying_asset = Asset(underlying_symbol)
            except UnknownAsset:
                log.error(
                    f'Found unexpected token symbol {underlying_symbol} during '
                    f'graph query. Skipping.', )
                continue
            timestamp = entry['blockTime']
            usd_price = query_usd_price_zero_if_error(
                asset=underlying_asset,
                time=timestamp,
                location=f'compound {event_type}',
                msg_aggregator=self.msg_aggregator,
            )
            underlying_amount = FVal(entry['underlyingAmount'])
            usd_value = underlying_amount * usd_price
            parse_result = _get_txhash_and_logidx(entry['id'])
            if parse_result is None:
                log.error(
                    f'Found unprocessable mint id from the graph {entry["id"]}. Skipping'
                )
                continue
            amount = FVal(entry['amount'])

            if event_type == 'mint':
                from_value = Balance(amount=underlying_amount,
                                     usd_value=usd_value)
                to_value = Balance(amount=amount, usd_value=usd_value)
                from_asset = underlying_asset
                to_asset = ctoken_asset
            else:  # redeem
                from_value = Balance(amount=amount, usd_value=usd_value)
                to_value = Balance(amount=underlying_amount,
                                   usd_value=usd_value)
                from_asset = ctoken_asset
                to_asset = underlying_asset

            events.append(
                CompoundEvent(
                    event_type=event_type,
                    address=address,
                    block_number=entry['blockNumber'],
                    timestamp=timestamp,
                    asset=from_asset,
                    value=from_value,
                    to_asset=to_asset,
                    to_value=to_value,
                    realized_pnl=None,
                    tx_hash=parse_result[0],
                    log_index=parse_result[1],
                ))

        return events
Exemple #3
0
    def _get_borrow_events(
        self,
        event_type: Literal['borrow', 'repay'],
        address: ChecksumEthAddress,
        from_ts: Timestamp,
        to_ts: Timestamp,
    ) -> List[CompoundEvent]:
        param_types, param_values = get_common_params(from_ts, to_ts, address)
        if event_type == 'borrow':
            graph_event_name = 'borrowEvents'
            payer_or_empty = ''
        elif event_type == 'repay':
            graph_event_name = 'repayEvents'
            payer_or_empty = 'payer'

        result = self.graph.query(  # type: ignore
            querystr=BORROW_EVENTS_QUERY_PREFIX.format(
                graph_event_name=graph_event_name,
                payer_or_empty=payer_or_empty,
            ),
            param_types=param_types,
            param_values=param_values,
        )

        events = []
        for entry in result[graph_event_name]:
            underlying_symbol = entry['underlyingSymbol']
            try:
                underlying_asset = Asset(underlying_symbol)
            except UnknownAsset:
                log.error(
                    f'Found unexpected token symbol {underlying_symbol} during '
                    f'graph query. Skipping.', )
                continue
            timestamp = entry['blockTime']
            usd_price = query_usd_price_zero_if_error(
                asset=underlying_asset,
                time=timestamp,
                location=f'compound {event_type}',
                msg_aggregator=self.msg_aggregator,
            )
            amount = FVal(entry['amount'])
            parse_result = _get_txhash_and_logidx(entry['id'])
            if parse_result is None:
                log.error(
                    f'Found unprocessable borrow/repay id from the graph {entry["id"]}. Skipping',
                )
                continue

            events.append(
                CompoundEvent(
                    event_type=event_type,
                    address=address,
                    block_number=entry['blockNumber'],
                    timestamp=timestamp,
                    asset=underlying_asset,
                    value=Balance(amount=amount, usd_value=amount * usd_price),
                    to_asset=None,
                    to_value=None,
                    realized_pnl=None,
                    tx_hash=parse_result[0],
                    log_index=parse_result[1],
                ))

        return events