ccxt 4.4.88__py2.py3-none-any.whl → 4.4.91__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.
Files changed (101) hide show
  1. ccxt/__init__.py +1 -3
  2. ccxt/abstract/bitget.py +58 -0
  3. ccxt/abstract/bitrue.py +65 -65
  4. ccxt/abstract/cryptocom.py +2 -0
  5. ccxt/abstract/luno.py +1 -0
  6. ccxt/async_support/__init__.py +1 -3
  7. ccxt/async_support/base/exchange.py +6 -3
  8. ccxt/async_support/base/ws/client.py +173 -64
  9. ccxt/async_support/base/ws/future.py +23 -50
  10. ccxt/async_support/binance.py +2 -2
  11. ccxt/async_support/bingx.py +55 -29
  12. ccxt/async_support/bitget.py +469 -147
  13. ccxt/async_support/bitmex.py +2 -1
  14. ccxt/async_support/bitrue.py +72 -66
  15. ccxt/async_support/bitvavo.py +34 -0
  16. ccxt/async_support/btcalpha.py +35 -0
  17. ccxt/async_support/btcbox.py +35 -0
  18. ccxt/async_support/btcmarkets.py +35 -0
  19. ccxt/async_support/btcturk.py +35 -0
  20. ccxt/async_support/bybit.py +9 -3
  21. ccxt/async_support/cex.py +61 -0
  22. ccxt/async_support/coinbase.py +1 -3
  23. ccxt/async_support/cryptocom.py +66 -2
  24. ccxt/async_support/cryptomus.py +1 -1
  25. ccxt/async_support/delta.py +2 -2
  26. ccxt/async_support/digifinex.py +39 -99
  27. ccxt/async_support/exmo.py +14 -7
  28. ccxt/async_support/gate.py +14 -7
  29. ccxt/async_support/hashkey.py +15 -28
  30. ccxt/async_support/hollaex.py +27 -22
  31. ccxt/async_support/hyperliquid.py +104 -53
  32. ccxt/async_support/kraken.py +54 -50
  33. ccxt/async_support/luno.py +87 -1
  34. ccxt/async_support/mexc.py +1 -0
  35. ccxt/async_support/modetrade.py +2 -2
  36. ccxt/async_support/okx.py +2 -1
  37. ccxt/async_support/paradex.py +1 -1
  38. ccxt/async_support/phemex.py +16 -8
  39. ccxt/async_support/tradeogre.py +3 -3
  40. ccxt/async_support/xt.py +1 -1
  41. ccxt/base/exchange.py +20 -8
  42. ccxt/binance.py +2 -2
  43. ccxt/bingx.py +55 -29
  44. ccxt/bitget.py +469 -147
  45. ccxt/bitmex.py +2 -1
  46. ccxt/bitrue.py +72 -66
  47. ccxt/bitvavo.py +34 -0
  48. ccxt/btcalpha.py +35 -0
  49. ccxt/btcbox.py +35 -0
  50. ccxt/btcmarkets.py +35 -0
  51. ccxt/btcturk.py +35 -0
  52. ccxt/bybit.py +9 -3
  53. ccxt/cex.py +61 -0
  54. ccxt/coinbase.py +1 -3
  55. ccxt/cryptocom.py +66 -2
  56. ccxt/cryptomus.py +1 -1
  57. ccxt/delta.py +2 -2
  58. ccxt/digifinex.py +39 -99
  59. ccxt/exmo.py +13 -7
  60. ccxt/gate.py +14 -7
  61. ccxt/hashkey.py +15 -28
  62. ccxt/hollaex.py +27 -22
  63. ccxt/hyperliquid.py +104 -53
  64. ccxt/kraken.py +53 -50
  65. ccxt/luno.py +87 -1
  66. ccxt/mexc.py +1 -0
  67. ccxt/modetrade.py +2 -2
  68. ccxt/okx.py +2 -1
  69. ccxt/paradex.py +1 -1
  70. ccxt/phemex.py +16 -8
  71. ccxt/pro/__init__.py +1 -127
  72. ccxt/pro/bitstamp.py +1 -1
  73. ccxt/pro/bybit.py +6 -136
  74. ccxt/pro/coinbase.py +2 -0
  75. ccxt/pro/cryptocom.py +27 -0
  76. ccxt/pro/kraken.py +249 -267
  77. ccxt/pro/mexc.py +0 -1
  78. ccxt/tradeogre.py +3 -3
  79. ccxt/xt.py +1 -1
  80. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/METADATA +64 -23
  81. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/RECORD +84 -101
  82. ccxt/abstract/coinlist.py +0 -57
  83. ccxt/async_support/base/ws/aiohttp_client.py +0 -147
  84. ccxt/async_support/bitcoincom.py +0 -18
  85. ccxt/async_support/bitfinex1.py +0 -1711
  86. ccxt/async_support/bitpanda.py +0 -17
  87. ccxt/async_support/coinlist.py +0 -2542
  88. ccxt/async_support/poloniexfutures.py +0 -1875
  89. ccxt/bitcoincom.py +0 -18
  90. ccxt/bitfinex1.py +0 -1710
  91. ccxt/bitpanda.py +0 -17
  92. ccxt/coinlist.py +0 -2542
  93. ccxt/poloniexfutures.py +0 -1875
  94. ccxt/pro/bitcoincom.py +0 -35
  95. ccxt/pro/bitfinex1.py +0 -635
  96. ccxt/pro/bitpanda.py +0 -16
  97. ccxt/pro/poloniexfutures.py +0 -1004
  98. ccxt/pro/wazirx.py +0 -766
  99. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/LICENSE.txt +0 -0
  100. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/WHEEL +0 -0
  101. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,7 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.kraken import ImplicitAPI
8
+ import asyncio
8
9
  import hashlib
9
10
  from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, IndexType, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry
10
11
  from typing import List
@@ -569,9 +570,12 @@ class kraken(Exchange, ImplicitAPI):
569
570
  :param dict [params]: extra parameters specific to the exchange API endpoint
570
571
  :returns dict[]: an array of objects representing market data
571
572
  """
573
+ promises = []
574
+ promises.append(self.publicGetAssetPairs(params))
572
575
  if self.options['adjustForTimeDifference']:
573
- await self.load_time_difference()
574
- response = await self.publicGetAssetPairs(params)
576
+ promises.append(self.load_time_difference())
577
+ responses = await asyncio.gather(*promises)
578
+ assetsResponse = responses[0]
575
579
  #
576
580
  # {
577
581
  # "error": [],
@@ -619,7 +623,8 @@ class kraken(Exchange, ImplicitAPI):
619
623
  # }
620
624
  # }
621
625
  #
622
- markets = self.safe_value(response, 'result', {})
626
+ markets = self.safe_dict(assetsResponse, 'result', {})
627
+ cachedCurrencies = self.safe_dict(self.options, 'cachedCurrencies', {})
623
628
  keys = list(markets.keys())
624
629
  result = []
625
630
  for i in range(0, len(keys)):
@@ -629,39 +634,45 @@ class kraken(Exchange, ImplicitAPI):
629
634
  quoteId = self.safe_string(market, 'quote')
630
635
  base = self.safe_currency_code(baseId)
631
636
  quote = self.safe_currency_code(quoteId)
632
- darkpool = id.find('.d') >= 0
633
- altname = self.safe_string(market, 'altname')
634
- makerFees = self.safe_value(market, 'fees_maker', [])
635
- firstMakerFee = self.safe_value(makerFees, 0, [])
637
+ makerFees = self.safe_list(market, 'fees_maker', [])
638
+ firstMakerFee = self.safe_list(makerFees, 0, [])
636
639
  firstMakerFeeRate = self.safe_string(firstMakerFee, 1)
637
640
  maker = None
638
641
  if firstMakerFeeRate is not None:
639
642
  maker = self.parse_number(Precise.string_div(firstMakerFeeRate, '100'))
640
- takerFees = self.safe_value(market, 'fees', [])
641
- firstTakerFee = self.safe_value(takerFees, 0, [])
643
+ takerFees = self.safe_list(market, 'fees', [])
644
+ firstTakerFee = self.safe_list(takerFees, 0, [])
642
645
  firstTakerFeeRate = self.safe_string(firstTakerFee, 1)
643
646
  taker = None
644
647
  if firstTakerFeeRate is not None:
645
648
  taker = self.parse_number(Precise.string_div(firstTakerFeeRate, '100'))
646
- leverageBuy = self.safe_value(market, 'leverage_buy', [])
649
+ leverageBuy = self.safe_list(market, 'leverage_buy', [])
647
650
  leverageBuyLength = len(leverageBuy)
648
651
  precisionPrice = self.parse_number(self.parse_precision(self.safe_string(market, 'pair_decimals')))
652
+ precisionAmount = self.parse_number(self.parse_precision(self.safe_string(market, 'lot_decimals')))
653
+ spot = True
654
+ # fix https://github.com/freqtrade/freqtrade/issues/11765#issuecomment-2894224103
655
+ if spot and (base in cachedCurrencies):
656
+ currency = cachedCurrencies[base]
657
+ currencyPrecision = self.safe_number(currency, 'precision')
658
+ # if currency precision is greater(e.g. 0.01) than market precision(e.g. 0.001)
659
+ if currencyPrecision > precisionAmount:
660
+ precisionAmount = currencyPrecision
649
661
  status = self.safe_string(market, 'status')
650
662
  isActive = status == 'online'
651
663
  result.append({
652
664
  'id': id,
653
665
  'wsId': self.safe_string(market, 'wsname'),
654
- 'symbol': altname if darkpool else (base + '/' + quote),
666
+ 'symbol': base + '/' + quote,
655
667
  'base': base,
656
668
  'quote': quote,
657
669
  'settle': None,
658
670
  'baseId': baseId,
659
671
  'quoteId': quoteId,
660
672
  'settleId': None,
661
- 'darkpool': darkpool,
662
673
  'altname': market['altname'],
663
674
  'type': 'spot',
664
- 'spot': True,
675
+ 'spot': spot,
665
676
  'margin': (leverageBuyLength > 0),
666
677
  'swap': False,
667
678
  'future': False,
@@ -678,7 +689,7 @@ class kraken(Exchange, ImplicitAPI):
678
689
  'strike': None,
679
690
  'optionType': None,
680
691
  'precision': {
681
- 'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'lot_decimals'))),
692
+ 'amount': precisionAmount,
682
693
  'price': precisionPrice,
683
694
  },
684
695
  'limits': {
@@ -691,7 +702,7 @@ class kraken(Exchange, ImplicitAPI):
691
702
  'max': None,
692
703
  },
693
704
  'price': {
694
- 'min': precisionPrice,
705
+ 'min': None,
695
706
  'max': None,
696
707
  },
697
708
  'cost': {
@@ -702,7 +713,6 @@ class kraken(Exchange, ImplicitAPI):
702
713
  'created': None,
703
714
  'info': market,
704
715
  })
705
- result = self.append_inactive_markets(result)
706
716
  self.options['marketsByAltname'] = self.index_by(result, 'altname')
707
717
  return result
708
718
 
@@ -714,32 +724,6 @@ class kraken(Exchange, ImplicitAPI):
714
724
  currencyId = currencyId[1:]
715
725
  return super(kraken, self).safe_currency(currencyId, currency)
716
726
 
717
- def append_inactive_markets(self, result):
718
- # result should be an array to append to
719
- precision: dict = {
720
- 'amount': self.parse_number('1e-8'),
721
- 'price': self.parse_number('1e-8'),
722
- }
723
- costLimits: dict = {'min': None, 'max': None}
724
- priceLimits: dict = {'min': precision['price'], 'max': None}
725
- amountLimits: dict = {'min': precision['amount'], 'max': None}
726
- limits: dict = {'amount': amountLimits, 'price': priceLimits, 'cost': costLimits}
727
- defaults: dict = {
728
- 'darkpool': False,
729
- 'info': None,
730
- 'maker': None,
731
- 'taker': None,
732
- 'active': False,
733
- 'precision': precision,
734
- 'limits': limits,
735
- }
736
- markets = [
737
- # {'id': 'XXLMZEUR', 'symbol': 'XLM/EUR', 'base': 'XLM', 'quote': 'EUR', 'altname': 'XLMEUR'},
738
- ]
739
- for i in range(0, len(markets)):
740
- result.append(self.extend(defaults, markets[i]))
741
- return result
742
-
743
727
  async def fetch_status(self, params={}):
744
728
  """
745
729
  the latest known information on the availability of the exchange API
@@ -980,8 +964,6 @@ class kraken(Exchange, ImplicitAPI):
980
964
  """
981
965
  await self.load_markets()
982
966
  market = self.market(symbol)
983
- if market['darkpool']:
984
- raise ExchangeError(self.id + ' fetchOrderBook() does not provide an order book for darkpool symbol ' + symbol)
985
967
  request: dict = {
986
968
  'pair': market['id'],
987
969
  }
@@ -1084,7 +1066,7 @@ class kraken(Exchange, ImplicitAPI):
1084
1066
  for i in range(0, len(symbols)):
1085
1067
  symbol = symbols[i]
1086
1068
  market = self.markets[symbol]
1087
- if market['active'] and not market['darkpool']:
1069
+ if market['active']:
1088
1070
  marketIds.append(market['id'])
1089
1071
  request['pair'] = ','.join(marketIds)
1090
1072
  response = await self.publicGetTicker(self.extend(request, params))
@@ -1110,9 +1092,6 @@ class kraken(Exchange, ImplicitAPI):
1110
1092
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1111
1093
  """
1112
1094
  await self.load_markets()
1113
- darkpool = symbol.find('.d') >= 0
1114
- if darkpool:
1115
- raise ExchangeError(self.id + ' fetchTicker() does not provide a ticker for darkpool symbol ' + symbol)
1116
1095
  market = self.market(symbol)
1117
1096
  request: dict = {
1118
1097
  'pair': market['id'],
@@ -1387,7 +1366,20 @@ class kraken(Exchange, ImplicitAPI):
1387
1366
  # "maker": False
1388
1367
  # }
1389
1368
  #
1369
+ # watchTrades
1370
+ #
1371
+ # {
1372
+ # "symbol": "BTC/USD",
1373
+ # "side": "buy",
1374
+ # "price": 109601.2,
1375
+ # "qty": 0.04561994,
1376
+ # "ord_type": "market",
1377
+ # "trade_id": 83449369,
1378
+ # "timestamp": "2025-05-27T11:24:03.847761Z"
1379
+ # }
1380
+ #
1390
1381
  timestamp = None
1382
+ datetime = None
1391
1383
  side = None
1392
1384
  type = None
1393
1385
  price = None
@@ -1430,6 +1422,14 @@ class kraken(Exchange, ImplicitAPI):
1430
1422
  'cost': self.safe_string(trade, 'fee'),
1431
1423
  'currency': currency,
1432
1424
  }
1425
+ else:
1426
+ symbol = self.safe_string(trade, 'symbol')
1427
+ datetime = self.safe_string(trade, 'timestamp')
1428
+ id = self.safe_string(trade, 'trade_id')
1429
+ side = self.safe_string(trade, 'side')
1430
+ type = self.safe_string(trade, 'ord_type')
1431
+ price = self.safe_string(trade, 'price')
1432
+ amount = self.safe_string(trade, 'qty')
1433
1433
  if market is not None:
1434
1434
  symbol = market['symbol']
1435
1435
  cost = self.safe_string(trade, 'cost')
@@ -1437,12 +1437,16 @@ class kraken(Exchange, ImplicitAPI):
1437
1437
  takerOrMaker = None
1438
1438
  if maker is not None:
1439
1439
  takerOrMaker = 'maker' if maker else 'taker'
1440
+ if datetime is None:
1441
+ datetime = self.iso8601(timestamp)
1442
+ else:
1443
+ timestamp = self.parse8601(datetime)
1440
1444
  return self.safe_trade({
1441
1445
  'id': id,
1442
1446
  'order': orderId,
1443
1447
  'info': trade,
1444
1448
  'timestamp': timestamp,
1445
- 'datetime': self.iso8601(timestamp),
1449
+ 'datetime': datetime,
1446
1450
  'symbol': symbol,
1447
1451
  'type': type,
1448
1452
  'side': side,
@@ -3329,6 +3333,6 @@ class kraken(Exchange, ImplicitAPI):
3329
3333
  for i in range(0, len(response['error'])):
3330
3334
  error = response['error'][i]
3331
3335
  self.throw_exactly_matched_exception(self.exceptions['exact'], error, message)
3332
- self.throw_exactly_matched_exception(self.exceptions['broad'], error, message)
3336
+ self.throw_broadly_matched_exception(self.exceptions['broad'], error, message)
3333
3337
  raise ExchangeError(message)
3334
3338
  return None
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.luno import ImplicitAPI
8
- from ccxt.base.types import Account, Any, Balances, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface
8
+ from ccxt.base.types import Account, Any, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import ArgumentsRequired
@@ -44,6 +44,7 @@ class luno(Exchange, ImplicitAPI):
44
44
  'fetchClosedOrders': True,
45
45
  'fetchCrossBorrowRate': False,
46
46
  'fetchCrossBorrowRates': False,
47
+ 'fetchCurrencies': True,
47
48
  'fetchDepositAddress': True,
48
49
  'fetchFundingHistory': False,
49
50
  'fetchFundingRate': False,
@@ -125,6 +126,7 @@ class luno(Exchange, ImplicitAPI):
125
126
  'accounts/{id}/transactions': 1,
126
127
  'balance': 1,
127
128
  'beneficiaries': 1,
129
+ 'send/networks': 1,
128
130
  'fee_info': 1,
129
131
  'funding_address': 1,
130
132
  'listorders': 1,
@@ -265,6 +267,90 @@ class luno(Exchange, ImplicitAPI):
265
267
  },
266
268
  })
267
269
 
270
+ async def fetch_currencies(self, params={}) -> Currencies:
271
+ """
272
+ fetches all available currencies on an exchange
273
+ :param dict [params]: extra parameters specific to the exchange API endpoint
274
+ :returns dict: an associative dictionary of currencies
275
+ """
276
+ if not self.check_required_credentials(False):
277
+ return None
278
+ response = await self.privateGetSendNetworks(params)
279
+ #
280
+ # {
281
+ # "networks": [
282
+ # {
283
+ # "id": 0,
284
+ # "name": "Ethereum",
285
+ # "native_currency": "ETH"
286
+ # },
287
+ # ...
288
+ # ]
289
+ # }
290
+ #
291
+ currenciesData = self.safe_list(response, 'data', [])
292
+ result: dict = {}
293
+ for i in range(0, len(currenciesData)):
294
+ networkEntry = currenciesData[i]
295
+ id = self.safe_string(networkEntry, 'native_currency')
296
+ code = self.safe_currency_code(id)
297
+ if not (code in result):
298
+ result[code] = {
299
+ 'id': id,
300
+ 'code': code,
301
+ 'precision': None,
302
+ 'type': None,
303
+ 'name': None,
304
+ 'active': None,
305
+ 'deposit': None,
306
+ 'withdraw': None,
307
+ 'fee': None,
308
+ 'limits': {
309
+ 'withdraw': {
310
+ 'min': None,
311
+ 'max': None,
312
+ },
313
+ 'deposit': {
314
+ 'min': None,
315
+ 'max': None,
316
+ },
317
+ },
318
+ 'networks': {},
319
+ 'info': {},
320
+ }
321
+ networkId = self.safe_string(networkEntry, 'name')
322
+ networkCode = self.network_id_to_code(networkId)
323
+ result[code]['networks'][networkCode] = {
324
+ 'id': networkId,
325
+ 'network': networkCode,
326
+ 'limits': {
327
+ 'withdraw': {
328
+ 'min': None,
329
+ 'max': None,
330
+ },
331
+ 'deposit': {
332
+ 'min': None,
333
+ 'max': None,
334
+ },
335
+ },
336
+ 'active': None,
337
+ 'deposit': None,
338
+ 'withdraw': None,
339
+ 'fee': None,
340
+ 'precision': None,
341
+ 'info': networkEntry,
342
+ }
343
+ # add entry in info
344
+ info = self.safe_list(result[code], 'info', [])
345
+ info.append(networkEntry)
346
+ result[code]['info'] = info
347
+ # only after all entries are formed in currencies, restructure each entry
348
+ allKeys = list(result.keys())
349
+ for i in range(0, len(allKeys)):
350
+ code = allKeys[i]
351
+ result[code] = self.safe_currency_structure(result[code]) # self is needed after adding network entry
352
+ return result
353
+
268
354
  async def fetch_markets(self, params={}) -> List[Market]:
269
355
  """
270
356
  retrieves data on all markets for luno
@@ -855,6 +855,7 @@ class mexc(Exchange, ImplicitAPI):
855
855
  'PROS': 'PROSFINANCE', # conflict with Prosper
856
856
  'SIN': 'SINCITYTOKEN',
857
857
  'SOUL': 'SOULSWAP',
858
+ 'XBT': 'XBT', # restore original mapping
858
859
  },
859
860
  'exceptions': {
860
861
  'exact': {
@@ -1651,7 +1651,7 @@ class modetrade(Exchange, ImplicitAPI):
1651
1651
  #
1652
1652
  # {
1653
1653
  # "success": True,
1654
- # "timestamp": 1702989203989,
1654
+ # "timestamp": 1702989203988,
1655
1655
  # "data": {
1656
1656
  # "status": "CANCEL_SENT"
1657
1657
  # }
@@ -1659,7 +1659,7 @@ class modetrade(Exchange, ImplicitAPI):
1659
1659
  #
1660
1660
  # {
1661
1661
  # "success": True,
1662
- # "timestamp": 1702989203989,
1662
+ # "timestamp": 1702989203988,
1663
1663
  # "status": "CANCEL_SENT"
1664
1664
  # }
1665
1665
  #
ccxt/async_support/okx.py CHANGED
@@ -1607,6 +1607,7 @@ class okx(Exchange, ImplicitAPI):
1607
1607
  # "instType": "OPTION",
1608
1608
  # "lever": "",
1609
1609
  # "listTime": "1631262612280",
1610
+ # "contTdSwTime": "1631262812280",
1610
1611
  # "lotSz": "1",
1611
1612
  # "minSz": "1",
1612
1613
  # "optType": "P",
@@ -1686,7 +1687,7 @@ class okx(Exchange, ImplicitAPI):
1686
1687
  'expiryDatetime': self.iso8601(expiry),
1687
1688
  'strike': self.parse_number(strikePrice),
1688
1689
  'optionType': optionType,
1689
- 'created': self.safe_integer(market, 'listTime'),
1690
+ 'created': self.safe_integer_2(market, 'contTdSwTime', 'listTime'), # contTdSwTime is public trading start time, while listTime considers pre-trading too
1690
1691
  'precision': {
1691
1692
  'amount': self.safe_number(market, 'lotSz'),
1692
1693
  'price': self.safe_number(market, 'tickSz'),
@@ -785,7 +785,7 @@ class paradex(Exchange, ImplicitAPI):
785
785
  # "ask": "69578.2",
786
786
  # "volume_24h": "5815541.397939004",
787
787
  # "total_volume": "584031465.525259686",
788
- # "created_at": 1718170156580,
788
+ # "created_at": 1718170156581,
789
789
  # "underlying_price": "67367.37268422",
790
790
  # "open_interest": "162.272",
791
791
  # "funding_rate": "0.01629574927887",
@@ -598,6 +598,7 @@ class phemex(Exchange, ImplicitAPI):
598
598
  },
599
599
  'defaultNetworks': {
600
600
  'USDT': 'ETH',
601
+ 'MKR': 'ETH',
601
602
  },
602
603
  'defaultSubType': 'linear',
603
604
  'accountsByType': {
@@ -3322,6 +3323,7 @@ class phemex(Exchange, ImplicitAPI):
3322
3323
  fetch the deposit address for a currency associated with self account
3323
3324
  :param str code: unified currency code
3324
3325
  :param dict [params]: extra parameters specific to the exchange API endpoint
3326
+ :param str [params.network]: the chain name to fetch the deposit address e.g. ETH, TRX, EOS, SOL, etc.
3325
3327
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
3326
3328
  """
3327
3329
  await self.load_markets()
@@ -3332,20 +3334,26 @@ class phemex(Exchange, ImplicitAPI):
3332
3334
  defaultNetworks = self.safe_dict(self.options, 'defaultNetworks')
3333
3335
  defaultNetwork = self.safe_string_upper(defaultNetworks, code)
3334
3336
  networks = self.safe_dict(self.options, 'networks', {})
3335
- network = self.safe_string_upper(params, 'network', defaultNetwork)
3337
+ network = self.safe_string_upper_2(params, 'network', 'chainName', defaultNetwork)
3336
3338
  network = self.safe_string(networks, network, network)
3337
3339
  if network is None:
3338
- request['chainName'] = currency['id']
3340
+ raise ArgumentsRequired(self.id + ' fetchDepositAddress() requires a network parameter')
3339
3341
  else:
3340
3342
  request['chainName'] = network
3341
3343
  params = self.omit(params, 'network')
3342
- response = await self.privateGetPhemexUserWalletsV2DepositAddress(self.extend(request, params))
3344
+ response = await self.privateGetExchangeWalletsV2DepositAddress(self.extend(request, params))
3345
+ #
3343
3346
  # {
3344
- # "code":0,
3345
- # "msg":"OK",
3346
- # "data":{
3347
- # "address":"0x5bfbf60e0fa7f63598e6cfd8a7fd3ffac4ccc6ad",
3348
- # "tag":null
3347
+ # "code": 0,
3348
+ # "msg": "OK",
3349
+ # "data": {
3350
+ # "address": "tb1qxel5wq5gumt",
3351
+ # "tag": "",
3352
+ # "notice": False,
3353
+ # "accountType": 1,
3354
+ # "contractName": null,
3355
+ # "chainTokenUrl": null,
3356
+ # "sign": null
3349
3357
  # }
3350
3358
  # }
3351
3359
  #
@@ -425,13 +425,13 @@ class tradeogre(Exchange, ImplicitAPI):
425
425
  'vwap': None,
426
426
  'open': self.safe_string(ticker, 'initialprice'),
427
427
  'close': self.safe_string(ticker, 'price'),
428
- 'last': None,
428
+ 'last': self.safe_string(ticker, 'price'),
429
429
  'previousClose': None,
430
430
  'change': None,
431
431
  'percentage': None,
432
432
  'average': None,
433
- 'baseVolume': None,
434
- 'quoteVolume': self.safe_string(ticker, 'volume'),
433
+ 'baseVolume': self.safe_string(ticker, 'volume'),
434
+ 'quoteVolume': None,
435
435
  'info': ticker,
436
436
  }, market)
437
437
 
ccxt/async_support/xt.py CHANGED
@@ -2847,7 +2847,7 @@ class xt(Exchange, ImplicitAPI):
2847
2847
  if trigger or stopLossTakeProfit:
2848
2848
  request['state'] = 'NOT_TRIGGERED'
2849
2849
  elif type == 'swap':
2850
- request['state'] = 'NEW'
2850
+ request['state'] = 'UNFINISHED' # NEW & PARTIALLY_FILLED
2851
2851
  elif status == 'closed':
2852
2852
  if trigger or stopLossTakeProfit:
2853
2853
  request['state'] = 'TRIGGERED'
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.88'
7
+ __version__ = '4.4.91'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -906,6 +906,10 @@ class Exchange(object):
906
906
  def keysort(dictionary):
907
907
  return collections.OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))
908
908
 
909
+ @staticmethod
910
+ def sort(array):
911
+ return sorted(array)
912
+
909
913
  @staticmethod
910
914
  def extend(*args):
911
915
  if args is not None:
@@ -956,6 +960,11 @@ class Exchange(object):
956
960
  def groupBy(array, key):
957
961
  return Exchange.group_by(array, key)
958
962
 
963
+
964
+ @staticmethod
965
+ def index_by_safe(array, key):
966
+ return Exchange.index_by(array, key) # wrapper for go
967
+
959
968
  @staticmethod
960
969
  def index_by(array, key):
961
970
  result = {}
@@ -1037,7 +1046,7 @@ class Exchange(object):
1037
1046
  return _urlencode.urlencode(result, quote_via=_urlencode.quote)
1038
1047
 
1039
1048
  @staticmethod
1040
- def rawencode(params={}):
1049
+ def rawencode(params={}, sort=False):
1041
1050
  return _urlencode.unquote(Exchange.urlencode(params))
1042
1051
 
1043
1052
  @staticmethod
@@ -2571,6 +2580,9 @@ class Exchange(object):
2571
2580
  def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}):
2572
2581
  raise NotSupported(self.id + ' watchTrades() is not supported yet')
2573
2582
 
2583
+ def un_watch_orders(self, symbol: Str = None, params={}):
2584
+ raise NotSupported(self.id + ' unWatchOrders() is not supported yet')
2585
+
2574
2586
  def un_watch_trades(self, symbol: str, params={}):
2575
2587
  raise NotSupported(self.id + ' unWatchTrades() is not supported yet')
2576
2588
 
@@ -3187,7 +3199,7 @@ class Exchange(object):
3187
3199
 
3188
3200
  def set_markets(self, markets, currencies=None):
3189
3201
  values = []
3190
- self.markets_by_id = {}
3202
+ self.markets_by_id = self.create_safe_dictionary()
3191
3203
  # handle marketId conflicts
3192
3204
  # we insert spot markets first
3193
3205
  marketValues = self.sort_by(self.to_array(markets), 'spot', True, True)
@@ -3262,7 +3274,7 @@ class Exchange(object):
3262
3274
  resultingCurrencies.append(highestPrecisionCurrency)
3263
3275
  sortedCurrencies = self.sort_by(resultingCurrencies, 'code')
3264
3276
  self.currencies = self.deep_extend(self.currencies, self.index_by(sortedCurrencies, 'code'))
3265
- self.currencies_by_id = self.index_by(self.currencies, 'id')
3277
+ self.currencies_by_id = self.index_by_safe(self.currencies, 'id')
3266
3278
  currenciesSortedByCode = self.keysort(self.currencies)
3267
3279
  self.codes = list(currenciesSortedByCode.keys())
3268
3280
  return self.markets
@@ -6885,7 +6897,7 @@ class Exchange(object):
6885
6897
  symbolAndTimeFrame = symbolsAndTimeFrames[i]
6886
6898
  symbol = self.safe_string(symbolAndTimeFrame, 0)
6887
6899
  timeframe = self.safe_string(symbolAndTimeFrame, 1)
6888
- if symbol in self.ohlcvs:
6900
+ if (self.ohlcvs is not None) and (symbol in self.ohlcvs):
6889
6901
  if timeframe in self.ohlcvs[symbol]:
6890
6902
  del self.ohlcvs[symbol][timeframe]
6891
6903
  elif symbolsLength > 0:
@@ -6901,7 +6913,7 @@ class Exchange(object):
6901
6913
  if symbol in self.tickers:
6902
6914
  del self.tickers[symbol]
6903
6915
  else:
6904
- if topic == 'myTrades':
6916
+ if topic == 'myTrades' and (self.myTrades is not None):
6905
6917
  # don't reset self.myTrades directly here
6906
6918
  # because in c# we need to use a different object(thread-safe dict)
6907
6919
  keys = list(self.myTrades.keys())
@@ -6909,13 +6921,13 @@ class Exchange(object):
6909
6921
  key = keys[i]
6910
6922
  if key in self.myTrades:
6911
6923
  del self.myTrades[key]
6912
- elif topic == 'orders':
6924
+ elif topic == 'orders' and (self.orders is not None):
6913
6925
  orderSymbols = list(self.orders.keys())
6914
6926
  for i in range(0, len(orderSymbols)):
6915
6927
  orderSymbol = orderSymbols[i]
6916
6928
  if orderSymbol in self.orders:
6917
6929
  del self.orders[orderSymbol]
6918
- elif topic == 'ticker':
6930
+ elif topic == 'ticker' and (self.tickers is not None):
6919
6931
  tickerSymbols = list(self.tickers.keys())
6920
6932
  for i in range(0, len(tickerSymbols)):
6921
6933
  tickerSymbol = tickerSymbols[i]
ccxt/binance.py CHANGED
@@ -3903,7 +3903,7 @@ class binance(Exchange, ImplicitAPI):
3903
3903
  #
3904
3904
  # {
3905
3905
  # "symbol": "BTCUSDT",
3906
- # "markPrice": "11793.63104562", # mark price
3906
+ # "markPrice": "11793.63104561", # mark price
3907
3907
  # "indexPrice": "11781.80495970", # index price
3908
3908
  # "estimatedSettlePrice": "11781.16138815", # Estimated Settle Price, only useful in the last hour before the settlement starts
3909
3909
  # "lastFundingRate": "0.00038246", # This is the lastest estimated funding rate
@@ -9833,7 +9833,7 @@ class binance(Exchange, ImplicitAPI):
9833
9833
  response = self.dapiPrivateV2GetLeverageBracket(query)
9834
9834
  else:
9835
9835
  raise NotSupported(self.id + ' loadLeverageBrackets() supports linear and inverse contracts only')
9836
- self.options['leverageBrackets'] = {}
9836
+ self.options['leverageBrackets'] = self.create_safe_dictionary()
9837
9837
  for i in range(0, len(response)):
9838
9838
  entry = response[i]
9839
9839
  marketId = self.safe_string(entry, 'symbol')