ccxt 4.4.87__py2.py3-none-any.whl → 4.4.90__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 (67) hide show
  1. ccxt/__init__.py +1 -1
  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 -1
  7. ccxt/async_support/base/exchange.py +4 -1
  8. ccxt/async_support/binance.py +1 -1
  9. ccxt/async_support/bingx.py +55 -29
  10. ccxt/async_support/bitget.py +469 -147
  11. ccxt/async_support/bitrue.py +72 -66
  12. ccxt/async_support/bitvavo.py +34 -0
  13. ccxt/async_support/btcalpha.py +35 -0
  14. ccxt/async_support/btcbox.py +35 -0
  15. ccxt/async_support/btcmarkets.py +35 -0
  16. ccxt/async_support/btcturk.py +35 -0
  17. ccxt/async_support/bybit.py +28 -60
  18. ccxt/async_support/coinbase.py +1 -3
  19. ccxt/async_support/cryptocom.py +49 -0
  20. ccxt/async_support/delta.py +2 -2
  21. ccxt/async_support/digifinex.py +39 -99
  22. ccxt/async_support/gate.py +12 -5
  23. ccxt/async_support/hashkey.py +15 -28
  24. ccxt/async_support/hollaex.py +27 -22
  25. ccxt/async_support/kraken.py +28 -49
  26. ccxt/async_support/luno.py +87 -1
  27. ccxt/async_support/modetrade.py +7 -7
  28. ccxt/async_support/okx.py +2 -1
  29. ccxt/async_support/phemex.py +16 -8
  30. ccxt/async_support/tradeogre.py +3 -3
  31. ccxt/async_support/xt.py +1 -1
  32. ccxt/base/exchange.py +15 -5
  33. ccxt/binance.py +1 -1
  34. ccxt/bingx.py +55 -29
  35. ccxt/bitget.py +469 -147
  36. ccxt/bitrue.py +72 -66
  37. ccxt/bitvavo.py +34 -0
  38. ccxt/btcalpha.py +35 -0
  39. ccxt/btcbox.py +35 -0
  40. ccxt/btcmarkets.py +35 -0
  41. ccxt/btcturk.py +35 -0
  42. ccxt/bybit.py +28 -60
  43. ccxt/coinbase.py +1 -3
  44. ccxt/cryptocom.py +49 -0
  45. ccxt/delta.py +2 -2
  46. ccxt/digifinex.py +39 -99
  47. ccxt/gate.py +12 -5
  48. ccxt/hashkey.py +15 -28
  49. ccxt/hollaex.py +27 -22
  50. ccxt/kraken.py +27 -49
  51. ccxt/luno.py +87 -1
  52. ccxt/modetrade.py +7 -7
  53. ccxt/okx.py +2 -1
  54. ccxt/phemex.py +16 -8
  55. ccxt/pro/__init__.py +1 -119
  56. ccxt/pro/coinbase.py +2 -0
  57. ccxt/pro/cryptocom.py +27 -0
  58. ccxt/pro/kraken.py +3 -9
  59. ccxt/test/tests_async.py +1 -1
  60. ccxt/test/tests_sync.py +1 -1
  61. ccxt/tradeogre.py +3 -3
  62. ccxt/xt.py +1 -1
  63. {ccxt-4.4.87.dist-info → ccxt-4.4.90.dist-info}/METADATA +62 -20
  64. {ccxt-4.4.87.dist-info → ccxt-4.4.90.dist-info}/RECORD +67 -67
  65. {ccxt-4.4.87.dist-info → ccxt-4.4.90.dist-info}/LICENSE.txt +0 -0
  66. {ccxt-4.4.87.dist-info → ccxt-4.4.90.dist-info}/WHEEL +0 -0
  67. {ccxt-4.4.87.dist-info → ccxt-4.4.90.dist-info}/top_level.txt +0 -0
ccxt/hollaex.py CHANGED
@@ -15,6 +15,7 @@ from ccxt.base.errors import InsufficientFunds
15
15
  from ccxt.base.errors import OrderNotFound
16
16
  from ccxt.base.errors import OrderImmediatelyFillable
17
17
  from ccxt.base.errors import NetworkError
18
+ from ccxt.base.errors import InvalidNonce
18
19
  from ccxt.base.decimal_to_precision import TICK_SIZE
19
20
  from ccxt.base.precise import Precise
20
21
 
@@ -262,6 +263,7 @@ class hollaex(Exchange, ImplicitAPI):
262
263
  },
263
264
  'exceptions': {
264
265
  'broad': {
266
+ 'API request is expired': InvalidNonce,
265
267
  'Invalid token': AuthenticationError,
266
268
  'Order not found': OrderNotFound,
267
269
  'Insufficient balance': InsufficientFunds,
@@ -796,7 +798,8 @@ class hollaex(Exchange, ImplicitAPI):
796
798
  # "price":0.147411,
797
799
  # "timestamp":"2022-01-26T17:53:34.650Z",
798
800
  # "order_id":"cba78ecb-4187-4da2-9d2f-c259aa693b5a",
799
- # "fee":0.01031877,"fee_coin":"usdt"
801
+ # "fee":0.01031877,
802
+ # "fee_coin":"usdt"
800
803
  # }
801
804
  #
802
805
  marketId = self.safe_string(trade, 'symbol')
@@ -809,11 +812,12 @@ class hollaex(Exchange, ImplicitAPI):
809
812
  priceString = self.safe_string(trade, 'price')
810
813
  amountString = self.safe_string(trade, 'size')
811
814
  feeCostString = self.safe_string(trade, 'fee')
815
+ feeCoin = self.safe_string(trade, 'fee_coin')
812
816
  fee = None
813
817
  if feeCostString is not None:
814
818
  fee = {
815
819
  'cost': feeCostString,
816
- 'currency': market['quote'],
820
+ 'currency': self.safe_currency_code(feeCoin),
817
821
  }
818
822
  return self.safe_trade({
819
823
  'info': trade,
@@ -899,7 +903,7 @@ class hollaex(Exchange, ImplicitAPI):
899
903
  :param str symbol: unified symbol of the market to fetch OHLCV data for
900
904
  :param str timeframe: the length of time each candle represents
901
905
  :param int [since]: timestamp in ms of the earliest candle to fetch
902
- :param int [limit]: the maximum amount of candles to fetch
906
+ :param int [limit]: the maximum amount of candles to fetch(max 500)
903
907
  :param dict [params]: extra parameters specific to the exchange API endpoint
904
908
  :param int [params.until]: timestamp in ms of the latest candle to fetch
905
909
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
@@ -910,16 +914,24 @@ class hollaex(Exchange, ImplicitAPI):
910
914
  'symbol': market['id'],
911
915
  'resolution': self.safe_string(self.timeframes, timeframe, timeframe),
912
916
  }
917
+ paginate = False
918
+ maxLimit = 500
919
+ paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate', paginate)
920
+ if paginate:
921
+ return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimit)
913
922
  until = self.safe_integer(params, 'until')
914
- end = self.seconds()
915
- if until is not None:
916
- end = self.parse_to_int(until / 1000)
917
- defaultSpan = 2592000 # 30 days
918
- if since is not None:
919
- request['from'] = self.parse_to_int(since / 1000)
920
- else:
921
- request['from'] = end - defaultSpan
922
- request['to'] = end
923
+ timeDelta = self.parse_timeframe(timeframe) * maxLimit * 1000
924
+ start = since
925
+ now = self.milliseconds()
926
+ if until is None and start is None:
927
+ until = now
928
+ start = until - timeDelta
929
+ elif until is None:
930
+ until = now # the exchange has not a lot of trades, so if we count until by limit and limit is small, it may return empty result
931
+ elif start is None:
932
+ start = until - timeDelta
933
+ request['from'] = self.parse_to_int(start / 1000) # convert to seconds
934
+ request['to'] = self.parse_to_int(until / 1000) # convert to seconds
923
935
  params = self.omit(params, 'until')
924
936
  response = self.publicGetChart(self.extend(request, params))
925
937
  #
@@ -1277,11 +1289,10 @@ class hollaex(Exchange, ImplicitAPI):
1277
1289
  """
1278
1290
  self.load_markets()
1279
1291
  market = self.market(symbol)
1280
- convertedAmount = float(self.amount_to_precision(symbol, amount))
1281
1292
  request: dict = {
1282
1293
  'symbol': market['id'],
1283
1294
  'side': side,
1284
- 'size': self.normalize_number_if_needed(convertedAmount),
1295
+ 'size': self.amount_to_precision(symbol, amount),
1285
1296
  'type': type,
1286
1297
  # 'stop': float(self.price_to_precision(symbol, stopPrice)),
1287
1298
  # 'meta': {}, # other options such
@@ -1292,10 +1303,9 @@ class hollaex(Exchange, ImplicitAPI):
1292
1303
  isMarketOrder = type == 'market'
1293
1304
  postOnly = self.is_post_only(isMarketOrder, exchangeSpecificParam, params)
1294
1305
  if not isMarketOrder:
1295
- convertedPrice = float(self.price_to_precision(symbol, price))
1296
- request['price'] = self.normalize_number_if_needed(convertedPrice)
1306
+ request['price'] = self.price_to_precision(symbol, price)
1297
1307
  if triggerPrice is not None:
1298
- request['stop'] = self.normalize_number_if_needed(float(self.price_to_precision(symbol, triggerPrice)))
1308
+ request['stop'] = self.price_to_precision(symbol, triggerPrice)
1299
1309
  if postOnly:
1300
1310
  request['meta'] = {'post_only': True}
1301
1311
  params = self.omit(params, ['postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stop'])
@@ -1943,11 +1953,6 @@ class hollaex(Exchange, ImplicitAPI):
1943
1953
  coins = self.safe_dict(response, 'coins', {})
1944
1954
  return self.parse_deposit_withdraw_fees(coins, codes, 'symbol')
1945
1955
 
1946
- def normalize_number_if_needed(self, number):
1947
- if self.is_round_number(number):
1948
- number = int(number)
1949
- return number
1950
-
1951
1956
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
1952
1957
  query = self.omit(params, self.extract_params(path))
1953
1958
  path = '/' + self.version + '/' + self.implode_params(path, params)
ccxt/kraken.py CHANGED
@@ -569,9 +569,12 @@ class kraken(Exchange, ImplicitAPI):
569
569
  :param dict [params]: extra parameters specific to the exchange API endpoint
570
570
  :returns dict[]: an array of objects representing market data
571
571
  """
572
+ promises = []
573
+ promises.append(self.publicGetAssetPairs(params))
572
574
  if self.options['adjustForTimeDifference']:
573
- self.load_time_difference()
574
- response = self.publicGetAssetPairs(params)
575
+ promises.append(self.load_time_difference())
576
+ responses = promises
577
+ assetsResponse = responses[0]
575
578
  #
576
579
  # {
577
580
  # "error": [],
@@ -619,7 +622,8 @@ class kraken(Exchange, ImplicitAPI):
619
622
  # }
620
623
  # }
621
624
  #
622
- markets = self.safe_value(response, 'result', {})
625
+ markets = self.safe_dict(assetsResponse, 'result', {})
626
+ cachedCurrencies = self.safe_dict(self.options, 'cachedCurrencies', {})
623
627
  keys = list(markets.keys())
624
628
  result = []
625
629
  for i in range(0, len(keys)):
@@ -629,39 +633,45 @@ class kraken(Exchange, ImplicitAPI):
629
633
  quoteId = self.safe_string(market, 'quote')
630
634
  base = self.safe_currency_code(baseId)
631
635
  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, [])
636
+ makerFees = self.safe_list(market, 'fees_maker', [])
637
+ firstMakerFee = self.safe_list(makerFees, 0, [])
636
638
  firstMakerFeeRate = self.safe_string(firstMakerFee, 1)
637
639
  maker = None
638
640
  if firstMakerFeeRate is not None:
639
641
  maker = self.parse_number(Precise.string_div(firstMakerFeeRate, '100'))
640
- takerFees = self.safe_value(market, 'fees', [])
641
- firstTakerFee = self.safe_value(takerFees, 0, [])
642
+ takerFees = self.safe_list(market, 'fees', [])
643
+ firstTakerFee = self.safe_list(takerFees, 0, [])
642
644
  firstTakerFeeRate = self.safe_string(firstTakerFee, 1)
643
645
  taker = None
644
646
  if firstTakerFeeRate is not None:
645
647
  taker = self.parse_number(Precise.string_div(firstTakerFeeRate, '100'))
646
- leverageBuy = self.safe_value(market, 'leverage_buy', [])
648
+ leverageBuy = self.safe_list(market, 'leverage_buy', [])
647
649
  leverageBuyLength = len(leverageBuy)
648
650
  precisionPrice = self.parse_number(self.parse_precision(self.safe_string(market, 'pair_decimals')))
651
+ precisionAmount = self.parse_number(self.parse_precision(self.safe_string(market, 'lot_decimals')))
652
+ spot = True
653
+ # fix https://github.com/freqtrade/freqtrade/issues/11765#issuecomment-2894224103
654
+ if spot and (base in cachedCurrencies):
655
+ currency = cachedCurrencies[base]
656
+ currencyPrecision = self.safe_number(currency, 'precision')
657
+ # if currency precision is greater(e.g. 0.01) than market precision(e.g. 0.001)
658
+ if currencyPrecision > precisionAmount:
659
+ precisionAmount = currencyPrecision
649
660
  status = self.safe_string(market, 'status')
650
661
  isActive = status == 'online'
651
662
  result.append({
652
663
  'id': id,
653
664
  'wsId': self.safe_string(market, 'wsname'),
654
- 'symbol': altname if darkpool else (base + '/' + quote),
665
+ 'symbol': base + '/' + quote,
655
666
  'base': base,
656
667
  'quote': quote,
657
668
  'settle': None,
658
669
  'baseId': baseId,
659
670
  'quoteId': quoteId,
660
671
  'settleId': None,
661
- 'darkpool': darkpool,
662
672
  'altname': market['altname'],
663
673
  'type': 'spot',
664
- 'spot': True,
674
+ 'spot': spot,
665
675
  'margin': (leverageBuyLength > 0),
666
676
  'swap': False,
667
677
  'future': False,
@@ -678,7 +688,7 @@ class kraken(Exchange, ImplicitAPI):
678
688
  'strike': None,
679
689
  'optionType': None,
680
690
  'precision': {
681
- 'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'lot_decimals'))),
691
+ 'amount': precisionAmount,
682
692
  'price': precisionPrice,
683
693
  },
684
694
  'limits': {
@@ -691,7 +701,7 @@ class kraken(Exchange, ImplicitAPI):
691
701
  'max': None,
692
702
  },
693
703
  'price': {
694
- 'min': precisionPrice,
704
+ 'min': None,
695
705
  'max': None,
696
706
  },
697
707
  'cost': {
@@ -702,7 +712,6 @@ class kraken(Exchange, ImplicitAPI):
702
712
  'created': None,
703
713
  'info': market,
704
714
  })
705
- result = self.append_inactive_markets(result)
706
715
  self.options['marketsByAltname'] = self.index_by(result, 'altname')
707
716
  return result
708
717
 
@@ -714,32 +723,6 @@ class kraken(Exchange, ImplicitAPI):
714
723
  currencyId = currencyId[1:]
715
724
  return super(kraken, self).safe_currency(currencyId, currency)
716
725
 
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
726
  def fetch_status(self, params={}):
744
727
  """
745
728
  the latest known information on the availability of the exchange API
@@ -980,8 +963,6 @@ class kraken(Exchange, ImplicitAPI):
980
963
  """
981
964
  self.load_markets()
982
965
  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
966
  request: dict = {
986
967
  'pair': market['id'],
987
968
  }
@@ -1084,7 +1065,7 @@ class kraken(Exchange, ImplicitAPI):
1084
1065
  for i in range(0, len(symbols)):
1085
1066
  symbol = symbols[i]
1086
1067
  market = self.markets[symbol]
1087
- if market['active'] and not market['darkpool']:
1068
+ if market['active']:
1088
1069
  marketIds.append(market['id'])
1089
1070
  request['pair'] = ','.join(marketIds)
1090
1071
  response = self.publicGetTicker(self.extend(request, params))
@@ -1110,9 +1091,6 @@ class kraken(Exchange, ImplicitAPI):
1110
1091
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1111
1092
  """
1112
1093
  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
1094
  market = self.market(symbol)
1117
1095
  request: dict = {
1118
1096
  'pair': market['id'],
@@ -3329,6 +3307,6 @@ class kraken(Exchange, ImplicitAPI):
3329
3307
  for i in range(0, len(response['error'])):
3330
3308
  error = response['error'][i]
3331
3309
  self.throw_exactly_matched_exception(self.exceptions['exact'], error, message)
3332
- self.throw_exactly_matched_exception(self.exceptions['broad'], error, message)
3310
+ self.throw_broadly_matched_exception(self.exceptions['broad'], error, message)
3333
3311
  raise ExchangeError(message)
3334
3312
  return None
ccxt/luno.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.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
+ 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 = 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
  def fetch_markets(self, params={}) -> List[Market]:
269
355
  """
270
356
  retrieves data on all markets for luno
ccxt/modetrade.py CHANGED
@@ -50,16 +50,16 @@ class modetrade(Exchange, ImplicitAPI):
50
50
  'createConvertTrade': False,
51
51
  'createDepositAddress': False,
52
52
  'createMarketBuyOrderWithCost': False,
53
- 'createMarketOrder': False,
53
+ 'createMarketOrder': True,
54
54
  'createMarketOrderWithCost': False,
55
55
  'createMarketSellOrderWithCost': False,
56
56
  'createOrder': True,
57
57
  'createOrderWithTakeProfitAndStopLoss': True,
58
58
  'createReduceOnlyOrder': True,
59
- 'createStopLimitOrder': False,
59
+ 'createStopLimitOrder': True,
60
60
  'createStopLossOrder': True,
61
- 'createStopMarketOrder': False,
62
- 'createStopOrder': False,
61
+ 'createStopMarketOrder': True,
62
+ 'createStopOrder': True,
63
63
  'createTakeProfitOrder': True,
64
64
  'createTrailingAmountOrder': False,
65
65
  'createTrailingPercentOrder': False,
@@ -298,7 +298,7 @@ class modetrade(Exchange, ImplicitAPI):
298
298
  },
299
299
  'options': {
300
300
  'sandboxMode': False,
301
- 'brokerId': 'CCXT',
301
+ 'brokerId': 'CCXTMODE',
302
302
  'verifyingContractAddress': '0x6F7a338F2aA472838dEFD3283eB360d4Dff5D203',
303
303
  },
304
304
  'features': {
@@ -2069,7 +2069,7 @@ class modetrade(Exchange, ImplicitAPI):
2069
2069
  code = self.safe_currency_code(self.safe_string(balance, 'token'))
2070
2070
  account = self.account()
2071
2071
  account['total'] = self.safe_string(balance, 'holding')
2072
- account['frozen'] = self.safe_string(balance, 'frozen')
2072
+ account['used'] = self.safe_string(balance, 'frozen')
2073
2073
  result[code] = account
2074
2074
  return self.safe_balance(result)
2075
2075
 
@@ -2671,7 +2671,7 @@ class modetrade(Exchange, ImplicitAPI):
2671
2671
  if isPostOrPut and isOrder:
2672
2672
  isSandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
2673
2673
  if not isSandboxMode:
2674
- brokerId = self.safe_string(self.options, 'brokerId', 'CCXT')
2674
+ brokerId = self.safe_string(self.options, 'brokerId', 'CCXTMODE')
2675
2675
  if path == 'batch-order':
2676
2676
  ordersList = self.safe_list(params, 'orders', [])
2677
2677
  for i in range(0, len(ordersList)):
ccxt/okx.py CHANGED
@@ -1606,6 +1606,7 @@ class okx(Exchange, ImplicitAPI):
1606
1606
  # "instType": "OPTION",
1607
1607
  # "lever": "",
1608
1608
  # "listTime": "1631262612280",
1609
+ # "contTdSwTime": "1631262812280",
1609
1610
  # "lotSz": "1",
1610
1611
  # "minSz": "1",
1611
1612
  # "optType": "P",
@@ -1685,7 +1686,7 @@ class okx(Exchange, ImplicitAPI):
1685
1686
  'expiryDatetime': self.iso8601(expiry),
1686
1687
  'strike': self.parse_number(strikePrice),
1687
1688
  'optionType': optionType,
1688
- 'created': self.safe_integer(market, 'listTime'),
1689
+ 'created': self.safe_integer_2(market, 'contTdSwTime', 'listTime'), # contTdSwTime is public trading start time, while listTime considers pre-trading too
1689
1690
  'precision': {
1690
1691
  'amount': self.safe_number(market, 'lotSz'),
1691
1692
  'price': self.safe_number(market, 'tickSz'),
ccxt/phemex.py CHANGED
@@ -597,6 +597,7 @@ class phemex(Exchange, ImplicitAPI):
597
597
  },
598
598
  'defaultNetworks': {
599
599
  'USDT': 'ETH',
600
+ 'MKR': 'ETH',
600
601
  },
601
602
  'defaultSubType': 'linear',
602
603
  'accountsByType': {
@@ -3321,6 +3322,7 @@ class phemex(Exchange, ImplicitAPI):
3321
3322
  fetch the deposit address for a currency associated with self account
3322
3323
  :param str code: unified currency code
3323
3324
  :param dict [params]: extra parameters specific to the exchange API endpoint
3325
+ :param str [params.network]: the chain name to fetch the deposit address e.g. ETH, TRX, EOS, SOL, etc.
3324
3326
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
3325
3327
  """
3326
3328
  self.load_markets()
@@ -3331,20 +3333,26 @@ class phemex(Exchange, ImplicitAPI):
3331
3333
  defaultNetworks = self.safe_dict(self.options, 'defaultNetworks')
3332
3334
  defaultNetwork = self.safe_string_upper(defaultNetworks, code)
3333
3335
  networks = self.safe_dict(self.options, 'networks', {})
3334
- network = self.safe_string_upper(params, 'network', defaultNetwork)
3336
+ network = self.safe_string_upper_2(params, 'network', 'chainName', defaultNetwork)
3335
3337
  network = self.safe_string(networks, network, network)
3336
3338
  if network is None:
3337
- request['chainName'] = currency['id']
3339
+ raise ArgumentsRequired(self.id + ' fetchDepositAddress() requires a network parameter')
3338
3340
  else:
3339
3341
  request['chainName'] = network
3340
3342
  params = self.omit(params, 'network')
3341
- response = self.privateGetPhemexUserWalletsV2DepositAddress(self.extend(request, params))
3343
+ response = self.privateGetExchangeWalletsV2DepositAddress(self.extend(request, params))
3344
+ #
3342
3345
  # {
3343
- # "code":0,
3344
- # "msg":"OK",
3345
- # "data":{
3346
- # "address":"0x5bfbf60e0fa7f63598e6cfd8a7fd3ffac4ccc6ad",
3347
- # "tag":null
3346
+ # "code": 0,
3347
+ # "msg": "OK",
3348
+ # "data": {
3349
+ # "address": "tb1qxel5wq5gumt",
3350
+ # "tag": "",
3351
+ # "notice": False,
3352
+ # "accountType": 1,
3353
+ # "contractName": null,
3354
+ # "chainTokenUrl": null,
3355
+ # "sign": null
3348
3356
  # }
3349
3357
  # }
3350
3358
  #
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.87'
7
+ __version__ = '4.4.90'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
@@ -56,124 +56,6 @@ from ccxt.base.errors import UnsubscribeError # noqa: F4
56
56
  from ccxt.base.errors import error_hierarchy # noqa: F401
57
57
  # DO_NOT_REMOVE__ERROR_IMPORTS_END
58
58
 
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
59
  from ccxt.pro.alpaca import alpaca # noqa: F401
178
60
  from ccxt.pro.apex import apex # noqa: F401
179
61
  from ccxt.pro.ascendex import ascendex # noqa: F401
ccxt/pro/coinbase.py CHANGED
@@ -160,6 +160,7 @@ class coinbase(ccxt.async_support.coinbase):
160
160
  :param dict [params]: extra parameters specific to the exchange API endpoint
161
161
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
162
162
  """
163
+ await self.load_markets()
163
164
  name = 'ticker'
164
165
  return await self.subscribe(name, False, symbol, params)
165
166
 
@@ -173,6 +174,7 @@ class coinbase(ccxt.async_support.coinbase):
173
174
  :param dict [params]: extra parameters specific to the exchange API endpoint
174
175
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
175
176
  """
177
+ await self.load_markets()
176
178
  if symbols is None:
177
179
  symbols = self.symbols
178
180
  name = 'ticker_batch'