Example #1
0
def iconomi_pair_to_world(pair: str) -> Tuple[Asset, Asset]:
    """May raise:
    - UnsupportedAsset
    - UnknownAsset
    """
    tx_asset = asset_from_iconomi(pair[:3])
    native_asset = asset_from_iconomi(pair[3:])
    return tx_asset, native_asset
Example #2
0
def test_iconomi_assets_are_known(
        database,
        inquirer,  # pylint: disable=unused-argument
):
    unsupported_assets = set(UNSUPPORTED_ICONOMI_ASSETS)
    common_items = unsupported_assets.intersection(
        set(WORLD_TO_ICONOMI.values()))
    assert not common_items, f'Iconomi assets {common_items} should not be unsupported'
    # use a real Iconomi instance so that we always get the latest data
    iconomi = Iconomi(
        name='iconomi1',
        api_key=make_api_key(),
        secret=make_api_secret(),
        database=database,
        msg_aggregator=MessagesAggregator(),
    )

    supported_tickers = iconomi.query_supported_tickers()
    for ticker in supported_tickers:
        try:
            _ = asset_from_iconomi(ticker)
        except UnknownAsset as e:
            test_warnings.warn(
                UserWarning(
                    f'Found unknown asset {e.asset_name} in ICONOMI. '
                    f'Support for it has to be added', ))
Example #3
0
    def query_balances(self, **kwargs: Any) -> ExchangeQueryBalances:
        assets_balance: Dict[Asset, Balance] = {}
        try:
            resp_info = self._api_query('get', 'user/balance')
        except RemoteError as e:
            msg = (
                'ICONOMI API request failed. Could not reach ICONOMI due '
                'to {}'.format(e)
            )
            log.error(msg)
            return None, msg

        if resp_info['currency'] != 'USD':
            raise RemoteError('Iconomi API did not return values in USD')

        for balance_info in resp_info['assetList']:
            ticker = balance_info['ticker']
            try:
                asset = asset_from_iconomi(ticker)

                # There seems to be a bug in the ICONOMI API regarding balance_info['value'].
                # The value is supposed to be in USD, but is actually returned
                # in EUR. So let's use the Inquirer for now.
                try:
                    usd_price = Inquirer().find_usd_price(asset=asset)
                except RemoteError as e:
                    self.msg_aggregator.add_error(
                        f'Error processing ICONOMI balance entry due to inability to '
                        f'query USD price: {str(e)}. Skipping balance entry',
                    )
                    continue

                try:
                    amount = deserialize_asset_amount(balance_info['balance'])
                except DeserializationError as e:
                    self.msg_aggregator.add_warning(
                        f'Skipping iconomi balance entry {balance_info} due to {str(e)}',
                    )
                    continue

                assets_balance[asset] = Balance(
                    amount=amount,
                    usd_value=amount * usd_price,
                )
            except (UnknownAsset, UnsupportedAsset) as e:
                asset_tag = 'unknown' if isinstance(e, UnknownAsset) else 'unsupported'
                self.msg_aggregator.add_warning(
                    f'Found {asset_tag} ICONOMI asset {ticker}. '
                    f' Ignoring its balance query.',
                )
                continue

        for balance_info in resp_info['daaList']:
            ticker = balance_info['ticker']
            self.msg_aggregator.add_warning(
                f'Found unsupported ICONOMI strategy {ticker}. '
                f' Ignoring its balance query.',
            )

        return assets_balance, ''
Example #4
0
def trade_from_iconomi(raw_trade: Dict) -> Trade:
    """Turn an iconomi trade entry to our own trade format

    May raise:
    - UnknownAsset
    - DeserializationError
    - KeyError
    """

    timestamp = raw_trade['timestamp']

    if raw_trade['type'] == 'buy_asset':
        trade_type = TradeType.BUY
        tx_asset = asset_from_iconomi(raw_trade['target_ticker'])
        tx_amount = deserialize_asset_amount(raw_trade['target_amount'])
        native_asset = asset_from_iconomi(raw_trade['source_ticker'])
        native_amount = deserialize_asset_amount(raw_trade['source_amount'])
    elif raw_trade['type'] == 'sell_asset':
        trade_type = TradeType.SELL
        tx_asset = asset_from_iconomi(raw_trade['source_ticker'])
        tx_amount = deserialize_asset_amount(raw_trade['source_amount'])
        native_amount = deserialize_asset_amount(raw_trade['target_amount'])
        native_asset = asset_from_iconomi(raw_trade['target_ticker'])

    amount = tx_amount
    rate = Price(native_amount / tx_amount)
    fee_amount = deserialize_fee(raw_trade['fee_amount'])
    fee_asset = asset_from_iconomi(raw_trade['fee_ticker'])
    return Trade(
        timestamp=timestamp,
        location=Location.ICONOMI,
        base_asset=tx_asset,
        quote_asset=native_asset,
        trade_type=trade_type,
        amount=amount,
        rate=rate,
        fee=fee_amount,
        fee_currency=fee_asset,
        link=str(raw_trade['transactionId']),
    )
Example #5
0
def test_iconomi_assets_are_known(
        database,
        inquirer,  # pylint: disable=unused-argument
):
    # use a real Iconomi instance so that we always get the latest data
    iconomi = Iconomi(
        api_key=make_api_key(),
        secret=make_api_secret(),
        database=database,
        msg_aggregator=MessagesAggregator(),
    )

    supported_tickers = iconomi.query_supported_tickers()
    for ticker in supported_tickers:
        try:
            _ = asset_from_iconomi(ticker)
        except UnknownAsset as e:
            test_warnings.warn(
                UserWarning(
                    f'Found unknown asset {e.asset_name} in ICONOMI. '
                    f'Support for it has to be added', ))
Example #6
0
    def query_balances(self, **kwargs: Any) -> ExchangeQueryBalances:
        assets_balance: Dict[Asset, Balance] = {}
        try:
            resp_info = self._api_query('get', 'user/balance')
        except RemoteError as e:
            msg = ('ICONOMI API request failed. Could not reach ICONOMI due '
                   'to {}'.format(e))
            log.error(msg)
            return None, msg

        if resp_info['currency'] != 'USD':
            raise RemoteError('Iconomi API did not return values in USD')

        for balance_info in resp_info['assetList']:
            ticker = balance_info['ticker']
            try:
                asset = asset_from_iconomi(ticker)

                try:
                    usd_value = deserialize_fval(balance_info['value'],
                                                 'usd_value', 'iconomi')
                except (DeserializationError, KeyError) as e:
                    msg = str(e)
                    if isinstance(e, KeyError):
                        msg = f'missing key entry for {msg}.'
                    self.msg_aggregator.add_warning(
                        f'Skipping iconomi balance entry {balance_info} due to {msg}',
                    )
                    continue

                try:
                    amount = deserialize_asset_amount(balance_info['balance'])
                except (DeserializationError, KeyError) as e:
                    msg = str(e)
                    if isinstance(e, KeyError):
                        msg = f'missing key entry for {msg}.'
                    self.msg_aggregator.add_warning(
                        f'Skipping iconomi balance entry {balance_info} due to {msg}',
                    )
                    continue

                assets_balance[asset] = Balance(
                    amount=amount,
                    usd_value=usd_value,
                )
            except (UnknownAsset, UnsupportedAsset) as e:
                asset_tag = 'unknown' if isinstance(
                    e, UnknownAsset) else 'unsupported'
                self.msg_aggregator.add_warning(
                    f'Found {asset_tag} ICONOMI asset {ticker}. '
                    f' Ignoring its balance query.', )
                continue

        for balance_info in resp_info['daaList']:
            ticker = balance_info['ticker']

            if ticker == 'AUSTS':
                # The AUSTS strategy is 'ICONOMI Earn'. We know that this strategy holds its
                # value in Anchor UST (AUST). That's why we report the user balance for this
                # strategy as usd_value / AUST price.
                try:
                    aust_usd_price = Inquirer().find_usd_price(asset=A_AUST)
                except RemoteError as e:
                    self.msg_aggregator.add_error(
                        f'Error processing ICONOMI balance entry due to inability to '
                        f'query USD price: {str(e)}. Skipping balance entry', )
                    continue

                if aust_usd_price == ZERO:
                    self.msg_aggregator.add_error(
                        'Error processing ICONOMI balance entry because the USD price '
                        'for AUST was reported as 0. Skipping balance entry', )
                    continue

                try:
                    usd_value = deserialize_fval(balance_info['value'],
                                                 'usd_value', 'iconomi')
                except (DeserializationError, KeyError) as e:
                    msg = str(e)
                    if isinstance(e, KeyError):
                        msg = f'missing key entry for {msg}.'
                    self.msg_aggregator.add_warning(
                        f'Skipping iconomi balance entry {balance_info} due to {msg}',
                    )
                    continue

                assets_balance[A_AUST] = Balance(
                    amount=usd_value / aust_usd_price,
                    usd_value=usd_value,
                )
            else:
                self.msg_aggregator.add_warning(
                    f'Found unsupported ICONOMI strategy {ticker}. '
                    f' Ignoring its balance query.', )

        return assets_balance, ''