Repository: rotki/rotki

Issue:
Coinbase deposits/withdrawals failing to fetch
Getting an error when trying to fetch deposits/withdrawals or generate a tax report using coinbase as an exchange.

Message is: `Failed query for all exchanges: Error: The backend query task died unexpectedly: 'NoneType' object has no attribute 'get'`

Here is the logs:

```
AttributeError: 'NoneType' object has no attribute 'get'
2022-01-02T20:41:06Z <Greenlet at 0x2815c54a948: <bound method RestAPI._do_query_async of <rotkehlchen.api.rest.RestAPI object at 0x0000028159FB2688>>('_get_asset_movements', 36, filter_query=AssetMovementsFilterQuery(and_op=True, filters=[DB, only_cache=False)> failed with AttributeError

Traceback (most recent call last):
  File "src\\gevent\\greenlet.py", line 906, in gevent._gevent_cgreenlet.Greenlet.run
  File "rotkehlchen\api\rest.py", line 294, in _do_query_async
  File "rotkehlchen\api\rest.py", line 895, in _get_asset_movements
  File "rotkehlchen\history\events.py", line 296, in query_asset_movements
  File "rotkehlchen\history\events.py", line 262, in _query_services_for_asset_movements
  File "rotkehlchen\utils\mixins\lockable.py", line 46, in wrapper
  File "rotkehlchen\exchanges\exchange.py", line 387, in query_deposits_withdrawals
  File "rotkehlchen\exchanges\coinbase.py", line 718, in query_online_deposits_withdrawals
  File "rotkehlchen\exchanges\coinbase.py", line 644, in _deserialize_asset_movement
  File "rotkehlchen\exchanges\utils.py", line 42, in deserialize_asset_movement_address
  File "rotkehlchen\exchanges\utils.py", line 30, in get_key_if_has_val
AttributeError: 'NoneType' object has no attribute 'get'
2022-01-02T21:01:46Z <Greenlet at 0x2815c337828: <bound method RestAPI._do_query_async of <rotkehlchen.api.rest.RestAPI object at 0x0000028159FB2688>>('_get_asset_movements', 37, filter_query=AssetMovementsFilterQuery(and_op=True, filters=[DB, only_cache=False)> failed with AttributeError

Traceback (most recent call last):
  File "src\\gevent\\greenlet.py", line 906, in gevent._gevent_cgreenlet.Greenlet.run
  File "rotkehlchen\api\rest.py", line 294, in _do_query_async
  File "rotkehlchen\api\rest.py", line 895, in _get_asset_movements
  File "rotkehlchen\history\events.py", line 296, in query_asset_movements
  File "rotkehlchen\history\events.py", line 262, in _query_services_for_asset_movements
  File "rotkehlchen\utils\mixins\lockable.py", line 46, in wrapper
  File "rotkehlchen\exchanges\exchange.py", line 387, in query_deposits_withdrawals
  File "rotkehlchen\exchanges\coinbase.py", line 718, in query_online_deposits_withdrawals
  File "rotkehlchen\exchanges\coinbase.py", line 644, in _deserialize_asset_movement
```
Coinbase deposits/withdrawals failing to fetch
Getting an error when trying to fetch deposits/withdrawals or generate a tax report using coinbase as an exchange.

Message is: `Failed query for all exchanges: Error: The backend query task died unexpectedly: 'NoneType' object has no attribute 'get'`

Here is the logs:

```
AttributeError: 'NoneType' object has no attribute 'get'
2022-01-02T20:41:06Z <Greenlet at 0x2815c54a948: <bound method RestAPI._do_query_async of <rotkehlchen.api.rest.RestAPI object at 0x0000028159FB2688>>('_get_asset_movements', 36, filter_query=AssetMovementsFilterQuery(and_op=True, filters=[DB, only_cache=False)> failed with AttributeError

Traceback (most recent call last):
  File "src\\gevent\\greenlet.py", line 906, in gevent._gevent_cgreenlet.Greenlet.run
  File "rotkehlchen\api\rest.py", line 294, in _do_query_async
  File "rotkehlchen\api\rest.py", line 895, in _get_asset_movements
  File "rotkehlchen\history\events.py", line 296, in query_asset_movements
  File "rotkehlchen\history\events.py", line 262, in _query_services_for_asset_movements
  File "rotkehlchen\utils\mixins\lockable.py", line 46, in wrapper
  File "rotkehlchen\exchanges\exchange.py", line 387, in query_deposits_withdrawals
  File "rotkehlchen\exchanges\coinbase.py", line 718, in query_online_deposits_withdrawals
  File "rotkehlchen\exchanges\coinbase.py", line 644, in _deserialize_asset_movement
  File "rotkehlchen\exchanges\utils.py", line 42, in deserialize_asset_movement_address
  File "rotkehlchen\exchanges\utils.py", line 30, in get_key_if_has_val
AttributeError: 'NoneType' object has no attribute 'get'
2022-01-02T21:01:46Z <Greenlet at 0x2815c337828: <bound method RestAPI._do_query_async of <rotkehlchen.api.rest.RestAPI object at 0x0000028159FB2688>>('_get_asset_movements', 37, filter_query=AssetMovementsFilterQuery(and_op=True, filters=[DB, only_cache=False)> failed with AttributeError

Traceback (most recent call last):
  File "src\\gevent\\greenlet.py", line 906, in gevent._gevent_cgreenlet.Greenlet.run
  File "rotkehlchen\api\rest.py", line 294, in _do_query_async
  File "rotkehlchen\api\rest.py", line 895, in _get_asset_movements
  File "rotkehlchen\history\events.py", line 296, in query_asset_movements
  File "rotkehlchen\history\events.py", line 262, in _query_services_for_asset_movements
  File "rotkehlchen\utils\mixins\lockable.py", line 46, in wrapper
  File "rotkehlchen\exchanges\exchange.py", line 387, in query_deposits_withdrawals
  File "rotkehlchen\exchanges\coinbase.py", line 718, in query_online_deposits_withdrawals
  File "rotkehlchen\exchanges\coinbase.py", line 644, in _deserialize_asset_movement
```


Discussion:
Hey DugganB this sounds like a bug triggered by your specific data! Can you join Discord and maybe send us a bigger part of the logs. This is not the entire stack trace.
Am in the discord now. Posted some extra logs.
Hey DugganB this sounds like a bug triggered by your specific data! Can you join Discord and maybe send us a bigger part of the logs. This is not the entire stack trace.
Am in the discord now. Posted some extra logs.

Resolving patch:
diff --git a/rotkehlchen/exchanges/coinbase.py b/rotkehlchen/exchanges/coinbase.py
--- a/rotkehlchen/exchanges/coinbase.py
+++ b/rotkehlchen/exchanges/coinbase.py
@@ -602,7 +602,6 @@ def _deserialize_asset_movement(self, raw_data: Dict[str, Any]) -> Optional[Asse
             transaction_id = None
             transaction_url = raw_data.get('id', '')
             fee = Fee(ZERO)
-            # movement_category: Union[Literal['deposit'], Literal['withdrawal']]
             if 'type' in raw_data:
                 # Then this should be a "send" which is the way Coinbase uses to send
                 # crypto outside of the exchange, or from one user to another.
@@ -640,8 +639,13 @@ def _deserialize_asset_movement(self, raw_data: Dict[str, Any]) -> Optional[Asse
                 if 'network' in raw_data:
                     transaction_id = get_key_if_has_val(raw_data['network'], 'hash')
                     transaction_url = get_key_if_has_val(raw_data['network'], 'transaction_url')
-                if 'to' in raw_data:
-                    address = deserialize_asset_movement_address(raw_data['to'], 'address', asset)
+                raw_to = raw_data.get('to')
+                if raw_to is not None:
+                    address = deserialize_asset_movement_address(raw_to, 'address', asset)
+
+                if 'to' in raw_data and raw_to is None:  # Internal movement between coinbase accs
+                    return None  # Can ignore. https://github.com/rotki/rotki/issues/3901
+
                 if 'from' in raw_data:
                     movement_category = AssetMovementCategory.DEPOSIT
             else:


Test patch: