Repository: rotki/rotki

Issue:
Loopring balances fail to load if account owns USDT in loopring
## Problem Definition

When the account has USDT in loopring the balance fails to load due to the following exception:

```
Exception Name: <class 'rotkehlchen.errors.UnsupportedAsset'>
Exception Info: Found asset USDT which is not supported.
Traceback:
   File "src/gevent/greenlet.py", line 906, in gevent._gevent_cgreenlet.Greenlet.run
  File "rotkehlchen/api/rest.py", line 268, in _do_query_async
  File "rotkehlchen/api/rest.py", line 1947, in _eth_module_query
  File "rotkehlchen/chain/ethereum/l2/loopring.py", line 350, in get_balances
  File "rotkehlchen/chain/ethereum/l2/loopring.py", line 317, in get_account_balances
  File "rotkehlchen/chain/ethereum/utils.py", line 67, in asset_normalized_value
```

### Task
- [ ] Fix the cause for the exception
Xpub address derivation and balance queries for legacy xpubs no longer works correctly due to blockchain.info response format change.
## Problem Definition

I just noticed it today due to a failing test [here](https://github.com/rotki/rotki/pull/2404/checks?check_run_id=1926740817).
It seems that blockchain.info changed the format of their responses for the endpoint we use and order is no longer guaranteed.

Which means we need to adjust our code that deals with blockchain.info.

## Task

Fix our code that deals with blockchain.info to not expect the returned addresses with the same order as they were given.


Discussion:
So ehm ...

https://github.com/rotki/rotki/blob/e73db77c66325343f52df0a0f78e09f8f571194b/rotkehlchen/chain/ethereum/l2/loopring.py#L308-L327

Look at the comment and look at the raised exception on the bug. I mean lol wtf?
Okay found the problem. It can be solved in two ways. Good news is one of them involves only changes in all_assets.json so not even a new release. Let me work on it.


Resolving patch:
diff --git a/rotkehlchen/chain/bitcoin/__init__.py b/rotkehlchen/chain/bitcoin/__init__.py
--- a/rotkehlchen/chain/bitcoin/__init__.py
+++ b/rotkehlchen/chain/bitcoin/__init__.py
@@ -40,8 +40,8 @@ def get_bitcoin_addresses_balances(accounts: List[BTCAddress]) -> Dict[BTCAddres
                 # https://blockchain.info/q
                 backoff_in_seconds=10,
             )
-            for idx, entry in enumerate(btc_resp['addresses']):
-                balances[accounts[idx]] = satoshis_to_btc(FVal(entry['final_balance']))
+            for entry in btc_resp['addresses']:
+                balances[entry['address']] = satoshis_to_btc(FVal(entry['final_balance']))
     except (
             requests.exceptions.RequestException,
             UnableToDecryptRemoteData,
@@ -76,7 +76,7 @@ def _check_blockstream_for_transactions(
 def _check_blockchaininfo_for_transactions(
         accounts: List[BTCAddress],
 ) -> Dict[BTCAddress, Tuple[bool, FVal]]:
-    """May raise connection errors or KeyError"""
+    """May raise RemotError or KeyError"""
     have_transactions = {}
     params = '|'.join(accounts)
     btc_resp = request_get_dict(
@@ -86,9 +86,9 @@ def _check_blockchaininfo_for_transactions(
         # https://blockchain.infoq/
         backoff_in_seconds=15,
     )
-    for idx, entry in enumerate(btc_resp['addresses']):
+    for entry in btc_resp['addresses']:
         balance = satoshis_to_btc(entry['final_balance'])
-        have_transactions[accounts[idx]] = (entry['n_tx'] != 0, balance)
+        have_transactions[entry['address']] = (entry['n_tx'] != 0, balance)
 
     return have_transactions
 
diff --git a/rotkehlchen/chain/ethereum/utils.py b/rotkehlchen/chain/ethereum/utils.py
--- a/rotkehlchen/chain/ethereum/utils.py
+++ b/rotkehlchen/chain/ethereum/utils.py
@@ -11,7 +11,7 @@
 from rotkehlchen.constants.ethereum import ETH_MULTICALL
 from rotkehlchen.errors import UnsupportedAsset
 from rotkehlchen.fval import FVal
-from rotkehlchen.typing import AssetType, ChecksumEthAddress, EthTokenInfo
+from rotkehlchen.typing import ChecksumEthAddress, EthTokenInfo
 from rotkehlchen.utils.misc import hexstring_to_bytes
 
 if TYPE_CHECKING:
@@ -63,7 +63,7 @@ def asset_normalized_value(amount: int, asset: Asset) -> FVal:
     if asset.identifier == 'ETH':
         decimals = 18
     else:
-        if asset.asset_type != AssetType.ETH_TOKEN:
+        if not asset.is_eth_token():
             raise UnsupportedAsset(asset.identifier)
         decimals = EthereumToken(asset.identifier).decimals
 
diff --git a/rotkehlchen/externalapis/coingecko.py b/rotkehlchen/externalapis/coingecko.py
--- a/rotkehlchen/externalapis/coingecko.py
+++ b/rotkehlchen/externalapis/coingecko.py
@@ -149,6 +149,7 @@ class CoingeckoAssetData(NamedTuple):
     'TRUMPLOSE',
     'TRUMPWIN',
     'ATX-2',
+    'SONIQ',
 ]
 
 COINGECKO_SIMPLE_VS_CURRENCIES = [


Test patch:
diff --git a/rotkehlchen/tests/api/test_bitcoin.py b/rotkehlchen/tests/api/test_bitcoin.py
--- a/rotkehlchen/tests/api/test_bitcoin.py
+++ b/rotkehlchen/tests/api/test_bitcoin.py
@@ -58,7 +58,7 @@
 
 
 def _check_xpub_addition_outcome(outcome, xpub):
-    """Checks the outcome of the xpub additions forthe following test.
+    """Checks the outcome of the xpub additions for the following test.
     Both results should be the same since the 2nd xpub derives no mainnet addresses
     """
     btc = outcome['per_account']['BTC']
diff --git a/rotkehlchen/tests/unit/test_assets.py b/rotkehlchen/tests/unit/test_assets.py
--- a/rotkehlchen/tests/unit/test_assets.py
+++ b/rotkehlchen/tests/unit/test_assets.py
@@ -191,7 +191,7 @@ def test_coingecko_identifiers_are_reachable(data_dir):
 def test_assets_json_meta():
     """Test that all_assets.json md5 matches and that if md5 changes since last
     time then version is also bumped"""
-    last_meta = {'md5': '6a8dba71c678a7541bd0352e6ec05c4c', 'version': 61}
+    last_meta = {'md5': '315486c0f601693f2a75f04e31d0fc74', 'version': 62}
     data_dir = Path(__file__).resolve().parent.parent.parent / 'data'
     data_md5 = file_md5(data_dir / 'all_assets.json')