def pair_get_assets(pair: TradePair) -> Tuple[Asset, Asset]:
    """Returns a tuple with the (base, quote) assets

    May raise:
    - UnprocessableTradePair
    - UnknownAsset
    """
    base_str, quote_str = _split_pair(pair)
    base_asset = get_asset_by_symbol(base_str)
    if base_asset is None:
        raise UnknownAsset(base_str)
    quote_asset = get_asset_by_symbol(quote_str)
    if quote_asset is None:
        raise UnknownAsset(quote_str)
    return base_asset, quote_asset
Exemple #2
0
def get_gitcoin_asset(symbol: str, token_address: str) -> Asset:
    """At the moment gitcoin keeps a symbol for the asset so mapping to asset can be ambiguous

    May raise:
    - UnknownAsset
    """
    if token_address != NO_ADDRESS:
        try:
            return EthereumToken(to_checksum_address(token_address))
        except (UnknownAsset, ValueError):
            pass  # let's try by symbol

    asset = get_asset_by_symbol(symbol)
    if asset is None:
        raise UnknownAsset(symbol)

    return asset
Exemple #3
0
    def handle_protocols(
        self,
        protocol_name: str,
        token_symbol: str,
        normalized_balance: FVal,
        token_address: str,
        token_name: str,
    ) -> Optional[DefiBalance]:
        """Special handling for price for token/protocols which are easier to do onchain
        or need some kind of special treatment.
        This method can raise DeserializationError
        """
        if protocol_name == 'PoolTogether':
            result = _handle_pooltogether(normalized_balance, token_name)
            if result is not None:
                return result

        asset = get_asset_by_symbol(token_symbol)
        if asset is None:
            return None

        token = EthereumToken.from_asset(asset)
        if token is None:
            return None
        underlying_asset_price = get_underlying_asset_price(token)
        usd_price = handle_defi_price_query(self.ethereum, token,
                                            underlying_asset_price)
        if usd_price is None:
            return None

        return DefiBalance(
            token_address=deserialize_ethereum_address(token_address),
            token_name=token_name,
            token_symbol=token_symbol,
            balance=Balance(amount=normalized_balance,
                            usd_value=normalized_balance * usd_price),
        )
Exemple #4
0
    def _consume_grant_entry(self, entry: Dict[str,
                                               Any]) -> Optional[LedgerAction]:
        """
        Consumes a grant entry from the CSV and turns it into a LedgerAction

        May raise:

        - DeserializationError
        - KeyError
        - UnknownAsset
        """
        if entry['Type'] != 'grant':
            return None

        timestamp = deserialize_timestamp_from_date(
            date=entry['date'],
            formatstr='%Y-%m-%dT%H:%M:%S',
            location='Gitcoin CSV',
            skip_milliseconds=True,
        )
        usd_value = deserialize_asset_amount(entry['Value In USD'])

        asset = get_asset_by_symbol(entry['token_name'])
        if asset is None:
            raise UnknownAsset(entry['token_name'])
        token_amount = deserialize_asset_amount(entry['token_value'])

        if token_amount == ZERO:  # try to make up for https://github.com/gitcoinco/web/issues/9213
            price = query_usd_price_zero_if_error(
                asset=asset,
                time=timestamp,
                location=f'Gitcoin CSV entry {entry["txid"]}',
                msg_aggregator=self.db.msg_aggregator,
            )
            if price == ZERO:
                self.db.msg_aggregator.add_warning(
                    f'Could not process gitcoin grant entry at {entry["date"]} for {asset.symbol} '
                    f'due to amount being zero and inability to find price. Skipping.',
                )
                return None
            # calculate the amount from price and value
            token_amount = usd_value / price  # type: ignore

        match = self.grantid_re.search(entry['url'])
        if match is None:
            self.db.msg_aggregator.add_warning(
                f'Could not process gitcoin grant entry at {entry["date"]} for {asset.symbol} '
                f'due to inability to read grant id. Skipping.', )
            return None

        grant_id = int(match.group(1))
        rate = Price(usd_value / token_amount)

        raw_txid = entry['txid']
        tx_type, tx_id = process_gitcoin_txid(key='txid', entry=entry)
        return LedgerAction(
            identifier=1,  # whatever does not go in the DB
            timestamp=timestamp,
            action_type=LedgerActionType.DONATION_RECEIVED,
            location=Location.GITCOIN,
            amount=token_amount,
            asset=asset,
            rate=rate,
            rate_asset=A_USD,  # let's use the rate gitcoin calculated
            link=raw_txid,
            notes=f'Gitcoin grant {grant_id} event',
            extra_data=GitcoinEventData(
                tx_id=tx_id,
                grant_id=grant_id,
                clr_round=None,  # can't get round from CSV
                tx_type=tx_type,
            ),
        )