ccxt 4.3.34__py2.py3-none-any.whl → 4.3.36__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ccxt might be problematic. Click here for more details.

Files changed (54) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/bitbay.py +6 -0
  3. ccxt/abstract/zonda.py +6 -0
  4. ccxt/alpaca.py +1 -1
  5. ccxt/async_support/__init__.py +1 -1
  6. ccxt/async_support/alpaca.py +1 -1
  7. ccxt/async_support/base/exchange.py +42 -42
  8. ccxt/async_support/binance.py +2 -2
  9. ccxt/async_support/bingx.py +4 -3
  10. ccxt/async_support/bit2c.py +2 -1
  11. ccxt/async_support/bitget.py +11 -5
  12. ccxt/async_support/bitmart.py +2 -7
  13. ccxt/async_support/btcmarkets.py +3 -1
  14. ccxt/async_support/bybit.py +1 -1
  15. ccxt/async_support/coinbase.py +60 -3
  16. ccxt/async_support/coinex.py +26 -19
  17. ccxt/async_support/gemini.py +1 -1
  18. ccxt/async_support/kraken.py +3 -1
  19. ccxt/async_support/paymium.py +4 -1
  20. ccxt/async_support/whitebit.py +24 -3
  21. ccxt/async_support/zaif.py +30 -2
  22. ccxt/async_support/zonda.py +6 -0
  23. ccxt/base/exchange.py +85 -76
  24. ccxt/binance.py +2 -2
  25. ccxt/bingx.py +4 -3
  26. ccxt/bit2c.py +2 -1
  27. ccxt/bitget.py +11 -5
  28. ccxt/bitmart.py +2 -7
  29. ccxt/btcmarkets.py +3 -1
  30. ccxt/bybit.py +1 -1
  31. ccxt/coinbase.py +60 -3
  32. ccxt/coinex.py +26 -19
  33. ccxt/gemini.py +1 -1
  34. ccxt/kraken.py +3 -1
  35. ccxt/paymium.py +4 -1
  36. ccxt/pro/__init__.py +1 -1
  37. ccxt/pro/binance.py +4 -4
  38. ccxt/pro/bingx.py +9 -4
  39. ccxt/pro/bitfinex2.py +4 -4
  40. ccxt/pro/bitget.py +24 -1
  41. ccxt/pro/bitmart.py +9 -7
  42. ccxt/pro/bybit.py +6 -6
  43. ccxt/pro/htx.py +5 -6
  44. ccxt/pro/kraken.py +1 -1
  45. ccxt/pro/okx.py +4 -5
  46. ccxt/pro/woo.py +4 -4
  47. ccxt/test/base/test_crypto.py +1 -1
  48. ccxt/whitebit.py +24 -3
  49. ccxt/zaif.py +30 -2
  50. ccxt/zonda.py +6 -0
  51. {ccxt-4.3.34.dist-info → ccxt-4.3.36.dist-info}/METADATA +4 -4
  52. {ccxt-4.3.34.dist-info → ccxt-4.3.36.dist-info}/RECORD +54 -54
  53. {ccxt-4.3.34.dist-info → ccxt-4.3.36.dist-info}/WHEEL +0 -0
  54. {ccxt-4.3.34.dist-info → ccxt-4.3.36.dist-info}/top_level.txt +0 -0
ccxt/bit2c.py CHANGED
@@ -448,7 +448,8 @@ class bit2c(Exchange, ImplicitAPI):
448
448
  request: dict = {
449
449
  'id': id,
450
450
  }
451
- return self.privatePostOrderCancelOrder(self.extend(request, params))
451
+ response = self.privatePostOrderCancelOrder(self.extend(request, params))
452
+ return self.parse_order(response)
452
453
 
453
454
  def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
454
455
  """
ccxt/bitget.py CHANGED
@@ -1249,6 +1249,7 @@ class bitget(Exchange, ImplicitAPI):
1249
1249
  '40712': InsufficientFunds, # Insufficient margin
1250
1250
  '40713': ExchangeError, # Cannot exceed the maximum transferable margin amount
1251
1251
  '40714': ExchangeError, # No direct margin call is allowed
1252
+ '40762': InsufficientFunds, # {"code":"40762","msg":"The order amount exceeds the balance","requestTime":1716572156622,"data":null}
1252
1253
  '40768': OrderNotFound, # Order does not exist"
1253
1254
  '41114': OnMaintenance, # {"code":"41114","msg":"The current trading pair is under maintenance, please refer to the official announcement for the opening time","requestTime":1679196062544,"data":null}
1254
1255
  '43011': InvalidOrder, # The parameter does not meet the specification executePrice <= 0
@@ -2723,7 +2724,7 @@ class bitget(Exchange, ImplicitAPI):
2723
2724
  request: dict = {}
2724
2725
  type = None
2725
2726
  type, params = self.handle_market_type_and_params('fetchTickers', market, params)
2726
- # Calls like `.fetch_tickers(None, {subType:'inverse'})` should be supported for self exchange, so
2727
+ # Calls like `.fetchTickers(None, {subType:'inverse'})` should be supported for self exchange, so
2727
2728
  # as "options.defaultSubType" is also set in exchange options, we should consider `params.subType`
2728
2729
  # with higher priority and only default to spot, if `subType` is not set in params
2729
2730
  passedSubType = self.safe_string(params, 'subType')
@@ -4138,18 +4139,23 @@ class bitget(Exchange, ImplicitAPI):
4138
4139
  marginMode = 'cross'
4139
4140
  marginModeRequest = 'crossed' if (marginMode == 'cross') else 'isolated'
4140
4141
  request['marginMode'] = marginModeRequest
4141
- oneWayMode = self.safe_bool(params, 'oneWayMode', False)
4142
- params = self.omit(params, 'oneWayMode')
4142
+ hedged = None
4143
+ hedged, params = self.handle_param_bool(params, 'hedged', False)
4144
+ # backward compatibility for `oneWayMode`
4145
+ oneWayMode = None
4146
+ oneWayMode, params = self.handle_param_bool(params, 'oneWayMode')
4147
+ if oneWayMode is not None:
4148
+ hedged = not oneWayMode
4143
4149
  requestSide = side
4144
4150
  if reduceOnly:
4145
- if oneWayMode:
4151
+ if not hedged:
4146
4152
  request['reduceOnly'] = 'YES'
4147
4153
  else:
4148
4154
  # on bitget hedge mode if the position is long the side is always buy, and if the position is short the side is always sell
4149
4155
  requestSide = 'sell' if (side == 'buy') else 'buy'
4150
4156
  request['tradeSide'] = 'Close'
4151
4157
  else:
4152
- if not oneWayMode:
4158
+ if hedged:
4153
4159
  request['tradeSide'] = 'Open'
4154
4160
  request['side'] = requestSide
4155
4161
  elif marketType == 'spot':
ccxt/bitmart.py CHANGED
@@ -1180,14 +1180,9 @@ class bitmart(Exchange, ImplicitAPI):
1180
1180
  market = self.safe_market(marketId, market)
1181
1181
  symbol = market['symbol']
1182
1182
  last = self.safe_string_2(ticker, 'close_24h', 'last_price')
1183
- percentage = self.safe_string(ticker, 'price_change_percent_24h')
1183
+ percentage = Precise.string_abs(self.safe_string(ticker, 'price_change_percent_24h'))
1184
1184
  if percentage is None:
1185
- percentageRaw = self.safe_string(ticker, 'fluctuation')
1186
- if (percentageRaw is not None) and (percentageRaw != '0'): # a few tickers show strictly '0' in fluctuation field
1187
- direction = percentageRaw[0]
1188
- percentage = direction + Precise.string_mul(percentageRaw.replace(direction, ''), '100')
1189
- elif percentageRaw == '0':
1190
- percentage = '0'
1185
+ percentage = Precise.string_abs(Precise.string_mul(self.safe_string(ticker, 'fluctuation'), '100'))
1191
1186
  baseVolume = self.safe_string(ticker, 'base_volume_24h')
1192
1187
  quoteVolume = self.safe_string(ticker, 'quote_volume_24h')
1193
1188
  if quoteVolume is None:
ccxt/btcmarkets.py CHANGED
@@ -876,7 +876,9 @@ class btcmarkets(Exchange, ImplicitAPI):
876
876
  """
877
877
  calculates the presumptive fee that would be charged for an order
878
878
  :param str symbol: unified market symbol
879
- :param str type: not used by btcmarkets.calculate_fee :param string side: not used by btcmarkets.calculate_fee :param float amount: how much you want to trade, in units of the base currency on most exchanges, or number of contracts
879
+ :param str type: not used by btcmarkets.calculateFee
880
+ :param str side: not used by btcmarkets.calculateFee
881
+ :param float amount: how much you want to trade, in units of the base currency on most exchanges, or number of contracts
880
882
  :param float price: the price for the order to be filled at, in units of the quote currency
881
883
  :param str takerOrMaker: 'taker' or 'maker'
882
884
  :param dict params:
ccxt/bybit.py CHANGED
@@ -2079,7 +2079,7 @@ class bybit(Exchange, ImplicitAPI):
2079
2079
  }
2080
2080
  type = None
2081
2081
  type, params = self.handle_market_type_and_params('fetchTickers', market, params)
2082
- # Calls like `.fetch_tickers(None, {subType:'inverse'})` should be supported for self exchange, so
2082
+ # Calls like `.fetchTickers(None, {subType:'inverse'})` should be supported for self exchange, so
2083
2083
  # as "options.defaultSubType" is also set in exchange options, we should consider `params.subType`
2084
2084
  # with higher priority and only default to spot, if `subType` is not set in params
2085
2085
  passedSubType = self.safe_string(params, 'subType')
ccxt/coinbase.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.coinbase import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Balances, Conversion, Currencies, Currency, Int, Market, MarketInterface, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
9
+ from ccxt.base.types import Account, Balances, Conversion, Currencies, Currency, Int, Market, MarketInterface, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -121,8 +121,8 @@ class coinbase(Exchange, ImplicitAPI):
121
121
  'fetchTickers': True,
122
122
  'fetchTime': True,
123
123
  'fetchTrades': True,
124
- 'fetchTradingFee': False,
125
- 'fetchTradingFees': False,
124
+ 'fetchTradingFee': 'emulated',
125
+ 'fetchTradingFees': True,
126
126
  'fetchWithdrawals': True,
127
127
  'reduceMargin': False,
128
128
  'setLeverage': False,
@@ -4272,6 +4272,63 @@ class coinbase(Exchange, ImplicitAPI):
4272
4272
  'takeProfitPrice': None,
4273
4273
  })
4274
4274
 
4275
+ def fetch_trading_fees(self, params={}) -> TradingFees:
4276
+ """
4277
+ :see: https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_gettransactionsummary/
4278
+ fetch the trading fees for multiple markets
4279
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4280
+ :param str [params.type]: 'spot' or 'swap'
4281
+ :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
4282
+ """
4283
+ self.load_markets()
4284
+ type = None
4285
+ type, params = self.handle_market_type_and_params('fetchTradingFees', None, params)
4286
+ isSpot = (type == 'spot')
4287
+ productType = 'SPOT' if isSpot else 'FUTURE'
4288
+ request: dict = {
4289
+ 'product_type': productType,
4290
+ }
4291
+ response = self.v3PrivateGetBrokerageTransactionSummary(self.extend(request, params))
4292
+ #
4293
+ # {
4294
+ # total_volume: '0',
4295
+ # total_fees: '0',
4296
+ # fee_tier: {
4297
+ # pricing_tier: 'Advanced 1',
4298
+ # usd_from: '0',
4299
+ # usd_to: '1000',
4300
+ # taker_fee_rate: '0.008',
4301
+ # maker_fee_rate: '0.006',
4302
+ # aop_from: '',
4303
+ # aop_to: ''
4304
+ # },
4305
+ # margin_rate: null,
4306
+ # goods_and_services_tax: null,
4307
+ # advanced_trade_only_volume: '0',
4308
+ # advanced_trade_only_fees: '0',
4309
+ # coinbase_pro_volume: '0',
4310
+ # coinbase_pro_fees: '0',
4311
+ # total_balance: '',
4312
+ # has_promo_fee: False
4313
+ # }
4314
+ #
4315
+ data = self.safe_dict(response, 'fee_tier', {})
4316
+ taker_fee = self.safe_number(data, 'taker_fee_rate')
4317
+ marker_fee = self.safe_number(data, 'maker_fee_rate')
4318
+ result: dict = {}
4319
+ for i in range(0, len(self.symbols)):
4320
+ symbol = self.symbols[i]
4321
+ market = self.market(symbol)
4322
+ if (isSpot and market['spot']) or (not isSpot and not market['spot']):
4323
+ result[symbol] = {
4324
+ 'info': response,
4325
+ 'symbol': symbol,
4326
+ 'maker': taker_fee,
4327
+ 'taker': marker_fee,
4328
+ 'percentage': True,
4329
+ }
4330
+ return result
4331
+
4275
4332
  def create_auth_token(self, seconds: Int, method: Str = None, url: Str = None):
4276
4333
  # it may not work for v2
4277
4334
  uri = None
ccxt/coinex.py CHANGED
@@ -4374,7 +4374,7 @@ class coinex(Exchange, ImplicitAPI):
4374
4374
  def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
4375
4375
  """
4376
4376
  make a withdrawal
4377
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account015_submit_withdraw
4377
+ :see: https://docs.coinex.com/api/v2/assets/deposit-withdrawal/http/withdrawal
4378
4378
  :param str code: unified currency code
4379
4379
  :param float amount: the amount to withdraw
4380
4380
  :param str address: the address to withdraw to
@@ -4387,35 +4387,42 @@ class coinex(Exchange, ImplicitAPI):
4387
4387
  self.check_address(address)
4388
4388
  self.load_markets()
4389
4389
  currency = self.currency(code)
4390
- networkCode = self.safe_string_upper(params, 'network')
4390
+ networkCode = self.safe_string_upper_2(params, 'network', 'chain')
4391
4391
  params = self.omit(params, 'network')
4392
4392
  if tag:
4393
4393
  address = address + ':' + tag
4394
4394
  request: dict = {
4395
- 'coin_type': currency['id'],
4396
- 'coin_address': address, # must be authorized, inter-user transfer by a registered mobile phone number or an email address is supported
4397
- 'actual_amount': float(self.number_to_string(amount)), # the actual amount without fees, https://www.coinex.com/fees
4398
- 'transfer_method': 'onchain', # onchain, local
4395
+ 'ccy': currency['id'],
4396
+ 'to_address': address, # must be authorized, inter-user transfer by a registered mobile phone number or an email address is supported
4397
+ 'amount': self.number_to_string(amount), # the actual amount without fees, https://www.coinex.com/fees
4399
4398
  }
4400
4399
  if networkCode is not None:
4401
- request['smart_contract_name'] = self.network_code_to_id(networkCode)
4402
- response = self.v1PrivatePostBalanceCoinWithdraw(self.extend(request, params))
4400
+ request['chain'] = self.network_code_to_id(networkCode) # required for on-chain, not required for inter-user transfer
4401
+ response = self.v2PrivatePostAssetsWithdraw(self.extend(request, params))
4403
4402
  #
4404
4403
  # {
4405
4404
  # "code": 0,
4406
4405
  # "data": {
4407
- # "actual_amount": "1.00000000",
4408
- # "amount": "1.00000000",
4409
- # "coin_address": "1KAv3pazbTk2JnQ5xTo6fpKK7p1it2RzD4",
4410
- # "coin_type": "BCH",
4411
- # "coin_withdraw_id": 206,
4406
+ # "withdraw_id": 31193755,
4407
+ # "created_at": 1716874165038,
4408
+ # "withdraw_method": "ON_CHAIN",
4409
+ # "ccy": "USDT",
4410
+ # "amount": "17.3",
4411
+ # "actual_amount": "15",
4412
+ # "chain": "TRC20",
4413
+ # "tx_fee": "2.3",
4414
+ # "fee_asset": "USDT",
4415
+ # "fee_amount": "2.3",
4416
+ # "to_address": "TY5vq3MT6b5cQVAHWHtpGyPg1ERcQgi3UN",
4417
+ # "memo": "",
4418
+ # "tx_id": "",
4412
4419
  # "confirmations": 0,
4413
- # "create_time": 1524228297,
4414
- # "status": "audit",
4415
- # "tx_fee": "0",
4416
- # "tx_id": ""
4420
+ # "explorer_address_url": "https://tronscan.org/#/address/TY5vq3MT6b5cQVAHWHtpGyPg1ERcQgi3UN",
4421
+ # "explorer_tx_url": "https://tronscan.org/#/transaction/",
4422
+ # "remark": "",
4423
+ # "status": "audit_required"
4417
4424
  # },
4418
- # "message": "Ok"
4425
+ # "message": "OK"
4419
4426
  # }
4420
4427
  #
4421
4428
  transaction = self.safe_dict(response, 'data', {})
@@ -4519,7 +4526,7 @@ class coinex(Exchange, ImplicitAPI):
4519
4526
  # "remark": ""
4520
4527
  # }
4521
4528
  #
4522
- # fetchWithdrawals
4529
+ # fetchWithdrawals and withdraw
4523
4530
  #
4524
4531
  # {
4525
4532
  # "withdraw_id": 259364,
ccxt/gemini.py CHANGED
@@ -831,7 +831,7 @@ class gemini(Exchange, ImplicitAPI):
831
831
  :see: https://docs.gemini.com/rest-api/#ticker-v2
832
832
  :param str symbol: unified symbol of the market to fetch the ticker for
833
833
  :param dict [params]: extra parameters specific to the exchange API endpoint
834
- :param dict [params.fetchTickerMethod]: 'fetchTickerV2', 'fetchTickerV1' or 'fetchTickerV1AndV2' - 'fetchTickerV1' for original ccxt.gemini.fetch_ticker- 'fetchTickerV1AndV2' for 2 api calls to get the result of both fetchTicker methods - default = 'fetchTickerV1'
834
+ :param dict [params.fetchTickerMethod]: 'fetchTickerV2', 'fetchTickerV1' or 'fetchTickerV1AndV2' - 'fetchTickerV1' for original ccxt.gemini.fetchTicker - 'fetchTickerV1AndV2' for 2 api calls to get the result of both fetchTicker methods - default = 'fetchTickerV1'
835
835
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
836
836
  """
837
837
  method = self.safe_value(self.options, 'fetchTickerMethod', 'fetchTickerV1')
ccxt/kraken.py CHANGED
@@ -970,7 +970,9 @@ class kraken(Exchange, ImplicitAPI):
970
970
  else:
971
971
  request['interval'] = timeframe
972
972
  if since is not None:
973
- request['since'] = self.number_to_string(self.parse_to_int(since / 1000)) # expected to be in seconds
973
+ scaledSince = self.parse_to_int(since / 1000)
974
+ timeFrameInSeconds = parsedTimeframe * 60
975
+ request['since'] = self.number_to_string(scaledSince - timeFrameInSeconds) # expected to be in seconds
974
976
  response = self.publicGetOHLC(self.extend(request, params))
975
977
  #
976
978
  # {
ccxt/paymium.py CHANGED
@@ -407,7 +407,10 @@ class paymium(Exchange, ImplicitAPI):
407
407
  request: dict = {
408
408
  'uuid': id,
409
409
  }
410
- return self.privateDeleteUserOrdersUuidCancel(self.extend(request, params))
410
+ response = self.privateDeleteUserOrdersUuidCancel(self.extend(request, params))
411
+ return self.safe_order({
412
+ 'info': response,
413
+ })
411
414
 
412
415
  def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
413
416
  """
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.34'
7
+ __version__ = '4.3.36'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/binance.py CHANGED
@@ -691,10 +691,10 @@ class binance(ccxt.async_support.binance):
691
691
  # todo: self is a synch blocking call - make it async
692
692
  # default 100, max 1000, valid limits 5, 10, 20, 50, 100, 500, 1000
693
693
  snapshot = await self.fetch_rest_order_book_safe(symbol, limit, params)
694
- orderbook = self.safe_value(self.orderbooks, symbol)
695
- if orderbook is None:
694
+ if self.safe_value(self.orderbooks, symbol) is None:
696
695
  # if the orderbook is dropped before the snapshot is received
697
696
  return
697
+ orderbook = self.orderbooks[symbol]
698
698
  orderbook.reset(snapshot)
699
699
  # unroll the accumulated deltas
700
700
  messages = orderbook.cache
@@ -770,8 +770,7 @@ class binance(ccxt.async_support.binance):
770
770
  symbol = market['symbol']
771
771
  name = 'depth'
772
772
  messageHash = market['lowercaseId'] + '@' + name
773
- orderbook = self.safe_value(self.orderbooks, symbol)
774
- if orderbook is None:
773
+ if not (symbol in self.orderbooks):
775
774
  #
776
775
  # https://github.com/ccxt/ccxt/issues/6672
777
776
  #
@@ -781,6 +780,7 @@ class binance(ccxt.async_support.binance):
781
780
  # therefore it is safe to drop these premature messages.
782
781
  #
783
782
  return
783
+ orderbook = self.orderbooks[symbol]
784
784
  nonce = self.safe_integer(orderbook, 'nonce')
785
785
  if nonce is None:
786
786
  # 2. Buffer the events you receive from the stream.
ccxt/pro/bingx.py CHANGED
@@ -928,13 +928,16 @@ class bingx(ccxt.async_support.bingx):
928
928
  # }
929
929
  #
930
930
  isSpot = ('dataType' in message)
931
- result = self.safe_value_2(message, 'data', 'o', {})
931
+ result = self.safe_dict_2(message, 'data', 'o', {})
932
932
  cachedTrades = self.myTrades
933
933
  if cachedTrades is None:
934
934
  limit = self.safe_integer(self.options, 'tradesLimit', 1000)
935
935
  cachedTrades = ArrayCacheBySymbolById(limit)
936
936
  self.myTrades = cachedTrades
937
- parsed = self.parse_trade(result)
937
+ type = 'spot' if isSpot else 'swap'
938
+ marketId = self.safe_string(result, 's')
939
+ market = self.safe_market(marketId, None, '-', type)
940
+ parsed = self.parse_trade(result, market)
938
941
  symbol = parsed['symbol']
939
942
  spotHash = 'spot:mytrades'
940
943
  swapHash = 'swap:mytrades'
@@ -980,10 +983,12 @@ class bingx(ccxt.async_support.bingx):
980
983
  # }
981
984
  # }
982
985
  #
983
- a = self.safe_value(message, 'a', {})
984
- data = self.safe_value(a, 'B', [])
986
+ a = self.safe_dict(message, 'a', {})
987
+ data = self.safe_list(a, 'B', [])
985
988
  timestamp = self.safe_integer_2(message, 'T', 'E')
986
989
  type = 'swap' if ('P' in a) else 'spot'
990
+ if not (type in self.balance):
991
+ self.balance[type] = {}
987
992
  self.balance[type]['info'] = data
988
993
  self.balance[type]['timestamp'] = timestamp
989
994
  self.balance[type]['datetime'] = self.iso8601(timestamp)
ccxt/pro/bitfinex2.py CHANGED
@@ -551,8 +551,7 @@ class bitfinex2(ccxt.async_support.bitfinex2):
551
551
  prec = self.safe_string(subscription, 'prec', 'P0')
552
552
  isRaw = (prec == 'R0')
553
553
  # if it is an initial snapshot
554
- orderbook = self.safe_value(self.orderbooks, symbol)
555
- if orderbook is None:
554
+ if not (symbol in self.orderbooks):
556
555
  limit = self.safe_integer(subscription, 'len')
557
556
  if isRaw:
558
557
  # raw order books
@@ -571,7 +570,7 @@ class bitfinex2(ccxt.async_support.bitfinex2):
571
570
  bookside = orderbook[side]
572
571
  idString = self.safe_string(delta, 0)
573
572
  price = self.safe_float(delta, 1)
574
- bookside.store(price, size, idString)
573
+ bookside.storeArray([price, size, idString])
575
574
  else:
576
575
  deltas = message[1]
577
576
  for i in range(0, len(deltas)):
@@ -582,10 +581,11 @@ class bitfinex2(ccxt.async_support.bitfinex2):
582
581
  size = -amount if (amount < 0) else amount
583
582
  side = 'asks' if (amount < 0) else 'bids'
584
583
  bookside = orderbook[side]
585
- bookside.store(price, size, counter)
584
+ bookside.storeArray([price, size, counter])
586
585
  orderbook['symbol'] = symbol
587
586
  client.resolve(orderbook, messageHash)
588
587
  else:
588
+ orderbook = self.orderbooks[symbol]
589
589
  deltas = message[1]
590
590
  orderbookItem = self.orderbooks[symbol]
591
591
  if isRaw:
ccxt/pro/bitget.py CHANGED
@@ -917,7 +917,9 @@ class bitget(ccxt.async_support.bitget):
917
917
  :param int [limit]: the maximum number of order structures to retrieve
918
918
  :param dict [params]: extra parameters specific to the exchange API endpoint
919
919
  :param boolean [params.stop]: *contract only* set to True for watching trigger orders
920
- :param str [params.marginMode]: 'isolated' or 'cross' for watching spot margin orders
920
+ :param str [params.marginMode]: 'isolated' or 'cross' for watching spot margin orders]
921
+ :param str [params.type]: 'spot', 'swap'
922
+ :param str [params.subType]: 'linear', 'inverse'
921
923
  :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
922
924
  """
923
925
  await self.load_markets()
@@ -932,10 +934,21 @@ class bitget(ccxt.async_support.bitget):
932
934
  symbol = market['symbol']
933
935
  marketId = market['id']
934
936
  messageHash = messageHash + ':' + symbol
937
+ productType = self.safe_string(params, 'productType')
935
938
  type = None
936
939
  type, params = self.handle_market_type_and_params('watchOrders', market, params)
940
+ subType = None
941
+ subType, params = self.handle_sub_type_and_params('watchOrders', market, params, 'linear')
937
942
  if (type == 'spot') and (symbol is None):
938
943
  raise ArgumentsRequired(self.id + ' watchOrders requires a symbol argument for ' + type + ' markets.')
944
+ if (productType is None) and (type != 'spot') and (symbol is None):
945
+ messageHash = messageHash + ':' + subType
946
+ elif productType == 'USDT-FUTURES':
947
+ messageHash = messageHash + ':linear'
948
+ elif productType == 'COIN-FUTURES':
949
+ messageHash = messageHash + ':inverse'
950
+ elif productType == 'USDC-FUTURES':
951
+ messageHash = messageHash + ':usdcfutures' # non unified channel
939
952
  instType = None
940
953
  instType, params = self.get_inst_type(market, params)
941
954
  if type == 'spot':
@@ -952,6 +965,7 @@ class bitget(ccxt.async_support.bitget):
952
965
  channel = 'orders-isolated'
953
966
  else:
954
967
  channel = 'orders-crossed'
968
+ subscriptionHash = subscriptionHash + ':' + instType
955
969
  args: dict = {
956
970
  'instType': instType,
957
971
  'channel': channel,
@@ -1007,6 +1021,9 @@ class bitget(ccxt.async_support.bitget):
1007
1021
  marketType = 'spot'
1008
1022
  else:
1009
1023
  marketType = 'contract'
1024
+ isLinearSwap = (instType == 'USDT-FUTURES')
1025
+ isInverseSwap = (instType == 'COIN-FUTURES')
1026
+ isUSDCFutures = (instType == 'USDC-FUTURES')
1010
1027
  data = self.safe_value(message, 'data', [])
1011
1028
  if self.orders is None:
1012
1029
  limit = self.safe_integer(self.options, 'ordersLimit', 1000)
@@ -1030,6 +1047,12 @@ class bitget(ccxt.async_support.bitget):
1030
1047
  innerMessageHash = messageHash + ':' + symbol
1031
1048
  client.resolve(stored, innerMessageHash)
1032
1049
  client.resolve(stored, messageHash)
1050
+ if isLinearSwap:
1051
+ client.resolve(stored, 'order:linear')
1052
+ if isInverseSwap:
1053
+ client.resolve(stored, 'order:inverse')
1054
+ if isUSDCFutures:
1055
+ client.resolve(stored, 'order:usdcfutures')
1033
1056
 
1034
1057
  def parse_ws_order(self, order, market=None):
1035
1058
  #
ccxt/pro/bitmart.py CHANGED
@@ -12,7 +12,6 @@ from ccxt.async_support.base.ws.client import Client
12
12
  from typing import List
13
13
  from ccxt.base.errors import ExchangeError
14
14
  from ccxt.base.errors import AuthenticationError
15
- from ccxt.base.errors import ArgumentsRequired
16
15
  from ccxt.base.errors import NotSupported
17
16
 
18
17
 
@@ -333,9 +332,9 @@ class bitmart(ccxt.async_support.bitmart):
333
332
 
334
333
  async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
335
334
  """
336
- :see: https://developer-pro.bitmart.com/en/spot/#private-order-channel
337
- :see: https://developer-pro.bitmart.com/en/futures/#private-order-channel
338
335
  watches information on multiple orders made by the user
336
+ :see: https://developer-pro.bitmart.com/en/spot/#private-order-progress
337
+ :see: https://developer-pro.bitmart.com/en/futures/#private-order-channel
339
338
  :param str symbol: unified market symbol of the market orders were made in
340
339
  :param int [since]: the earliest time in ms to fetch orders for
341
340
  :param int [limit]: the maximum number of order structures to retrieve
@@ -354,11 +353,14 @@ class bitmart(ccxt.async_support.bitmart):
354
353
  await self.authenticate(type, params)
355
354
  request = None
356
355
  if type == 'spot':
357
- if symbol is None:
358
- raise ArgumentsRequired(self.id + ' watchOrders() requires a symbol argument for spot markets')
356
+ argsRequest = 'spot/user/order:'
357
+ if symbol is not None:
358
+ argsRequest += market['id']
359
+ else:
360
+ argsRequest = 'spot/user/orders:ALL_SYMBOLS'
359
361
  request = {
360
362
  'op': 'subscribe',
361
- 'args': ['spot/user/order:' + market['id']],
363
+ 'args': [argsRequest],
362
364
  }
363
365
  else:
364
366
  request = {
@@ -506,7 +508,7 @@ class bitmart(ccxt.async_support.bitmart):
506
508
  amount = self.safe_string(order, 'size')
507
509
  type = self.safe_string(order, 'type')
508
510
  rawState = self.safe_string(order, 'state')
509
- status = self.parseOrderStatusByType(market['type'], rawState)
511
+ status = self.parse_order_status_by_type(market['type'], rawState)
510
512
  timestamp = self.safe_integer(order, 'ms_t')
511
513
  symbol = market['symbol']
512
514
  side = self.safe_string_lower(order, 'side')
ccxt/pro/bybit.py CHANGED
@@ -678,21 +678,21 @@ class bybit(ccxt.async_support.bybit):
678
678
  isSpot = client.url.find('spot') >= 0
679
679
  type = self.safe_string(message, 'type')
680
680
  isSnapshot = (type == 'snapshot')
681
- data = self.safe_value(message, 'data', {})
681
+ data = self.safe_dict(message, 'data', {})
682
682
  marketId = self.safe_string(data, 's')
683
683
  marketType = 'spot' if isSpot else 'contract'
684
684
  market = self.safe_market(marketId, None, None, marketType)
685
685
  symbol = market['symbol']
686
686
  timestamp = self.safe_integer(message, 'ts')
687
- orderbook = self.safe_value(self.orderbooks, symbol)
688
- if orderbook is None:
689
- orderbook = self.order_book()
687
+ if not (symbol in self.orderbooks):
688
+ self.orderbooks[symbol] = self.order_book()
689
+ orderbook = self.orderbooks[symbol]
690
690
  if isSnapshot:
691
691
  snapshot = self.parse_order_book(data, symbol, timestamp, 'b', 'a')
692
692
  orderbook.reset(snapshot)
693
693
  else:
694
- asks = self.safe_value(data, 'a', [])
695
- bids = self.safe_value(data, 'b', [])
694
+ asks = self.safe_list(data, 'a', [])
695
+ bids = self.safe_list(data, 'b', [])
696
696
  self.handle_deltas(orderbook['asks'], asks)
697
697
  self.handle_deltas(orderbook['bids'], bids)
698
698
  orderbook['timestamp'] = timestamp
ccxt/pro/htx.py CHANGED
@@ -608,19 +608,18 @@ class htx(ccxt.async_support.htx):
608
608
  # }
609
609
  #
610
610
  messageHash = self.safe_string(message, 'ch')
611
- tick = self.safe_value(message, 'tick')
611
+ tick = self.safe_dict(message, 'tick')
612
612
  event = self.safe_string(tick, 'event')
613
- ch = self.safe_value(message, 'ch')
613
+ ch = self.safe_string(message, 'ch')
614
614
  parts = ch.split('.')
615
615
  marketId = self.safe_string(parts, 1)
616
616
  symbol = self.safe_symbol(marketId)
617
- orderbook = self.safe_value(self.orderbooks, symbol)
618
- if orderbook is None:
617
+ if not (symbol in self.orderbooks):
619
618
  size = self.safe_string(parts, 3)
620
619
  sizeParts = size.split('_')
621
620
  limit = self.safe_integer(sizeParts, 1)
622
- orderbook = self.order_book({}, limit)
623
- self.orderbooks[symbol] = orderbook
621
+ self.orderbooks[symbol] = self.order_book({}, limit)
622
+ orderbook = self.orderbooks[symbol]
624
623
  if (event is None) and (orderbook['nonce'] is None):
625
624
  orderbook.cache.append(message)
626
625
  else:
ccxt/pro/kraken.py CHANGED
@@ -1230,7 +1230,7 @@ class kraken(ccxt.async_support.kraken):
1230
1230
  messageHashes = []
1231
1231
  for i in range(0, len(symbols)):
1232
1232
  messageHashes.append(self.get_message_hash(unifiedName, None, self.symbol(symbols[i])))
1233
- # for WS subscriptions, we can't use .market_ids(symbols), instead a custom is field needed
1233
+ # for WS subscriptions, we can't use .marketIds(symbols), instead a custom is field needed
1234
1234
  markets = self.markets_for_symbols(symbols)
1235
1235
  wsMarketIds = []
1236
1236
  for i in range(0, len(markets)):
ccxt/pro/okx.py CHANGED
@@ -164,7 +164,7 @@ class okx(ccxt.async_support.okx):
164
164
  self.deep_extend(firstArgument, params),
165
165
  ],
166
166
  }
167
- return self.watch(url, messageHash, request, messageHash)
167
+ return await self.watch(url, messageHash, request, messageHash)
168
168
 
169
169
  async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
170
170
  """
@@ -1004,10 +1004,9 @@ class okx(ccxt.async_support.okx):
1004
1004
  self.handle_order_book_message(client, update, orderbook, messageHash)
1005
1005
  client.resolve(orderbook, messageHash)
1006
1006
  elif (channel == 'books5') or (channel == 'bbo-tbt'):
1007
- orderbook = self.safe_value(self.orderbooks, symbol)
1008
- if orderbook is None:
1009
- orderbook = self.order_book({}, limit)
1010
- self.orderbooks[symbol] = orderbook
1007
+ if not (symbol in self.orderbooks):
1008
+ self.orderbooks[symbol] = self.order_book({}, limit)
1009
+ orderbook = self.orderbooks[symbol]
1011
1010
  for i in range(0, len(data)):
1012
1011
  update = data[i]
1013
1012
  timestamp = self.safe_integer(update, 'ts')
ccxt/pro/woo.py CHANGED
@@ -130,14 +130,14 @@ class woo(ccxt.async_support.woo):
130
130
  # }
131
131
  # }
132
132
  #
133
- data = self.safe_value(message, 'data')
133
+ data = self.safe_dict(message, 'data')
134
134
  marketId = self.safe_string(data, 'symbol')
135
135
  market = self.safe_market(marketId)
136
136
  symbol = market['symbol']
137
137
  topic = self.safe_string(message, 'topic')
138
- orderbook = self.safe_value(self.orderbooks, symbol)
139
- if orderbook is None:
140
- orderbook = self.order_book({})
138
+ if not (symbol in self.orderbooks):
139
+ self.orderbooks[symbol] = self.order_book({})
140
+ orderbook = self.orderbooks[symbol]
141
141
  timestamp = self.safe_integer(message, 'ts')
142
142
  snapshot = self.parse_order_book(data, symbol, timestamp, 'bids', 'asks')
143
143
  orderbook.reset(snapshot)
@@ -42,7 +42,7 @@ assert hash(encode('sexyfish'), 'md5', 'hex') == 'c8a35464aa9d5683585786f44d5889
42
42
  assert hash(encode(''), 'sha1', 'hex') == 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
43
43
  assert hash(encode('nutella'), 'sha1', 'hex') == 'b3d60a34b744159793c483b067c56d8affc5111a'
44
44
  assert hmac(encode('hello'), encode('there'), hashlib.sha256, 'hex') == '551e1c1ecbce0fe9b643745a376584a6289f5f43a46861b315fac9edc8d52a26'
45
- assert hmac(encode('a message'), encode('a secret'), 'md5', 'hex') == '0bfa503bdbc7358185fcd49b4869e23d'
45
+ assert hmac(encode('a message'), encode('a secret'), hashlib.md5, 'hex') == '0bfa503bdbc7358185fcd49b4869e23d'
46
46
 
47
47
  # ---------------------------------------------------------------------------------------------------------------------
48
48