Repository: rotki/rotki

Issue:
Change the trade database and datastructure format to accept assets instead of a pair
## Abstract

Related to #2240 (it does that only in the frontend part)

Change the backend DB schema for trades to accept individual assets and not a trade pair. This is going to be a big improvement as the legacy format of having a trade pair is much harder to work with as you need to always serialize to/from a pair each time you want to analyze a trade.

## Task

- [ ] Change the DB schema to accept assets instead of a pair string
- [ ] Change the data structure to use assets instead of a pair string
- [ ] Add a DB upgrade to upgrade all places where trades with a pair were used to the new schema. This needs A LOT of testing.
- [ ] Change all places in the code where the new schema needs to be used.


Discussion:

Resolving patch:
diff --git a/rotkehlchen/exchanges/kraken.py b/rotkehlchen/exchanges/kraken.py
--- a/rotkehlchen/exchanges/kraken.py
+++ b/rotkehlchen/exchanges/kraken.py
@@ -245,23 +245,24 @@ def _check_and_get_response(response: Response, method: str) -> Union[str, Dict]
     except json.decoder.JSONDecodeError as e:
         raise RemoteError(f'Invalid JSON in Kraken response. {e}') from e
 
-    try:
-        if decoded_json['error']:
-            if isinstance(decoded_json['error'], list):
-                error = decoded_json['error'][0]
-            else:
-                error = decoded_json['error']
+    error = decoded_json.get('error', None)
+    if error:
+        if isinstance(error, list) and len(error) != 0:
+            error = error[0]
 
-            if 'Rate limit exceeded' in error:
-                log.debug(f'Kraken: Got rate limit exceeded error: {error}')
-                return 'Rate limited exceeded'
+        if 'Rate limit exceeded' in error:
+            log.debug(f'Kraken: Got rate limit exceeded error: {error}')
+            return 'Rate limited exceeded'
 
-            # else
-            raise RemoteError(error)
+        # else
+        raise RemoteError(error)
+
+    result = decoded_json.get('result', None)
+    if result is None:
+        if method == 'Balance':
+            return {}
 
-        result = decoded_json['result']
-    except KeyError as e:
-        raise RemoteError(f'Unexpected format of Kraken response. Missing key: {e}') from e
+        raise RemoteError(f'Missing result in kraken response for {method}')
 
     return result
 


Test patch:
diff --git a/rotkehlchen/tests/exchanges/test_kraken.py b/rotkehlchen/tests/exchanges/test_kraken.py
--- a/rotkehlchen/tests/exchanges/test_kraken.py
+++ b/rotkehlchen/tests/exchanges/test_kraken.py
@@ -12,6 +12,7 @@
 from rotkehlchen.exchanges.kraken import KRAKEN_DELISTED, Kraken, kraken_to_world_pair
 from rotkehlchen.fval import FVal
 from rotkehlchen.tests.utils.history import TEST_END_TS
+from rotkehlchen.tests.utils.mock import MockResponse
 from rotkehlchen.typing import AssetMovementCategory
 from rotkehlchen.utils.misc import ts_now
 
@@ -362,3 +363,19 @@ def query_kraken_and_test(input_trades, expected_warnings_num, expected_errors_n
     input_trades = test_trades
     input_trades = input_trades.replace('"vol": "1",', '')
     query_kraken_and_test(input_trades, expected_warnings_num=0, expected_errors_num=1)
+
+
+def test_emptry_kraken_balance_response():
+    """Balance api query returns a response without a result
+
+    Regression test for: https://github.com/rotki/rotki/issues/2443
+    """
+    kraken = Kraken('a', b'YW55IGNhcm5hbCBwbGVhc3VyZS4=', object(), object())
+
+    def mock_post(url, data):  # pylint: disable=unused-argument
+        return MockResponse(200, '{"error":[]}')
+
+    with patch.object(kraken.session, 'post', wraps=mock_post):
+        result, msg = kraken.query_balances()
+        assert msg == ''
+        assert result == {}