ccxt 4.4.80__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.
@@ -2179,6 +2179,10 @@ class hyperliquid(Exchange, ImplicitAPI):
2179
2179
  return self.parse_order(data, market)
2180
2180
 
2181
2181
  def parse_order(self, order: dict, market: Market = None) -> Order:
2182
+ #
2183
+ # createOrdersWs error
2184
+ #
2185
+ # {error: 'Insufficient margin to place order. asset=159'}
2182
2186
  #
2183
2187
  # fetchOpenOrders
2184
2188
  #
@@ -2270,6 +2274,12 @@ class hyperliquid(Exchange, ImplicitAPI):
2270
2274
  # "triggerPx": "0.6"
2271
2275
  # }
2272
2276
  #
2277
+ error = self.safe_string(order, 'error')
2278
+ if error is not None:
2279
+ return self.safe_order({
2280
+ 'info': order,
2281
+ 'status': 'rejected',
2282
+ })
2273
2283
  entry = self.safe_dict_n(order, ['order', 'resting', 'filled'])
2274
2284
  if entry is None:
2275
2285
  entry = order
@@ -3445,9 +3455,12 @@ class hyperliquid(Exchange, ImplicitAPI):
3445
3455
  # {"status":"ok","response":{"type":"order","data":{"statuses":[{"error":"Insufficient margin to place order. asset=84"}]}}}
3446
3456
  #
3447
3457
  status = self.safe_string(response, 'status', '')
3458
+ error = self.safe_string(response, 'error')
3448
3459
  message = None
3449
3460
  if status == 'err':
3450
3461
  message = self.safe_string(response, 'response')
3462
+ elif error is not None:
3463
+ message = error
3451
3464
  else:
3452
3465
  responsePayload = self.safe_dict(response, 'response', {})
3453
3466
  data = self.safe_dict(responsePayload, 'data', {})
ccxt/async_support/okx.py CHANGED
@@ -1648,7 +1648,6 @@ class okx(Exchange, ImplicitAPI):
1648
1648
  ymd = self.yymmdd(expiry)
1649
1649
  symbol = symbol + '-' + ymd + '-' + strikePrice + '-' + optionType
1650
1650
  optionType = 'put' if (optionType == 'P') else 'call'
1651
- tickSize = self.safe_string(market, 'tickSz')
1652
1651
  fees = self.safe_dict_2(self.fees, type, 'trading', {})
1653
1652
  maxLeverage = self.safe_string(market, 'lever', '1')
1654
1653
  maxLeverage = Precise.string_max(maxLeverage, '1')
@@ -1680,7 +1679,7 @@ class okx(Exchange, ImplicitAPI):
1680
1679
  'created': self.safe_integer(market, 'listTime'),
1681
1680
  'precision': {
1682
1681
  'amount': self.safe_number(market, 'lotSz'),
1683
- 'price': self.parse_number(tickSize),
1682
+ 'price': self.safe_number(market, 'tickSz'),
1684
1683
  },
1685
1684
  'limits': {
1686
1685
  'leverage': {
@@ -84,7 +84,7 @@ class oxfun(Exchange, ImplicitAPI):
84
84
  'fetchDepositWithdrawFee': False,
85
85
  'fetchDepositWithdrawFees': False,
86
86
  'fetchFundingHistory': True,
87
- 'fetchFundingRate': 'emulated',
87
+ 'fetchFundingRate': True,
88
88
  'fetchFundingRateHistory': True,
89
89
  'fetchFundingRates': True,
90
90
  'fetchIndexOHLCV': False,
@@ -1104,6 +1104,26 @@ class oxfun(Exchange, ImplicitAPI):
1104
1104
  data = self.safe_list(response, 'data', [])
1105
1105
  return self.parse_funding_rates(data, symbols)
1106
1106
 
1107
+ async def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
1108
+ """
1109
+ fetch the current funding rates for a symbol
1110
+
1111
+ https://docs.ox.fun/?json#get-v3-funding-estimates
1112
+
1113
+ :param str symbol: unified market symbols
1114
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1115
+ :returns Order[]: an array of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-structure>`
1116
+ """
1117
+ await self.load_markets()
1118
+ request: dict = {
1119
+ 'marketCode': self.market_id(symbol),
1120
+ }
1121
+ response = await self.publicGetV3FundingEstimates(self.extend(request, params))
1122
+ #
1123
+ data = self.safe_list(response, 'data', [])
1124
+ first = self.safe_dict(data, 0, {})
1125
+ return self.parse_funding_rate(first, self.market(symbol))
1126
+
1107
1127
  def parse_funding_rate(self, fundingRate, market: Market = None) -> FundingRate:
1108
1128
  #
1109
1129
  # {
ccxt/base/errors.py CHANGED
@@ -1,3 +1,9 @@
1
+ # ----------------------------------------------------------------------------
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+ # EDIT THE CORRESPONDENT .ts FILE INSTEAD
6
+
1
7
  error_hierarchy = {
2
8
  'BaseError': {
3
9
  'ExchangeError': {
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.80'
7
+ __version__ = '4.4.82'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -1000,7 +1000,7 @@ class Exchange(object):
1000
1000
  return string
1001
1001
 
1002
1002
  @staticmethod
1003
- def urlencode(params={}, doseq=False):
1003
+ def urlencode(params={}, doseq=False, sort=False):
1004
1004
  newParams = params.copy()
1005
1005
  for key, value in params.items():
1006
1006
  if isinstance(value, bool):
@@ -5522,6 +5522,24 @@ class Exchange(object):
5522
5522
  def create_expired_option_market(self, symbol: str):
5523
5523
  raise NotSupported(self.id + ' createExpiredOptionMarket() is not supported yet')
5524
5524
 
5525
+ def is_leveraged_currency(self, currencyCode, checkBaseCoin: Bool = False, existingCurrencies: dict = None):
5526
+ leverageSuffixes = [
5527
+ '2L', '2S', '3L', '3S', '4L', '4S', '5L', '5S', # Leveraged Tokens(LT)
5528
+ 'UP', 'DOWN', # exchange-specific(e.g. BLVT)
5529
+ 'BULL', 'BEAR', # similar
5530
+ ]
5531
+ for i in range(0, len(leverageSuffixes)):
5532
+ leverageSuffix = leverageSuffixes[i]
5533
+ if currencyCode.endswith(leverageSuffix):
5534
+ if not checkBaseCoin:
5535
+ return True
5536
+ else:
5537
+ # check if base currency is inside dict
5538
+ baseCurrencyCode = currencyCode.replace(leverageSuffix, '')
5539
+ if baseCurrencyCode in existingCurrencies:
5540
+ return True
5541
+ return False
5542
+
5525
5543
  def handle_withdraw_tag_and_params(self, tag, params):
5526
5544
  if (tag is not None) and (isinstance(tag, dict)):
5527
5545
  params = self.extend(tag, params)
ccxt/bigone.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bigone import ImplicitAPI
8
- from ccxt.base.types import Any, Balances, Bool, Currencies, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
8
+ from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import AuthenticationError
@@ -509,19 +509,15 @@ class bigone(Exchange, ImplicitAPI):
509
509
  id = self.safe_string(currency, 'symbol')
510
510
  code = self.safe_currency_code(id)
511
511
  name = self.safe_string(currency, 'name')
512
- type = 'fiat' if self.safe_bool(currency, 'is_fiat') else 'crypto'
513
512
  networks: dict = {}
514
513
  chains = self.safe_list(currency, 'binding_gateways', [])
515
514
  currencyMaxPrecision = self.parse_precision(self.safe_string_2(currency, 'withdrawal_scale', 'scale'))
516
- currencyDepositEnabled: Bool = None
517
- currencyWithdrawEnabled: Bool = None
518
515
  for j in range(0, len(chains)):
519
516
  chain = chains[j]
520
517
  networkId = self.safe_string(chain, 'gateway_name')
521
518
  networkCode = self.network_id_to_code(networkId)
522
519
  deposit = self.safe_bool(chain, 'is_deposit_enabled')
523
520
  withdraw = self.safe_bool(chain, 'is_withdrawal_enabled')
524
- isActive = (deposit and withdraw)
525
521
  minDepositAmount = self.safe_string(chain, 'min_deposit_amount')
526
522
  minWithdrawalAmount = self.safe_string(chain, 'min_withdrawal_amount')
527
523
  withdrawalFee = self.safe_string(chain, 'withdrawal_fee')
@@ -532,7 +528,7 @@ class bigone(Exchange, ImplicitAPI):
532
528
  'margin': None,
533
529
  'deposit': deposit,
534
530
  'withdraw': withdraw,
535
- 'active': isActive,
531
+ 'active': None,
536
532
  'fee': self.parse_number(withdrawalFee),
537
533
  'precision': self.parse_number(precision),
538
534
  'limits': {
@@ -547,19 +543,26 @@ class bigone(Exchange, ImplicitAPI):
547
543
  },
548
544
  'info': chain,
549
545
  }
550
- # fill global values
551
- currencyDepositEnabled = (currencyDepositEnabled is None) or deposit if deposit else currencyDepositEnabled
552
- currencyWithdrawEnabled = (currencyWithdrawEnabled is None) or withdraw if withdraw else currencyWithdrawEnabled
553
- currencyMaxPrecision = (currencyMaxPrecision is None) or precision if Precise.string_gt(currencyMaxPrecision, precision) else currencyMaxPrecision
554
- result[code] = {
546
+ chainLength = len(chains)
547
+ type: Str = None
548
+ if self.safe_bool(currency, 'is_fiat'):
549
+ type = 'fiat'
550
+ elif chainLength == 0:
551
+ if self.is_leveraged_currency(id):
552
+ type = 'leveraged'
553
+ else:
554
+ type = 'other'
555
+ else:
556
+ type = 'crypto'
557
+ result[code] = self.safe_currency_structure({
555
558
  'id': id,
556
559
  'code': code,
557
560
  'info': currency,
558
561
  'name': name,
559
562
  'type': type,
560
563
  'active': None,
561
- 'deposit': currencyDepositEnabled,
562
- 'withdraw': currencyWithdrawEnabled,
564
+ 'deposit': None,
565
+ 'withdraw': None,
563
566
  'fee': None,
564
567
  'precision': self.parse_number(currencyMaxPrecision),
565
568
  'limits': {
@@ -573,7 +576,7 @@ class bigone(Exchange, ImplicitAPI):
573
576
  },
574
577
  },
575
578
  'networks': networks,
576
- }
579
+ })
577
580
  return result
578
581
 
579
582
  def fetch_markets(self, params={}) -> List[Market]:
ccxt/bingx.py CHANGED
@@ -766,56 +766,41 @@ class bingx(Exchange, ImplicitAPI):
766
766
  name = self.safe_string(entry, 'name')
767
767
  networkList = self.safe_list(entry, 'networkList')
768
768
  networks: dict = {}
769
- fee = None
770
- depositEnabled = False
771
- withdrawEnabled = False
772
- defaultLimits: dict = {}
773
769
  for j in range(0, len(networkList)):
774
770
  rawNetwork = networkList[j]
775
771
  network = self.safe_string(rawNetwork, 'network')
776
772
  networkCode = self.network_id_to_code(network)
777
- isDefault = self.safe_bool(rawNetwork, 'isDefault')
778
- networkDepositEnabled = self.safe_bool(rawNetwork, 'depositEnable')
779
- if networkDepositEnabled:
780
- depositEnabled = True
781
- networkWithdrawEnabled = self.safe_bool(rawNetwork, 'withdrawEnable')
782
- if networkWithdrawEnabled:
783
- withdrawEnabled = True
784
773
  limits: dict = {
785
774
  'withdraw': {
786
775
  'min': self.safe_number(rawNetwork, 'withdrawMin'),
787
776
  'max': self.safe_number(rawNetwork, 'withdrawMax'),
788
777
  },
789
778
  }
790
- fee = self.safe_number(rawNetwork, 'withdrawFee')
791
- if isDefault:
792
- defaultLimits = limits
793
- precision = self.safe_number(rawNetwork, 'withdrawPrecision')
794
- networkActive = networkDepositEnabled or networkWithdrawEnabled
779
+ precision = self.parse_number(self.parse_precision(self.safe_string(rawNetwork, 'withdrawPrecision')))
795
780
  networks[networkCode] = {
796
781
  'info': rawNetwork,
797
782
  'id': network,
798
783
  'network': networkCode,
799
- 'fee': fee,
800
- 'active': networkActive,
801
- 'deposit': networkDepositEnabled,
802
- 'withdraw': networkWithdrawEnabled,
784
+ 'fee': self.safe_number(rawNetwork, 'withdrawFee'),
785
+ 'active': None,
786
+ 'deposit': self.safe_bool(rawNetwork, 'depositEnable'),
787
+ 'withdraw': self.safe_bool(rawNetwork, 'withdrawEnable'),
803
788
  'precision': precision,
804
789
  'limits': limits,
805
790
  }
806
- active = depositEnabled or withdrawEnabled
807
791
  result[code] = self.safe_currency_structure({
808
792
  'info': entry,
809
793
  'code': code,
810
794
  'id': currencyId,
811
795
  'precision': None,
812
796
  'name': name,
813
- 'active': active,
814
- 'deposit': depositEnabled,
815
- 'withdraw': withdrawEnabled,
797
+ 'active': None,
798
+ 'deposit': None,
799
+ 'withdraw': None,
816
800
  'networks': networks,
817
- 'fee': fee,
818
- 'limits': defaultLimits,
801
+ 'fee': None,
802
+ 'limits': None,
803
+ 'type': 'crypto', # only cryptos now
819
804
  })
820
805
  return result
821
806
 
@@ -5535,18 +5520,14 @@ class bingx(Exchange, ImplicitAPI):
5535
5520
  :param str address: the address to withdraw to
5536
5521
  :param str [tag]:
5537
5522
  :param dict [params]: extra parameters specific to the exchange API endpoint
5538
- :param int [params.walletType]: 1 fund account, 2 standard account, 3 perpetual account
5523
+ :param int [params.walletType]: 1 fund account, 2 standard account, 3 perpetual account, 15 spot account
5539
5524
  :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
5540
5525
  """
5541
5526
  tag, params = self.handle_withdraw_tag_and_params(tag, params)
5542
5527
  self.check_address(address)
5543
5528
  self.load_markets()
5544
5529
  currency = self.currency(code)
5545
- walletType = self.safe_integer(params, 'walletType')
5546
- if walletType is None:
5547
- walletType = 1
5548
- if not self.in_array(walletType, [1, 2, 3]):
5549
- raise BadRequest(self.id + ' withdraw() requires either 1 fund account, 2 standard futures account, 3 perpetual account for walletType')
5530
+ walletType = self.safe_integer(params, 'walletType', 1)
5550
5531
  request: dict = {
5551
5532
  'coin': currency['id'],
5552
5533
  'address': address,
ccxt/bitfinex.py CHANGED
@@ -751,6 +751,7 @@ class bitfinex(Exchange, ImplicitAPI):
751
751
  'pub:map:currency:explorer', # maps symbols to their recognised block explorer URLs
752
752
  'pub:map:currency:tx:fee', # maps currencies to their withdrawal fees https://github.com/ccxt/ccxt/issues/7745,
753
753
  'pub:map:tx:method', # maps withdrawal/deposit methods to their API symbols
754
+ 'pub:info:tx:status', # maps withdrawal/deposit statuses, coins: 1 = enabled, 0 = maintenance
754
755
  ]
755
756
  config = ','.join(labels)
756
757
  request: dict = {
@@ -833,40 +834,81 @@ class bitfinex(Exchange, ImplicitAPI):
833
834
  # ["ABS",[0,131.3]],
834
835
  # ["ADA",[0,0.3]],
835
836
  # ],
837
+ # # deposit/withdrawal data
838
+ # [
839
+ # ["BITCOIN", 1, 1, null, null, null, null, 0, 0, null, null, 3],
840
+ # ...
841
+ # ]
836
842
  # ]
837
843
  #
838
844
  indexed: dict = {
839
- 'sym': self.index_by(self.safe_value(response, 1, []), 0),
840
- 'label': self.index_by(self.safe_value(response, 2, []), 0),
841
- 'unit': self.index_by(self.safe_value(response, 3, []), 0),
842
- 'undl': self.index_by(self.safe_value(response, 4, []), 0),
843
- 'pool': self.index_by(self.safe_value(response, 5, []), 0),
844
- 'explorer': self.index_by(self.safe_value(response, 6, []), 0),
845
- 'fees': self.index_by(self.safe_value(response, 7, []), 0),
845
+ 'sym': self.index_by(self.safe_list(response, 1, []), 0),
846
+ 'label': self.index_by(self.safe_list(response, 2, []), 0),
847
+ 'unit': self.index_by(self.safe_list(response, 3, []), 0),
848
+ 'undl': self.index_by(self.safe_list(response, 4, []), 0),
849
+ 'pool': self.index_by(self.safe_list(response, 5, []), 0),
850
+ 'explorer': self.index_by(self.safe_list(response, 6, []), 0),
851
+ 'fees': self.index_by(self.safe_list(response, 7, []), 0),
852
+ 'networks': self.safe_list(response, 8, []),
853
+ 'statuses': self.index_by(self.safe_list(response, 9, []), 0),
846
854
  }
847
- ids = self.safe_value(response, 0, [])
855
+ indexedNetworks: dict = {}
856
+ for i in range(0, len(indexed['networks'])):
857
+ networkObj = indexed['networks'][i]
858
+ networkId = self.safe_string(networkObj, 0)
859
+ valuesList = self.safe_list(networkObj, 1)
860
+ networkName = self.safe_string(valuesList, 0)
861
+ # for GOlang transpiler, do with "safe" method
862
+ networksList = self.safe_list(indexedNetworks, networkName, [])
863
+ networksList.append(networkId)
864
+ indexedNetworks[networkName] = networksList
865
+ ids = self.safe_list(response, 0, [])
848
866
  result: dict = {}
849
867
  for i in range(0, len(ids)):
850
868
  id = ids[i]
851
- if id.find('F0') >= 0:
869
+ if id.endswith('F0'):
852
870
  # we get a lot of F0 currencies, skip those
853
871
  continue
854
872
  code = self.safe_currency_code(id)
855
- label = self.safe_value(indexed['label'], id, [])
873
+ label = self.safe_list(indexed['label'], id, [])
856
874
  name = self.safe_string(label, 1)
857
- pool = self.safe_value(indexed['pool'], id, [])
875
+ pool = self.safe_list(indexed['pool'], id, [])
858
876
  rawType = self.safe_string(pool, 1)
859
877
  isCryptoCoin = (rawType is not None) or (id in indexed['explorer']) # "hacky" solution
860
878
  type = None
861
879
  if isCryptoCoin:
862
880
  type = 'crypto'
863
- feeValues = self.safe_value(indexed['fees'], id, [])
864
- fees = self.safe_value(feeValues, 1, [])
881
+ feeValues = self.safe_list(indexed['fees'], id, [])
882
+ fees = self.safe_list(feeValues, 1, [])
865
883
  fee = self.safe_number(fees, 1)
866
- undl = self.safe_value(indexed['undl'], id, [])
884
+ undl = self.safe_list(indexed['undl'], id, [])
867
885
  precision = '8' # default precision, todo: fix "magic constants"
868
886
  fid = 'f' + id
869
- result[code] = {
887
+ dwStatuses = self.safe_list(indexed['statuses'], id, [])
888
+ depositEnabled = self.safe_integer(dwStatuses, 1) == 1
889
+ withdrawEnabled = self.safe_integer(dwStatuses, 2) == 1
890
+ networks: dict = {}
891
+ netwokIds = self.safe_list(indexedNetworks, id, [])
892
+ for j in range(0, len(netwokIds)):
893
+ networkId = netwokIds[j]
894
+ network = self.network_id_to_code(networkId)
895
+ networks[network] = {
896
+ 'info': networkId,
897
+ 'id': networkId.lower(),
898
+ 'network': networkId,
899
+ 'active': None,
900
+ 'deposit': None,
901
+ 'withdraw': None,
902
+ 'fee': None,
903
+ 'precision': None,
904
+ 'limits': {
905
+ 'withdraw': {
906
+ 'min': None,
907
+ 'max': None,
908
+ },
909
+ },
910
+ }
911
+ result[code] = self.safe_currency_structure({
870
912
  'id': fid,
871
913
  'uppercaseId': id,
872
914
  'code': code,
@@ -874,8 +916,8 @@ class bitfinex(Exchange, ImplicitAPI):
874
916
  'type': type,
875
917
  'name': name,
876
918
  'active': True,
877
- 'deposit': None,
878
- 'withdraw': None,
919
+ 'deposit': depositEnabled,
920
+ 'withdraw': withdrawEnabled,
879
921
  'fee': fee,
880
922
  'precision': int(precision),
881
923
  'limits': {
@@ -888,37 +930,8 @@ class bitfinex(Exchange, ImplicitAPI):
888
930
  'max': None,
889
931
  },
890
932
  },
891
- 'networks': {},
892
- }
893
- networks: dict = {}
894
- currencyNetworks = self.safe_value(response, 8, [])
895
- cleanId = id.replace('F0', '')
896
- for j in range(0, len(currencyNetworks)):
897
- pair = currencyNetworks[j]
898
- networkId = self.safe_string(pair, 0)
899
- currencyId = self.safe_string(self.safe_value(pair, 1, []), 0)
900
- if currencyId == cleanId:
901
- network = self.network_id_to_code(networkId)
902
- networks[network] = {
903
- 'info': networkId,
904
- 'id': networkId.lower(),
905
- 'network': networkId,
906
- 'active': None,
907
- 'deposit': None,
908
- 'withdraw': None,
909
- 'fee': None,
910
- 'precision': None,
911
- 'limits': {
912
- 'withdraw': {
913
- 'min': None,
914
- 'max': None,
915
- },
916
- },
917
- }
918
- keysNetworks = list(networks.keys())
919
- networksLength = len(keysNetworks)
920
- if networksLength > 0:
921
- result[code]['networks'] = networks
933
+ 'networks': networks,
934
+ })
922
935
  return result
923
936
 
924
937
  def fetch_balance(self, params={}) -> Balances:
ccxt/bitget.py CHANGED
@@ -3407,6 +3407,7 @@ class bitget(Exchange, ImplicitAPI):
3407
3407
  :param dict [params]: extra parameters specific to the exchange API endpoint
3408
3408
  :param int [params.until]: timestamp in ms of the latest candle to fetch
3409
3409
  :param boolean [params.useHistoryEndpoint]: whether to force to use historical endpoint(it has max limit of 200)
3410
+ :param boolean [params.useHistoryEndpointForPagination]: whether to force to use historical endpoint for pagination(default True)
3410
3411
  :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3411
3412
  :param str [params.price]: *swap only* "mark"(to fetch mark price candles) or "index"(to fetch index price candles)
3412
3413
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
@@ -3415,11 +3416,13 @@ class bitget(Exchange, ImplicitAPI):
3415
3416
  defaultLimit = 100 # default 100, max 1000
3416
3417
  maxLimitForRecentEndpoint = 1000
3417
3418
  maxLimitForHistoryEndpoint = 200 # note, max 1000 bars are supported for "recent-candles" endpoint, but "historical-candles" support only max 200
3419
+ useHistoryEndpoint = self.safe_bool(params, 'useHistoryEndpoint', False)
3420
+ useHistoryEndpointForPagination = self.safe_bool(params, 'useHistoryEndpointForPagination', True)
3418
3421
  paginate = False
3419
3422
  paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate')
3420
3423
  if paginate:
3421
- return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimitForRecentEndpoint)
3422
- useHistoryEndpoint = self.safe_bool(params, 'useHistoryEndpoint', False)
3424
+ limitForPagination = maxLimitForHistoryEndpoint if useHistoryEndpointForPagination else maxLimitForRecentEndpoint
3425
+ return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, limitForPagination)
3423
3426
  market = self.market(symbol)
3424
3427
  marketType = 'spot' if market['spot'] else 'swap'
3425
3428
  timeframes = self.options['timeframes'][marketType]
@@ -4038,6 +4041,7 @@ class bitget(Exchange, ImplicitAPI):
4038
4041
  timestamp = self.safe_integer_2(order, 'cTime', 'ctime')
4039
4042
  updateTimestamp = self.safe_integer(order, 'uTime')
4040
4043
  rawStatus = self.safe_string_2(order, 'status', 'state')
4044
+ rawStatus = self.safe_string(order, 'planStatus', rawStatus)
4041
4045
  fee = None
4042
4046
  feeCostString = self.safe_string(order, 'fee')
4043
4047
  if feeCostString is not None:
ccxt/bybit.py CHANGED
@@ -1704,6 +1704,7 @@ class bybit(Exchange, ImplicitAPI):
1704
1704
  },
1705
1705
  },
1706
1706
  'networks': networks,
1707
+ 'type': 'crypto', # atm exchange api provides only cryptos
1707
1708
  }
1708
1709
  return result
1709
1710
 
@@ -2127,6 +2128,7 @@ class bybit(Exchange, ImplicitAPI):
2127
2128
  strike = self.safe_string(splitId, 2)
2128
2129
  optionLetter = self.safe_string(splitId, 3)
2129
2130
  isActive = (status == 'Trading')
2131
+ isInverse = base == settle
2130
2132
  if isActive or (self.options['loadAllOptions']) or (self.options['loadExpiredOptions']):
2131
2133
  result.append(self.safe_market_structure({
2132
2134
  'id': id,
@@ -2146,8 +2148,8 @@ class bybit(Exchange, ImplicitAPI):
2146
2148
  'option': True,
2147
2149
  'active': isActive,
2148
2150
  'contract': True,
2149
- 'linear': None,
2150
- 'inverse': None,
2151
+ 'linear': not isInverse,
2152
+ 'inverse': isInverse,
2151
2153
  'taker': self.safe_number(market, 'takerFee', self.parse_number('0.0006')),
2152
2154
  'maker': self.safe_number(market, 'makerFee', self.parse_number('0.0001')),
2153
2155
  'contractSize': self.parse_number('1'),
ccxt/htx.py CHANGED
@@ -6945,7 +6945,7 @@ class htx(Exchange, ImplicitAPI):
6945
6945
  if method != 'POST':
6946
6946
  request = self.extend(request, query)
6947
6947
  sortedRequest = self.keysort(request)
6948
- auth = self.urlencode(sortedRequest)
6948
+ auth = self.urlencode(sortedRequest, True) # True is a go only requirment
6949
6949
  # unfortunately, PHP demands double quotes for the escaped newline symbol
6950
6950
  payload = "\n".join([method, self.hostname, url, auth]) # eslint-disable-line quotes
6951
6951
  signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256, 'base64')
@@ -7011,7 +7011,7 @@ class htx(Exchange, ImplicitAPI):
7011
7011
  if method != 'POST':
7012
7012
  sortedQuery = self.keysort(query)
7013
7013
  request = self.extend(request, sortedQuery)
7014
- 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
7015
7015
  # unfortunately, PHP demands double quotes for the escaped newline symbol
7016
7016
  payload = "\n".join([method, hostname, url, auth]) # eslint-disable-line quotes
7017
7017
  signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256, 'base64')
ccxt/hyperliquid.py CHANGED
@@ -2178,6 +2178,10 @@ class hyperliquid(Exchange, ImplicitAPI):
2178
2178
  return self.parse_order(data, market)
2179
2179
 
2180
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'}
2181
2185
  #
2182
2186
  # fetchOpenOrders
2183
2187
  #
@@ -2269,6 +2273,12 @@ class hyperliquid(Exchange, ImplicitAPI):
2269
2273
  # "triggerPx": "0.6"
2270
2274
  # }
2271
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
+ })
2272
2282
  entry = self.safe_dict_n(order, ['order', 'resting', 'filled'])
2273
2283
  if entry is None:
2274
2284
  entry = order
@@ -3444,9 +3454,12 @@ class hyperliquid(Exchange, ImplicitAPI):
3444
3454
  # {"status":"ok","response":{"type":"order","data":{"statuses":[{"error":"Insufficient margin to place order. asset=84"}]}}}
3445
3455
  #
3446
3456
  status = self.safe_string(response, 'status', '')
3457
+ error = self.safe_string(response, 'error')
3447
3458
  message = None
3448
3459
  if status == 'err':
3449
3460
  message = self.safe_string(response, 'response')
3461
+ elif error is not None:
3462
+ message = error
3450
3463
  else:
3451
3464
  responsePayload = self.safe_dict(response, 'response', {})
3452
3465
  data = self.safe_dict(responsePayload, 'data', {})
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': {
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/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.80'
7
+ __version__ = '4.4.82'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10