ccxt 4.4.60__py2.py3-none-any.whl → 4.4.62__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/gate.py CHANGED
@@ -674,23 +674,67 @@ class gate(Exchange, ImplicitAPI):
674
674
  },
675
675
  'createMarketBuyOrderRequiresPrice': True,
676
676
  'networks': {
677
- 'LINEA': 'LINEAETH',
678
- 'KON': 'KONET',
679
- 'AVAXC': 'AVAX_C',
677
+ 'BTC': 'BTC',
678
+ 'BRC20': 'BTCBRC', # for eg: ORDI, RATS, ...
679
+ 'ETH': 'ETH',
680
+ 'ERC20': 'ETH',
681
+ 'TRX': 'TRX',
682
+ 'TRC20': 'TRX',
683
+ 'HECO': 'HT',
684
+ 'HRC20': 'HT',
685
+ 'BSC': 'BSC',
680
686
  'BEP20': 'BSC',
687
+ 'SOL': 'SOL',
688
+ 'POLYGON': 'POL',
689
+ 'MATIC': 'POL',
690
+ 'OP': 'OPETH',
691
+ 'OPTIMISM': 'OPETH',
692
+ 'ADA': 'ADA', # CARDANO
693
+ 'AVAXC': 'AVAX_C',
694
+ 'NEAR': 'NEAR',
695
+ 'ARBONE': 'ARBEVM',
696
+ 'BASE': 'BASEEVM',
697
+ 'SUI': 'SUI',
698
+ 'CRONOS': 'CRO',
699
+ 'CRO': 'CRO',
700
+ 'APT': 'APT',
701
+ 'SCROLL': 'SCROLLETH',
702
+ 'TAIKO': 'TAIKOETH',
703
+ 'HYPE': 'HYPE',
704
+ 'ALGO': 'ALGO',
705
+ # KAVA: ['KAVA', 'KAVAEVM']
706
+ # SEI: ['SEI', 'SEIEVM']
707
+ 'LINEA': 'LINEAETH',
708
+ 'BLAST': 'BLASTETH',
709
+ 'XLM': 'XLM',
710
+ 'RSK': 'RBTC',
711
+ 'TON': 'TON',
712
+ 'MNT': 'MNT',
713
+ # 'RUNE': 'BTCRUNES', probably, cant verify atm
714
+ 'CELO': 'CELO',
715
+ 'HBAR': 'HBAR',
716
+ # 'FTM': SONIC REBRAND, todo
717
+ 'ZKSERA': 'ZKSERA',
718
+ 'KLAY': 'KLAY',
681
719
  'EOS': 'EOS',
682
- 'ERC20': 'ETH',
720
+ 'ACA': 'ACA',
721
+ # TLOS: ['TLOS', 'TLOSEVM']
722
+ # ASTR: ['ASTR', 'ASTREVM']
723
+ # CFX: ['CFX', 'CFXEVM']
724
+ 'XTZ': 'XTZ',
725
+ 'EGLD': 'EGLD',
726
+ 'GLMR': 'GLMR',
727
+ 'AURORA': 'AURORAEVM',
728
+ # others
729
+ 'KON': 'KONET',
683
730
  'GATECHAIN': 'GTEVM',
684
- 'HRC20': 'HT',
685
731
  'KUSAMA': 'KSMSM',
686
- 'NEAR': 'NEAR',
687
732
  'OKC': 'OKT',
688
- 'OPTIMISM': 'OPETH',
689
- 'POLKADOT': 'DOTSM',
690
- 'TRC20': 'TRX',
733
+ 'POLKADOT': 'DOTSM', # todo: DOT for main DOT
691
734
  'LUNA': 'LUNC',
692
- 'BASE': 'BASEEVM',
693
- 'BRC20': 'BTCBRC',
735
+ },
736
+ 'networksById': {
737
+ 'OPETH': 'OP',
694
738
  },
695
739
  'timeInForce': {
696
740
  'GTC': 'gtc',
@@ -3525,6 +3569,7 @@ class gate(Exchange, ImplicitAPI):
3525
3569
  #
3526
3570
  # public
3527
3571
  #
3572
+ # spot:
3528
3573
  # {
3529
3574
  # "id": "1334253759",
3530
3575
  # "create_time": "1626342738",
@@ -3535,6 +3580,18 @@ class gate(Exchange, ImplicitAPI):
3535
3580
  # "price": "32452.16"
3536
3581
  # }
3537
3582
  #
3583
+ # swap:
3584
+ #
3585
+ # {
3586
+ # "id": "442288327",
3587
+ # "contract": "BTC_USDT",
3588
+ # "create_time": "1739814676.707",
3589
+ # "create_time_ms": "1739814676.707",
3590
+ # "size": "-105",
3591
+ # "price": "95594.8"
3592
+ # }
3593
+ #
3594
+ #
3538
3595
  # public ws
3539
3596
  #
3540
3597
  # {
@@ -3611,8 +3668,14 @@ class gate(Exchange, ImplicitAPI):
3611
3668
  # }
3612
3669
  #
3613
3670
  id = self.safe_string_2(trade, 'id', 'trade_id')
3614
- timestamp = self.safe_timestamp_2(trade, 'time', 'create_time')
3615
- timestamp = self.safe_integer(trade, 'create_time_ms', timestamp)
3671
+ timestamp: Int = None
3672
+ msString = self.safe_string(trade, 'create_time_ms')
3673
+ if msString is not None:
3674
+ msString = Precise.string_mul(msString, '1000')
3675
+ msString = msString[0:13]
3676
+ timestamp = self.parse_to_int(msString)
3677
+ else:
3678
+ timestamp = self.safe_timestamp_2(trade, 'time', 'create_time')
3616
3679
  marketId = self.safe_string_2(trade, 'currency_pair', 'contract')
3617
3680
  marketType = 'contract' if ('contract' in trade) else 'spot'
3618
3681
  market = self.safe_market(marketId, market, '_', marketType)
ccxt/kraken.py CHANGED
@@ -981,9 +981,9 @@ class kraken(Exchange, ImplicitAPI):
981
981
  'high': self.safe_string(high, 1),
982
982
  'low': self.safe_string(low, 1),
983
983
  'bid': self.safe_string(bid, 0),
984
- 'bidVolume': None,
984
+ 'bidVolume': self.safe_string(bid, 2),
985
985
  'ask': self.safe_string(ask, 0),
986
- 'askVolume': None,
986
+ 'askVolume': self.safe_string(ask, 2),
987
987
  'vwap': vwap,
988
988
  'open': self.safe_string(ticker, 'o'),
989
989
  'close': last,
ccxt/phemex.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.phemex import ImplicitAPI
8
8
  import hashlib
9
9
  import numbers
10
- from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Any, Balances, Conversion, Currencies, Currency, DepositAddress, Int, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -50,6 +50,7 @@ class phemex(Exchange, ImplicitAPI):
50
50
  'cancelAllOrders': True,
51
51
  'cancelOrder': True,
52
52
  'closePosition': False,
53
+ 'createConvertTrade': True,
53
54
  'createOrder': True,
54
55
  'createReduceOnlyOrder': True,
55
56
  'createStopLimitOrder': True,
@@ -60,6 +61,9 @@ class phemex(Exchange, ImplicitAPI):
60
61
  'fetchBorrowRateHistories': False,
61
62
  'fetchBorrowRateHistory': False,
62
63
  'fetchClosedOrders': True,
64
+ 'fetchConvertQuote': True,
65
+ 'fetchConvertTrade': False,
66
+ 'fetchConvertTradeHistory': True,
63
67
  'fetchCrossBorrowRate': False,
64
68
  'fetchCrossBorrowRates': False,
65
69
  'fetchCurrencies': True,
@@ -1078,7 +1082,7 @@ class phemex(Exchange, ImplicitAPI):
1078
1082
  for i in range(0, len(products)):
1079
1083
  market = products[i]
1080
1084
  type = self.safe_string_lower(market, 'type')
1081
- if (type == 'perpetual') or (type == 'perpetualv2'):
1085
+ if (type == 'perpetual') or (type == 'perpetualv2') or (type == 'perpetualpilot'):
1082
1086
  id = self.safe_string(market, 'symbol')
1083
1087
  riskLimitValues = self.safe_value(riskLimitsById, id, {})
1084
1088
  market = self.extend(market, riskLimitValues)
@@ -1254,7 +1258,7 @@ class phemex(Exchange, ImplicitAPI):
1254
1258
  precise.decimals = precise.decimals - scale
1255
1259
  precise.reduce()
1256
1260
  preciseString = str(precise)
1257
- return self.parse_to_int(preciseString)
1261
+ return self.parse_to_numeric(preciseString)
1258
1262
 
1259
1263
  def to_ev(self, amount, market: Market = None):
1260
1264
  if (amount is None) or (market is None):
@@ -2547,7 +2551,6 @@ class phemex(Exchange, ImplicitAPI):
2547
2551
  market = self.market(symbol)
2548
2552
  requestSide = self.capitalize(side)
2549
2553
  type = self.capitalize(type)
2550
- reduceOnly = self.safe_bool(params, 'reduceOnly')
2551
2554
  request: dict = {
2552
2555
  # common
2553
2556
  'symbol': market['id'],
@@ -2630,8 +2633,10 @@ class phemex(Exchange, ImplicitAPI):
2630
2633
  posSide = self.safe_string_lower(params, 'posSide')
2631
2634
  if posSide is None:
2632
2635
  if hedged:
2636
+ reduceOnly = self.safe_bool(params, 'reduceOnly')
2633
2637
  if reduceOnly:
2634
2638
  side = 'sell' if (side == 'buy') else 'buy'
2639
+ params = self.omit(params, 'reduceOnly')
2635
2640
  posSide = 'Long' if (side == 'buy') else 'Short'
2636
2641
  else:
2637
2642
  posSide = 'Merged'
@@ -2709,7 +2714,6 @@ class phemex(Exchange, ImplicitAPI):
2709
2714
  else:
2710
2715
  request['stopLossEp'] = self.to_ep(stopLossPrice, market)
2711
2716
  params = self.omit(params, 'stopLossPrice')
2712
- params = self.omit(params, 'reduceOnly')
2713
2717
  response = None
2714
2718
  if market['settle'] == 'USDT':
2715
2719
  response = self.privatePostGOrders(self.extend(request, params))
@@ -4760,6 +4764,218 @@ class phemex(Exchange, ImplicitAPI):
4760
4764
  'datetime': self.iso8601(timestamp),
4761
4765
  }, market)
4762
4766
 
4767
+ def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
4768
+ """
4769
+ fetch a quote for converting from one currency to another
4770
+
4771
+ https://phemex-docs.github.io/#rfq-quote
4772
+
4773
+ :param str fromCode: the currency that you want to sell and convert from
4774
+ :param str toCode: the currency that you want to buy and convert into
4775
+ :param float amount: how much you want to trade in units of the from currency
4776
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4777
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
4778
+ """
4779
+ self.load_markets()
4780
+ fromCurrency = self.currency(fromCode)
4781
+ toCurrency = self.currency(toCode)
4782
+ valueScale = self.safe_integer(fromCurrency, 'valueScale')
4783
+ request: dict = {
4784
+ 'fromCurrency': fromCode,
4785
+ 'toCurrency': toCode,
4786
+ 'fromAmountEv': self.to_en(amount, valueScale),
4787
+ }
4788
+ response = self.privateGetAssetsQuote(self.extend(request, params))
4789
+ #
4790
+ # {
4791
+ # "code": 0,
4792
+ # "msg": "OK",
4793
+ # "data": {
4794
+ # "code": "GIF...AAA",
4795
+ # "quoteArgs": {
4796
+ # "origin": 10,
4797
+ # "price": "0.00000939",
4798
+ # "proceeds": "0.00000000",
4799
+ # "ttlMs": 7000,
4800
+ # "expireAt": 1739875826009,
4801
+ # "requestAt": 1739875818009,
4802
+ # "quoteAt": 1739875816594
4803
+ # }
4804
+ # }
4805
+ # }
4806
+ #
4807
+ data = self.safe_dict(response, 'data', {})
4808
+ return self.parse_conversion(data, fromCurrency, toCurrency)
4809
+
4810
+ def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
4811
+ """
4812
+ convert from one currency to another
4813
+
4814
+ https://phemex-docs.github.io/#convert
4815
+
4816
+ :param str id: the id of the trade that you want to make
4817
+ :param str fromCode: the currency that you want to sell and convert from
4818
+ :param str toCode: the currency that you want to buy and convert into
4819
+ :param float [amount]: how much you want to trade in units of the from currency
4820
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4821
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
4822
+ """
4823
+ self.load_markets()
4824
+ fromCurrency = self.currency(fromCode)
4825
+ toCurrency = self.currency(toCode)
4826
+ valueScale = self.safe_integer(fromCurrency, 'valueScale')
4827
+ request: dict = {
4828
+ 'code': id,
4829
+ 'fromCurrency': fromCode,
4830
+ 'toCurrency': toCode,
4831
+ }
4832
+ if amount is not None:
4833
+ request['fromAmountEv'] = self.to_en(amount, valueScale)
4834
+ response = self.privatePostAssetsConvert(self.extend(request, params))
4835
+ #
4836
+ # {
4837
+ # "code": 0,
4838
+ # "msg": "OK",
4839
+ # "data": {
4840
+ # "moveOp": 0,
4841
+ # "fromCurrency": "USDT",
4842
+ # "toCurrency": "BTC",
4843
+ # "fromAmountEv": 4000000000,
4844
+ # "toAmountEv": 41511,
4845
+ # "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
4846
+ # "status": 10
4847
+ # }
4848
+ # }
4849
+ #
4850
+ data = self.safe_dict(response, 'data', {})
4851
+ fromCurrencyId = self.safe_string(data, 'fromCurrency')
4852
+ fromResult = self.safe_currency(fromCurrencyId, fromCurrency)
4853
+ toCurrencyId = self.safe_string(data, 'toCurrency')
4854
+ to = self.safe_currency(toCurrencyId, toCurrency)
4855
+ return self.parse_conversion(data, fromResult, to)
4856
+
4857
+ def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Conversion]:
4858
+ """
4859
+ fetch the users history of conversion trades
4860
+
4861
+ https://phemex-docs.github.io/#query-convert-history
4862
+
4863
+ :param str [code]: the unified currency code
4864
+ :param int [since]: the earliest time in ms to fetch conversions for
4865
+ :param int [limit]: the maximum number of conversion structures to retrieve, default 20, max 200
4866
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4867
+ :param str [params.until]: the end time in ms
4868
+ :param str [params.fromCurrency]: the currency that you sold and converted from
4869
+ :param str [params.toCurrency]: the currency that you bought and converted into
4870
+ :returns dict[]: a list of `conversion structures <https://docs.ccxt.com/#/?id=conversion-structure>`
4871
+ """
4872
+ self.load_markets()
4873
+ request: dict = {}
4874
+ if code is not None:
4875
+ request['fromCurrency'] = code
4876
+ if since is not None:
4877
+ request['startTime'] = since
4878
+ if limit is not None:
4879
+ request['limit'] = limit
4880
+ request, params = self.handle_until_option('endTime', request, params)
4881
+ response = self.privateGetAssetsConvert(self.extend(request, params))
4882
+ #
4883
+ # {
4884
+ # "code": 0,
4885
+ # "msg": "OK",
4886
+ # "data": {
4887
+ # "total": 2,
4888
+ # "rows": [
4889
+ # {
4890
+ # "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
4891
+ # "createTime": 1739882294000,
4892
+ # "fromCurrency": "USDT",
4893
+ # "toCurrency": "BTC",
4894
+ # "fromAmountEv": 4000000000,
4895
+ # "toAmountEv": 41511,
4896
+ # "status": 10,
4897
+ # "conversionRate": 1037,
4898
+ # "errorCode": 0
4899
+ # },
4900
+ # ]
4901
+ # }
4902
+ # }
4903
+ #
4904
+ data = self.safe_dict(response, 'data', {})
4905
+ rows = self.safe_list(data, 'rows', [])
4906
+ return self.parse_conversions(rows, code, 'fromCurrency', 'toCurrency', since, limit)
4907
+
4908
+ def parse_conversion(self, conversion: dict, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
4909
+ #
4910
+ # fetchConvertQuote
4911
+ #
4912
+ # {
4913
+ # "code": "GIF...AAA",
4914
+ # "quoteArgs": {
4915
+ # "origin": 10,
4916
+ # "price": "0.00000939",
4917
+ # "proceeds": "0.00000000",
4918
+ # "ttlMs": 7000,
4919
+ # "expireAt": 1739875826009,
4920
+ # "requestAt": 1739875818009,
4921
+ # "quoteAt": 1739875816594
4922
+ # }
4923
+ # }
4924
+ #
4925
+ # createConvertTrade
4926
+ #
4927
+ # {
4928
+ # "moveOp": 0,
4929
+ # "fromCurrency": "USDT",
4930
+ # "toCurrency": "BTC",
4931
+ # "fromAmountEv": 4000000000,
4932
+ # "toAmountEv": 41511,
4933
+ # "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
4934
+ # "status": 10
4935
+ # }
4936
+ #
4937
+ # fetchConvertTradeHistory
4938
+ #
4939
+ # {
4940
+ # "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
4941
+ # "createTime": 1739882294000,
4942
+ # "fromCurrency": "USDT",
4943
+ # "toCurrency": "BTC",
4944
+ # "fromAmountEv": 4000000000,
4945
+ # "toAmountEv": 41511,
4946
+ # "status": 10,
4947
+ # "conversionRate": 1037,
4948
+ # "errorCode": 0
4949
+ # }
4950
+ #
4951
+ quoteArgs = self.safe_dict(conversion, 'quoteArgs', {})
4952
+ requestTime = self.safe_integer(quoteArgs, 'requestAt')
4953
+ timestamp = self.safe_integer(conversion, 'createTime', requestTime)
4954
+ fromCoin = self.safe_string(conversion, 'fromCurrency', self.safe_string(fromCurrency, 'code'))
4955
+ fromCode = self.safe_currency_code(fromCoin, fromCurrency)
4956
+ toCoin = self.safe_string(conversion, 'toCurrency', self.safe_string(toCurrency, 'code'))
4957
+ toCode = self.safe_currency_code(toCoin, toCurrency)
4958
+ fromValueScale = self.safe_integer(fromCurrency, 'valueScale')
4959
+ toValueScale = self.safe_integer(toCurrency, 'valueScale')
4960
+ fromAmount = self.from_en(self.safe_string(conversion, 'fromAmountEv'), fromValueScale)
4961
+ if fromAmount is None and quoteArgs is not None:
4962
+ fromAmount = self.from_en(self.safe_string(quoteArgs, 'origin'), fromValueScale)
4963
+ toAmount = self.from_en(self.safe_string(conversion, 'toAmountEv'), toValueScale)
4964
+ if toAmount is None and quoteArgs is not None:
4965
+ toAmount = self.from_en(self.safe_string(quoteArgs, 'proceeds'), toValueScale)
4966
+ return {
4967
+ 'info': conversion,
4968
+ 'timestamp': timestamp,
4969
+ 'datetime': self.iso8601(timestamp),
4970
+ 'id': self.safe_string(conversion, 'code'),
4971
+ 'fromCurrency': fromCode,
4972
+ 'fromAmount': self.parse_number(fromAmount),
4973
+ 'toCurrency': toCode,
4974
+ 'toAmount': self.parse_number(toAmount),
4975
+ 'price': self.safe_number(quoteArgs, 'price'),
4976
+ 'fee': None,
4977
+ }
4978
+
4763
4979
  def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
4764
4980
  if response is None:
4765
4981
  return None # fallback to default error handler
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.60'
7
+ __version__ = '4.4.62'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/binance.py CHANGED
@@ -78,6 +78,7 @@ class binance(ccxt.async_support.binance):
78
78
  'ws-api': {
79
79
  'spot': 'wss://testnet.binance.vision/ws-api/v3',
80
80
  'future': 'wss://testnet.binancefuture.com/ws-fapi/v1',
81
+ 'delivery': 'wss://testnet.binancefuture.com/ws-dapi/v1',
81
82
  },
82
83
  },
83
84
  },
@@ -90,6 +91,7 @@ class binance(ccxt.async_support.binance):
90
91
  'ws-api': {
91
92
  'spot': 'wss://ws-api.binance.com:443/ws-api/v3',
92
93
  'future': 'wss://ws-fapi.binance.com/ws-fapi/v1',
94
+ 'delivery': 'wss://ws-dapi.binance.com/ws-dapi/v1',
93
95
  },
94
96
  'papi': 'wss://fstream.binance.com/pm/ws',
95
97
  },
@@ -2334,6 +2336,7 @@ class binance(ccxt.async_support.binance):
2334
2336
 
2335
2337
  https://developers.binance.com/docs/derivatives/usds-margined-futures/account/websocket-api/Futures-Account-Balance
2336
2338
  https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#account-information-user_data
2339
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/account/websocket-api
2337
2340
 
2338
2341
  :param dict [params]: extra parameters specific to the exchange API endpoint
2339
2342
  :param str|None [params.type]: 'future', 'delivery', 'savings', 'funding', or 'spot'
@@ -2344,7 +2347,7 @@ class binance(ccxt.async_support.binance):
2344
2347
  """
2345
2348
  await self.load_markets()
2346
2349
  type = self.get_market_type('fetchBalanceWs', None, params)
2347
- if type != 'spot' and type != 'future':
2350
+ if type != 'spot' and type != 'future' and type != 'delivery':
2348
2351
  raise BadRequest(self.id + ' fetchBalanceWs only supports spot or swap markets')
2349
2352
  url = self.urls['api']['ws']['ws-api'][type]
2350
2353
  requestId = self.request_id(url)
@@ -2450,6 +2453,7 @@ class binance(ccxt.async_support.binance):
2450
2453
  fetch all open positions
2451
2454
 
2452
2455
  https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Position-Information
2456
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Position-Information
2453
2457
 
2454
2458
  :param str[] [symbols]: list of unified market symbols
2455
2459
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2458,15 +2462,20 @@ class binance(ccxt.async_support.binance):
2458
2462
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2459
2463
  """
2460
2464
  await self.load_markets()
2461
- symbols = self.market_symbols(symbols, 'swap', True, True, True)
2462
- url = self.urls['api']['ws']['ws-api']['future']
2463
- requestId = self.request_id(url)
2464
- messageHash = str(requestId)
2465
2465
  payload: dict = {}
2466
+ market = None
2467
+ symbols = self.market_symbols(symbols, 'swap', True, True, True)
2466
2468
  if symbols is not None:
2467
2469
  symbolsLength = len(symbols)
2468
2470
  if symbolsLength == 1:
2469
- payload['symbol'] = self.market_id(symbols[0])
2471
+ market = self.market(symbols[0])
2472
+ payload['symbol'] = market['id']
2473
+ type = self.get_market_type('fetchPositionsWs', market, params)
2474
+ if type != 'future' and type != 'delivery':
2475
+ raise BadRequest(self.id + ' fetchPositionsWs only supports swap markets')
2476
+ url = self.urls['api']['ws']['ws-api'][type]
2477
+ requestId = self.request_id(url)
2478
+ messageHash = str(requestId)
2470
2479
  returnRateLimits = False
2471
2480
  returnRateLimits, params = self.handle_option_and_params(params, 'fetchPositionsWs', 'returnRateLimits', False)
2472
2481
  payload['returnRateLimits'] = returnRateLimits
@@ -2675,6 +2684,7 @@ class binance(ccxt.async_support.binance):
2675
2684
 
2676
2685
  https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#place-new-order-trade
2677
2686
  https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/New-Order
2687
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api
2678
2688
 
2679
2689
  :param str symbol: unified symbol of the market to create an order in
2680
2690
  :param str type: 'market' or 'limit'
@@ -2689,7 +2699,7 @@ class binance(ccxt.async_support.binance):
2689
2699
  await self.load_markets()
2690
2700
  market = self.market(symbol)
2691
2701
  marketType = self.get_market_type('createOrderWs', market, params)
2692
- if marketType != 'spot' and marketType != 'future':
2702
+ if marketType != 'spot' and marketType != 'future' and marketType != 'delivery':
2693
2703
  raise BadRequest(self.id + ' createOrderWs only supports spot or swap markets')
2694
2704
  url = self.urls['api']['ws']['ws-api'][marketType]
2695
2705
  requestId = self.request_id(url)
@@ -2819,6 +2829,7 @@ class binance(ccxt.async_support.binance):
2819
2829
 
2820
2830
  https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#cancel-and-replace-order-trade
2821
2831
  https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Modify-Order
2832
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Modify-Order
2822
2833
 
2823
2834
  :param str id: order id
2824
2835
  :param str symbol: unified symbol of the market to create an order in
@@ -2832,22 +2843,23 @@ class binance(ccxt.async_support.binance):
2832
2843
  await self.load_markets()
2833
2844
  market = self.market(symbol)
2834
2845
  marketType = self.get_market_type('editOrderWs', market, params)
2835
- if marketType != 'spot' and marketType != 'future':
2846
+ if marketType != 'spot' and marketType != 'future' and marketType != 'delivery':
2836
2847
  raise BadRequest(self.id + ' editOrderWs only supports spot or swap markets')
2837
2848
  url = self.urls['api']['ws']['ws-api'][marketType]
2838
2849
  requestId = self.request_id(url)
2839
2850
  messageHash = str(requestId)
2851
+ isSwap = (marketType == 'future' or marketType == 'delivery')
2840
2852
  payload = None
2841
2853
  if marketType == 'spot':
2842
2854
  payload = self.editSpotOrderRequest(id, symbol, type, side, amount, price, params)
2843
- elif marketType == 'future':
2855
+ elif isSwap:
2844
2856
  payload = self.editContractOrderRequest(id, symbol, type, side, amount, price, params)
2845
2857
  returnRateLimits = False
2846
2858
  returnRateLimits, params = self.handle_option_and_params(params, 'editOrderWs', 'returnRateLimits', False)
2847
2859
  payload['returnRateLimits'] = returnRateLimits
2848
2860
  message: dict = {
2849
2861
  'id': messageHash,
2850
- 'method': 'order.modify' if (marketType == 'future') else 'order.cancelReplace',
2862
+ 'method': 'order.modify' if (isSwap) else 'order.cancelReplace',
2851
2863
  'params': self.sign_params(self.extend(payload, params)),
2852
2864
  }
2853
2865
  subscription: dict = {
@@ -2970,6 +2982,7 @@ class binance(ccxt.async_support.binance):
2970
2982
 
2971
2983
  https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#cancel-order-trade
2972
2984
  https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Cancel-Order
2985
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Cancel-Order
2973
2986
 
2974
2987
  :param str id: order id
2975
2988
  :param str [symbol]: unified market symbol, default is None
@@ -3047,6 +3060,7 @@ class binance(ccxt.async_support.binance):
3047
3060
 
3048
3061
  https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#query-order-user_data
3049
3062
  https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Query-Order
3063
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Query-Order
3050
3064
 
3051
3065
  :param str id: order id
3052
3066
  :param str [symbol]: unified symbol of the market the order was made in
@@ -3058,7 +3072,7 @@ class binance(ccxt.async_support.binance):
3058
3072
  raise BadRequest(self.id + ' cancelOrderWs requires a symbol')
3059
3073
  market = self.market(symbol)
3060
3074
  type = self.get_market_type('fetchOrderWs', market, params)
3061
- if type != 'spot' and type != 'future':
3075
+ if type != 'spot' and type != 'future' and type != 'delivery':
3062
3076
  raise BadRequest(self.id + ' fetchOrderWs only supports spot or swap markets')
3063
3077
  url = self.urls['api']['ws']['ws-api'][type]
3064
3078
  requestId = self.request_id(url)
ccxt/pro/gate.py CHANGED
@@ -1493,6 +1493,27 @@ class gate(ccxt.async_support.gate):
1493
1493
  # data: {errs: {label: 'AUTHENTICATION_FAILED', message: 'Not login'}},
1494
1494
  # request_id: '10406147'
1495
1495
  # }
1496
+ # {
1497
+ # "time": 1739853211,
1498
+ # "time_ms": 1739853211201,
1499
+ # "id": 1,
1500
+ # "conn_id": "62f2c1dabbe186d7",
1501
+ # "trace_id": "cdb02a8c0b61086b2fe6f8fad2f98c54",
1502
+ # "channel": "spot.trades",
1503
+ # "event": "subscribe",
1504
+ # "payload": [
1505
+ # "LUNARLENS_USDT",
1506
+ # "ETH_USDT"
1507
+ # ],
1508
+ # "error": {
1509
+ # "code": 2,
1510
+ # "message": "unknown currency pair: LUNARLENS_USDT"
1511
+ # },
1512
+ # "result": {
1513
+ # "status": "fail"
1514
+ # },
1515
+ # "requestId": "cdb02a8c0b61086b2fe6f8fad2f98c54"
1516
+ # }
1496
1517
  #
1497
1518
  data = self.safe_dict(message, 'data')
1498
1519
  errs = self.safe_dict(data, 'errs')
@@ -1511,6 +1532,17 @@ class gate(ccxt.async_support.gate):
1511
1532
  client.reject(e, messageHash)
1512
1533
  if (messageHash is not None) and (messageHash in client.subscriptions):
1513
1534
  del client.subscriptions[messageHash]
1535
+ # remove subscriptions for watchSymbols
1536
+ channel = self.safe_string(message, 'channel')
1537
+ if (channel is not None) and (channel.find('.') > 0):
1538
+ parsedChannel = channel.split('.')
1539
+ payload = self.safe_list(message, 'payload', [])
1540
+ for i in range(0, len(payload)):
1541
+ marketType = parsedChannel[0] == 'swap' if 'futures' else parsedChannel[0]
1542
+ symbol = self.safe_symbol(payload[i], None, '_', marketType)
1543
+ messageHashSymbol = parsedChannel[1] + ':' + symbol
1544
+ if (messageHashSymbol is not None) and (messageHashSymbol in client.subscriptions):
1545
+ del client.subscriptions[messageHashSymbol]
1514
1546
  if (id is not None) and (id in client.subscriptions):
1515
1547
  del client.subscriptions[id]
1516
1548
  return True
ccxt/pro/lbank.py CHANGED
@@ -429,7 +429,7 @@ class lbank(ccxt.async_support.lbank):
429
429
  # "volume":6.3607,
430
430
  # "amount":77148.9303,
431
431
  # "price":12129,
432
- # "direction":"sell", # or "sell_market"
432
+ # "direction":"sell", # buy, sell, buy_market, sell_market, buy_maker, sell_maker, buy_ioc, sell_ioc, buy_fok, sell_fok
433
433
  # "TS":"2019-06-28T19:55:49.460"
434
434
  # },
435
435
  # "type":"trade",
@@ -467,7 +467,7 @@ class lbank(ccxt.async_support.lbank):
467
467
  # "volume":6.3607,
468
468
  # "amount":77148.9303,
469
469
  # "price":12129,
470
- # "direction":"sell", # or "sell_market"
470
+ # "direction":"sell", # buy, sell, buy_market, sell_market, buy_maker, sell_maker, buy_ioc, sell_ioc, buy_fok, sell_fok
471
471
  # "TS":"2019-06-28T19:55:49.460"
472
472
  # }
473
473
  #
@@ -475,8 +475,14 @@ class lbank(ccxt.async_support.lbank):
475
475
  datetime = (self.iso8601(timestamp)) if (timestamp is not None) else (self.safe_string(trade, 'TS'))
476
476
  if timestamp is None:
477
477
  timestamp = self.parse8601(datetime)
478
- side = self.safe_string_2(trade, 'direction', 3)
479
- side = side.replace('_market', '')
478
+ rawSide = self.safe_string_2(trade, 'direction', 3)
479
+ parts = rawSide.split('_')
480
+ firstPart = self.safe_string(parts, 0)
481
+ secondPart = self.safe_string(parts, 1)
482
+ side = firstPart
483
+ # reverse if it was 'maker'
484
+ if secondPart is not None and secondPart == 'maker':
485
+ side = 'sell' if (side == 'buy') else 'buy'
480
486
  return self.safe_trade({
481
487
  'timestamp': timestamp,
482
488
  'datetime': datetime,