Repository: rotki/rotki

Issue:
Error processing kraken trade -- float timestamp
## Problem Definition

I saw this on one of my test accounts. Starting happening today but can't be related to v1.16.0 since Kraken always returned integer timestamps. So they must have changed something on their side.


## Logs

{'ordertxid': 'XXXX', 'postxid': 'XXX', 'pair': 'XXBTZEUR', 'time': 1619057345.6829, 'type': 'buy', 'ordertype': 'limit', 'price': '44196.00000', 'cost': '47.09835132', 'fee': '1.98354', 'vol': '0.00106567', 'margin': '0.00000', 'misc': ''}, error=Failed to deserialize a timestamp entry from a <class 'float'> entry in kraken


## Task

Fix it. Must from now on also account for floating point timestamps in Kraken


Discussion:

Resolving patch:
diff --git a/rotkehlchen/serialization/deserialize.py b/rotkehlchen/serialization/deserialize.py
--- a/rotkehlchen/serialization/deserialize.py
+++ b/rotkehlchen/serialization/deserialize.py
@@ -164,7 +164,7 @@ def deserialize_timestamp_from_bitstamp_date(date: str) -> Timestamp:
     )
 
 
-def deserialize_timestamp_from_kraken(time: Union[str, FVal, int]) -> Timestamp:
+def deserialize_timestamp_from_kraken(time: Union[str, FVal, int, float]) -> Timestamp:
     """Deserializes a timestamp from a kraken api query result entry
     Kraken has timestamps in floating point strings. Example: '1561161486.3056'.
 
@@ -179,12 +179,12 @@ def deserialize_timestamp_from_kraken(time: Union[str, FVal, int]) -> Timestamp:
 
     if isinstance(time, int):
         return Timestamp(time)
-    if isinstance(time, str):
+    if isinstance(time, (float, str)):
         try:
             return Timestamp(convert_to_int(time, accept_only_exact=False))
         except ConversionError as e:
             raise DeserializationError(
-                f'Failed to deserialize {time} kraken timestamp entry',
+                f'Failed to deserialize {time} kraken timestamp entry from {type(time)}',
             ) from e
     if isinstance(time, FVal):
         try:


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
@@ -11,6 +11,7 @@
 from rotkehlchen.exchanges.data_structures import Trade
 from rotkehlchen.exchanges.kraken import KRAKEN_DELISTED, Kraken, kraken_to_world_pair
 from rotkehlchen.fval import FVal
+from rotkehlchen.serialization.deserialize import deserialize_timestamp_from_kraken
 from rotkehlchen.tests.utils.constants import (
     A_ADA,
     A_AUD,
@@ -358,6 +359,11 @@ def query_kraken_and_test(input_trades, expected_warnings_num, expected_errors_n
     target = 'rotkehlchen.tests.utils.kraken.KRAKEN_SPECIFIC_TRADES_HISTORY_RESPONSE'
     query_kraken_and_test(test_trades, expected_warnings_num=0, expected_errors_num=0)
 
+    # Kraken also uses floats for timestamps, this should also work
+    input_trades = test_trades
+    input_trades = input_trades.replace('"time": "1458994442.2353"', '"time": 1458994442.2353')
+    query_kraken_and_test(input_trades, expected_warnings_num=0, expected_errors_num=0)
+
     # From here and on let's check trades with unexpected data
     input_trades = test_trades
     input_trades = input_trades.replace('"pair": "XXBTZEUR"', '"pair": "aadda"')
@@ -407,3 +413,15 @@ def mock_post(url, data):  # pylint: disable=unused-argument
         result, msg = kraken.query_balances()
         assert msg == ''
         assert result == {}
+
+
+def test_timestamp_deserialization():
+    """Test the function that allows to deserialize timestamp from different types"""
+    assert deserialize_timestamp_from_kraken("1458994442.2353") == 1458994442
+    assert deserialize_timestamp_from_kraken(1458994442.2353) == 1458994442
+    assert deserialize_timestamp_from_kraken(1458994442) == 1458994442
+    assert deserialize_timestamp_from_kraken(FVal(1458994442.2353)) == 1458994442
+    with pytest.raises(DeserializationError):
+        deserialize_timestamp_from_kraken("234a")
+    with pytest.raises(DeserializationError):
+        deserialize_timestamp_from_kraken("")