ccxt 4.4.88__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 (63) 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 +1 -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 +9 -3
  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/okx.py +2 -1
  28. ccxt/async_support/phemex.py +16 -8
  29. ccxt/async_support/tradeogre.py +3 -3
  30. ccxt/async_support/xt.py +1 -1
  31. ccxt/base/exchange.py +13 -4
  32. ccxt/binance.py +1 -1
  33. ccxt/bingx.py +55 -29
  34. ccxt/bitget.py +469 -147
  35. ccxt/bitrue.py +72 -66
  36. ccxt/bitvavo.py +34 -0
  37. ccxt/btcalpha.py +35 -0
  38. ccxt/btcbox.py +35 -0
  39. ccxt/btcmarkets.py +35 -0
  40. ccxt/btcturk.py +35 -0
  41. ccxt/bybit.py +9 -3
  42. ccxt/coinbase.py +1 -3
  43. ccxt/cryptocom.py +49 -0
  44. ccxt/delta.py +2 -2
  45. ccxt/digifinex.py +39 -99
  46. ccxt/gate.py +12 -5
  47. ccxt/hashkey.py +15 -28
  48. ccxt/hollaex.py +27 -22
  49. ccxt/kraken.py +27 -49
  50. ccxt/luno.py +87 -1
  51. ccxt/okx.py +2 -1
  52. ccxt/phemex.py +16 -8
  53. ccxt/pro/__init__.py +1 -127
  54. ccxt/pro/coinbase.py +2 -0
  55. ccxt/pro/cryptocom.py +27 -0
  56. ccxt/pro/kraken.py +3 -9
  57. ccxt/tradeogre.py +3 -3
  58. ccxt/xt.py +1 -1
  59. {ccxt-4.4.88.dist-info → ccxt-4.4.90.dist-info}/METADATA +62 -20
  60. {ccxt-4.4.88.dist-info → ccxt-4.4.90.dist-info}/RECORD +63 -63
  61. {ccxt-4.4.88.dist-info → ccxt-4.4.90.dist-info}/LICENSE.txt +0 -0
  62. {ccxt-4.4.88.dist-info → ccxt-4.4.90.dist-info}/WHEEL +0 -0
  63. {ccxt-4.4.88.dist-info → ccxt-4.4.90.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'],
@@ -3329,6 +3308,6 @@ class kraken(Exchange, ImplicitAPI):
3329
3308
  for i in range(0, len(response['error'])):
3330
3309
  error = response['error'][i]
3331
3310
  self.throw_exactly_matched_exception(self.exceptions['exact'], error, message)
3332
- self.throw_exactly_matched_exception(self.exceptions['broad'], error, message)
3311
+ self.throw_broadly_matched_exception(self.exceptions['broad'], error, message)
3333
3312
  raise ExchangeError(message)
3334
3313
  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
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'),
@@ -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.90'
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
@@ -3187,7 +3196,7 @@ class Exchange(object):
3187
3196
 
3188
3197
  def set_markets(self, markets, currencies=None):
3189
3198
  values = []
3190
- self.markets_by_id = {}
3199
+ self.markets_by_id = self.create_safe_dictionary()
3191
3200
  # handle marketId conflicts
3192
3201
  # we insert spot markets first
3193
3202
  marketValues = self.sort_by(self.to_array(markets), 'spot', True, True)
@@ -3262,7 +3271,7 @@ class Exchange(object):
3262
3271
  resultingCurrencies.append(highestPrecisionCurrency)
3263
3272
  sortedCurrencies = self.sort_by(resultingCurrencies, 'code')
3264
3273
  self.currencies = self.deep_extend(self.currencies, self.index_by(sortedCurrencies, 'code'))
3265
- self.currencies_by_id = self.index_by(self.currencies, 'id')
3274
+ self.currencies_by_id = self.index_by_safe(self.currencies, 'id')
3266
3275
  currenciesSortedByCode = self.keysort(self.currencies)
3267
3276
  self.codes = list(currenciesSortedByCode.keys())
3268
3277
  return self.markets
ccxt/binance.py CHANGED
@@ -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')