示例#1
0
def test_bitpanda_exchange_assets_are_known():
    """Since normal Bitpanda API has no endpoint listing supposrted assets
    https://developers.bitpanda.com/platform/#bitpanda-public-api

    Bitpanda PRO leasts some of the same assets but not all. So this test catches some,
    but unfortunately not all assets
    """
    request_url = 'https://api.exchange.bitpanda.com/public/v1/currencies'
    try:
        response = requests.get(request_url)
    except requests.exceptions.RequestException as e:
        raise RemoteError(
            f'Bitpanda get request at {request_url} connection error: {str(e)}.',
        ) from e

    if response.status_code != 200:
        raise RemoteError(
            f'Bitpanda query responded with error status code: {response.status_code} '
            f'and text: {response.text}', )
    try:
        response_list = jsonloads_list(response.text)
    except json.JSONDecodeError as e:
        raise RemoteError(
            f'Bitpanda returned invalid JSON response: {response.text}') from e

    for entry in response_list:
        try:
            asset_from_bitpanda(entry['code'])
        except UnknownAsset as e:
            test_warnings.warn(
                UserWarning(
                    f'Found unknown asset {e.asset_name} in bitpanda. '
                    f'Support for it has to be added', ))
示例#2
0
    def query_balances(self) -> ExchangeQueryBalances:
        try:
            wallets, _, _ = self._api_query('wallets')
            # asset_wallets = self._api_query('asset-wallets')
            fiat_wallets, _, _ = self._api_query('fiatwallets')
        except RemoteError as e:
            msg = f'Failed to query Bitpanda balances. {str(e)}'
            return None, msg

        assets_balance: DefaultDict[Asset, Balance] = defaultdict(Balance)
        wallets_len = len(wallets)
        for idx, entry in enumerate(wallets + fiat_wallets):

            if idx < wallets_len:
                symbol_key = 'cryptocoin_symbol'
            else:
                symbol_key = 'fiat_symbol'

            try:
                amount = deserialize_asset_amount(
                    entry['attributes']['balance'])
                asset = asset_from_bitpanda(entry['attributes'][symbol_key])
            except UnknownAsset as e:
                self.msg_aggregator.add_warning(
                    f'Found unsupported/unknown Bitpanda asset {e.asset_name}. '
                    f' Ignoring its balance query.', )
                continue
            except (DeserializationError, KeyError) as e:
                msg = str(e)
                if isinstance(e, KeyError):
                    msg = f'Missing key entry for {msg}.'
                self.msg_aggregator.add_error(
                    'Error processing Bitpanda balance. Check logs '
                    'for details. Ignoring it.', )
                log.error(
                    'Error processing bitpanda balance',
                    entry=entry,
                    error=msg,
                )
                continue

            if amount == ZERO:
                continue

            try:
                usd_price = Inquirer().find_usd_price(asset=asset)
            except RemoteError as e:
                self.msg_aggregator.add_error(
                    f'Error processing Bitpanda balance entry due to inability to '
                    f'query USD price: {str(e)}. Skipping balance entry', )
                continue
            assets_balance[asset] += Balance(
                amount=amount,
                usd_value=amount * usd_price,
            )

        return dict(assets_balance), ''
示例#3
0
    def first_connection(self) -> None:
        if self.first_connection_made:
            return

        try:
            wallets, _, _ = self._api_query('wallets')
            fiat_wallets, _, _ = self._api_query('fiatwallets')
        except RemoteError as e:
            self.msg_aggregator.add_error(
                f'Failed to query Bitpanda wallets at first connection. {str(e)}',
            )
            return

        wallets_len = len(wallets)
        for idx, entry in enumerate(wallets + fiat_wallets):
            if idx < wallets_len:
                id_key = 'cryptocoin_id'
                symbol_key = 'cryptocoin_symbol'
                mapping = self.cryptocoin_map
            else:
                id_key = 'fiat_id'
                symbol_key = 'fiat_symbol'
                mapping = self.fiat_map

            try:
                coin_id = entry['attributes'][id_key]
                asset = asset_from_bitpanda(entry['attributes'][symbol_key])
            except UnknownAsset as e:
                self.msg_aggregator.add_warning(
                    f'Found unsupported/unknown Bitpanda asset {e.asset_name}. '
                    f' Not adding asset to mapping during first connection.', )
                continue
            except (DeserializationError, KeyError) as e:
                msg = str(e)
                if isinstance(e, KeyError):
                    msg = f'Missing key entry for {msg}.'
                self.msg_aggregator.add_error(
                    'Error processing Bitpanda wallets query. Check logs '
                    'for details. Ignoring it.', )
                log.error(
                    'Error processing bitpanda wallet entry at first connection',
                    entry=entry,
                    error=msg,
                )
                continue

            mapping[coin_id] = asset

        self.first_connection_made = True