ccxt 4.4.100__py2.py3-none-any.whl → 4.5.1__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.
ccxt/pro/bitget.py CHANGED
@@ -51,10 +51,14 @@ class bitget(ccxt.async_support.bitget):
51
51
  'ws': {
52
52
  'public': 'wss://ws.bitget.com/v2/ws/public',
53
53
  'private': 'wss://ws.bitget.com/v2/ws/private',
54
+ 'utaPublic': 'wss://ws.bitget.com/v3/ws/public',
55
+ 'utaPrivate': 'wss://ws.bitget.com/v3/ws/private',
54
56
  },
55
57
  'demo': {
56
58
  'public': 'wss://wspap.bitget.com/v2/ws/public',
57
59
  'private': 'wss://wspap.bitget.com/v2/ws/private',
60
+ 'utaPublic': 'wss://wspap.bitget.com/v3/ws/public',
61
+ 'utaPrivate': 'wss://wspap.bitget.com/v3/ws/private',
58
62
  },
59
63
  },
60
64
  },
@@ -106,7 +110,9 @@ class bitget(ccxt.async_support.bitget):
106
110
  },
107
111
  })
108
112
 
109
- def get_inst_type(self, market, params={}):
113
+ def get_inst_type(self, market, uta: bool = False, params={}):
114
+ if (uta is None) or not uta:
115
+ uta, params = self.handle_option_and_params(params, 'getInstType', 'uta', False)
110
116
  instType = None
111
117
  if market is None:
112
118
  instType, params = self.handleProductTypeAndParams(None, params)
@@ -117,6 +123,8 @@ class bitget(ccxt.async_support.bitget):
117
123
  instypeAux = None
118
124
  instypeAux, params = self.handle_option_and_params(params, 'getInstType', 'instType', instType)
119
125
  instType = instypeAux
126
+ if uta:
127
+ instType = instType.lower()
120
128
  return [instType, params]
121
129
 
122
130
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
@@ -125,9 +133,11 @@ class bitget(ccxt.async_support.bitget):
125
133
 
126
134
  https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
127
135
  https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
136
+ https://www.bitget.com/api-doc/uta/websocket/public/Tickers-Channel
128
137
 
129
138
  :param str symbol: unified symbol of the market to watch the ticker for
130
139
  :param dict [params]: extra parameters specific to the exchange API endpoint
140
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
131
141
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
132
142
  """
133
143
  await self.load_markets()
@@ -135,12 +145,16 @@ class bitget(ccxt.async_support.bitget):
135
145
  symbol = market['symbol']
136
146
  messageHash = 'ticker:' + symbol
137
147
  instType = None
138
- instType, params = self.get_inst_type(market, params)
148
+ uta = None
149
+ uta, params = self.handle_option_and_params(params, 'watchTicker', 'uta', False)
150
+ instType, params = self.get_inst_type(market, uta, params)
139
151
  args: dict = {
140
152
  'instType': instType,
141
- 'channel': 'ticker',
142
- 'instId': market['id'],
143
153
  }
154
+ topicOrChannel = 'topic' if uta else 'channel'
155
+ symbolOrInstId = 'symbol' if uta else 'instId'
156
+ args[topicOrChannel] = 'ticker'
157
+ args[symbolOrInstId] = market['id']
144
158
  return await self.watch_public(messageHash, args, params)
145
159
 
146
160
  async def un_watch_ticker(self, symbol: str, params={}) -> Any:
@@ -163,16 +177,20 @@ class bitget(ccxt.async_support.bitget):
163
177
 
164
178
  https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
165
179
  https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
180
+ https://www.bitget.com/api-doc/uta/websocket/public/Tickers-Channel
166
181
 
167
182
  :param str[] symbols: unified symbol of the market to watch the tickers for
168
183
  :param dict [params]: extra parameters specific to the exchange API endpoint
184
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
169
185
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
170
186
  """
171
187
  await self.load_markets()
172
188
  symbols = self.market_symbols(symbols, None, False)
173
189
  market = self.market(symbols[0])
174
190
  instType = None
175
- instType, params = self.get_inst_type(market, params)
191
+ uta = None
192
+ uta, params = self.handle_option_and_params(params, 'watchTickers', 'uta', False)
193
+ instType, params = self.get_inst_type(market, uta, params)
176
194
  topics = []
177
195
  messageHashes = []
178
196
  for i in range(0, len(symbols)):
@@ -180,9 +198,11 @@ class bitget(ccxt.async_support.bitget):
180
198
  marketInner = self.market(symbol)
181
199
  args: dict = {
182
200
  'instType': instType,
183
- 'channel': 'ticker',
184
- 'instId': marketInner['id'],
185
201
  }
202
+ topicOrChannel = 'topic' if uta else 'channel'
203
+ symbolOrInstId = 'symbol' if uta else 'instId'
204
+ args[topicOrChannel] = 'ticker'
205
+ args[symbolOrInstId] = marketInner['id']
186
206
  topics.append(args)
187
207
  messageHashes.append('ticker:' + symbol)
188
208
  tickers = await self.watch_public_multiple(messageHashes, topics, params)
@@ -193,6 +213,8 @@ class bitget(ccxt.async_support.bitget):
193
213
  return self.filter_by_array(self.tickers, 'symbol', symbols)
194
214
 
195
215
  def handle_ticker(self, client: Client, message):
216
+ #
217
+ # default
196
218
  #
197
219
  # {
198
220
  # "action": "snapshot",
@@ -223,6 +245,29 @@ class bitget(ccxt.async_support.bitget):
223
245
  # "ts": 1701842994341
224
246
  # }
225
247
  #
248
+ # uta
249
+ #
250
+ # {
251
+ # "action": "snapshot",
252
+ # "arg": {"instType": "spot", topic: "ticker", symbol: "BTCUSDT"},
253
+ # "data": [
254
+ # {
255
+ # "highPrice24h": "120255.61",
256
+ # "lowPrice24h": "116145.88",
257
+ # "openPrice24h": "118919.38",
258
+ # "lastPrice": "119818.83",
259
+ # "turnover24h": "215859996.272276",
260
+ # "volume24h": "1819.756798",
261
+ # "bid1Price": "119811.26",
262
+ # "ask1Price": "119831.18",
263
+ # "bid1Size": "0.008732",
264
+ # "ask1Size": "0.004297",
265
+ # "price24hPcnt": "0.02002"
266
+ # }
267
+ # ],
268
+ # "ts": 1753230479687
269
+ # }
270
+ #
226
271
  self.handle_bid_ask(client, message)
227
272
  ticker = self.parse_ws_ticker(message)
228
273
  symbol = ticker['symbol']
@@ -301,56 +346,85 @@ class bitget(ccxt.async_support.bitget):
301
346
  # "ts": 1701843962812
302
347
  # }
303
348
  #
349
+ # uta
350
+ #
351
+ # {
352
+ # "action": "snapshot",
353
+ # "arg": {"instType": "spot", topic: "ticker", symbol: "BTCUSDT"},
354
+ # "data": [
355
+ # {
356
+ # "highPrice24h": "120255.61",
357
+ # "lowPrice24h": "116145.88",
358
+ # "openPrice24h": "118919.38",
359
+ # "lastPrice": "119818.83",
360
+ # "turnover24h": "215859996.272276",
361
+ # "volume24h": "1819.756798",
362
+ # "bid1Price": "119811.26",
363
+ # "ask1Price": "119831.18",
364
+ # "bid1Size": "0.008732",
365
+ # "ask1Size": "0.004297",
366
+ # "price24hPcnt": "0.02002"
367
+ # }
368
+ # ],
369
+ # "ts": 1753230479687
370
+ # }
371
+ #
304
372
  arg = self.safe_value(message, 'arg', {})
305
373
  data = self.safe_value(message, 'data', [])
306
374
  ticker = self.safe_value(data, 0, {})
307
- timestamp = self.safe_integer(ticker, 'ts')
308
- instType = self.safe_string(arg, 'instType')
309
- marketType = 'spot' if (instType == 'SPOT') else 'contract'
310
- marketId = self.safe_string(ticker, 'instId')
375
+ utaTimestamp = self.safe_integer(message, 'ts')
376
+ timestamp = self.safe_integer(ticker, 'ts', utaTimestamp)
377
+ instType = self.safe_string_lower(arg, 'instType')
378
+ marketType = 'spot' if (instType == 'spot') else 'contract'
379
+ utaMarketId = self.safe_string(arg, 'symbol')
380
+ marketId = self.safe_string(ticker, 'instId', utaMarketId)
311
381
  market = self.safe_market(marketId, market, None, marketType)
312
- close = self.safe_string(ticker, 'lastPr')
313
- changeDecimal = self.safe_string(ticker, 'change24h')
314
- change = Precise.string_mul(changeDecimal, '100')
382
+ close = self.safe_string_2(ticker, 'lastPr', 'lastPrice')
383
+ changeDecimal = self.safe_string(ticker, 'change24h', '')
384
+ change = self.safe_string(ticker, 'price24hPcnt', Precise.string_mul(changeDecimal, '100'))
315
385
  return self.safe_ticker({
316
386
  'symbol': market['symbol'],
317
387
  'timestamp': timestamp,
318
388
  'datetime': self.iso8601(timestamp),
319
- 'high': self.safe_string(ticker, 'high24h'),
320
- 'low': self.safe_string(ticker, 'low24h'),
321
- 'bid': self.safe_string(ticker, 'bidPr'),
322
- 'bidVolume': self.safe_string(ticker, 'bidSz'),
323
- 'ask': self.safe_string(ticker, 'askPr'),
324
- 'askVolume': self.safe_string(ticker, 'askSz'),
389
+ 'high': self.safe_string_2(ticker, 'high24h', 'highPrice24h'),
390
+ 'low': self.safe_string_2(ticker, 'low24h', 'lowPrice24h'),
391
+ 'bid': self.safe_string_2(ticker, 'bidPr', 'bid1Price'),
392
+ 'bidVolume': self.safe_string_2(ticker, 'bidSz', 'bid1Size'),
393
+ 'ask': self.safe_string_2(ticker, 'askPr', 'ask1Price'),
394
+ 'askVolume': self.safe_string_2(ticker, 'askSz', 'ask1Size'),
325
395
  'vwap': None,
326
- 'open': self.safe_string(ticker, 'open24h'),
396
+ 'open': self.safe_string_2(ticker, 'open24h', 'openPrice24h'),
327
397
  'close': close,
328
398
  'last': close,
329
399
  'previousClose': None,
330
400
  'change': None,
331
401
  'percentage': change,
332
402
  'average': None,
333
- 'baseVolume': self.safe_string(ticker, 'baseVolume'),
334
- 'quoteVolume': self.safe_string(ticker, 'quoteVolume'),
403
+ 'baseVolume': self.safe_string_2(ticker, 'baseVolume', 'volume24h'),
404
+ 'quoteVolume': self.safe_string_2(ticker, 'quoteVolume', 'turnover24h'),
335
405
  'info': ticker,
336
406
  }, market)
337
407
 
338
408
  async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
339
409
  """
410
+ watches best bid & ask for symbols
340
411
 
341
412
  https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
342
413
  https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
414
+ https://www.bitget.com/api-doc/uta/websocket/public/Tickers-Channel
343
415
 
344
- watches best bid & ask for symbols
345
416
  :param str[] symbols: unified symbol of the market to fetch the ticker for
346
417
  :param dict [params]: extra parameters specific to the exchange API endpoint
418
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
347
419
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
348
420
  """
349
421
  await self.load_markets()
350
422
  symbols = self.market_symbols(symbols, None, False)
351
423
  market = self.market(symbols[0])
352
424
  instType = None
353
- instType, params = self.get_inst_type(market, params)
425
+ uta = None
426
+ uta, params = self.handle_option_and_params(params, 'watchBidsAsks', 'uta', False)
427
+ instType, params = self.get_inst_type(market, uta, params)
354
428
  topics = []
355
429
  messageHashes = []
356
430
  for i in range(0, len(symbols)):
@@ -358,9 +432,11 @@ class bitget(ccxt.async_support.bitget):
358
432
  marketInner = self.market(symbol)
359
433
  args: dict = {
360
434
  'instType': instType,
361
- 'channel': 'ticker',
362
- 'instId': marketInner['id'],
363
435
  }
436
+ topicOrChannel = 'topic' if uta else 'channel'
437
+ symbolOrInstId = 'symbol' if uta else 'instId'
438
+ args[topicOrChannel] = 'ticker'
439
+ args[symbolOrInstId] = marketInner['id']
364
440
  topics.append(args)
365
441
  messageHashes.append('bidask:' + symbol)
366
442
  tickers = await self.watch_public_multiple(messageHashes, topics, params)
@@ -381,19 +457,21 @@ class bitget(ccxt.async_support.bitget):
381
457
  arg = self.safe_value(message, 'arg', {})
382
458
  data = self.safe_value(message, 'data', [])
383
459
  ticker = self.safe_value(data, 0, {})
384
- timestamp = self.safe_integer(ticker, 'ts')
385
- instType = self.safe_string(arg, 'instType')
386
- marketType = 'spot' if (instType == 'SPOT') else 'contract'
387
- marketId = self.safe_string(ticker, 'instId')
460
+ utaTimestamp = self.safe_integer(message, 'ts')
461
+ timestamp = self.safe_integer(ticker, 'ts', utaTimestamp)
462
+ instType = self.safe_string_lower(arg, 'instType')
463
+ marketType = 'spot' if (instType == 'spot') else 'contract'
464
+ utaMarketId = self.safe_string(arg, 'symbol')
465
+ marketId = self.safe_string(ticker, 'instId', utaMarketId)
388
466
  market = self.safe_market(marketId, market, None, marketType)
389
467
  return self.safe_ticker({
390
468
  'symbol': market['symbol'],
391
469
  'timestamp': timestamp,
392
470
  'datetime': self.iso8601(timestamp),
393
- 'ask': self.safe_string(ticker, 'askPr'),
394
- 'askVolume': self.safe_string(ticker, 'askSz'),
395
- 'bid': self.safe_string(ticker, 'bidPr'),
396
- 'bidVolume': self.safe_string(ticker, 'bidSz'),
471
+ 'ask': self.safe_string_2(ticker, 'askPr', 'ask1Price'),
472
+ 'askVolume': self.safe_string_2(ticker, 'askSz', 'ask1Size'),
473
+ 'bid': self.safe_string_2(ticker, 'bidPr', 'bid1Price'),
474
+ 'bidVolume': self.safe_string_2(ticker, 'bidSz', 'bid1Size'),
397
475
  'info': ticker,
398
476
  }, market)
399
477
 
@@ -418,7 +496,7 @@ class bitget(ccxt.async_support.bitget):
418
496
  interval = self.safe_string(timeframes, timeframe)
419
497
  messageHash = 'candles:' + timeframe + ':' + symbol
420
498
  instType = None
421
- instType, params = self.get_inst_type(market, params)
499
+ instType, params = self.get_inst_type(market, False, params)
422
500
  args: dict = {
423
501
  'instType': instType,
424
502
  'channel': 'candle' + interval,
@@ -566,7 +644,7 @@ class bitget(ccxt.async_support.bitget):
566
644
  market = self.market(symbol)
567
645
  messageHash = 'unsubscribe:' + messageHashTopic + ':' + market['symbol']
568
646
  instType = None
569
- instType, params = self.get_inst_type(market, params)
647
+ instType, params = self.get_inst_type(market, False, params)
570
648
  args: dict = {
571
649
  'instType': instType,
572
650
  'channel': channel,
@@ -599,7 +677,7 @@ class bitget(ccxt.async_support.bitget):
599
677
  symbol = symbols[i]
600
678
  market = self.market(symbol)
601
679
  instType = None
602
- instType, params = self.get_inst_type(market, params)
680
+ instType, params = self.get_inst_type(market, False, params)
603
681
  args: dict = {
604
682
  'instType': instType,
605
683
  'channel': channel,
@@ -757,7 +835,7 @@ class bitget(ccxt.async_support.bitget):
757
835
  symbol = symbols[i]
758
836
  market = self.market(symbol)
759
837
  instType = None
760
- instType, params = self.get_inst_type(market, params)
838
+ instType, params = self.get_inst_type(market, False, params)
761
839
  args: dict = {
762
840
  'instType': instType,
763
841
  'channel': 'trade',
@@ -941,7 +1019,7 @@ class bitget(ccxt.async_support.bitget):
941
1019
  symbols = self.market_symbols(symbols)
942
1020
  if not self.is_empty(symbols):
943
1021
  market = self.get_market_from_symbols(symbols)
944
- instType, params = self.get_inst_type(market, params)
1022
+ instType, params = self.get_inst_type(market, False, params)
945
1023
  messageHash = instType + ':positions' + messageHash
946
1024
  args: dict = {
947
1025
  'instType': instType,
@@ -1136,7 +1214,7 @@ class bitget(ccxt.async_support.bitget):
1136
1214
  if market is None and type == 'spot':
1137
1215
  instType = 'SPOT'
1138
1216
  else:
1139
- instType, params = self.get_inst_type(market, params)
1217
+ instType, params = self.get_inst_type(market, False, params)
1140
1218
  if type == 'spot' and (symbol is not None):
1141
1219
  subscriptionHash = subscriptionHash + ':' + symbol
1142
1220
  if isTrigger:
@@ -1487,7 +1565,7 @@ class bitget(ccxt.async_support.bitget):
1487
1565
  if market is None and type == 'spot':
1488
1566
  instType = 'spot'
1489
1567
  else:
1490
- instType, params = self.get_inst_type(market, params)
1568
+ instType, params = self.get_inst_type(market, False, params)
1491
1569
  subscriptionHash = 'fill:' + instType
1492
1570
  args: dict = {
1493
1571
  'instType': instType,
@@ -1708,12 +1786,21 @@ class bitget(ccxt.async_support.bitget):
1708
1786
  client.resolve(self.balance, messageHash)
1709
1787
 
1710
1788
  async def watch_public(self, messageHash, args, params={}):
1711
- url = self.urls['api']['ws']['public']
1789
+ uta = None
1790
+ url = None
1791
+ uta, params = self.handle_option_and_params(params, 'watchPublic', 'uta', False)
1792
+ if uta:
1793
+ url = self.urls['api']['ws']['utaPublic']
1794
+ else:
1795
+ url = self.urls['api']['ws']['public']
1712
1796
  sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
1713
1797
  if sandboxMode:
1714
1798
  instType = self.safe_string(args, 'instType')
1715
1799
  if (instType != 'SCOIN-FUTURES') and (instType != 'SUSDT-FUTURES') and (instType != 'SUSDC-FUTURES'):
1716
- url = self.urls['api']['demo']['public']
1800
+ if uta:
1801
+ url = self.urls['api']['demo']['utaPublic']
1802
+ else:
1803
+ url = self.urls['api']['demo']['public']
1717
1804
  request: dict = {
1718
1805
  'op': 'subscribe',
1719
1806
  'args': [args],
@@ -1722,12 +1809,21 @@ class bitget(ccxt.async_support.bitget):
1722
1809
  return await self.watch(url, messageHash, message, messageHash)
1723
1810
 
1724
1811
  async def un_watch_public(self, messageHash, args, params={}):
1725
- url = self.urls['api']['ws']['public']
1812
+ uta = None
1813
+ url = None
1814
+ uta, params = self.handle_option_and_params(params, 'unWatchPublic', 'uta', False)
1815
+ if uta:
1816
+ url = self.urls['api']['ws']['utaPublic']
1817
+ else:
1818
+ url = self.urls['api']['ws']['public']
1726
1819
  sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
1727
1820
  if sandboxMode:
1728
1821
  instType = self.safe_string(args, 'instType')
1729
1822
  if (instType != 'SCOIN-FUTURES') and (instType != 'SUSDT-FUTURES') and (instType != 'SUSDC-FUTURES'):
1730
- url = self.urls['api']['demo']['public']
1823
+ if uta:
1824
+ url = self.urls['api']['demo']['utaPublic']
1825
+ else:
1826
+ url = self.urls['api']['demo']['public']
1731
1827
  request: dict = {
1732
1828
  'op': 'unsubscribe',
1733
1829
  'args': [args],
@@ -1736,13 +1832,22 @@ class bitget(ccxt.async_support.bitget):
1736
1832
  return await self.watch(url, messageHash, message, messageHash)
1737
1833
 
1738
1834
  async def watch_public_multiple(self, messageHashes, argsArray, params={}):
1739
- url = self.urls['api']['ws']['public']
1835
+ uta = None
1836
+ url = None
1837
+ uta, params = self.handle_option_and_params(params, 'watchPublicMultiple', 'uta', False)
1838
+ if uta:
1839
+ url = self.urls['api']['ws']['utaPublic']
1840
+ else:
1841
+ url = self.urls['api']['ws']['public']
1740
1842
  sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
1741
1843
  if sandboxMode:
1742
1844
  argsArrayFirst = self.safe_dict(argsArray, 0, {})
1743
1845
  instType = self.safe_string(argsArrayFirst, 'instType')
1744
1846
  if (instType != 'SCOIN-FUTURES') and (instType != 'SUSDT-FUTURES') and (instType != 'SUSDC-FUTURES'):
1745
- url = self.urls['api']['demo']['public']
1847
+ if uta:
1848
+ url = self.urls['api']['demo']['utaPublic']
1849
+ else:
1850
+ url = self.urls['api']['demo']['public']
1746
1851
  request: dict = {
1747
1852
  'op': 'subscribe',
1748
1853
  'args': argsArray,
@@ -1871,6 +1976,29 @@ class bitget(ccxt.async_support.bitget):
1871
1976
  # ]
1872
1977
  # }
1873
1978
  #
1979
+ # uta
1980
+ #
1981
+ # {
1982
+ # "action": "snapshot",
1983
+ # "arg": {"instType": "spot", topic: "ticker", symbol: "BTCUSDT"},
1984
+ # "data": [
1985
+ # {
1986
+ # "highPrice24h": "120255.61",
1987
+ # "lowPrice24h": "116145.88",
1988
+ # "openPrice24h": "118919.38",
1989
+ # "lastPrice": "119818.83",
1990
+ # "turnover24h": "215859996.272276",
1991
+ # "volume24h": "1819.756798",
1992
+ # "bid1Price": "119811.26",
1993
+ # "ask1Price": "119831.18",
1994
+ # "bid1Size": "0.008732",
1995
+ # "ask1Size": "0.004297",
1996
+ # "price24hPcnt": "0.02002"
1997
+ # }
1998
+ # ],
1999
+ # "ts": 1753230479687
2000
+ # }
2001
+ #
1874
2002
  if self.handle_error_message(client, message):
1875
2003
  return
1876
2004
  content = self.safe_string(message, 'message')
@@ -1905,7 +2033,7 @@ class bitget(ccxt.async_support.bitget):
1905
2033
  'account-crossed': self.handle_balance,
1906
2034
  }
1907
2035
  arg = self.safe_value(message, 'arg', {})
1908
- topic = self.safe_value(arg, 'channel', '')
2036
+ topic = self.safe_value_2(arg, 'channel', 'topic', '')
1909
2037
  method = self.safe_value(methods, topic)
1910
2038
  if method is not None:
1911
2039
  method(client, message)
@@ -1981,7 +2109,7 @@ class bitget(ccxt.async_support.bitget):
1981
2109
  arg = self.safe_dict(message, 'arg', {})
1982
2110
  instType = self.safe_string_lower(arg, 'instType')
1983
2111
  type = 'spot' if (instType == 'spot') else 'contract'
1984
- instId = self.safe_string(arg, 'instId')
2112
+ instId = self.safe_string_2(arg, 'instId', 'symbol')
1985
2113
  market = self.safe_market(instId, None, None, type)
1986
2114
  symbol = market['symbol']
1987
2115
  messageHash = 'unsubscribe:ticker:' + market['symbol']
@@ -2042,7 +2170,7 @@ class bitget(ccxt.async_support.bitget):
2042
2170
  argsList = [self.safe_dict(message, 'arg', {})]
2043
2171
  for i in range(0, len(argsList)):
2044
2172
  arg = argsList[i]
2045
- channel = self.safe_string(arg, 'channel')
2173
+ channel = self.safe_string_2(arg, 'channel', 'topic')
2046
2174
  if channel == 'books':
2047
2175
  # for now only unWatchOrderBook is supporteod
2048
2176
  self.handle_order_book_un_subscription(client, message)
ccxt/pro/bybit.py CHANGED
@@ -848,16 +848,14 @@ class bybit(ccxt.async_support.bybit):
848
848
  if market['option']:
849
849
  limit = 100
850
850
  else:
851
- if not market['spot']:
852
- if market['option']:
853
- if (limit != 25) and (limit != 100):
854
- raise BadRequest(self.id + ' watchOrderBookForSymbols() can only use limit 25 and 100 for option markets.')
855
- elif (limit != 1) and (limit != 50) and (limit != 200) and (limit != 500):
856
- # bybit only support limit 1, 50, 200, 500 for contract
857
- raise BadRequest(self.id + ' watchOrderBookForSymbols() can only use limit 1, 50, 200 and 500 for swap and future markets.')
858
- else:
859
- if (limit != 1) and (limit != 50) and (limit != 200):
860
- raise BadRequest(self.id + ' watchOrderBookForSymbols() can only use limit 1,50, and 200 for spot markets.')
851
+ limits = {
852
+ 'spot': [1, 50, 200, 1000],
853
+ 'option': [25, 100],
854
+ 'default': [1, 50, 200, 500, 1000],
855
+ }
856
+ selectedLimits = self.safe_list_2(limits, market['type'], 'default')
857
+ if not self.in_array(limit, selectedLimits):
858
+ raise BadRequest(self.id + ' watchOrderBookForSymbols(): for ' + market['type'] + ' markets limit can be one of: ' + self.json(selectedLimits))
861
859
  topics = []
862
860
  messageHashes = []
863
861
  for i in range(0, len(symbols)):
ccxt/pro/gate.py CHANGED
@@ -365,6 +365,13 @@ class gate(ccxt.async_support.gate):
365
365
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
366
366
  """
367
367
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
368
+
369
+ https://www.gate.com/docs/developers/apiv4/ws/en/#order-book-channel
370
+ https://www.gate.com/docs/developers/apiv4/ws/en/#order-book-v2-api
371
+ https://www.gate.com/docs/developers/futures/ws/en/#order-book-api
372
+ https://www.gate.com/docs/developers/futures/ws/en/#order-book-v2-api
373
+ https://www.gate.com/docs/developers/delivery/ws/en/#order-book-api
374
+
368
375
  :param str symbol: unified symbol of the market to fetch the order book for
369
376
  :param int [limit]: the maximum amount of order book entries to return
370
377
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -381,7 +388,7 @@ class gate(ccxt.async_support.gate):
381
388
  url = self.get_url_by_market(market)
382
389
  payload = [marketId, interval]
383
390
  if limit is None:
384
- limit = 100
391
+ limit = 100 # max 100 atm
385
392
  if market['contract']:
386
393
  stringLimit = str(limit)
387
394
  payload.append(stringLimit)
ccxt/pro/hyperliquid.py CHANGED
@@ -905,6 +905,8 @@ class hyperliquid(ccxt.async_support.hyperliquid):
905
905
  return True
906
906
  data = self.safe_dict(message, 'data', {})
907
907
  id = self.safe_string(message, 'id')
908
+ if id is None:
909
+ id = self.safe_string(data, 'id')
908
910
  response = self.safe_dict(data, 'response', {})
909
911
  payload = self.safe_dict(response, 'payload', {})
910
912
  status = self.safe_string(payload, 'status')
ccxt/pro/kraken.py CHANGED
@@ -86,6 +86,7 @@ class kraken(ccxt.async_support.kraken):
86
86
  'broad': {
87
87
  'Already subscribed': BadRequest,
88
88
  'Currency pair not in ISO 4217-A3 format': BadSymbol,
89
+ 'Currency pair not supported': BadSymbol,
89
90
  'Malformed request': BadRequest,
90
91
  'Pair field must be an array': BadRequest,
91
92
  'Pair field unsupported for self subscription type': BadRequest,
ccxt/pro/lbank.py CHANGED
@@ -6,7 +6,7 @@
6
6
  import ccxt.async_support
7
7
  from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
8
8
  import math
9
- from ccxt.base.types import Any, Int, Order, OrderBook, Str, Ticker, Trade
9
+ from ccxt.base.types import Any, Balances, Int, Order, OrderBook, Str, Ticker, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
@@ -22,7 +22,7 @@ class lbank(ccxt.async_support.lbank):
22
22
  'fetchOrderBookWs': True,
23
23
  'fetchTickerWs': True,
24
24
  'fetchTradesWs': True,
25
- 'watchBalance': False,
25
+ 'watchBalance': True,
26
26
  'watchTicker': True,
27
27
  'watchTickers': False,
28
28
  'watchTrades': True,
@@ -658,6 +658,59 @@ class lbank(ccxt.async_support.lbank):
658
658
  }
659
659
  return self.safe_string(statuses, status, status)
660
660
 
661
+ async def watch_balance(self, params={}) -> Balances:
662
+ """
663
+ watch balance and get the amount of funds available for trading or funds locked in orders
664
+
665
+ https://www.lbank.com/docs/index.html#update-subscribed-asset
666
+
667
+ :param dict [params]: extra parameters specific to the exchange API endpoint
668
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
669
+ """
670
+ await self.load_markets()
671
+ key = await self.authenticate(params)
672
+ url = self.urls['api']['ws']
673
+ messageHash = 'balance'
674
+ message: dict = {
675
+ 'action': 'subscribe',
676
+ 'subscribe': 'assetUpdate',
677
+ 'subscribeKey': key,
678
+ }
679
+ request = self.deep_extend(message, params)
680
+ return await self.watch(url, messageHash, request, messageHash, request)
681
+
682
+ def handle_balance(self, client: Client, message):
683
+ #
684
+ # {
685
+ # "data": {
686
+ # "asset": "114548.31881315",
687
+ # "assetCode": "usdt",
688
+ # "free": "97430.6739041",
689
+ # "freeze": "17117.64490905",
690
+ # "time": 1627300043270,
691
+ # "type": "ORDER_CREATE"
692
+ # },
693
+ # "SERVER": "V2",
694
+ # "type": "assetUpdate",
695
+ # "TS": "2021-07-26T19:48:03.548"
696
+ # }
697
+ #
698
+ data = self.safe_dict(message, 'data', {})
699
+ timestamp = self.parse8601(self.safe_string(message, 'TS'))
700
+ datetime = self.iso8601(timestamp)
701
+ self.balance['info'] = data
702
+ self.balance['timestamp'] = timestamp
703
+ self.balance['datetime'] = datetime
704
+ currencyId = self.safe_string(data, 'assetCode')
705
+ code = self.safe_currency_code(currencyId)
706
+ account = self.account()
707
+ account['free'] = self.safe_string(data, 'free')
708
+ account['used'] = self.safe_string(data, 'freeze')
709
+ account['total'] = self.safe_string(data, 'asset')
710
+ self.balance[code] = account
711
+ self.balance = self.safe_balance(self.balance)
712
+ client.resolve(self.balance, 'balance')
713
+
661
714
  async def fetch_order_book_ws(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
662
715
  """
663
716
 
@@ -827,6 +880,7 @@ class lbank(ccxt.async_support.lbank):
827
880
  'trade': self.handle_trades,
828
881
  'tick': self.handle_ticker,
829
882
  'orderUpdate': self.handle_orders,
883
+ 'assetUpdate': self.handle_balance,
830
884
  }
831
885
  handler = self.safe_value(handlers, type)
832
886
  if handler is not None: