def _deserialize_asset_movement( raw_movement: Dict[str, Any], ) -> AssetMovement: """Process a deposit/withdrawal user transaction from Bitstamp and deserialize it. Can raise DeserializationError. From Bitstamp documentation, deposits/withdrawals can have a fee (the amount is expected to be in the currency involved) https://www.bitstamp.net/fee-schedule/ Endpoint docs: https://www.bitstamp.net/api/#user-transactions """ type_ = deserialize_int_from_str(raw_movement['type'], 'bitstamp asset movement') category: AssetMovementCategory if type_ == 0: category = AssetMovementCategory.DEPOSIT elif type_ == 1: category = AssetMovementCategory.WITHDRAWAL else: raise AssertionError( f'Unexpected Bitstamp asset movement case: {type_}.') timestamp = deserialize_timestamp_from_bitstamp_date( raw_movement['datetime']) amount: FVal fee_asset: Asset for symbol in BITSTAMP_ASSET_MOVEMENT_SYMBOLS: amount = deserialize_asset_amount(raw_movement.get(symbol, '0')) if amount != ZERO: fee_asset = asset_from_bitstamp(symbol) break if amount == ZERO: raise DeserializationError( 'Could not deserialize Bitstamp asset movement from user transaction. ' f'Unexpected asset amount combination found in: {raw_movement}.', ) asset_movement = AssetMovement( timestamp=timestamp, location=Location.BITSTAMP, category=category, address=None, # requires query "crypto_transactions" endpoint transaction_id=None, # requires query "crypto_transactions" endpoint asset=fee_asset, amount=abs(amount), fee_asset=fee_asset, fee=deserialize_fee(raw_movement['fee']), link=str(raw_movement['id']), ) return asset_movement
def _deserialize_trade( self, raw_trade: Dict[str, Any], ) -> Trade: """Process a trade user transaction from Bitstamp and deserialize it. Can raise DeserializationError. """ timestamp = deserialize_timestamp_from_bitstamp_date(raw_trade['datetime']) trade_pair_data = self._get_trade_pair_data_from_transaction(raw_trade) base_asset_amount = deserialize_asset_amount( raw_trade[trade_pair_data.base_asset_symbol], ) quote_asset_amount = deserialize_asset_amount( raw_trade[trade_pair_data.quote_asset_symbol], ) rate = deserialize_price(raw_trade[trade_pair_data.pair]) fee_currency = trade_pair_data.quote_asset if base_asset_amount >= ZERO: trade_type = TradeType.BUY else: if quote_asset_amount < 0: raise DeserializationError( f'Unexpected bitstamp trade format. Both base and quote ' f'amounts are negative: {raw_trade}', ) trade_type = TradeType.SELL trade = Trade( timestamp=timestamp, location=Location.BITSTAMP, base_asset=trade_pair_data.base_asset, quote_asset=trade_pair_data.quote_asset, trade_type=trade_type, amount=AssetAmount(abs(base_asset_amount)), rate=rate, fee=deserialize_fee(raw_trade['fee']), fee_currency=fee_currency, link=str(raw_trade['id']), notes='', ) return trade
def _deserialize_trade( self, raw_trade: Dict[str, Any], ) -> Trade: """Process a trade user transaction from Bitstamp and deserialize it. Can raise DeserializationError. """ timestamp = deserialize_timestamp_from_bitstamp_date(raw_trade['datetime']) trade_pair_data = self._get_trade_pair_data_from_transaction(raw_trade) base_asset_amount = deserialize_asset_amount( raw_trade[trade_pair_data.base_asset_symbol], ) quote_asset_amount = deserialize_asset_amount( raw_trade[trade_pair_data.quote_asset_symbol], ) if base_asset_amount >= ZERO: trade_type = TradeType.BUY amount = base_asset_amount fee_currency = trade_pair_data.quote_asset else: trade_type = TradeType.SELL amount = quote_asset_amount fee_currency = trade_pair_data.base_asset trade = Trade( timestamp=timestamp, location=Location.BITSTAMP, pair=trade_pair_data.trade_pair, trade_type=trade_type, amount=amount, rate=deserialize_price(raw_trade[trade_pair_data.pair]), fee=deserialize_fee(raw_trade['fee']), fee_currency=fee_currency, link=str(raw_trade['id']), notes='', ) return trade
def _deserialize_asset_movement( self, raw_movement: Dict[str, Any], ) -> AssetMovement: """Process a deposit/withdrawal user transaction from Bitstamp and deserialize it. Can raise DeserializationError. From Bitstamp documentation, deposits/withdrawals can have a fee (the amount is expected to be in the currency involved) https://www.bitstamp.net/fee-schedule/ Bitstamp support confirmed the following withdrawal JSON: { "fee": "0.00050000", "btc_usd": "0.00", "datetime": "2020-12-04 09:30:00.000000", "usd": "0.0", "btc": "-0.50000000", "type": "1", "id": 123456789, "eur": "0.0" } NB: any asset key not related with the pair is discarded (e.g. 'eur'). """ type_ = raw_movement['type'] category: AssetMovementCategory if type_ == 0: category = AssetMovementCategory.DEPOSIT elif type_ == 1: category = AssetMovementCategory.WITHDRAWAL else: raise AssertionError(f'Unexpected Bitstamp asset movement case: {type_}.') timestamp = deserialize_timestamp_from_bitstamp_date(raw_movement['datetime']) trade_pair_data = self._get_trade_pair_data_from_transaction(raw_movement) base_asset_amount = deserialize_asset_amount( raw_movement[trade_pair_data.base_asset_symbol], ) quote_asset_amount = deserialize_asset_amount( raw_movement[trade_pair_data.quote_asset_symbol], ) amount: FVal fee_asset: Asset if base_asset_amount != ZERO and quote_asset_amount == ZERO: amount = base_asset_amount fee_asset = trade_pair_data.base_asset elif base_asset_amount == ZERO and quote_asset_amount != ZERO: amount = quote_asset_amount fee_asset = trade_pair_data.quote_asset else: raise DeserializationError( 'Could not deserialize Bitstamp asset movement from user transaction. ' f'Unexpected asset amount combination found in: {raw_movement}.', ) asset_movement = AssetMovement( timestamp=timestamp, location=Location.BITSTAMP, category=category, address=None, # requires query "crypto_transactions" endpoint transaction_id=None, # requires query "crypto_transactions" endpoint asset=fee_asset, amount=abs(amount), fee_asset=fee_asset, fee=deserialize_fee(raw_movement['fee']), link=str(raw_movement['id']), ) return asset_movement
log.error(msg) self.msg_aggregator.add_error( f'Got remote error while querying Bistamp trades: {msg}', ) no_results: Union[List[Trade], List[AssetMovement]] = [] # type: ignore return no_results has_results = False is_result_timesamp_gt_end_ts = False result: Union[Trade, AssetMovement] for raw_result in response_list: if raw_result['type'] not in raw_result_type_filter: continue try: result_timestamp = deserialize_timestamp_from_bitstamp_date( raw_result['datetime'], ) if result_timestamp > end_ts: is_result_timesamp_gt_end_ts = True # prevent extra request break result = deserialization_method(raw_result) except DeserializationError as e: msg = str(e) log.error( f'Error processing a Bitstamp {case_pretty}.', raw_result=raw_result, error=msg, )