ccxt 4.3.83__py2.py3-none-any.whl → 4.3.85__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/cryptocom.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.cryptocom import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Balances, Currency, Int, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
9
+ from ccxt.base.types import Account, Balances, Currency, Int, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -109,8 +109,8 @@ class cryptocom(Exchange, ImplicitAPI):
109
109
  'fetchTickers': True,
110
110
  'fetchTime': False,
111
111
  'fetchTrades': True,
112
- 'fetchTradingFee': False,
113
- 'fetchTradingFees': False,
112
+ 'fetchTradingFee': True,
113
+ 'fetchTradingFees': True,
114
114
  'fetchTransactionFees': False,
115
115
  'fetchTransactions': False,
116
116
  'fetchTransfers': False,
@@ -211,6 +211,8 @@ class cryptocom(Exchange, ImplicitAPI):
211
211
  'private/get-accounts': 10 / 3,
212
212
  'private/get-withdrawal-history': 10 / 3,
213
213
  'private/get-deposit-history': 10 / 3,
214
+ 'private/get-fee-rate': 2,
215
+ 'private/get-instrument-fee-rate': 2,
214
216
  'private/staking/stake': 2,
215
217
  'private/staking/unstake': 2,
216
218
  'private/staking/get-staking-position': 2,
@@ -2806,6 +2808,114 @@ class cryptocom(Exchange, ImplicitAPI):
2806
2808
  result = self.safe_dict(response, 'result')
2807
2809
  return self.parse_order(result, market)
2808
2810
 
2811
+ def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
2812
+ """
2813
+ fetch the trading fees for a market
2814
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-instrument-fee-rate
2815
+ :param str symbol: unified market symbol
2816
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2817
+ :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
2818
+ """
2819
+ self.load_markets()
2820
+ market = self.market(symbol)
2821
+ request: dict = {
2822
+ 'instrument_name': market['id'],
2823
+ }
2824
+ response = self.v1PrivatePostPrivateGetInstrumentFeeRate(self.extend(request, params))
2825
+ #
2826
+ # {
2827
+ # "id": 1,
2828
+ # "code": 0,
2829
+ # "method": "private/staking/unstake",
2830
+ # "result": {
2831
+ # "staking_id": "1",
2832
+ # "instrument_name": "SOL.staked",
2833
+ # "status": "NEW",
2834
+ # "quantity": "1",
2835
+ # "underlying_inst_name": "SOL",
2836
+ # "reason": "NO_ERROR"
2837
+ # }
2838
+ # }
2839
+ #
2840
+ data = self.safe_dict(response, 'result', {})
2841
+ return self.parse_trading_fee(data, market)
2842
+
2843
+ def fetch_trading_fees(self, params={}) -> TradingFees:
2844
+ """
2845
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-fee-rate
2846
+ fetch the trading fees for multiple markets
2847
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2848
+ :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
2849
+ """
2850
+ self.load_markets()
2851
+ response = self.v1PrivatePostPrivateGetFeeRate(params)
2852
+ #
2853
+ # {
2854
+ # "id": 1,
2855
+ # "method": "/private/get-fee-rate",
2856
+ # "code": 0,
2857
+ # "result": {
2858
+ # "spot_tier": "3",
2859
+ # "deriv_tier": "3",
2860
+ # "effective_spot_maker_rate_bps": "6.5",
2861
+ # "effective_spot_taker_rate_bps": "6.9",
2862
+ # "effective_deriv_maker_rate_bps": "1.1",
2863
+ # "effective_deriv_taker_rate_bps": "3"
2864
+ # }
2865
+ # }
2866
+ #
2867
+ result = self.safe_dict(response, 'result', {})
2868
+ return self.parse_trading_fees(result)
2869
+
2870
+ def parse_trading_fees(self, response):
2871
+ #
2872
+ # {
2873
+ # "spot_tier": "3",
2874
+ # "deriv_tier": "3",
2875
+ # "effective_spot_maker_rate_bps": "6.5",
2876
+ # "effective_spot_taker_rate_bps": "6.9",
2877
+ # "effective_deriv_maker_rate_bps": "1.1",
2878
+ # "effective_deriv_taker_rate_bps": "3"
2879
+ # }
2880
+ #
2881
+ result: dict = {}
2882
+ result['info'] = response
2883
+ for i in range(0, len(self.symbols)):
2884
+ symbol = self.symbols[i]
2885
+ market = self.market(symbol)
2886
+ isSwap = market['swap']
2887
+ takerFeeKey = 'effective_deriv_taker_rate_bps' if isSwap else 'effective_spot_taker_rate_bps'
2888
+ makerFeeKey = 'effective_deriv_maker_rate_bps' if isSwap else 'effective_spot_maker_rate_bps'
2889
+ tradingFee = {
2890
+ 'info': response,
2891
+ 'symbol': symbol,
2892
+ 'maker': self.parse_number(Precise.string_div(self.safe_string(response, makerFeeKey), '10000')),
2893
+ 'taker': self.parse_number(Precise.string_div(self.safe_string(response, takerFeeKey), '10000')),
2894
+ 'percentage': None,
2895
+ 'tierBased': None,
2896
+ }
2897
+ result[symbol] = tradingFee
2898
+ return result
2899
+
2900
+ def parse_trading_fee(self, fee: dict, market: Market = None) -> TradingFeeInterface:
2901
+ #
2902
+ # {
2903
+ # "instrument_name": "BTC_USD",
2904
+ # "effective_maker_rate_bps": "6.5",
2905
+ # "effective_taker_rate_bps": "6.9"
2906
+ # }
2907
+ #
2908
+ marketId = self.safe_string(fee, 'instrument_name')
2909
+ symbol = self.safe_symbol(marketId, market)
2910
+ return {
2911
+ 'info': fee,
2912
+ 'symbol': symbol,
2913
+ 'maker': self.parse_number(Precise.string_div(self.safe_string(fee, 'effective_maker_rate_bps'), '10000')),
2914
+ 'taker': self.parse_number(Precise.string_div(self.safe_string(fee, 'effective_taker_rate_bps'), '10000')),
2915
+ 'percentage': None,
2916
+ 'tierBased': None,
2917
+ }
2918
+
2809
2919
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2810
2920
  type = self.safe_string(api, 0)
2811
2921
  access = self.safe_string(api, 1)
ccxt/kraken.py CHANGED
@@ -1181,6 +1181,26 @@ class kraken(Exchange, ImplicitAPI):
1181
1181
  # "misc": ''
1182
1182
  # }
1183
1183
  #
1184
+ # fetchMyTrades
1185
+ #
1186
+ # {
1187
+ # "ordertxid": "OSJVN7-A2AE-63WZV",
1188
+ # "postxid": "TBP7O6-PNXI-CONU",
1189
+ # "pair": "XXBTZUSD",
1190
+ # "time": 1710429248.3052235,
1191
+ # "type": "sell",
1192
+ # "ordertype": "liquidation market",
1193
+ # "price": "72026.50000",
1194
+ # "cost": "7.20265",
1195
+ # "fee": "0.01873",
1196
+ # "vol": "0.00010000",
1197
+ # "margin": "1.44053",
1198
+ # "leverage": "5",
1199
+ # "misc": "closing",
1200
+ # "trade_id": 68230622,
1201
+ # "maker": False
1202
+ # }
1203
+ #
1184
1204
  timestamp = None
1185
1205
  side = None
1186
1206
  type = None
@@ -1227,6 +1247,10 @@ class kraken(Exchange, ImplicitAPI):
1227
1247
  if market is not None:
1228
1248
  symbol = market['symbol']
1229
1249
  cost = self.safe_string(trade, 'cost')
1250
+ maker = self.safe_bool(trade, 'maker')
1251
+ takerOrMaker = None
1252
+ if maker is not None:
1253
+ takerOrMaker = 'maker' if maker else 'taker'
1230
1254
  return self.safe_trade({
1231
1255
  'id': id,
1232
1256
  'order': orderId,
@@ -1236,7 +1260,7 @@ class kraken(Exchange, ImplicitAPI):
1236
1260
  'symbol': symbol,
1237
1261
  'type': type,
1238
1262
  'side': side,
1239
- 'takerOrMaker': None,
1263
+ 'takerOrMaker': takerOrMaker,
1240
1264
  'price': price,
1241
1265
  'amount': amount,
1242
1266
  'cost': cost,
@@ -2001,7 +2025,10 @@ class kraken(Exchange, ImplicitAPI):
2001
2025
  # "fee": "0.000026",
2002
2026
  # "vol": "16.00000000",
2003
2027
  # "margin": "0.000000",
2028
+ # "leverage": "5",
2004
2029
  # "misc": ""
2030
+ # "trade_id": 68230622,
2031
+ # "maker": False
2005
2032
  # },
2006
2033
  # ...
2007
2034
  # },
@@ -2367,13 +2394,11 @@ class kraken(Exchange, ImplicitAPI):
2367
2394
  :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2368
2395
  """
2369
2396
  # https://www.kraken.com/en-us/help/api#deposit-status
2370
- if code is None:
2371
- raise ArgumentsRequired(self.id + ' fetchDeposits() requires a currency code argument')
2372
2397
  self.load_markets()
2373
- currency = self.currency(code)
2374
- request: dict = {
2375
- 'asset': currency['id'],
2376
- }
2398
+ request: dict = {}
2399
+ if code is not None:
2400
+ currency = self.currency(code)
2401
+ request['asset'] = currency['id']
2377
2402
  if since is not None:
2378
2403
  request['start'] = since
2379
2404
  response = self.privatePostDepositStatus(self.extend(request, params))
ccxt/kucoinfutures.py CHANGED
@@ -137,6 +137,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
137
137
  'contracts/{symbol}': 1,
138
138
  'contracts/risk-limit/{symbol}': 1,
139
139
  'ticker': 1,
140
+ 'allTickers': 1,
140
141
  'level2/snapshot': 1.33,
141
142
  'level2/depth{limit}': 1,
142
143
  'level2/message/query': 1,
@@ -180,6 +181,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
180
181
  'trade-statistics': 1,
181
182
  'trade-fees': 1,
182
183
  'history-positions': 1,
184
+ 'getMaxOpenSize': 1,
183
185
  },
184
186
  'post': {
185
187
  'withdrawals': 1,
@@ -325,6 +327,9 @@ class kucoinfutures(kucoin, ImplicitAPI):
325
327
  # endpoint versions
326
328
  'versions': {
327
329
  'futuresPrivate': {
330
+ 'GET': {
331
+ 'getMaxOpenSize': 'v2',
332
+ },
328
333
  'POST': {
329
334
  'transfer-out': 'v2',
330
335
  },
ccxt/mexc.py CHANGED
@@ -1158,7 +1158,7 @@ class mexc(Exchange, ImplicitAPI):
1158
1158
  # "symbols": [
1159
1159
  # {
1160
1160
  # "symbol": "OGNUSDT",
1161
- # "status": "ENABLED",
1161
+ # "status": "1",
1162
1162
  # "baseAsset": "OGN",
1163
1163
  # "baseAssetPrecision": "2",
1164
1164
  # "quoteAsset": "USDT",
@@ -1203,7 +1203,7 @@ class mexc(Exchange, ImplicitAPI):
1203
1203
  status = self.safe_string(market, 'status')
1204
1204
  isSpotTradingAllowed = self.safe_value(market, 'isSpotTradingAllowed')
1205
1205
  active = False
1206
- if (status == 'ENABLED') and (isSpotTradingAllowed):
1206
+ if (status == '1') and (isSpotTradingAllowed):
1207
1207
  active = True
1208
1208
  isMarginTradingAllowed = self.safe_value(market, 'isMarginTradingAllowed')
1209
1209
  makerCommission = self.safe_number(market, 'makerCommission')
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.83'
7
+ __version__ = '4.3.85'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/binance.py CHANGED
@@ -228,7 +228,7 @@ class binance(ccxt.async_support.binance):
228
228
  else:
229
229
  for i in range(0, len(symbols)):
230
230
  market = self.market(symbols[i])
231
- subscriptionHashes.append(market['id'] + '@forceOrder')
231
+ subscriptionHashes.append(market['lowercaseId'] + '@forceOrder')
232
232
  messageHashes.append('liquidations::' + symbols[i])
233
233
  streamHash += '::' + ','.join(symbols)
234
234
  firstMarket = self.get_market_from_symbols(symbols)
@@ -1133,6 +1133,9 @@ class binance(ccxt.async_support.binance):
1133
1133
  :param dict [params.timezone]: if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1134
1134
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
1135
1135
  """
1136
+ await self.load_markets()
1137
+ market = self.market(symbol)
1138
+ symbol = market['symbol']
1136
1139
  params['callerMethodName'] = 'watchOHLCV'
1137
1140
  result = await self.watch_ohlcv_for_symbols([[symbol, timeframe]], since, limit, params)
1138
1141
  return result[symbol][timeframe]
@@ -1179,7 +1182,7 @@ class binance(ccxt.async_support.binance):
1179
1182
  suffix = '@+08:00'
1180
1183
  utcSuffix = suffix if shouldUseUTC8 else ''
1181
1184
  rawHashes.append(marketId + '@' + klineType + '_' + interval + utcSuffix)
1182
- messageHashes.append('ohlcv::' + symbolString + '::' + timeframeString)
1185
+ messageHashes.append('ohlcv::' + market['symbol'] + '::' + timeframeString)
1183
1186
  url = self.urls['api']['ws'][type] + '/' + self.stream(type, 'multipleOHLCV')
1184
1187
  requestId = self.request_id(url)
1185
1188
  request = {
@@ -1434,6 +1437,8 @@ class binance(ccxt.async_support.binance):
1434
1437
  :param dict [params]: extra parameters specific to the exchange API endpoint
1435
1438
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1436
1439
  """
1440
+ await self.load_markets()
1441
+ symbols = self.market_symbols(symbols, None, True, False, True)
1437
1442
  result = await self.watch_multi_ticker_helper('watchBidsAsks', 'bookTicker', symbols, params)
1438
1443
  if self.newUpdates:
1439
1444
  return result
ccxt/pro/bitget.py CHANGED
@@ -9,6 +9,7 @@ import hashlib
9
9
  from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
+ from typing import Any
12
13
  from ccxt.base.errors import ExchangeError
13
14
  from ccxt.base.errors import AuthenticationError
14
15
  from ccxt.base.errors import ArgumentsRequired
@@ -429,6 +430,32 @@ class bitget(ccxt.async_support.bitget):
429
430
  """
430
431
  return await self.watch_order_book_for_symbols([symbol], limit, params)
431
432
 
433
+ async def un_watch_order_book(self, symbol: str, params={}) -> Any:
434
+ """
435
+ unsubscribe from the orderbook channel
436
+ :see: https://www.bitget.com/api-doc/spot/websocket/public/Depth-Channel
437
+ :see: https://www.bitget.com/api-doc/contract/websocket/public/Order-Book-Channel
438
+ :param str symbol: unified symbol of the market to fetch the order book for
439
+ :param int [params.limit]: orderbook limit, default is None
440
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
441
+ """
442
+ await self.load_markets()
443
+ market = self.market(symbol)
444
+ messageHash = 'unsubscribe:orderbook:' + market['symbol']
445
+ channel = 'books'
446
+ limit = self.safe_integer(params, 'limit')
447
+ if (limit == 1) or (limit == 5) or (limit == 15):
448
+ params = self.omit(params, 'limit')
449
+ channel += str(limit)
450
+ instType = None
451
+ instType, params = self.get_inst_type(market, params)
452
+ args: dict = {
453
+ 'instType': instType,
454
+ 'channel': channel,
455
+ 'instId': market['id'],
456
+ }
457
+ return await self.un_watch_public(messageHash, args, params)
458
+
432
459
  async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
433
460
  """
434
461
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
@@ -542,10 +569,11 @@ class bitget(ccxt.async_support.bitget):
542
569
  calculatedChecksum = self.crc32(payload, True)
543
570
  responseChecksum = self.safe_integer(rawOrderBook, 'checksum')
544
571
  if calculatedChecksum != responseChecksum:
545
- del client.subscriptions[messageHash]
546
- del self.orderbooks[symbol]
547
- error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
548
- client.reject(error, messageHash)
572
+ # if messageHash in client.subscriptions:
573
+ # # del client.subscriptions[messageHash]
574
+ # # del self.orderbooks[symbol]
575
+ # }
576
+ self.spawn(self.handle_check_sum_error, client, symbol, messageHash)
549
577
  return
550
578
  else:
551
579
  orderbook = self.order_book({})
@@ -554,6 +582,11 @@ class bitget(ccxt.async_support.bitget):
554
582
  self.orderbooks[symbol] = orderbook
555
583
  client.resolve(self.orderbooks[symbol], messageHash)
556
584
 
585
+ async def handle_check_sum_error(self, client: Client, symbol: str, messageHash: str):
586
+ await self.un_watch_order_book(symbol)
587
+ error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
588
+ client.reject(error, messageHash)
589
+
557
590
  def handle_delta(self, bookside, delta):
558
591
  bidAsk = self.parse_bid_ask(delta, 0, 1)
559
592
  # we store the string representations in the orderbook for checksum calculation
@@ -1524,6 +1557,15 @@ class bitget(ccxt.async_support.bitget):
1524
1557
  message = self.extend(request, params)
1525
1558
  return await self.watch(url, messageHash, message, messageHash)
1526
1559
 
1560
+ async def un_watch_public(self, messageHash, args, params={}):
1561
+ url = self.urls['api']['ws']['public']
1562
+ request: dict = {
1563
+ 'op': 'unsubscribe',
1564
+ 'args': [args],
1565
+ }
1566
+ message = self.extend(request, params)
1567
+ return await self.watch(url, messageHash, message, messageHash)
1568
+
1527
1569
  async def watch_public_multiple(self, messageHashes, argsArray, params={}):
1528
1570
  url = self.urls['api']['ws']['public']
1529
1571
  request: dict = {
@@ -1637,6 +1679,17 @@ class bitget(ccxt.async_support.bitget):
1637
1679
  # "event": "subscribe",
1638
1680
  # "arg": {instType: 'SPOT', channel: "account", instId: "default"}
1639
1681
  # }
1682
+ # unsubscribe
1683
+ # {
1684
+ # "op":"unsubscribe",
1685
+ # "args":[
1686
+ # {
1687
+ # "instType":"USDT-FUTURES",
1688
+ # "channel":"ticker",
1689
+ # "instId":"BTCUSDT"
1690
+ # }
1691
+ # ]
1692
+ # }
1640
1693
  #
1641
1694
  if self.handle_error_message(client, message):
1642
1695
  return
@@ -1654,6 +1707,9 @@ class bitget(ccxt.async_support.bitget):
1654
1707
  if event == 'subscribe':
1655
1708
  self.handle_subscription_status(client, message)
1656
1709
  return
1710
+ if event == 'unsubscribe':
1711
+ self.handle_un_subscription_status(client, message)
1712
+ return
1657
1713
  methods: dict = {
1658
1714
  'ticker': self.handle_ticker,
1659
1715
  'trade': self.handle_trades,
@@ -1693,3 +1749,47 @@ class bitget(ccxt.async_support.bitget):
1693
1749
  # }
1694
1750
  #
1695
1751
  return message
1752
+
1753
+ def handle_un_subscription_status(self, client: Client, message):
1754
+ #
1755
+ # {
1756
+ # "op":"unsubscribe",
1757
+ # "args":[
1758
+ # {
1759
+ # "instType":"USDT-FUTURES",
1760
+ # "channel":"ticker",
1761
+ # "instId":"BTCUSDT"
1762
+ # },
1763
+ # {
1764
+ # "instType":"USDT-FUTURES",
1765
+ # "channel":"candle1m",
1766
+ # "instId":"BTCUSDT"
1767
+ # }
1768
+ # ]
1769
+ # }
1770
+ # or
1771
+ # {"event":"unsubscribe","arg":{"instType":"SPOT","channel":"books","instId":"BTCUSDT"}}
1772
+ #
1773
+ argsList = self.safe_list(message, 'args')
1774
+ if argsList is None:
1775
+ argsList = [self.safe_dict(message, 'arg', {})]
1776
+ for i in range(0, len(argsList)):
1777
+ arg = argsList[i]
1778
+ channel = self.safe_string(arg, 'channel')
1779
+ if channel == 'books':
1780
+ # for now only unWatchOrderBook is supporteod
1781
+ instType = self.safe_string_lower(arg, 'instType')
1782
+ type = 'spot' if (instType == 'spot') else 'contract'
1783
+ instId = self.safe_string(arg, 'instId')
1784
+ market = self.safe_market(instId, None, None, type)
1785
+ symbol = market['symbol']
1786
+ messageHash = 'unsubscribe:orderbook:' + market['symbol']
1787
+ subMessageHash = 'orderbook:' + symbol
1788
+ if symbol in self.orderbooks:
1789
+ del self.orderbooks[symbol]
1790
+ if subMessageHash in client.subscriptions:
1791
+ del client.subscriptions[subMessageHash]
1792
+ if messageHash in client.subscriptions:
1793
+ del client.subscriptions[messageHash]
1794
+ client.resolve(True, messageHash)
1795
+ return message
ccxt/pro/bitrue.py CHANGED
@@ -401,13 +401,7 @@ class bitrue(ccxt.async_support.bitrue):
401
401
  async def authenticate(self, params={}):
402
402
  listenKey = self.safe_value(self.options, 'listenKey')
403
403
  if listenKey is None:
404
- response = None
405
- try:
406
- response = await self.openPrivatePostPoseidonApiV1ListenKey(params)
407
- except Exception as error:
408
- self.options['listenKey'] = None
409
- self.options['listenKeyUrl'] = None
410
- return None
404
+ response = await self.openPrivatePostPoseidonApiV1ListenKey(params)
411
405
  #
412
406
  # {
413
407
  # "msg": "succ",
ccxt/pro/gate.py CHANGED
@@ -1408,7 +1408,7 @@ class gate(ccxt.async_support.gate):
1408
1408
  errs = self.safe_dict(data, 'errs')
1409
1409
  error = self.safe_dict(message, 'error', errs)
1410
1410
  code = self.safe_string_2(error, 'code', 'label')
1411
- id = self.safe_string_2(message, 'id', 'requestId')
1411
+ id = self.safe_string_n(message, ['id', 'requestId', 'request_id'])
1412
1412
  if error is not None:
1413
1413
  messageHash = self.safe_string(client.subscriptions, id)
1414
1414
  try:
@@ -1421,7 +1421,7 @@ class gate(ccxt.async_support.gate):
1421
1421
  client.reject(e, messageHash)
1422
1422
  if (messageHash is not None) and (messageHash in client.subscriptions):
1423
1423
  del client.subscriptions[messageHash]
1424
- if id is not None:
1424
+ if (id is not None) and (id in client.subscriptions):
1425
1425
  del client.subscriptions[id]
1426
1426
  return True
1427
1427
  return False
@@ -1686,7 +1686,7 @@ class gate(ccxt.async_support.gate):
1686
1686
  'event': event,
1687
1687
  'payload': payload,
1688
1688
  }
1689
- return await self.watch(url, messageHash, request, messageHash)
1689
+ return await self.watch(url, messageHash, request, messageHash, requestId)
1690
1690
 
1691
1691
  async def subscribe_private(self, url, messageHash, payload, channel, params, requiresUid=False):
1692
1692
  self.check_required_credentials()
@@ -1724,4 +1724,4 @@ class gate(ccxt.async_support.gate):
1724
1724
  # in case of authenticationError we will throw
1725
1725
  client.subscriptions[tempSubscriptionHash] = messageHash
1726
1726
  message = self.extend(request, params)
1727
- return await self.watch(url, messageHash, message, messageHash)
1727
+ return await self.watch(url, messageHash, message, messageHash, messageHash)
ccxt/pro/okx.py CHANGED
@@ -419,8 +419,13 @@ class okx(ccxt.async_support.okx):
419
419
  await self.load_markets()
420
420
  symbols = self.market_symbols(symbols, None, True, True)
421
421
  messageHash = 'liquidations'
422
+ messageHashes = []
422
423
  if symbols is not None:
423
- messageHash += '::' + ','.join(symbols)
424
+ for i in range(0, len(symbols)):
425
+ symbol = symbols[i]
426
+ messageHashes.append(messageHash + '::' + symbol)
427
+ else:
428
+ messageHashes.append(messageHash)
424
429
  market = self.get_market_from_symbols(symbols)
425
430
  type = None
426
431
  type, params = self.handle_market_type_and_params('watchliquidationsForSymbols', market, params)
@@ -431,9 +436,16 @@ class okx(ccxt.async_support.okx):
431
436
  type = 'futures'
432
437
  uppercaseType = type.upper()
433
438
  request = {
434
- 'instType': uppercaseType,
439
+ 'op': 'subscribe',
440
+ 'args': [
441
+ {
442
+ 'channel': channel,
443
+ 'instType': uppercaseType,
444
+ },
445
+ ],
435
446
  }
436
- newLiquidations = await self.subscribe('public', messageHash, channel, None, self.extend(request, params))
447
+ url = self.get_url(channel, 'public')
448
+ newLiquidations = await self.watch_multiple(url, messageHashes, request, messageHashes)
437
449
  if self.newUpdates:
438
450
  return newLiquidations
439
451
  return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
@@ -1305,6 +1317,12 @@ class okx(ccxt.async_support.okx):
1305
1317
  for i in range(0, len(data)):
1306
1318
  rawPosition = data[i]
1307
1319
  position = self.parse_position(rawPosition)
1320
+ if position['contracts'] == 0:
1321
+ position['side'] = 'long'
1322
+ shortPosition = self.clone(position)
1323
+ shortPosition['side'] = 'short'
1324
+ cache.append(shortPosition)
1325
+ newPositions.append(shortPosition)
1308
1326
  newPositions.append(position)
1309
1327
  cache.append(position)
1310
1328
  messageHashes = self.find_message_hashes(client, channel + '::')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.3.83
3
+ Version: 4.3.85
4
4
  Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges
5
5
  Home-page: https://ccxt.com
6
6
  Author: Igor Kroitor
@@ -269,13 +269,13 @@ console.log(version, Object.keys(exchanges));
269
269
 
270
270
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
271
271
 
272
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.83/dist/ccxt.browser.min.js
273
- * unpkg: https://unpkg.com/ccxt@4.3.83/dist/ccxt.browser.min.js
272
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.85/dist/ccxt.browser.min.js
273
+ * unpkg: https://unpkg.com/ccxt@4.3.85/dist/ccxt.browser.min.js
274
274
 
275
275
  CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
276
276
 
277
277
  ```HTML
278
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.83/dist/ccxt.browser.min.js"></script>
278
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.85/dist/ccxt.browser.min.js"></script>
279
279
  ```
280
280
 
281
281
  Creates a global `ccxt` object: