예제 #1
0
def _maybe_update_events_legacy_contrats(
    decoded_events: List[HistoryBaseEntry],
    sender: ChecksumEthAddress,
    source_token: Asset,
    destination_token: Asset,
    spent_amount: FVal,
    return_amount: FVal,
) -> None:
    """
    Use the information from a trade transaction to modify the HistoryEvents from receive/send to
    trade if the conditions are correct.
    """
    in_event = out_event = None
    for event in decoded_events:
        if event.event_type == HistoryEventType.SPEND and event.location_label == sender and event.asset == source_token and event.balance.amount == spent_amount:  # noqa: E501
            event.event_type = HistoryEventType.TRADE
            event.event_subtype = HistoryEventSubType.SPEND
            event.counterparty = CPT_KYBER
            event.notes = f'Swap {event.balance.amount} {event.asset.symbol} in kyber'
            out_event = event
        elif event.event_type == HistoryEventType.RECEIVE and event.location_label == sender and event.balance.amount == return_amount and destination_token == event.asset:  # noqa: E501
            event.event_type = HistoryEventType.TRADE
            event.event_subtype = HistoryEventSubType.RECEIVE
            event.counterparty = CPT_KYBER
            event.notes = f'Receive {event.balance.amount} {event.asset.symbol} from kyber swap'  # noqa: E501
            in_event = event

        maybe_reshuffle_events(out_event=out_event, in_event=in_event)
예제 #2
0
    def _decode_redeem(
            self,
            tx_log: EthereumTxReceiptLog,
            decoded_events: List[HistoryBaseEntry],
            compound_token: EthereumToken,
    ) -> Tuple[Optional[HistoryBaseEntry], Optional[ActionItem]]:
        redeemer = hex_or_bytes_to_address(tx_log.data[0:32])
        if not self.base.is_tracked(redeemer):
            return None, None

        redeem_amount_raw = hex_or_bytes_to_int(tx_log.data[32:64])
        redeem_tokens_raw = hex_or_bytes_to_int(tx_log.data[64:96])
        underlying_token = symbol_to_asset_or_token(compound_token.symbol[1:])
        redeem_amount = asset_normalized_value(redeem_amount_raw, underlying_token)
        redeem_tokens = token_normalized_value(redeem_tokens_raw, compound_token)
        out_event = in_event = None
        for event in decoded_events:
            # Find the transfer event which should have come before the redeeming
            if event.event_type == HistoryEventType.RECEIVE and event.asset == underlying_token and event.balance.amount == redeem_amount:  # noqa: E501
                event.event_type = HistoryEventType.WITHDRAWAL
                event.event_subtype = HistoryEventSubType.REMOVE_ASSET
                event.counterparty = CPT_COMPOUND
                event.notes = f'Withdraw {redeem_amount} {underlying_token.symbol} from compound'
                in_event = event
            if event.event_type == HistoryEventType.SPEND and event.asset == compound_token and event.balance.amount == redeem_tokens:  # noqa: E501
                event.event_type = HistoryEventType.SPEND
                event.event_subtype = HistoryEventSubType.RETURN_WRAPPED
                event.counterparty = CPT_COMPOUND
                event.notes = f'Return {redeem_tokens} {compound_token.symbol} to compound'
                out_event = event

        maybe_reshuffle_events(out_event=out_event, in_event=in_event, events_list=decoded_events)
        return None, None
예제 #3
0
    def _decode_swapped(  # pylint: disable=no-self-use
        self,
        tx_log: EthereumTxReceiptLog,
        transaction: EthereumTransaction,  # pylint: disable=unused-argument
        decoded_events: List[HistoryBaseEntry],  # pylint: disable=unused-argument
        all_logs: List[EthereumTxReceiptLog],  # pylint: disable=unused-argument
    ) -> Tuple[Optional[HistoryBaseEntry], Optional[ActionItem]]:
        sender = hex_or_bytes_to_address(tx_log.topics[1])
        source_token_address = hex_or_bytes_to_address(tx_log.topics[2])
        destination_token_address = hex_or_bytes_to_address(tx_log.topics[3])

        source_token = ethaddress_to_asset(source_token_address)
        if source_token is None:
            return None, None
        destination_token = ethaddress_to_asset(destination_token_address)
        if destination_token is None:
            return None, None

        receiver = hex_or_bytes_to_address(tx_log.data[0:32])
        spent_amount_raw = hex_or_bytes_to_int(tx_log.data[64:96])
        return_amount_raw = hex_or_bytes_to_int(tx_log.data[96:128])
        spent_amount = asset_normalized_value(amount=spent_amount_raw,
                                              asset=source_token)
        return_amount = asset_normalized_value(amount=return_amount_raw,
                                               asset=destination_token)

        out_event = in_event = None
        for event in decoded_events:
            # Now find the sending and receiving events
            if event.event_type == HistoryEventType.SPEND and event.location_label == sender and spent_amount == event.balance.amount and source_token == event.asset:  # noqa: E501
                event.event_type = HistoryEventType.TRADE
                event.event_subtype = HistoryEventSubType.SPEND
                event.counterparty = CPT_ONEINCH_V2
                event.notes = f'Swap {spent_amount} {source_token.symbol} in {CPT_ONEINCH_V2}'  # noqa: E501
                out_event = event
            elif event.event_type == HistoryEventType.RECEIVE and event.location_label == sender and receiver == event.location_label and return_amount == event.balance.amount and destination_token == event.asset:  # noqa: E501
                event.event_type = HistoryEventType.TRADE
                event.event_subtype = HistoryEventSubType.RECEIVE
                event.counterparty = CPT_ONEINCH_V2
                event.notes = f'Receive {return_amount} {destination_token.symbol} from {CPT_ONEINCH_V2} swap'  # noqa: E501
                # use this index as the event may be an ETH transfer and appear at the start
                event.sequence_index = tx_log.log_index
                in_event = event

        maybe_reshuffle_events(out_event=out_event,
                               in_event=in_event,
                               events_list=decoded_events)
        return None, None
예제 #4
0
    def _decode_history(
        self,
        tx_log: EthereumTxReceiptLog,
        transaction: EthereumTransaction,  # pylint: disable=unused-argument
        decoded_events: List[HistoryBaseEntry],  # pylint: disable=unused-argument
        all_logs: List[EthereumTxReceiptLog],  # pylint: disable=unused-argument
    ) -> Tuple[Optional[HistoryBaseEntry], Optional[ActionItem]]:
        sender = hex_or_bytes_to_address(tx_log.topics[1])
        if not self.base.is_tracked(sender):
            return None, None

        from_token_address = hex_or_bytes_to_address(tx_log.data[0:32])
        to_token_address = hex_or_bytes_to_address(tx_log.data[32:64])
        from_asset = ethaddress_to_asset(from_token_address)
        to_asset = ethaddress_to_asset(to_token_address)
        if None in (from_asset, to_asset):
            return None, None

        from_raw = hex_or_bytes_to_int(tx_log.data[64:96])
        from_amount = asset_normalized_value(from_raw,
                                             from_asset)  # type: ignore
        to_raw = hex_or_bytes_to_int(tx_log.data[96:128])
        to_amount = asset_normalized_value(to_raw, to_asset)  # type: ignore

        out_event = in_event = None
        for event in decoded_events:
            if event.event_type == HistoryEventType.SPEND and event.location_label == sender and from_amount == event.balance.amount and from_asset == event.asset:  # noqa: E501
                # find the send event
                event.event_type = HistoryEventType.TRADE
                event.event_subtype = HistoryEventSubType.SPEND
                event.counterparty = CPT_ONEINCH_V1
                event.notes = f'Swap {from_amount} {from_asset.symbol} in {CPT_ONEINCH_V1} from {event.location_label}'  # noqa: E501
                out_event = event
            elif event.event_type == HistoryEventType.RECEIVE and event.location_label == sender and to_amount == event.balance.amount and to_asset == event.asset:  # noqa: E501
                # find the receive event
                event.event_type = HistoryEventType.TRADE
                event.event_subtype = HistoryEventSubType.RECEIVE
                event.counterparty = CPT_ONEINCH_V1
                event.notes = f'Receive {to_amount} {to_asset.symbol} from {CPT_ONEINCH_V1} swap in {event.location_label}'  # noqa: E501
                # use this index as the event may be an ETH transfer and appear at the start
                event.sequence_index = tx_log.log_index
                in_event = event

        maybe_reshuffle_events(out_event=out_event,
                               in_event=in_event,
                               events_list=decoded_events)
        return None, None
예제 #5
0
    def _decode_redeem_underlying_event(  # pylint: disable=no-self-use
        self,
        tx_log: EthereumTxReceiptLog,
        transaction: EthereumTransaction,  # pylint: disable=unused-argument
        decoded_events: List[HistoryBaseEntry],  # pylint: disable=unused-argument
        all_logs: List[EthereumTxReceiptLog],  # pylint: disable=unused-argument
        action_items: List[ActionItem],  # pylint: disable=unused-argument
    ) -> Tuple[Optional[HistoryBaseEntry], Optional[ActionItem]]:
        reserve_address = hex_or_bytes_to_address(tx_log.topics[1])
        reserve_asset = ethaddress_to_asset(reserve_address)
        if reserve_asset is None:
            return None, None
        user_address = hex_or_bytes_to_address(tx_log.topics[2])
        raw_amount = hex_or_bytes_to_int(tx_log.data[0:32])
        amount = asset_normalized_value(raw_amount, reserve_asset)
        atoken = asset_to_atoken(asset=reserve_asset, version=1)
        if atoken is None:
            return None, None

        receive_event = return_event = None
        for event in decoded_events:
            if event.event_type == HistoryEventType.RECEIVE and event.location_label == user_address and amount == event.balance.amount and reserve_asset == event.asset:  # noqa: E501
                event.event_type = HistoryEventType.WITHDRAWAL
                event.event_subtype = HistoryEventSubType.REMOVE_ASSET
                event.counterparty = CPT_AAVE_V1
                event.notes = f'Withdraw {amount} {reserve_asset.symbol} from aave-v1'
                receive_event = event
            elif event.event_type == HistoryEventType.SPEND and event.location_label == user_address and amount == event.balance.amount and atoken == event.asset:  # noqa: E501
                # find the redeem aToken transfer
                event.event_type = HistoryEventType.SPEND
                event.event_subtype = HistoryEventSubType.RETURN_WRAPPED
                event.counterparty = CPT_AAVE_V1
                event.notes = f'Return {amount} {atoken.symbol} to aave-v1'
                return_event = event
            elif event.event_type == HistoryEventType.RECEIVE and event.location_label == user_address and event.counterparty == ZERO_ADDRESS and event.asset == atoken:  # noqa: E501
                event.event_subtype = HistoryEventSubType.REWARD
                event.counterparty = CPT_AAVE_V1
                event.notes = f'Gain {event.balance.amount} {atoken.symbol} from aave-v1 as interest'  # noqa: E501

        maybe_reshuffle_events(out_event=return_event,
                               in_event=receive_event,
                               events_list=decoded_events)  # noqa: E501
        return None, None
예제 #6
0
    def _maybe_decode_swap(  # pylint: disable=no-self-use
            self,
            token: Optional[EthereumToken],  # pylint: disable=unused-argument
            tx_log: EthereumTxReceiptLog,
            transaction: EthereumTransaction,  # pylint: disable=unused-argument
            decoded_events: List[HistoryBaseEntry],
            action_items: List[ActionItem],  # pylint: disable=unused-argument
    ) -> None:
        """Search for both events. Since the order is not guaranteed try reshuffle in both cases"""
        out_event = in_event = None
        if tx_log.topics[0] == TOKEN_PURCHASE:
            buyer = hex_or_bytes_to_address(tx_log.topics[1])
            # search for a send to buyer from a tracked address
            for event in decoded_events:
                if event.event_type == HistoryEventType.SPEND and event.counterparty == buyer:
                    event.event_type = HistoryEventType.TRADE
                    event.event_subtype = HistoryEventSubType.SPEND
                    event.counterparty = CPT_UNISWAP_V1
                    event.notes = f'Swap {event.balance.amount} {event.asset.symbol} in uniswap-v1 from {event.location_label}'  # noqa: E501
                    out_event = event
                elif event.event_type == HistoryEventType.TRADE and event.event_subtype == HistoryEventSubType.RECEIVE and event.counterparty == CPT_UNISWAP_V1:  # noqa: :E501
                    in_event = event

        elif tx_log.topics[0] == ETH_PURCHASE:
            buyer = hex_or_bytes_to_address(tx_log.topics[1])
            # search for a receive to buyer
            for event in decoded_events:
                if event.event_type == HistoryEventType.RECEIVE and event.location_label == buyer:
                    event.event_type = HistoryEventType.TRADE
                    event.event_subtype = HistoryEventSubType.RECEIVE
                    event.counterparty = CPT_UNISWAP_V1
                    event.notes = f'Receive {event.balance.amount} {event.asset.symbol} from uniswap-v1 swap in {event.location_label}'  # noqa: E501
                    in_event = event
                elif event.event_type == HistoryEventType.TRADE and event.event_subtype == HistoryEventSubType.SPEND and event.counterparty == CPT_UNISWAP_V1:  # noqa: :E501
                    out_event = event

        maybe_reshuffle_events(out_event=out_event, in_event=in_event)