ccxt 4.2.38__py2.py3-none-any.whl → 4.2.40__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 (141) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/bingx.py +4 -0
  3. ccxt/abstract/coinbase.py +1 -0
  4. ccxt/abstract/coinbasepro.py +1 -0
  5. ccxt/abstract/okx.py +1 -0
  6. ccxt/ascendex.py +31 -27
  7. ccxt/async_support/__init__.py +1 -1
  8. ccxt/async_support/ascendex.py +31 -27
  9. ccxt/async_support/base/exchange.py +19 -7
  10. ccxt/async_support/bigone.py +2 -2
  11. ccxt/async_support/binance.py +478 -188
  12. ccxt/async_support/bingx.py +250 -28
  13. ccxt/async_support/bitfinex.py +3 -3
  14. ccxt/async_support/bitfinex2.py +2 -2
  15. ccxt/async_support/bitget.py +16 -7
  16. ccxt/async_support/bitmart.py +2 -2
  17. ccxt/async_support/bitmex.py +2 -2
  18. ccxt/async_support/bitrue.py +2 -2
  19. ccxt/async_support/bitso.py +19 -3
  20. ccxt/async_support/bitstamp.py +25 -3
  21. ccxt/async_support/bitvavo.py +1 -1
  22. ccxt/async_support/bl3p.py +6 -0
  23. ccxt/async_support/blockchaincom.py +21 -0
  24. ccxt/async_support/blofin.py +2 -2
  25. ccxt/async_support/btcalpha.py +9 -0
  26. ccxt/async_support/btcbox.py +9 -0
  27. ccxt/async_support/btcmarkets.py +19 -0
  28. ccxt/async_support/bybit.py +9 -7
  29. ccxt/async_support/cex.py +1 -1
  30. ccxt/async_support/coinbase.py +20 -9
  31. ccxt/async_support/coinbasepro.py +1 -0
  32. ccxt/async_support/coinex.py +4 -4
  33. ccxt/async_support/coinlist.py +11 -9
  34. ccxt/async_support/coinmetro.py +2 -1
  35. ccxt/async_support/coinone.py +1 -1
  36. ccxt/async_support/delta.py +2 -2
  37. ccxt/async_support/deribit.py +3 -3
  38. ccxt/async_support/digifinex.py +3 -3
  39. ccxt/async_support/exmo.py +2 -2
  40. ccxt/async_support/gate.py +6 -6
  41. ccxt/async_support/hitbtc.py +2 -2
  42. ccxt/async_support/hollaex.py +1 -1
  43. ccxt/async_support/htx.py +3 -3
  44. ccxt/async_support/huobijp.py +1 -1
  45. ccxt/async_support/kraken.py +2 -2
  46. ccxt/async_support/krakenfutures.py +117 -16
  47. ccxt/async_support/kucoin.py +5 -5
  48. ccxt/async_support/kucoinfutures.py +2 -2
  49. ccxt/async_support/latoken.py +1 -1
  50. ccxt/async_support/lbank.py +2 -2
  51. ccxt/async_support/luno.py +2 -2
  52. ccxt/async_support/mexc.py +5 -5
  53. ccxt/async_support/ndax.py +1 -1
  54. ccxt/async_support/novadax.py +1 -1
  55. ccxt/async_support/okcoin.py +2 -2
  56. ccxt/async_support/okx.py +18 -21
  57. ccxt/async_support/paymium.py +2 -2
  58. ccxt/async_support/phemex.py +5 -4
  59. ccxt/async_support/poloniex.py +2 -2
  60. ccxt/async_support/poloniexfutures.py +10 -6
  61. ccxt/async_support/probit.py +1 -1
  62. ccxt/async_support/timex.py +1 -1
  63. ccxt/async_support/upbit.py +1 -1
  64. ccxt/async_support/wavesexchange.py +1 -1
  65. ccxt/async_support/whitebit.py +2 -2
  66. ccxt/async_support/woo.py +4 -4
  67. ccxt/async_support/zonda.py +3 -3
  68. ccxt/base/exchange.py +37 -25
  69. ccxt/bigone.py +2 -2
  70. ccxt/binance.py +478 -188
  71. ccxt/bingx.py +250 -28
  72. ccxt/bitfinex.py +3 -3
  73. ccxt/bitfinex2.py +2 -2
  74. ccxt/bitget.py +16 -7
  75. ccxt/bitmart.py +2 -2
  76. ccxt/bitmex.py +2 -2
  77. ccxt/bitrue.py +2 -2
  78. ccxt/bitso.py +19 -3
  79. ccxt/bitstamp.py +25 -3
  80. ccxt/bitvavo.py +1 -1
  81. ccxt/bl3p.py +6 -0
  82. ccxt/blockchaincom.py +21 -0
  83. ccxt/blofin.py +2 -2
  84. ccxt/btcalpha.py +9 -0
  85. ccxt/btcbox.py +9 -0
  86. ccxt/btcmarkets.py +19 -0
  87. ccxt/bybit.py +9 -7
  88. ccxt/cex.py +1 -1
  89. ccxt/coinbase.py +20 -9
  90. ccxt/coinbasepro.py +1 -0
  91. ccxt/coinex.py +4 -4
  92. ccxt/coinlist.py +11 -9
  93. ccxt/coinmetro.py +2 -1
  94. ccxt/coinone.py +1 -1
  95. ccxt/delta.py +2 -2
  96. ccxt/deribit.py +3 -3
  97. ccxt/digifinex.py +3 -3
  98. ccxt/exmo.py +2 -2
  99. ccxt/gate.py +6 -6
  100. ccxt/hitbtc.py +2 -2
  101. ccxt/hollaex.py +1 -1
  102. ccxt/htx.py +3 -3
  103. ccxt/huobijp.py +1 -1
  104. ccxt/kraken.py +2 -2
  105. ccxt/krakenfutures.py +117 -16
  106. ccxt/kucoin.py +5 -5
  107. ccxt/kucoinfutures.py +2 -2
  108. ccxt/latoken.py +1 -1
  109. ccxt/lbank.py +2 -2
  110. ccxt/luno.py +2 -2
  111. ccxt/mexc.py +5 -5
  112. ccxt/ndax.py +1 -1
  113. ccxt/novadax.py +1 -1
  114. ccxt/okcoin.py +2 -2
  115. ccxt/okx.py +18 -21
  116. ccxt/paymium.py +2 -2
  117. ccxt/phemex.py +5 -4
  118. ccxt/poloniex.py +2 -2
  119. ccxt/poloniexfutures.py +10 -6
  120. ccxt/pro/__init__.py +1 -1
  121. ccxt/pro/bitmart.py +129 -46
  122. ccxt/pro/bitvavo.py +1 -1
  123. ccxt/pro/bybit.py +6 -6
  124. ccxt/pro/cex.py +2 -2
  125. ccxt/pro/coinbase.py +2 -2
  126. ccxt/pro/coinex.py +1 -1
  127. ccxt/pro/lbank.py +1 -1
  128. ccxt/pro/mexc.py +1 -1
  129. ccxt/probit.py +1 -1
  130. ccxt/test/test_async.py +3 -1
  131. ccxt/test/test_sync.py +3 -1
  132. ccxt/timex.py +1 -1
  133. ccxt/upbit.py +1 -1
  134. ccxt/wavesexchange.py +1 -1
  135. ccxt/whitebit.py +2 -2
  136. ccxt/woo.py +4 -4
  137. ccxt/zonda.py +3 -3
  138. {ccxt-4.2.38.dist-info → ccxt-4.2.40.dist-info}/METADATA +4 -4
  139. {ccxt-4.2.38.dist-info → ccxt-4.2.40.dist-info}/RECORD +141 -141
  140. {ccxt-4.2.38.dist-info → ccxt-4.2.40.dist-info}/WHEEL +0 -0
  141. {ccxt-4.2.38.dist-info → ccxt-4.2.40.dist-info}/top_level.txt +0 -0
ccxt/phemex.py CHANGED
@@ -50,6 +50,7 @@ class phemex(Exchange, ImplicitAPI):
50
50
  'addMargin': False,
51
51
  'cancelAllOrders': True,
52
52
  'cancelOrder': True,
53
+ 'closePosition': False,
53
54
  'createOrder': True,
54
55
  'createReduceOnlyOrder': True,
55
56
  'createStopLimitOrder': True,
@@ -2589,7 +2590,7 @@ class phemex(Exchange, ImplicitAPI):
2589
2590
  data = self.safe_value(response, 'data', {})
2590
2591
  return self.parse_order(data, market)
2591
2592
 
2592
- def edit_order(self, id: str, symbol, type=None, side=None, amount=None, price=None, params={}):
2593
+ def edit_order(self, id: str, symbol: str, type: OrderType = None, side: OrderSide = None, amount: float = None, price: float = None, params={}):
2593
2594
  """
2594
2595
  edit a trade order
2595
2596
  :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#amend-order-by-orderid
@@ -3797,7 +3798,7 @@ class phemex(Exchange, ImplicitAPI):
3797
3798
  'status': self.parse_margin_status(self.safe_string(data, 'code')),
3798
3799
  }
3799
3800
 
3800
- def set_margin_mode(self, marginMode, symbol: Str = None, params={}):
3801
+ def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
3801
3802
  """
3802
3803
  set margin mode to 'cross' or 'isolated'
3803
3804
  :param str marginMode: 'cross' or 'isolated'
@@ -3825,7 +3826,7 @@ class phemex(Exchange, ImplicitAPI):
3825
3826
  }
3826
3827
  return self.privatePutPositionsLeverage(self.extend(request, params))
3827
3828
 
3828
- def set_position_mode(self, hedged, symbol: Str = None, params={}):
3829
+ def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
3829
3830
  """
3830
3831
  set hedged to True or False for a market
3831
3832
  :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#switch-position-mode-synchronously
@@ -4054,7 +4055,7 @@ class phemex(Exchange, ImplicitAPI):
4054
4055
  response = self.privatePutPositionsLeverage(self.extend(request, params))
4055
4056
  return response
4056
4057
 
4057
- def transfer(self, code: str, amount: float, fromAccount, toAccount, params={}) -> TransferEntry:
4058
+ def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
4058
4059
  """
4059
4060
  transfer currency internally between wallets on the same account
4060
4061
  :param str code: unified currency code
ccxt/poloniex.py CHANGED
@@ -1300,7 +1300,7 @@ class poloniex(Exchange, ImplicitAPI):
1300
1300
  # remember the timestamp before issuing the request
1301
1301
  return [request, params]
1302
1302
 
1303
- def edit_order(self, id: str, symbol, type, side, amount=None, price=None, params={}):
1303
+ def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: float = None, price: float = None, params={}):
1304
1304
  """
1305
1305
  edit a trade order
1306
1306
  :see: https://docs.poloniex.com/#authenticated-endpoints-orders-cancel-replace-order
@@ -1736,7 +1736,7 @@ class poloniex(Exchange, ImplicitAPI):
1736
1736
  'info': response,
1737
1737
  }
1738
1738
 
1739
- def transfer(self, code: str, amount: float, fromAccount, toAccount, params={}) -> TransferEntry:
1739
+ def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
1740
1740
  """
1741
1741
  transfer currency internally between wallets on the same account
1742
1742
  :see: https://docs.poloniex.com/#authenticated-endpoints-accounts-accounts-transfer
ccxt/poloniexfutures.py CHANGED
@@ -1321,7 +1321,7 @@ class poloniexfutures(Exchange, ImplicitAPI):
1321
1321
  """
1322
1322
  return self.fetch_orders_by_status('closed', symbol, since, limit, params)
1323
1323
 
1324
- def fetch_order(self, id=None, symbol: Str = None, params={}):
1324
+ def fetch_order(self, id: str = None, symbol: Str = None, params={}):
1325
1325
  """
1326
1326
  fetches information on an order made by the user
1327
1327
  :see: https://futures-docs.poloniex.com/#get-details-of-a-single-order
@@ -1619,24 +1619,28 @@ class poloniexfutures(Exchange, ImplicitAPI):
1619
1619
  trades = self.safe_value(data, 'items', {})
1620
1620
  return self.parse_trades(trades, market, since, limit)
1621
1621
 
1622
- def set_margin_mode(self, marginMode, symbol, params={}):
1622
+ def set_margin_mode(self, marginMode: str, symbol: str = None, params={}):
1623
1623
  """
1624
1624
  set margin mode to 'cross' or 'isolated'
1625
1625
  :see: https://futures-docs.poloniex.com/#change-margin-mode
1626
- :param int marginMode: 0(isolated) or 1(cross)
1626
+ :param str marginMode: "0"(isolated) or "1"(cross)
1627
1627
  :param str symbol: unified market symbol
1628
1628
  :param dict [params]: extra parameters specific to the exchange API endpoint
1629
1629
  :returns dict: response from the exchange
1630
1630
  """
1631
1631
  if symbol is None:
1632
1632
  raise ArgumentsRequired(self.id + ' setMarginMode() requires a symbol argument')
1633
- if (marginMode != 0) and (marginMode != 1):
1634
- raise ArgumentsRequired(self.id + ' setMarginMode() marginMode must be 0(isolated) or 1(cross)')
1633
+ if (marginMode != '0') and (marginMode != '1') and (marginMode != 'isolated') and (marginMode != 'cross'):
1634
+ raise ArgumentsRequired(self.id + ' setMarginMode() marginMode must be 0/isolated or 1/cross')
1635
1635
  self.load_markets()
1636
+ if marginMode == 'isolated':
1637
+ marginMode = '0'
1638
+ if marginMode == 'cross':
1639
+ marginMode = '1'
1636
1640
  market = self.market(symbol)
1637
1641
  request = {
1638
1642
  'symbol': market['id'],
1639
- 'marginType': marginMode,
1643
+ 'marginType': self.parse_to_int(marginMode),
1640
1644
  }
1641
1645
  return self.privatePostMarginTypeChange(request)
1642
1646
 
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.38'
7
+ __version__ = '4.2.40'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/bitmart.py CHANGED
@@ -33,8 +33,10 @@ class bitmart(ccxt.async_support.bitmart):
33
33
  'watchTicker': True,
34
34
  'watchTickers': True,
35
35
  'watchOrderBook': True,
36
+ 'watchOrderBookForSymbols': True,
36
37
  'watchOrders': True,
37
38
  'watchTrades': True,
39
+ 'watchTradesForSymbols': True,
38
40
  'watchOHLCV': True,
39
41
  'watchPosition': 'emulated',
40
42
  'watchPositions': True,
@@ -59,8 +61,15 @@ class bitmart(ccxt.async_support.bitmart):
59
61
  'fetchBalanceSnapshot': True, # or False
60
62
  'awaitBalanceSnapshot': False, # whether to wait for the balance snapshot before providing updates
61
63
  },
64
+ #
65
+ # orderbook channels can have:
66
+ # - 'depth5', 'depth20', 'depth50' # these endpoints emit full Orderbooks once in every 500ms
67
+ # - 'depth/increase100' # self endpoint is preferred, because it emits once in 100ms. however, when self value is chosen, it only affects spot-market, but contracts markets automatically `depth50` will be being used
62
68
  'watchOrderBook': {
63
- 'depth': 'depth/increase100', # depth/increase100, depth5, depth20, depth50
69
+ 'depth': 'depth/increase100',
70
+ },
71
+ 'watchOrderBookForSymbols': {
72
+ 'depth': 'depth/increase100',
64
73
  },
65
74
  'ws': {
66
75
  'inflate': True,
@@ -105,6 +114,23 @@ class bitmart(ccxt.async_support.bitmart):
105
114
  }
106
115
  return await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
107
116
 
117
+ async def subscribe_multiple(self, channel: str, type: str, symbols: List[str], params={}):
118
+ url = self.implode_hostname(self.urls['api']['ws'][type]['public'])
119
+ channelType = 'spot' if (type == 'spot') else 'futures'
120
+ actionType = 'op' if (type == 'spot') else 'action'
121
+ rawSubscriptions = []
122
+ messageHashes = []
123
+ for i in range(0, len(symbols)):
124
+ market = self.market(symbols[i])
125
+ message = channelType + '/' + channel + ':' + market['id']
126
+ rawSubscriptions.append(message)
127
+ messageHashes.append(channel + ':' + market['symbol'])
128
+ request = {
129
+ 'args': rawSubscriptions,
130
+ }
131
+ request[actionType] = 'subscribe'
132
+ return await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), rawSubscriptions)
133
+
108
134
  async def watch_balance(self, params={}) -> Balances:
109
135
  """
110
136
  :see: https://developer-pro.bitmart.com/en/spot/#private-balance-change
@@ -236,16 +262,39 @@ class bitmart(ccxt.async_support.bitmart):
236
262
  :param dict [params]: extra parameters specific to the exchange API endpoint
237
263
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
238
264
  """
265
+ return await self.watch_trades_for_symbols([symbol], since, limit, params)
266
+
267
+ async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
268
+ """
269
+ :see: https://developer-pro.bitmart.com/en/spot/#public-trade-channel
270
+ get the list of most recent trades for a list of symbols
271
+ :param str[] symbols: unified symbol of the market to fetch trades for
272
+ :param int [since]: timestamp in ms of the earliest trade to fetch
273
+ :param int [limit]: the maximum amount of trades to fetch
274
+ :param dict [params]: extra parameters specific to the exchange API endpoint
275
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
276
+ """
239
277
  await self.load_markets()
240
- symbol = self.symbol(symbol)
241
- market = self.market(symbol)
242
- type = 'spot'
243
- type, params = self.handle_market_type_and_params('watchTrades', market, params)
244
- trades = await self.subscribe('trade', symbol, type, params)
278
+ marketType = None
279
+ symbols, marketType, params = self.get_params_for_multiple_sub('watchTradesForSymbols', symbols, limit, params)
280
+ channelName = 'trade'
281
+ trades = await self.subscribe_multiple(channelName, marketType, symbols, params)
245
282
  if self.newUpdates:
246
- limit = trades.getLimit(symbol, limit)
283
+ first = self.safe_dict(trades, 0)
284
+ tradeSymbol = self.safe_string(first, 'symbol')
285
+ limit = trades.getLimit(tradeSymbol, limit)
247
286
  return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
248
287
 
288
+ def get_params_for_multiple_sub(self, methodName: str, symbols: List[str], limit: Int = None, params={}):
289
+ symbols = self.market_symbols(symbols, None, False, True)
290
+ length = len(symbols)
291
+ if length > 20:
292
+ raise NotSupported(self.id + ' ' + methodName + '() accepts a maximum of 20 symbols in one request')
293
+ market = self.market(symbols[0])
294
+ marketType = None
295
+ marketType, params = self.handle_market_type_and_params(methodName, market, params)
296
+ return [symbols, marketType, params]
297
+
249
298
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
250
299
  """
251
300
  :see: https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
@@ -747,12 +796,11 @@ class bitmart(ccxt.async_support.bitmart):
747
796
  # ]
748
797
  # }
749
798
  #
750
- channel = self.safe_string_2(message, 'table', 'group')
751
- isSpot = (channel.find('spot') >= 0)
752
799
  data = self.safe_value(message, 'data')
753
800
  if data is None:
754
801
  return
755
802
  stored = None
803
+ symbol = None
756
804
  for i in range(0, len(data)):
757
805
  trade = self.parse_ws_trade(data[i])
758
806
  symbol = trade['symbol']
@@ -762,9 +810,7 @@ class bitmart(ccxt.async_support.bitmart):
762
810
  stored = ArrayCache(tradesLimit)
763
811
  self.trades[symbol] = stored
764
812
  stored.append(trade)
765
- messageHash = channel
766
- if isSpot:
767
- messageHash += ':' + self.safe_string(data[0], 'symbol')
813
+ messageHash = 'trade:' + symbol
768
814
  client.resolve(stored, messageHash)
769
815
 
770
816
  def parse_ws_trade(self, trade, market: Market = None):
@@ -1084,8 +1130,8 @@ class bitmart(ccxt.async_support.bitmart):
1084
1130
  # "symbol": "BTC_USDT"
1085
1131
  # }
1086
1132
  #
1087
- asks = self.safe_value(message, 'asks', [])
1088
- bids = self.safe_value(message, 'bids', [])
1133
+ asks = self.safe_list(message, 'asks', [])
1134
+ bids = self.safe_list(message, 'bids', [])
1089
1135
  self.handle_deltas(orderbook['asks'], asks)
1090
1136
  self.handle_deltas(orderbook['bids'], bids)
1091
1137
  timestamp = self.safe_integer(message, 'ms_t')
@@ -1099,6 +1145,7 @@ class bitmart(ccxt.async_support.bitmart):
1099
1145
  def handle_order_book(self, client: Client, message):
1100
1146
  #
1101
1147
  # spot depth-all
1148
+ #
1102
1149
  # {
1103
1150
  # "data": [
1104
1151
  # {
@@ -1118,33 +1165,31 @@ class bitmart(ccxt.async_support.bitmart):
1118
1165
  # ],
1119
1166
  # "table": "spot/depth5"
1120
1167
  # }
1168
+ #
1121
1169
  # spot increse depth snapshot
1170
+ #
1122
1171
  # {
1123
1172
  # "data":[
1124
1173
  # {
1125
- # "asks":[
1126
- # [
1127
- # "43652.52",
1128
- # "0.02039"
1129
- # ],
1130
- # ...
1131
- # ],
1132
- # "bids":[
1133
- # [
1134
- # "43652.51",
1135
- # "0.00500"
1174
+ # "asks":[
1175
+ # ["43652.52", "0.02039"],
1176
+ # ...
1136
1177
  # ],
1137
- # ...
1138
- # ],
1139
- # "ms_t":1703376836487,
1140
- # "symbol":"BTC_USDT",
1141
- # "type":"snapshot", # or update
1142
- # "version":2141731
1178
+ # "bids":[
1179
+ # ["43652.51", "0.00500"],
1180
+ # ...
1181
+ # ],
1182
+ # "ms_t":1703376836487,
1183
+ # "symbol":"BTC_USDT",
1184
+ # "type":"snapshot", # or update
1185
+ # "version":2141731
1143
1186
  # }
1144
1187
  # ],
1145
1188
  # "table":"spot/depth/increase100"
1146
1189
  # }
1190
+ #
1147
1191
  # swap
1192
+ #
1148
1193
  # {
1149
1194
  # "group":"futures/depth50:BTCUSDT",
1150
1195
  # "data":{
@@ -1165,43 +1210,58 @@ class bitmart(ccxt.async_support.bitmart):
1165
1210
  # }
1166
1211
  # }
1167
1212
  #
1168
- data = self.safe_value(message, 'data')
1169
- if data is None:
1213
+ isSpot = ('table' in message)
1214
+ datas = []
1215
+ if isSpot:
1216
+ datas = self.safe_list(message, 'data', datas)
1217
+ else:
1218
+ orderBookEntry = self.safe_dict(message, 'data')
1219
+ if orderBookEntry is not None:
1220
+ datas.append(orderBookEntry)
1221
+ length = len(datas)
1222
+ if length <= 0:
1170
1223
  return
1171
- depths = self.safe_value(data, 'depths')
1172
- isSpot = (depths is None)
1173
- table = self.safe_string_2(message, 'table', 'group')
1224
+ channelName = self.safe_string_2(message, 'table', 'group')
1174
1225
  # find limit subscribed to
1175
1226
  limitsToCheck = ['100', '50', '20', '10', '5']
1176
1227
  limit = 0
1177
1228
  for i in range(0, len(limitsToCheck)):
1178
1229
  limitString = limitsToCheck[i]
1179
- if table.find(limitString) >= 0:
1230
+ if channelName.find(limitString) >= 0:
1180
1231
  limit = self.parse_to_int(limitString)
1181
1232
  break
1182
1233
  if isSpot:
1183
- for i in range(0, len(data)):
1184
- update = data[i]
1234
+ channel = channelName.replace('spot/', '')
1235
+ for i in range(0, len(datas)):
1236
+ update = datas[i]
1185
1237
  marketId = self.safe_string(update, 'symbol')
1186
1238
  symbol = self.safe_symbol(marketId)
1187
- orderbook = self.safe_value(self.orderbooks, symbol)
1239
+ orderbook = self.safe_dict(self.orderbooks, symbol)
1188
1240
  if orderbook is None:
1189
1241
  orderbook = self.order_book({}, limit)
1190
1242
  orderbook['symbol'] = symbol
1191
1243
  self.orderbooks[symbol] = orderbook
1192
1244
  type = self.safe_value(update, 'type')
1193
- if (type == 'snapshot') or (not(table.find('increase') >= 0)):
1245
+ if (type == 'snapshot') or (not(channelName.find('increase') >= 0)):
1194
1246
  orderbook.reset({})
1195
1247
  self.handle_order_book_message(client, update, orderbook)
1196
1248
  timestamp = self.safe_integer(update, 'ms_t')
1197
- orderbook['timestamp'] = timestamp
1198
- orderbook['datetime'] = self.iso8601(timestamp)
1199
- messageHash = table + ':' + marketId
1249
+ if orderbook['timestamp'] is None:
1250
+ orderbook['timestamp'] = timestamp
1251
+ orderbook['datetime'] = self.iso8601(timestamp)
1252
+ messageHash = channelName + ':' + marketId
1200
1253
  client.resolve(orderbook, messageHash)
1254
+ # resolve ForSymbols
1255
+ messageHashForMulti = channel + ':' + symbol
1256
+ client.resolve(orderbook, messageHashForMulti)
1201
1257
  else:
1258
+ tableParts = channelName.split(':')
1259
+ channel = tableParts[0].replace('futures/', '')
1260
+ data = datas[0] # contract markets always contain only one member
1261
+ depths = data['depths']
1202
1262
  marketId = self.safe_string(data, 'symbol')
1203
1263
  symbol = self.safe_symbol(marketId)
1204
- orderbook = self.safe_value(self.orderbooks, symbol)
1264
+ orderbook = self.safe_dict(self.orderbooks, symbol)
1205
1265
  if orderbook is None:
1206
1266
  orderbook = self.order_book({}, limit)
1207
1267
  orderbook['symbol'] = symbol
@@ -1225,8 +1285,31 @@ class bitmart(ccxt.async_support.bitmart):
1225
1285
  timestamp = self.safe_integer(data, 'ms_t')
1226
1286
  orderbook['timestamp'] = timestamp
1227
1287
  orderbook['datetime'] = self.iso8601(timestamp)
1228
- messageHash = table
1288
+ messageHash = channelName
1229
1289
  client.resolve(orderbook, messageHash)
1290
+ # resolve ForSymbols
1291
+ messageHashForMulti = channel + ':' + symbol
1292
+ client.resolve(orderbook, messageHashForMulti)
1293
+
1294
+ async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
1295
+ """
1296
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1297
+ :see: https://developer-pro.bitmart.com/en/spot/#public-depth-increase-channel
1298
+ :param str[] symbols: unified array of symbols
1299
+ :param int [limit]: the maximum amount of order book entries to return
1300
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1301
+ :param str [params.depth]: the type of order book to subscribe to, default is 'depth/increase100', also accepts 'depth5' or 'depth20' or depth50
1302
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
1303
+ """
1304
+ await self.load_markets()
1305
+ type = None
1306
+ symbols, type, params = self.get_params_for_multiple_sub('watchOrderBookForSymbols', symbols, limit, params)
1307
+ channel = None
1308
+ channel, params = self.handle_option_and_params(params, 'watchOrderBookForSymbols', 'depth', 'depth/increase100')
1309
+ if type == 'swap' and channel == 'depth/increase100':
1310
+ channel = 'depth50'
1311
+ orderbook = await self.subscribe_multiple(channel, type, symbols, params)
1312
+ return orderbook.limit()
1230
1313
 
1231
1314
  async def authenticate(self, type, params={}):
1232
1315
  self.check_required_credentials()
ccxt/pro/bitvavo.py CHANGED
@@ -530,7 +530,7 @@ class bitvavo(ccxt.async_support.bitvavo):
530
530
  request = self.create_order_request(symbol, type, side, amount, price, params)
531
531
  return await self.watch_request('privateCreateOrder', request)
532
532
 
533
- async def edit_order_ws(self, id: str, symbol, type, side, amount=None, price=None, params={}) -> Order:
533
+ async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: float = None, price: float = None, params={}) -> Order:
534
534
  """
535
535
  edit a trade order
536
536
  :see: https://docs.bitvavo.com/#tag/Orders/paths/~1order/put
ccxt/pro/bybit.py CHANGED
@@ -136,7 +136,7 @@ class bybit(ccxt.async_support.bybit):
136
136
  self.options['requestId'] = requestId
137
137
  return requestId
138
138
 
139
- def get_url_by_market_type(self, symbol: Str = None, isPrivate=False, method=None, params={}):
139
+ def get_url_by_market_type(self, symbol: Str = None, isPrivate=False, method: str = None, params={}):
140
140
  accessibility = 'private' if isPrivate else 'public'
141
141
  isUsdcSettled = None
142
142
  isSpot = None
@@ -185,7 +185,7 @@ class bybit(ccxt.async_support.bybit):
185
185
  market = self.market(symbol)
186
186
  symbol = market['symbol']
187
187
  messageHash = 'ticker:' + symbol
188
- url = self.get_url_by_market_type(symbol, False, params)
188
+ url = self.get_url_by_market_type(symbol, False, 'watchTicker', params)
189
189
  params = self.clean_params(params)
190
190
  options = self.safe_value(self.options, 'watchTicker', {})
191
191
  topic = self.safe_string(options, 'name', 'tickers')
@@ -207,7 +207,7 @@ class bybit(ccxt.async_support.bybit):
207
207
  await self.load_markets()
208
208
  symbols = self.market_symbols(symbols, None, False)
209
209
  messageHashes = []
210
- url = self.get_url_by_market_type(symbols[0], False, params)
210
+ url = self.get_url_by_market_type(symbols[0], False, 'watchTickers', params)
211
211
  params = self.clean_params(params)
212
212
  options = self.safe_value(self.options, 'watchTickers', {})
213
213
  topic = self.safe_string(options, 'name', 'tickers')
@@ -368,7 +368,7 @@ class bybit(ccxt.async_support.bybit):
368
368
  await self.load_markets()
369
369
  market = self.market(symbol)
370
370
  symbol = market['symbol']
371
- url = self.get_url_by_market_type(symbol, False, params)
371
+ url = self.get_url_by_market_type(symbol, False, 'watchOHLCV', params)
372
372
  params = self.clean_params(params)
373
373
  ohlcv = None
374
374
  timeframeId = self.safe_string(self.timeframes, timeframe, timeframe)
@@ -477,7 +477,7 @@ class bybit(ccxt.async_support.bybit):
477
477
  if symbolsLength == 0:
478
478
  raise ArgumentsRequired(self.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols')
479
479
  symbols = self.market_symbols(symbols)
480
- url = self.get_url_by_market_type(symbols[0], False, params)
480
+ url = self.get_url_by_market_type(symbols[0], False, 'watchOrderBook', params)
481
481
  params = self.clean_params(params)
482
482
  market = self.market(symbols[0])
483
483
  if limit is None:
@@ -595,7 +595,7 @@ class bybit(ccxt.async_support.bybit):
595
595
  if symbolsLength == 0:
596
596
  raise ArgumentsRequired(self.id + ' watchTradesForSymbols() requires a non-empty array of symbols')
597
597
  params = self.clean_params(params)
598
- url = self.get_url_by_market_type(symbols[0], False, params)
598
+ url = self.get_url_by_market_type(symbols[0], False, 'watchTrades', params)
599
599
  topics = []
600
600
  messageHashes = []
601
601
  for i in range(0, len(symbols)):
ccxt/pro/cex.py CHANGED
@@ -1196,7 +1196,7 @@ class cex(ccxt.async_support.cex):
1196
1196
  rawOrder = await self.watch(url, messageHash, request, messageHash)
1197
1197
  return self.parse_order(rawOrder, market)
1198
1198
 
1199
- async def edit_order_ws(self, id: str, symbol, type, side, amount=None, price=None, params={}) -> Order:
1199
+ async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: float = None, price: float = None, params={}) -> Order:
1200
1200
  """
1201
1201
  edit a trade order
1202
1202
  :see: https://docs.cex.io/#ws-api-cancel-replace
@@ -1260,7 +1260,7 @@ class cex(ccxt.async_support.cex):
1260
1260
  response = await self.watch(url, messageHash, request, messageHash, messageHash)
1261
1261
  return self.parse_order(response, market)
1262
1262
 
1263
- async def cancel_orders_ws(self, ids, symbol: str = None, params={}):
1263
+ async def cancel_orders_ws(self, ids: List[str], symbol: str = None, params={}):
1264
1264
  """
1265
1265
  cancel multiple orders
1266
1266
  :see: https://docs.cex.io/#ws-api-mass-cancel-place
ccxt/pro/coinbase.py CHANGED
@@ -88,7 +88,7 @@ class coinbase(ccxt.async_support.coinbase):
88
88
  }
89
89
  return await self.watch(url, messageHash, subscribe, messageHash)
90
90
 
91
- async def watch_ticker(self, symbol, params={}) -> Ticker:
91
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
92
92
  """
93
93
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
94
94
  :see: https://docs.cloud.coinbase.com/advanced-trade-api/docs/ws-channels#ticker-channel
@@ -251,7 +251,7 @@ class coinbase(ccxt.async_support.coinbase):
251
251
  limit = trades.getLimit(symbol, limit)
252
252
  return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
253
253
 
254
- async def watch_orders(self, symbol=None, since=None, limit=None, params={}) -> List[Order]:
254
+ async def watch_orders(self, symbol: str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
255
255
  """
256
256
  watches information on multiple orders made by the user
257
257
  :see: https://docs.cloud.coinbase.com/advanced-trade-api/docs/ws-channels#user-channel
ccxt/pro/coinex.py CHANGED
@@ -554,7 +554,7 @@ class coinex(ccxt.async_support.coinex):
554
554
  limit = ohlcvs.getLimit(symbol, limit)
555
555
  return self.filter_by_since_limit(ohlcvs, since, limit, 0)
556
556
 
557
- async def fetch_ohlcv_ws(self, symbol, timeframe='1m', since=None, limit=None, params={}) -> List[list]:
557
+ async def fetch_ohlcv_ws(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
558
558
  """
559
559
  :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket005_kline_query
560
560
  query historical candlestick data containing the open, high, low, and close price, and the volume of a market
ccxt/pro/lbank.py CHANGED
@@ -248,7 +248,7 @@ class lbank(ccxt.async_support.lbank):
248
248
  requestId = self.request_id()
249
249
  return await self.watch(url, messageHash, request, requestId, request)
250
250
 
251
- async def watch_ticker(self, symbol, params={}) -> Ticker:
251
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
252
252
  """
253
253
  :see: https://www.lbank.com/en-US/docs/index.html#market
254
254
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
ccxt/pro/mexc.py CHANGED
@@ -455,7 +455,7 @@ class mexc(ccxt.async_support.mexc):
455
455
  return
456
456
  try:
457
457
  self.handle_delta(storedOrderBook, data)
458
- timestamp = self.safe_integer(message, 't')
458
+ timestamp = self.safe_integer_2(message, 't', 'ts')
459
459
  storedOrderBook['timestamp'] = timestamp
460
460
  storedOrderBook['datetime'] = self.iso8601(timestamp)
461
461
  except Exception as e:
ccxt/probit.py CHANGED
@@ -1311,7 +1311,7 @@ class probit(Exchange, ImplicitAPI):
1311
1311
  raise InvalidAddress(self.id + ' fetchDepositAddress() returned an empty response')
1312
1312
  return self.parse_deposit_address(firstAddress, currency)
1313
1313
 
1314
- def fetch_deposit_addresses(self, codes=None, params={}):
1314
+ def fetch_deposit_addresses(self, codes: List[str] = None, params={}):
1315
1315
  """
1316
1316
  :see: https://docs-en.probit.com/reference/deposit_address
1317
1317
  fetch deposit addresses for multiple currencies and chain types
ccxt/test/test_async.py CHANGED
@@ -373,7 +373,8 @@ class testMainClass(baseMainTestClass):
373
373
  final_value = exchange_settings[key]
374
374
  set_exchange_prop(exchange, key, final_value)
375
375
  # credentials
376
- self.load_credentials_from_env(exchange)
376
+ if self.load_keys:
377
+ self.load_credentials_from_env(exchange)
377
378
  # skipped tests
378
379
  skipped_file = self.root_dir_for_skips + 'skip-tests.json'
379
380
  skipped_settings = io_file_read(skipped_file)
@@ -1053,6 +1054,7 @@ class testMainClass(baseMainTestClass):
1053
1054
  currencies = self.load_currencies_from_file(exchange_name)
1054
1055
  exchange = init_exchange(exchange_name, {
1055
1056
  'markets': markets,
1057
+ 'currencies': currencies,
1056
1058
  'enableRateLimit': False,
1057
1059
  'rateLimit': 1,
1058
1060
  'httpProxy': 'http://fake:8080',
ccxt/test/test_sync.py CHANGED
@@ -372,7 +372,8 @@ class testMainClass(baseMainTestClass):
372
372
  final_value = exchange_settings[key]
373
373
  set_exchange_prop(exchange, key, final_value)
374
374
  # credentials
375
- self.load_credentials_from_env(exchange)
375
+ if self.load_keys:
376
+ self.load_credentials_from_env(exchange)
376
377
  # skipped tests
377
378
  skipped_file = self.root_dir_for_skips + 'skip-tests.json'
378
379
  skipped_settings = io_file_read(skipped_file)
@@ -1052,6 +1053,7 @@ class testMainClass(baseMainTestClass):
1052
1053
  currencies = self.load_currencies_from_file(exchange_name)
1053
1054
  exchange = init_exchange(exchange_name, {
1054
1055
  'markets': markets,
1056
+ 'currencies': currencies,
1055
1057
  'enableRateLimit': False,
1056
1058
  'rateLimit': 1,
1057
1059
  'httpProxy': 'http://fake:8080',
ccxt/timex.py CHANGED
@@ -755,7 +755,7 @@ class timex(Exchange, ImplicitAPI):
755
755
  order = self.safe_value(orders, 0, {})
756
756
  return self.parse_order(order, market)
757
757
 
758
- def edit_order(self, id: str, symbol, type, side, amount=None, price=None, params={}):
758
+ def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: float = None, price: float = None, params={}):
759
759
  self.load_markets()
760
760
  market = self.market(symbol)
761
761
  request = {
ccxt/upbit.py CHANGED
@@ -1522,7 +1522,7 @@ class upbit(Exchange, ImplicitAPI):
1522
1522
  #
1523
1523
  return self.parse_order(response)
1524
1524
 
1525
- def fetch_deposit_addresses(self, codes=None, params={}):
1525
+ def fetch_deposit_addresses(self, codes: List[str] = None, params={}):
1526
1526
  """
1527
1527
  :see: https://docs.upbit.com/reference/%EC%A0%84%EC%B2%B4-%EC%9E%85%EA%B8%88-%EC%A3%BC%EC%86%8C-%EC%A1%B0%ED%9A%8C
1528
1528
  fetch deposit addresses for multiple currencies and chain types
ccxt/wavesexchange.py CHANGED
@@ -324,7 +324,7 @@ class wavesexchange(Exchange, ImplicitAPI):
324
324
  },
325
325
  },
326
326
  'currencies': {
327
- 'WX': self.safe_currency_structure({'id': 'EMAMLxDnv3xiz8RXg8Btj33jcEw3wLczL3JKYYmuubpc', 'numericId': None, 'code': 'WX', 'precision': self.parse_number('8')}),
327
+ 'WX': self.safe_currency_structure({'id': 'EMAMLxDnv3xiz8RXg8Btj33jcEw3wLczL3JKYYmuubpc', 'numericId': None, 'code': 'WX', 'precision': self.parse_to_int('8')}),
328
328
  },
329
329
  'precisionMode': DECIMAL_PLACES,
330
330
  'options': {
ccxt/whitebit.py CHANGED
@@ -456,7 +456,7 @@ class whitebit(Exchange, ImplicitAPI):
456
456
  }
457
457
  return result
458
458
 
459
- def fetch_transaction_fees(self, codes=None, params={}):
459
+ def fetch_transaction_fees(self, codes: List[str] = None, params={}):
460
460
  """
461
461
  * @deprecated
462
462
  please use fetchDepositWithdrawFees instead
@@ -1616,7 +1616,7 @@ class whitebit(Exchange, ImplicitAPI):
1616
1616
  # "leverage": 5
1617
1617
  # }
1618
1618
 
1619
- def transfer(self, code: str, amount: float, fromAccount, toAccount, params={}) -> TransferEntry:
1619
+ def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
1620
1620
  """
1621
1621
  transfer currency internally between wallets on the same account
1622
1622
  :see: https://docs.whitebit.com/private/http-main-v4/#transfer-between-main-and-trade-balances