ccxt 4.4.78__py2.py3-none-any.whl → 4.4.82__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 (87) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/bitmart.py +1 -0
  3. ccxt/apex.py +21 -31
  4. ccxt/ascendex.py +23 -6
  5. ccxt/async_support/__init__.py +1 -1
  6. ccxt/async_support/apex.py +21 -31
  7. ccxt/async_support/ascendex.py +23 -6
  8. ccxt/async_support/base/exchange.py +5 -1
  9. ccxt/async_support/bigone.py +17 -14
  10. ccxt/async_support/binance.py +6 -0
  11. ccxt/async_support/bingx.py +16 -35
  12. ccxt/async_support/bitfinex.py +120 -82
  13. ccxt/async_support/bitget.py +58 -66
  14. ccxt/async_support/bitmart.py +7 -2
  15. ccxt/async_support/bitmex.py +8 -1
  16. ccxt/async_support/bitopro.py +5 -1
  17. ccxt/async_support/bitrue.py +2 -1
  18. ccxt/async_support/bitso.py +1 -1
  19. ccxt/async_support/bitteam.py +2 -0
  20. ccxt/async_support/bitvavo.py +25 -10
  21. ccxt/async_support/btcalpha.py +1 -1
  22. ccxt/async_support/btcmarkets.py +1 -1
  23. ccxt/async_support/btcturk.py +1 -1
  24. ccxt/async_support/bybit.py +29 -15
  25. ccxt/async_support/coinbase.py +3 -15
  26. ccxt/async_support/coinex.py +1 -0
  27. ccxt/async_support/coinlist.py +1 -0
  28. ccxt/async_support/coinone.py +1 -0
  29. ccxt/async_support/delta.py +3 -0
  30. ccxt/async_support/deribit.py +1 -0
  31. ccxt/async_support/hollaex.py +1 -0
  32. ccxt/async_support/htx.py +9 -5
  33. ccxt/async_support/huobijp.py +1 -0
  34. ccxt/async_support/hyperliquid.py +14 -0
  35. ccxt/async_support/kraken.py +2 -0
  36. ccxt/async_support/okx.py +2 -3
  37. ccxt/async_support/oxfun.py +21 -1
  38. ccxt/async_support/poloniex.py +1 -0
  39. ccxt/async_support/timex.py +2 -2
  40. ccxt/async_support/upbit.py +43 -21
  41. ccxt/async_support/whitebit.py +65 -12
  42. ccxt/base/exchange.py +20 -2
  43. ccxt/bigone.py +17 -14
  44. ccxt/binance.py +6 -0
  45. ccxt/bingx.py +16 -35
  46. ccxt/bitfinex.py +120 -82
  47. ccxt/bitget.py +58 -66
  48. ccxt/bitmart.py +7 -2
  49. ccxt/bitmex.py +8 -1
  50. ccxt/bitopro.py +5 -1
  51. ccxt/bitrue.py +2 -1
  52. ccxt/bitso.py +1 -1
  53. ccxt/bitteam.py +2 -0
  54. ccxt/bitvavo.py +25 -10
  55. ccxt/btcalpha.py +1 -1
  56. ccxt/btcmarkets.py +1 -1
  57. ccxt/btcturk.py +1 -1
  58. ccxt/bybit.py +29 -15
  59. ccxt/coinbase.py +3 -15
  60. ccxt/coinex.py +1 -0
  61. ccxt/coinlist.py +1 -0
  62. ccxt/coinone.py +1 -0
  63. ccxt/delta.py +3 -0
  64. ccxt/deribit.py +1 -0
  65. ccxt/hollaex.py +1 -0
  66. ccxt/htx.py +9 -5
  67. ccxt/huobijp.py +1 -0
  68. ccxt/hyperliquid.py +14 -0
  69. ccxt/kraken.py +2 -0
  70. ccxt/okx.py +2 -3
  71. ccxt/oxfun.py +21 -1
  72. ccxt/poloniex.py +1 -0
  73. ccxt/pro/__init__.py +1 -1
  74. ccxt/pro/binance.py +3 -3
  75. ccxt/pro/coinbase.py +41 -53
  76. ccxt/pro/hyperliquid.py +10 -2
  77. ccxt/pro/upbit.py +42 -0
  78. ccxt/test/tests_async.py +0 -1
  79. ccxt/test/tests_sync.py +0 -1
  80. ccxt/timex.py +2 -2
  81. ccxt/upbit.py +43 -21
  82. ccxt/whitebit.py +65 -12
  83. {ccxt-4.4.78.dist-info → ccxt-4.4.82.dist-info}/METADATA +9 -13
  84. {ccxt-4.4.78.dist-info → ccxt-4.4.82.dist-info}/RECORD +87 -87
  85. {ccxt-4.4.78.dist-info → ccxt-4.4.82.dist-info}/LICENSE.txt +0 -0
  86. {ccxt-4.4.78.dist-info → ccxt-4.4.82.dist-info}/WHEEL +0 -0
  87. {ccxt-4.4.78.dist-info → ccxt-4.4.82.dist-info}/top_level.txt +0 -0
ccxt/bitso.py CHANGED
@@ -742,7 +742,7 @@ class bitso(Exchange, ImplicitAPI):
742
742
  # {
743
743
  # "bucket_start_time":1648219140000,
744
744
  # "first_trade_time":1648219154990,
745
- # "last_trade_time":1648219189441,
745
+ # "last_trade_time":1648219189442,
746
746
  # "first_rate":"44958.60",
747
747
  # "last_rate":"44979.88",
748
748
  # "min_rate":"44957.33",
ccxt/bitteam.py CHANGED
@@ -650,6 +650,7 @@ class bitteam(Exchange, ImplicitAPI):
650
650
  networkIds = list(feesByNetworkId.keys())
651
651
  networks: dict = {}
652
652
  networkPrecision = self.parse_number(self.parse_precision(self.safe_string(currency, 'decimals')))
653
+ typeRaw = self.safe_string(currency, 'type')
653
654
  for j in range(0, len(networkIds)):
654
655
  networkId = networkIds[j]
655
656
  networkCode = self.network_id_to_code(networkId, code)
@@ -703,6 +704,7 @@ class bitteam(Exchange, ImplicitAPI):
703
704
  'max': None,
704
705
  },
705
706
  },
707
+ 'type': typeRaw, # 'crypto' or 'fiat'
706
708
  'networks': networks,
707
709
  }
708
710
  return result
ccxt/bitvavo.py CHANGED
@@ -361,6 +361,8 @@ class bitvavo(Exchange, ImplicitAPI):
361
361
  'ERC20': 'ETH',
362
362
  'TRC20': 'TRX',
363
363
  },
364
+ 'operatorId': None, # self will be required soon for order-related endpoints
365
+ 'fiatCurrencies': ['EUR'], # only fiat atm
364
366
  },
365
367
  'precisionMode': SIGNIFICANT_DIGITS,
366
368
  'commonCurrencies': {
@@ -567,24 +569,24 @@ class bitvavo(Exchange, ImplicitAPI):
567
569
  # },
568
570
  # ]
569
571
  #
572
+ fiatCurrencies = self.safe_list(self.options, 'fiatCurrencies', [])
570
573
  result: dict = {}
571
574
  for i in range(0, len(currencies)):
572
575
  currency = currencies[i]
573
576
  id = self.safe_string(currency, 'symbol')
574
577
  code = self.safe_currency_code(id)
578
+ isFiat = self.in_array(code, fiatCurrencies)
575
579
  networks: dict = {}
576
- networksArray = self.safe_value(currency, 'networks', [])
577
- networksLength = len(networksArray)
578
- isOneNetwork = (networksLength == 1)
579
- deposit = (self.safe_value(currency, 'depositStatus') == 'OK')
580
- withdrawal = (self.safe_value(currency, 'withdrawalStatus') == 'OK')
580
+ networksArray = self.safe_list(currency, 'networks', [])
581
+ deposit = self.safe_string(currency, 'depositStatus') == 'OK'
582
+ withdrawal = self.safe_string(currency, 'withdrawalStatus') == 'OK'
581
583
  active = deposit and withdrawal
582
584
  withdrawFee = self.safe_number(currency, 'withdrawalFee')
583
585
  precision = self.safe_integer(currency, 'decimals', 8)
584
586
  minWithdraw = self.safe_number(currency, 'withdrawalMinAmount')
585
- # absolutely all of them have 1 network atm - ETH. So, we can reliably assign that inside networks
586
- if isOneNetwork:
587
- networkId = networksArray[0]
587
+ # btw, absolutely all of them have 1 network atm
588
+ for j in range(0, len(networksArray)):
589
+ networkId = networksArray[j]
588
590
  networkCode = self.network_id_to_code(networkId)
589
591
  networks[networkCode] = {
590
592
  'info': currency,
@@ -602,7 +604,7 @@ class bitvavo(Exchange, ImplicitAPI):
602
604
  },
603
605
  },
604
606
  }
605
- result[code] = {
607
+ result[code] = self.safe_currency_structure({
606
608
  'info': currency,
607
609
  'id': id,
608
610
  'code': code,
@@ -613,6 +615,7 @@ class bitvavo(Exchange, ImplicitAPI):
613
615
  'networks': networks,
614
616
  'fee': withdrawFee,
615
617
  'precision': precision,
618
+ 'type': 'fiat' if isFiat else 'crypto',
616
619
  'limits': {
617
620
  'amount': {
618
621
  'min': None,
@@ -627,7 +630,7 @@ class bitvavo(Exchange, ImplicitAPI):
627
630
  'max': None,
628
631
  },
629
632
  },
630
- }
633
+ })
631
634
  # set currencies here to avoid calling publicGetAssets twice
632
635
  self.currencies = self.deep_extend(self.currencies, result)
633
636
  return result
@@ -1166,6 +1169,10 @@ class bitvavo(Exchange, ImplicitAPI):
1166
1169
  request['timeInForce'] = timeInForce
1167
1170
  if postOnly:
1168
1171
  request['postOnly'] = True
1172
+ operatorId = None
1173
+ operatorId, params = self.handle_option_and_params(params, 'createOrder', 'operatorId')
1174
+ if operatorId is not None:
1175
+ request['operatorId'] = self.parse_to_int(operatorId)
1169
1176
  return self.extend(request, params)
1170
1177
 
1171
1178
  def create_order(self, symbol: Str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
@@ -1259,6 +1266,10 @@ class bitvavo(Exchange, ImplicitAPI):
1259
1266
  clientOrderId = self.safe_string(params, 'clientOrderId')
1260
1267
  if clientOrderId is None:
1261
1268
  request['orderId'] = id
1269
+ operatorId = None
1270
+ operatorId, params = self.handle_option_and_params(params, 'editOrder', 'operatorId')
1271
+ if operatorId is not None:
1272
+ request['operatorId'] = self.parse_to_int(operatorId)
1262
1273
  request['market'] = market['id']
1263
1274
  return request
1264
1275
 
@@ -1293,6 +1304,10 @@ class bitvavo(Exchange, ImplicitAPI):
1293
1304
  clientOrderId = self.safe_string(params, 'clientOrderId')
1294
1305
  if clientOrderId is None:
1295
1306
  request['orderId'] = id
1307
+ operatorId = None
1308
+ operatorId, params = self.handle_option_and_params(params, 'cancelOrder', 'operatorId')
1309
+ if operatorId is not None:
1310
+ request['operatorId'] = self.parse_to_int(operatorId)
1296
1311
  return self.extend(request, params)
1297
1312
 
1298
1313
  def cancel_order(self, id: str, symbol: Str = None, params={}):
ccxt/btcalpha.py CHANGED
@@ -216,7 +216,7 @@ class btcalpha(Exchange, ImplicitAPI):
216
216
  'symbolRequired': False,
217
217
  },
218
218
  'fetchOHLCV': {
219
- 'max': 720,
219
+ 'limit': 720,
220
220
  },
221
221
  },
222
222
  'swap': {
ccxt/btcmarkets.py CHANGED
@@ -455,7 +455,7 @@ class btcmarkets(Exchange, ImplicitAPI):
455
455
  # "marketId":"COMP-AUD",
456
456
  # "baseAssetName":"COMP",
457
457
  # "quoteAssetName":"AUD",
458
- # "minOrderAmount":"0.00007",
458
+ # "minOrderAmount":"0.00006",
459
459
  # "maxOrderAmount":"1000000",
460
460
  # "amountDecimals":"8",
461
461
  # "priceDecimals":"2",
ccxt/btcturk.py CHANGED
@@ -248,7 +248,7 @@ class btcturk(Exchange, ImplicitAPI):
248
248
  # "minPrice": "0.0000000000001",
249
249
  # "maxPrice": "10000000",
250
250
  # "tickSize": "10",
251
- # "minExchangeValue": "99.91",
251
+ # "minExchangeValue": "99.92",
252
252
  # "minAmount": null,
253
253
  # "maxAmount": null
254
254
  # }
ccxt/bybit.py CHANGED
@@ -1040,9 +1040,6 @@ class bybit(Exchange, ImplicitAPI):
1040
1040
  'usePrivateInstrumentsInfo': False,
1041
1041
  'enableDemoTrading': False,
1042
1042
  'fetchMarkets': ['spot', 'linear', 'inverse', 'option'],
1043
- 'createOrder': {
1044
- 'method': 'privatePostV5OrderCreate', # 'privatePostV5PositionTradingStop'
1045
- },
1046
1043
  'enableUnifiedMargin': None,
1047
1044
  'enableUnifiedAccount': None,
1048
1045
  'unifiedMarginStatus': None,
@@ -1707,6 +1704,7 @@ class bybit(Exchange, ImplicitAPI):
1707
1704
  },
1708
1705
  },
1709
1706
  'networks': networks,
1707
+ 'type': 'crypto', # atm exchange api provides only cryptos
1710
1708
  }
1711
1709
  return result
1712
1710
 
@@ -2130,6 +2128,7 @@ class bybit(Exchange, ImplicitAPI):
2130
2128
  strike = self.safe_string(splitId, 2)
2131
2129
  optionLetter = self.safe_string(splitId, 3)
2132
2130
  isActive = (status == 'Trading')
2131
+ isInverse = base == settle
2133
2132
  if isActive or (self.options['loadAllOptions']) or (self.options['loadExpiredOptions']):
2134
2133
  result.append(self.safe_market_structure({
2135
2134
  'id': id,
@@ -2141,7 +2140,7 @@ class bybit(Exchange, ImplicitAPI):
2141
2140
  'quoteId': quoteId,
2142
2141
  'settleId': settleId,
2143
2142
  'type': 'option',
2144
- 'subType': 'linear',
2143
+ 'subType': None,
2145
2144
  'spot': False,
2146
2145
  'margin': False,
2147
2146
  'swap': False,
@@ -2149,8 +2148,8 @@ class bybit(Exchange, ImplicitAPI):
2149
2148
  'option': True,
2150
2149
  'active': isActive,
2151
2150
  'contract': True,
2152
- 'linear': True,
2153
- 'inverse': False,
2151
+ 'linear': not isInverse,
2152
+ 'inverse': isInverse,
2154
2153
  'taker': self.safe_number(market, 'takerFee', self.parse_number('0.0006')),
2155
2154
  'maker': self.safe_number(market, 'makerFee', self.parse_number('0.0001')),
2156
2155
  'contractSize': self.parse_number('1'),
@@ -3774,12 +3773,21 @@ class bybit(Exchange, ImplicitAPI):
3774
3773
  parts = self.is_unified_enabled()
3775
3774
  enableUnifiedAccount = parts[1]
3776
3775
  trailingAmount = self.safe_string_2(params, 'trailingAmount', 'trailingStop')
3776
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
3777
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
3777
3778
  isTrailingAmountOrder = trailingAmount is not None
3779
+ isStopLoss = stopLossPrice is not None
3780
+ isTakeProfit = takeProfitPrice is not None
3778
3781
  orderRequest = self.create_order_request(symbol, type, side, amount, price, params, enableUnifiedAccount)
3779
- options = self.safe_dict(self.options, 'createOrder', {})
3780
- defaultMethod = self.safe_string(options, 'method', 'privatePostV5OrderCreate')
3782
+ defaultMethod = None
3783
+ if isTrailingAmountOrder or isStopLoss or isTakeProfit:
3784
+ defaultMethod = 'privatePostV5PositionTradingStop'
3785
+ else:
3786
+ defaultMethod = 'privatePostV5OrderCreate'
3787
+ method = None
3788
+ method, params = self.handle_option_and_params(params, 'createOrder', 'method', defaultMethod)
3781
3789
  response = None
3782
- if isTrailingAmountOrder or (defaultMethod == 'privatePostV5PositionTradingStop'):
3790
+ if method == 'privatePostV5PositionTradingStop':
3783
3791
  response = self.privatePostV5PositionTradingStop(orderRequest)
3784
3792
  else:
3785
3793
  response = self.privatePostV5OrderCreate(orderRequest) # already extended inside createOrderRequest
@@ -3804,8 +3812,6 @@ class bybit(Exchange, ImplicitAPI):
3804
3812
  lowerCaseType = type.lower()
3805
3813
  if (price is None) and (lowerCaseType == 'limit'):
3806
3814
  raise ArgumentsRequired(self.id + ' createOrder requires a price argument for limit orders')
3807
- defaultMethod = None
3808
- defaultMethod, params = self.handle_option_and_params(params, 'createOrder', 'method', 'privatePostV5OrderCreate')
3809
3815
  request: dict = {
3810
3816
  'symbol': market['id'],
3811
3817
  # 'side': self.capitalize(side),
@@ -3849,7 +3855,14 @@ class bybit(Exchange, ImplicitAPI):
3849
3855
  isMarket = lowerCaseType == 'market'
3850
3856
  isLimit = lowerCaseType == 'limit'
3851
3857
  isBuy = side == 'buy'
3852
- isAlternativeEndpoint = defaultMethod == 'privatePostV5PositionTradingStop'
3858
+ defaultMethod = None
3859
+ if isTrailingAmountOrder or isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3860
+ defaultMethod = 'privatePostV5PositionTradingStop'
3861
+ else:
3862
+ defaultMethod = 'privatePostV5OrderCreate'
3863
+ method = None
3864
+ method, params = self.handle_option_and_params(params, 'createOrder', 'method', defaultMethod)
3865
+ isAlternativeEndpoint = method == 'privatePostV5PositionTradingStop'
3853
3866
  amountString = self.get_amount(symbol, amount)
3854
3867
  priceString = self.get_price(symbol, self.number_to_string(price)) if (price is not None) else None
3855
3868
  if isTrailingAmountOrder or isAlternativeEndpoint:
@@ -3900,12 +3913,12 @@ class bybit(Exchange, ImplicitAPI):
3900
3913
  request['price'] = priceString
3901
3914
  if market['spot']:
3902
3915
  request['category'] = 'spot'
3916
+ elif market['option']:
3917
+ request['category'] = 'option'
3903
3918
  elif market['linear']:
3904
3919
  request['category'] = 'linear'
3905
3920
  elif market['inverse']:
3906
3921
  request['category'] = 'inverse'
3907
- elif market['option']:
3908
- request['category'] = 'option'
3909
3922
  cost = self.safe_string(params, 'cost')
3910
3923
  params = self.omit(params, 'cost')
3911
3924
  # if the cost is inferable, let's keep the old logic and ignore marketUnit, to minimize the impact of the changes
@@ -5650,7 +5663,8 @@ classic accounts only/ spot not supported* fetches information on an order made
5650
5663
  subType, params = self.handle_sub_type_and_params('fetchLedger', None, params)
5651
5664
  response = None
5652
5665
  if enableUnified[1]:
5653
- if subType == 'inverse':
5666
+ unifiedMarginStatus = self.safe_integer(self.options, 'unifiedMarginStatus', 5) # 3/4 uta 1.0, 5/6 uta 2.0
5667
+ if subType == 'inverse' and (unifiedMarginStatus < 5):
5654
5668
  response = self.privateGetV5AccountContractTransactionLog(self.extend(request, params))
5655
5669
  else:
5656
5670
  response = self.privateGetV5AccountTransactionLog(self.extend(request, params))
ccxt/coinbase.py CHANGED
@@ -386,7 +386,6 @@ class coinbase(Exchange, ImplicitAPI):
386
386
  'fetchBalance': 'v2PrivateGetAccounts', # 'v2PrivateGetAccounts' or 'v3PrivateGetBrokerageAccounts'
387
387
  'fetchTime': 'v2PublicGetTime', # 'v2PublicGetTime' or 'v3PublicGetBrokerageTime'
388
388
  'user_native_currency': 'USD', # needed to get fees for v3
389
- 'aliasCbMarketIds': {},
390
389
  },
391
390
  'features': {
392
391
  'default': {
@@ -1474,8 +1473,6 @@ class coinbase(Exchange, ImplicitAPI):
1474
1473
  perpetualData = self.safe_list(perpetualFutures, 'products', [])
1475
1474
  for i in range(0, len(perpetualData)):
1476
1475
  result.append(self.parse_contract_market(perpetualData[i], perpetualFeeTier))
1477
- # remove aliases
1478
- self.options['aliasCbMarketIds'] = {}
1479
1476
  newMarkets = []
1480
1477
  for i in range(0, len(result)):
1481
1478
  market = result[i]
@@ -1483,21 +1480,12 @@ class coinbase(Exchange, ImplicitAPI):
1483
1480
  realMarketIds = self.safe_list(info, 'alias_to', [])
1484
1481
  length = len(realMarketIds)
1485
1482
  if length > 0:
1486
- self.options['aliasCbMarketIds'][market['id']] = realMarketIds[0]
1487
- self.options['aliasCbMarketIds'][market['symbol']] = realMarketIds[0]
1483
+ market['alias'] = realMarketIds[0]
1488
1484
  else:
1489
- newMarkets.append(market)
1485
+ market['alias'] = None
1486
+ newMarkets.append(market)
1490
1487
  return newMarkets
1491
1488
 
1492
- def market(self, symbol: str) -> MarketInterface:
1493
- finalSymbol = self.safe_string(self.options['aliasCbMarketIds'], symbol, symbol)
1494
- return super(coinbase, self).market(finalSymbol)
1495
-
1496
- def safe_market(self, marketId: Str = None, market: Market = None, delimiter: Str = None, marketType: Str = None) -> MarketInterface:
1497
- if marketId in self.options['aliasCbMarketIds']:
1498
- return self.market(marketId)
1499
- return super(coinbase, self).safe_market(marketId, market, delimiter, marketType)
1500
-
1501
1489
  def parse_spot_market(self, market, feeTier) -> MarketInterface:
1502
1490
  #
1503
1491
  # {
ccxt/coinex.py CHANGED
@@ -757,6 +757,7 @@ class coinex(Exchange, ImplicitAPI):
757
757
  },
758
758
  },
759
759
  'networks': {},
760
+ 'type': 'crypto',
760
761
  'info': coin,
761
762
  }
762
763
  for j in range(0, len(chains)):
ccxt/coinlist.py CHANGED
@@ -489,6 +489,7 @@ class coinlist(Exchange, ImplicitAPI):
489
489
  'withdraw': {'min': minWithdrawal, 'max': None},
490
490
  },
491
491
  'networks': {},
492
+ 'type': 'crypto',
492
493
  }
493
494
  return result
494
495
 
ccxt/coinone.py CHANGED
@@ -330,6 +330,7 @@ class coinone(Exchange, ImplicitAPI):
330
330
  },
331
331
  },
332
332
  'networks': {},
333
+ 'type': 'crypto',
333
334
  }
334
335
  return result
335
336
 
ccxt/delta.py CHANGED
@@ -357,6 +357,8 @@ class delta(Exchange, ImplicitAPI):
357
357
  base = self.safe_string(optionParts, 1)
358
358
  expiry = self.safe_string(optionParts, 3)
359
359
  optionType = self.safe_string(optionParts, 0)
360
+ if expiry is not None:
361
+ expiry = expiry[4:] + expiry[2:4] + expiry[0:2]
360
362
  settle = quote
361
363
  strike = self.safe_string(optionParts, 2)
362
364
  datetime = self.convert_expire_date(expiry)
@@ -567,6 +569,7 @@ class delta(Exchange, ImplicitAPI):
567
569
  },
568
570
  },
569
571
  'networks': {},
572
+ 'type': 'crypto',
570
573
  }
571
574
  return result
572
575
 
ccxt/deribit.py CHANGED
@@ -655,6 +655,7 @@ class deribit(Exchange, ImplicitAPI):
655
655
  'active': None,
656
656
  'deposit': None,
657
657
  'withdraw': None,
658
+ 'type': 'crypto',
658
659
  'fee': self.safe_number(currency, 'withdrawal_fee'),
659
660
  'precision': self.parse_number(self.parse_precision(self.safe_string(currency, 'fee_precision'))),
660
661
  'limits': {
ccxt/hollaex.py CHANGED
@@ -493,6 +493,7 @@ class hollaex(Exchange, ImplicitAPI):
493
493
  },
494
494
  },
495
495
  'networks': {},
496
+ 'type': 'crypto',
496
497
  }
497
498
  return result
498
499
 
ccxt/htx.py CHANGED
@@ -962,6 +962,7 @@ class htx(Exchange, ImplicitAPI):
962
962
  },
963
963
  'precisionMode': TICK_SIZE,
964
964
  'options': {
965
+ 'include_OS_certificates': False, # temporarily leave self, remove in future
965
966
  'fetchMarkets': {
966
967
  'types': {
967
968
  'spot': True,
@@ -2172,14 +2173,14 @@ class htx(Exchange, ImplicitAPI):
2172
2173
  ask = None
2173
2174
  askVolume = None
2174
2175
  if 'bid' in ticker:
2175
- if isinstance(ticker['bid'], list):
2176
+ if ticker['bid'] is not None and isinstance(ticker['bid'], list):
2176
2177
  bid = self.safe_string(ticker['bid'], 0)
2177
2178
  bidVolume = self.safe_string(ticker['bid'], 1)
2178
2179
  else:
2179
2180
  bid = self.safe_string(ticker, 'bid')
2180
2181
  bidVolume = self.safe_string(ticker, 'bidSize')
2181
2182
  if 'ask' in ticker:
2182
- if isinstance(ticker['ask'], list):
2183
+ if ticker['ask'] is not None and isinstance(ticker['ask'], list):
2183
2184
  ask = self.safe_string(ticker['ask'], 0)
2184
2185
  askVolume = self.safe_string(ticker['ask'], 1)
2185
2186
  else:
@@ -3270,7 +3271,7 @@ class htx(Exchange, ImplicitAPI):
3270
3271
  # "withdrawQuotaPerYear": null,
3271
3272
  # "withdrawQuotaTotal": null,
3272
3273
  # "withdrawFeeType": "fixed",
3273
- # "transactFeeWithdraw": "11.1653",
3274
+ # "transactFeeWithdraw": "11.1654",
3274
3275
  # "addrWithTag": False,
3275
3276
  # "addrDepositTag": False
3276
3277
  # }
@@ -3293,6 +3294,8 @@ class htx(Exchange, ImplicitAPI):
3293
3294
  chains = self.safe_value(entry, 'chains', [])
3294
3295
  networks: dict = {}
3295
3296
  instStatus = self.safe_string(entry, 'instStatus')
3297
+ assetType = self.safe_string(entry, 'assetType')
3298
+ type = assetType == 'crypto' if '1' else 'fiat'
3296
3299
  currencyActive = instStatus == 'normal'
3297
3300
  minPrecision = None
3298
3301
  minDeposit = None
@@ -3350,6 +3353,7 @@ class htx(Exchange, ImplicitAPI):
3350
3353
  'withdraw': withdraw,
3351
3354
  'fee': None,
3352
3355
  'name': None,
3356
+ 'type': type,
3353
3357
  'limits': {
3354
3358
  'amount': {
3355
3359
  'min': None,
@@ -6941,7 +6945,7 @@ class htx(Exchange, ImplicitAPI):
6941
6945
  if method != 'POST':
6942
6946
  request = self.extend(request, query)
6943
6947
  sortedRequest = self.keysort(request)
6944
- auth = self.urlencode(sortedRequest)
6948
+ auth = self.urlencode(sortedRequest, True) # True is a go only requirment
6945
6949
  # unfortunately, PHP demands double quotes for the escaped newline symbol
6946
6950
  payload = "\n".join([method, self.hostname, url, auth]) # eslint-disable-line quotes
6947
6951
  signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256, 'base64')
@@ -7007,7 +7011,7 @@ class htx(Exchange, ImplicitAPI):
7007
7011
  if method != 'POST':
7008
7012
  sortedQuery = self.keysort(query)
7009
7013
  request = self.extend(request, sortedQuery)
7010
- auth = self.urlencode(request).replace('%2c', '%2C') # in c# it manually needs to be uppercased
7014
+ auth = self.urlencode(request, True).replace('%2c', '%2C') # in c# it manually needs to be uppercased
7011
7015
  # unfortunately, PHP demands double quotes for the escaped newline symbol
7012
7016
  payload = "\n".join([method, hostname, url, auth]) # eslint-disable-line quotes
7013
7017
  signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256, 'base64')
ccxt/huobijp.py CHANGED
@@ -1110,6 +1110,7 @@ class huobijp(Exchange, ImplicitAPI):
1110
1110
  'withdraw': withdrawEnabled,
1111
1111
  'fee': None, # todo need to fetch from fee endpoint
1112
1112
  'precision': precision,
1113
+ 'networks': None,
1113
1114
  'limits': {
1114
1115
  'amount': {
1115
1116
  'min': precision,
ccxt/hyperliquid.py CHANGED
@@ -379,6 +379,7 @@ class hyperliquid(Exchange, ImplicitAPI):
379
379
  'withdraw': None,
380
380
  'networks': None,
381
381
  'fee': None,
382
+ 'type': 'crypto',
382
383
  'limits': {
383
384
  'amount': {
384
385
  'min': None,
@@ -2177,6 +2178,10 @@ class hyperliquid(Exchange, ImplicitAPI):
2177
2178
  return self.parse_order(data, market)
2178
2179
 
2179
2180
  def parse_order(self, order: dict, market: Market = None) -> Order:
2181
+ #
2182
+ # createOrdersWs error
2183
+ #
2184
+ # {error: 'Insufficient margin to place order. asset=159'}
2180
2185
  #
2181
2186
  # fetchOpenOrders
2182
2187
  #
@@ -2268,6 +2273,12 @@ class hyperliquid(Exchange, ImplicitAPI):
2268
2273
  # "triggerPx": "0.6"
2269
2274
  # }
2270
2275
  #
2276
+ error = self.safe_string(order, 'error')
2277
+ if error is not None:
2278
+ return self.safe_order({
2279
+ 'info': order,
2280
+ 'status': 'rejected',
2281
+ })
2271
2282
  entry = self.safe_dict_n(order, ['order', 'resting', 'filled'])
2272
2283
  if entry is None:
2273
2284
  entry = order
@@ -3443,9 +3454,12 @@ class hyperliquid(Exchange, ImplicitAPI):
3443
3454
  # {"status":"ok","response":{"type":"order","data":{"statuses":[{"error":"Insufficient margin to place order. asset=84"}]}}}
3444
3455
  #
3445
3456
  status = self.safe_string(response, 'status', '')
3457
+ error = self.safe_string(response, 'error')
3446
3458
  message = None
3447
3459
  if status == 'err':
3448
3460
  message = self.safe_string(response, 'response')
3461
+ elif error is not None:
3462
+ message = error
3449
3463
  else:
3450
3464
  responsePayload = self.safe_dict(response, 'response', {})
3451
3465
  data = self.safe_dict(responsePayload, 'data', {})
ccxt/kraken.py CHANGED
@@ -864,12 +864,14 @@ class kraken(Exchange, ImplicitAPI):
864
864
  precision = self.parse_number(self.parse_precision(self.safe_string(currency, 'decimals')))
865
865
  # assumes all currencies are active except those listed above
866
866
  active = self.safe_string(currency, 'status') == 'enabled'
867
+ isFiat = code.find('.HOLD') >= 0
867
868
  result[code] = {
868
869
  'id': id,
869
870
  'code': code,
870
871
  'info': currency,
871
872
  'name': self.safe_string(currency, 'altname'),
872
873
  'active': active,
874
+ 'type': 'fiat' if isFiat else 'crypto',
873
875
  'deposit': None,
874
876
  'withdraw': None,
875
877
  'fee': None,
ccxt/okx.py CHANGED
@@ -1647,7 +1647,6 @@ class okx(Exchange, ImplicitAPI):
1647
1647
  ymd = self.yymmdd(expiry)
1648
1648
  symbol = symbol + '-' + ymd + '-' + strikePrice + '-' + optionType
1649
1649
  optionType = 'put' if (optionType == 'P') else 'call'
1650
- tickSize = self.safe_string(market, 'tickSz')
1651
1650
  fees = self.safe_dict_2(self.fees, type, 'trading', {})
1652
1651
  maxLeverage = self.safe_string(market, 'lever', '1')
1653
1652
  maxLeverage = Precise.string_max(maxLeverage, '1')
@@ -1679,7 +1678,7 @@ class okx(Exchange, ImplicitAPI):
1679
1678
  'created': self.safe_integer(market, 'listTime'),
1680
1679
  'precision': {
1681
1680
  'amount': self.safe_number(market, 'lotSz'),
1682
- 'price': self.parse_number(tickSize),
1681
+ 'price': self.safe_number(market, 'tickSz'),
1683
1682
  },
1684
1683
  'limits': {
1685
1684
  'leverage': {
@@ -4831,7 +4830,7 @@ class okx(Exchange, ImplicitAPI):
4831
4830
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
4832
4831
  """
4833
4832
  self.load_markets()
4834
- rawNetwork = self.safe_string_upper(params, 'network')
4833
+ rawNetwork = self.safe_string(params, 'network') # some networks are like "Dora Vota Mainnet"
4835
4834
  params = self.omit(params, 'network')
4836
4835
  code = self.safe_currency_code(code)
4837
4836
  network = self.network_id_to_code(rawNetwork, code)
ccxt/oxfun.py CHANGED
@@ -83,7 +83,7 @@ class oxfun(Exchange, ImplicitAPI):
83
83
  'fetchDepositWithdrawFee': False,
84
84
  'fetchDepositWithdrawFees': False,
85
85
  'fetchFundingHistory': True,
86
- 'fetchFundingRate': 'emulated',
86
+ 'fetchFundingRate': True,
87
87
  'fetchFundingRateHistory': True,
88
88
  'fetchFundingRates': True,
89
89
  'fetchIndexOHLCV': False,
@@ -1103,6 +1103,26 @@ class oxfun(Exchange, ImplicitAPI):
1103
1103
  data = self.safe_list(response, 'data', [])
1104
1104
  return self.parse_funding_rates(data, symbols)
1105
1105
 
1106
+ def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
1107
+ """
1108
+ fetch the current funding rates for a symbol
1109
+
1110
+ https://docs.ox.fun/?json#get-v3-funding-estimates
1111
+
1112
+ :param str symbol: unified market symbols
1113
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1114
+ :returns Order[]: an array of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-structure>`
1115
+ """
1116
+ self.load_markets()
1117
+ request: dict = {
1118
+ 'marketCode': self.market_id(symbol),
1119
+ }
1120
+ response = self.publicGetV3FundingEstimates(self.extend(request, params))
1121
+ #
1122
+ data = self.safe_list(response, 'data', [])
1123
+ first = self.safe_dict(data, 0, {})
1124
+ return self.parse_funding_rate(first, self.market(symbol))
1125
+
1106
1126
  def parse_funding_rate(self, fundingRate, market: Market = None) -> FundingRate:
1107
1127
  #
1108
1128
  # {
ccxt/poloniex.py CHANGED
@@ -1203,6 +1203,7 @@ class poloniex(Exchange, ImplicitAPI):
1203
1203
  'withdraw': withdrawEnabled,
1204
1204
  'fee': self.parse_number(feeString),
1205
1205
  'precision': None,
1206
+ 'type': 'crypto',
1206
1207
  'limits': {
1207
1208
  'amount': {
1208
1209
  'min': None,
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.78'
7
+ __version__ = '4.4.82'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/binance.py CHANGED
@@ -71,12 +71,12 @@ class binance(ccxt.async_support.binance):
71
71
  'urls': {
72
72
  'test': {
73
73
  'ws': {
74
- 'spot': 'wss://testnet.binance.vision/ws',
75
- 'margin': 'wss://testnet.binance.vision/ws',
74
+ 'spot': 'wss://stream.testnet.binance.vision/ws',
75
+ 'margin': 'wss://stream.testnet.binance.vision/ws',
76
76
  'future': 'wss://fstream.binancefuture.com/ws',
77
77
  'delivery': 'wss://dstream.binancefuture.com/ws',
78
78
  'ws-api': {
79
- 'spot': 'wss://testnet.binance.vision/ws-api/v3',
79
+ 'spot': 'wss://ws-api.testnet.binance.vision/ws-api/v3',
80
80
  'future': 'wss://testnet.binancefuture.com/ws-fapi/v1',
81
81
  'delivery': 'wss://testnet.binancefuture.com/ws-dapi/v1',
82
82
  },