ccxt 4.2.85__py2.py3-none-any.whl → 4.2.87__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 (84) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/coinex.py +232 -123
  3. ccxt/ascendex.py +16 -6
  4. ccxt/async_support/__init__.py +1 -1
  5. ccxt/async_support/ascendex.py +16 -6
  6. ccxt/async_support/base/exchange.py +1 -1
  7. ccxt/async_support/binance.py +18 -5
  8. ccxt/async_support/bingx.py +72 -22
  9. ccxt/async_support/bitbank.py +19 -21
  10. ccxt/async_support/bitfinex.py +2 -0
  11. ccxt/async_support/bitfinex2.py +18 -4
  12. ccxt/async_support/bitflyer.py +18 -0
  13. ccxt/async_support/bitget.py +20 -6
  14. ccxt/async_support/bitopro.py +2 -0
  15. ccxt/async_support/bitrue.py +16 -8
  16. ccxt/async_support/bitvavo.py +2 -0
  17. ccxt/async_support/btcmarkets.py +1 -1
  18. ccxt/async_support/btcturk.py +2 -1
  19. ccxt/async_support/coinex.py +572 -306
  20. ccxt/async_support/currencycom.py +1 -1
  21. ccxt/async_support/delta.py +8 -6
  22. ccxt/async_support/digifinex.py +9 -7
  23. ccxt/async_support/exmo.py +15 -15
  24. ccxt/async_support/gate.py +9 -6
  25. ccxt/async_support/hitbtc.py +31 -7
  26. ccxt/async_support/htx.py +2 -2
  27. ccxt/async_support/huobijp.py +1 -1
  28. ccxt/async_support/hyperliquid.py +242 -16
  29. ccxt/async_support/idex.py +11 -11
  30. ccxt/async_support/krakenfutures.py +2 -4
  31. ccxt/async_support/kucoinfutures.py +2 -2
  32. ccxt/async_support/lbank.py +2 -0
  33. ccxt/async_support/mexc.py +3 -3
  34. ccxt/async_support/oceanex.py +1 -1
  35. ccxt/async_support/okcoin.py +2 -1
  36. ccxt/async_support/okx.py +29 -15
  37. ccxt/async_support/phemex.py +6 -4
  38. ccxt/async_support/wazirx.py +1 -1
  39. ccxt/async_support/zonda.py +2 -0
  40. ccxt/base/exchange.py +1 -1
  41. ccxt/base/types.py +12 -0
  42. ccxt/binance.py +18 -5
  43. ccxt/bingx.py +72 -22
  44. ccxt/bitbank.py +19 -21
  45. ccxt/bitfinex.py +2 -0
  46. ccxt/bitfinex2.py +18 -4
  47. ccxt/bitflyer.py +18 -0
  48. ccxt/bitget.py +20 -6
  49. ccxt/bitopro.py +2 -0
  50. ccxt/bitrue.py +16 -8
  51. ccxt/bitvavo.py +2 -0
  52. ccxt/btcmarkets.py +1 -1
  53. ccxt/btcturk.py +2 -1
  54. ccxt/coinex.py +572 -306
  55. ccxt/currencycom.py +1 -1
  56. ccxt/delta.py +8 -6
  57. ccxt/digifinex.py +9 -7
  58. ccxt/exmo.py +15 -15
  59. ccxt/gate.py +9 -6
  60. ccxt/hitbtc.py +31 -7
  61. ccxt/htx.py +2 -2
  62. ccxt/huobijp.py +1 -1
  63. ccxt/hyperliquid.py +241 -16
  64. ccxt/idex.py +11 -11
  65. ccxt/krakenfutures.py +2 -4
  66. ccxt/kucoinfutures.py +2 -2
  67. ccxt/lbank.py +2 -0
  68. ccxt/mexc.py +3 -3
  69. ccxt/oceanex.py +1 -1
  70. ccxt/okcoin.py +2 -1
  71. ccxt/okx.py +29 -15
  72. ccxt/phemex.py +6 -4
  73. ccxt/pro/__init__.py +1 -1
  74. ccxt/pro/bitget.py +1 -0
  75. ccxt/pro/kucoin.py +10 -6
  76. ccxt/test/base/test_last_price.py +0 -1
  77. ccxt/test/base/test_shared_methods.py +1 -2
  78. ccxt/test/base/test_status.py +1 -1
  79. ccxt/wazirx.py +1 -1
  80. ccxt/zonda.py +2 -0
  81. {ccxt-4.2.85.dist-info → ccxt-4.2.87.dist-info}/METADATA +6 -6
  82. {ccxt-4.2.85.dist-info → ccxt-4.2.87.dist-info}/RECORD +84 -84
  83. {ccxt-4.2.85.dist-info → ccxt-4.2.87.dist-info}/WHEEL +0 -0
  84. {ccxt-4.2.85.dist-info → ccxt-4.2.87.dist-info}/top_level.txt +0 -0
ccxt/hyperliquid.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.hyperliquid import ImplicitAPI
8
- from ccxt.base.types import Balances, Int, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Trade, TransferEntry
8
+ from ccxt.base.types import Balances, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Trade, TransferEntry
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import ArgumentsRequired
@@ -32,7 +32,7 @@ class hyperliquid(Exchange, ImplicitAPI):
32
32
  'pro': True,
33
33
  'has': {
34
34
  'CORS': None,
35
- 'spot': False,
35
+ 'spot': True,
36
36
  'margin': False,
37
37
  'swap': True,
38
38
  'future': True,
@@ -165,6 +165,10 @@ class hyperliquid(Exchange, ImplicitAPI):
165
165
  'taker': self.parse_number('0.00035'),
166
166
  'maker': self.parse_number('0.0001'),
167
167
  },
168
+ 'spot': {
169
+ 'taker': self.parse_number('0.00035'),
170
+ 'maker': self.parse_number('0.0001'),
171
+ },
168
172
  },
169
173
  'requiredCredentials': {
170
174
  'apiKey': False,
@@ -192,6 +196,7 @@ class hyperliquid(Exchange, ImplicitAPI):
192
196
  'commonCurrencies': {
193
197
  },
194
198
  'options': {
199
+ 'defaultType': 'swap',
195
200
  'sandboxMode': False,
196
201
  'defaultSlippage': 0.05,
197
202
  'zeroAddress': '0x0000000000000000000000000000000000000000',
@@ -257,6 +262,22 @@ class hyperliquid(Exchange, ImplicitAPI):
257
262
  :param dict [params]: extra parameters specific to the exchange API endpoint
258
263
  :returns dict[]: an array of objects representing market data
259
264
  """
265
+ rawPromises = [
266
+ self.fetch_swap_markets(params),
267
+ self.fetch_spot_markets(params),
268
+ ]
269
+ promises = rawPromises
270
+ swapMarkets = promises[0]
271
+ spotMarkets = promises[1]
272
+ return self.array_concat(swapMarkets, spotMarkets)
273
+
274
+ def fetch_swap_markets(self, params={}) -> List[Market]:
275
+ """
276
+ retrieves data on all swap markets for hyperliquid
277
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-asset-contexts-includes-mark-price-current-funding-open-interest-etc
278
+ :param dict [params]: extra parameters specific to the exchange API endpoint
279
+ :returns dict[]: an array of objects representing market data
280
+ """
260
281
  request = {
261
282
  'type': 'metaAndAssetCtxs',
262
283
  }
@@ -304,6 +325,129 @@ class hyperliquid(Exchange, ImplicitAPI):
304
325
  result.append(data)
305
326
  return self.parse_markets(result)
306
327
 
328
+ def fetch_spot_markets(self, params={}) -> List[Market]:
329
+ """
330
+ retrieves data on all spot markets for hyperliquid
331
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-asset-contexts-includes-mark-price-current-funding-open-interest-etc
332
+ :param dict [params]: extra parameters specific to the exchange API endpoint
333
+ :returns dict[]: an array of objects representing market data
334
+ """
335
+ request = {
336
+ 'type': 'spotMetaAndAssetCtxs',
337
+ }
338
+ response = self.publicPostInfo(self.extend(request, params))
339
+ #
340
+ # [
341
+ # {
342
+ # 'tokens': [
343
+ # {
344
+ # 'name': 'USDC',
345
+ # 'szDecimals': '8',
346
+ # 'weiDecimals': '8',
347
+ # },
348
+ # {
349
+ # 'name': 'PURR',
350
+ # 'szDecimals': '0',
351
+ # 'weiDecimals': '5',
352
+ # },
353
+ # ],
354
+ # 'universe': [
355
+ # {
356
+ # 'name': 'PURR/USDC',
357
+ # 'tokens': [
358
+ # 1,
359
+ # 0,
360
+ # ],
361
+ # },
362
+ # ],
363
+ # },
364
+ # [
365
+ # {
366
+ # 'dayNtlVlm': '264250385.14640012',
367
+ # 'markPx': '0.018314',
368
+ # 'midPx': '0.0182235',
369
+ # 'prevDayPx': '0.017427',
370
+ # },
371
+ # ],
372
+ # ]
373
+ #
374
+ first = self.safe_dict(response, 0, {})
375
+ meta = self.safe_list(first, 'universe', [])
376
+ tokens = self.safe_list(first, 'tokens', [])
377
+ markets = []
378
+ for i in range(0, len(meta)):
379
+ market = self.safe_dict(meta, i, {})
380
+ marketName = self.safe_string(market, 'name')
381
+ marketParts = marketName.split('/')
382
+ baseName = self.safe_string(marketParts, 0)
383
+ quoteId = self.safe_string(marketParts, 1)
384
+ base = self.safe_currency_code(baseName)
385
+ quote = self.safe_currency_code(quoteId)
386
+ symbol = base + '/' + quote
387
+ fees = self.safe_dict(self.fees, 'spot', {})
388
+ taker = self.safe_number(fees, 'taker')
389
+ maker = self.safe_number(fees, 'maker')
390
+ tokensPos = self.safe_list(market, 'tokens', [])
391
+ baseTokenPos = self.safe_integer(tokensPos, 0)
392
+ quoteTokenPos = self.safe_integer(tokensPos, 1)
393
+ baseTokenInfo = self.safe_dict(tokens, baseTokenPos, {})
394
+ quoteTokenInfo = self.safe_dict(tokens, quoteTokenPos, {})
395
+ baseDecimals = self.safe_string(baseTokenInfo, 'szDecimals')
396
+ quoteDecimals = self.safe_integer(quoteTokenInfo, 'szDecimals')
397
+ baseId = self.number_to_string(i + 10000)
398
+ markets.append(self.safe_market_structure({
399
+ 'id': baseId,
400
+ 'symbol': symbol,
401
+ 'base': base,
402
+ 'quote': quote,
403
+ 'settle': None,
404
+ 'baseId': baseId,
405
+ 'quoteId': quoteId,
406
+ 'settleId': None,
407
+ 'type': 'spot',
408
+ 'spot': True,
409
+ 'margin': None,
410
+ 'swap': False,
411
+ 'future': False,
412
+ 'option': False,
413
+ 'active': True,
414
+ 'contract': False,
415
+ 'linear': True,
416
+ 'inverse': False,
417
+ 'taker': taker,
418
+ 'maker': maker,
419
+ 'contractSize': None,
420
+ 'expiry': None,
421
+ 'expiryDatetime': None,
422
+ 'strike': None,
423
+ 'optionType': None,
424
+ 'precision': {
425
+ 'amount': self.parse_number(self.parse_precision(baseDecimals)), # decimal places
426
+ 'price': quoteDecimals, # significant digits
427
+ },
428
+ 'limits': {
429
+ 'leverage': {
430
+ 'min': None,
431
+ 'max': None,
432
+ },
433
+ 'amount': {
434
+ 'min': None,
435
+ 'max': None,
436
+ },
437
+ 'price': {
438
+ 'min': None,
439
+ 'max': None,
440
+ },
441
+ 'cost': {
442
+ 'min': None,
443
+ 'max': None,
444
+ },
445
+ },
446
+ 'created': None,
447
+ 'info': market,
448
+ }))
449
+ return markets
450
+
307
451
  def parse_market(self, market) -> Market:
308
452
  #
309
453
  # {
@@ -398,12 +542,17 @@ class hyperliquid(Exchange, ImplicitAPI):
398
542
  :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
399
543
  :param dict [params]: extra parameters specific to the exchange API endpoint
400
544
  :param str [params.user]: user address, will default to self.walletAddress if not provided
545
+ :param str [params.type]: wallet type, ['spot', 'swap'], defaults to swap
401
546
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
402
547
  """
403
548
  userAddress = None
404
549
  userAddress, params = self.handle_public_address('fetchBalance', params)
550
+ type = None
551
+ type, params = self.handle_market_type_and_params('fetchBalance', None, params)
552
+ isSpot = (type == 'spot')
553
+ reqType = 'spotClearinghouseState' if (isSpot) else 'clearinghouseState'
405
554
  request = {
406
- 'type': 'clearinghouseState',
555
+ 'type': reqType,
407
556
  'user': userAddress,
408
557
  }
409
558
  response = self.publicPostInfo(self.extend(request, params))
@@ -426,7 +575,35 @@ class hyperliquid(Exchange, ImplicitAPI):
426
575
  # "time": "1704261007014",
427
576
  # "withdrawable": "100.0"
428
577
  # }
578
+ # spot
579
+ #
580
+ # {
581
+ # "balances":[
582
+ # {
583
+ # "coin":"USDC",
584
+ # "hold":"0.0",
585
+ # "total":"1481.844"
586
+ # },
587
+ # {
588
+ # "coin":"PURR",
589
+ # "hold":"0.0",
590
+ # "total":"999.65004"
591
+ # }
592
+ # }
429
593
  #
594
+ balances = self.safe_list(response, 'balances')
595
+ if balances is not None:
596
+ spotBalances = {'info': response}
597
+ for i in range(0, len(balances)):
598
+ balance = balances[i]
599
+ code = self.safe_currency_code(self.safe_string(balance, 'coin'))
600
+ account = self.account()
601
+ total = self.safe_string(balance, 'total')
602
+ free = self.safe_string(balance, 'hold')
603
+ account['total'] = total
604
+ account['free'] = free
605
+ spotBalances[code] = account
606
+ return self.safe_balance(spotBalances)
430
607
  data = self.safe_dict(response, 'marginSummary', {})
431
608
  result = {
432
609
  'info': response,
@@ -915,6 +1092,7 @@ class hyperliquid(Exchange, ImplicitAPI):
915
1092
  :param str symbol: unified symbol of the market the order was made in
916
1093
  :param dict [params]: extra parameters specific to the exchange API endpoint
917
1094
  :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1095
+ :param str [params.vaultAddress]: the vault address for order
918
1096
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
919
1097
  """
920
1098
  return self.cancel_orders([id], symbol, params)
@@ -928,6 +1106,7 @@ class hyperliquid(Exchange, ImplicitAPI):
928
1106
  :param str [symbol]: unified market symbol
929
1107
  :param dict [params]: extra parameters specific to the exchange API endpoint
930
1108
  :param string|str[] [params.clientOrderId]: client order ids,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1109
+ :param str [params.vaultAddress]: the vault address
931
1110
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
932
1111
  """
933
1112
  self.check_required_credentials()
@@ -1377,7 +1556,10 @@ class hyperliquid(Exchange, ImplicitAPI):
1377
1556
  coin = self.safe_string(entry, 'coin')
1378
1557
  marketId = None
1379
1558
  if coin is not None:
1380
- marketId = coin + '/USDC:USDC'
1559
+ if coin.find('/') > -1:
1560
+ marketId = coin
1561
+ else:
1562
+ marketId = coin + '/USDC:USDC'
1381
1563
  if self.safe_string(entry, 'id') is None:
1382
1564
  market = self.safe_market(marketId, None)
1383
1565
  else:
@@ -1772,7 +1954,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1772
1954
  #
1773
1955
  return response
1774
1956
 
1775
- def add_margin(self, symbol: str, amount, params={}):
1957
+ def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
1776
1958
  """
1777
1959
  add margin
1778
1960
  :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
@@ -1783,7 +1965,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1783
1965
  """
1784
1966
  return self.modify_margin_helper(symbol, amount, 'add', params)
1785
1967
 
1786
- def reduce_margin(self, symbol: str, amount, params={}):
1968
+ def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
1787
1969
  """
1788
1970
  :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
1789
1971
  remove margin from a position
@@ -1794,7 +1976,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1794
1976
  """
1795
1977
  return self.modify_margin_helper(symbol, amount, 'reduce', params)
1796
1978
 
1797
- def modify_margin_helper(self, symbol: str, amount, type, params={}):
1979
+ def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
1798
1980
  self.load_markets()
1799
1981
  market = self.market(symbol)
1800
1982
  asset = self.parse_to_int(market['baseId'])
@@ -1828,10 +2010,27 @@ class hyperliquid(Exchange, ImplicitAPI):
1828
2010
  # 'status': 'ok'
1829
2011
  # }
1830
2012
  #
1831
- return response
1832
- # return self.extend(self.parse_margin_modification(response, market), {
1833
- # 'code': code,
1834
- # })
2013
+ return self.extend(self.parse_margin_modification(response, market), {
2014
+ 'code': self.safe_string(response, 'status'),
2015
+ })
2016
+
2017
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
2018
+ #
2019
+ # {
2020
+ # 'type': 'default'
2021
+ # }
2022
+ #
2023
+ return {
2024
+ 'info': data,
2025
+ 'symbol': self.safe_symbol(None, market),
2026
+ 'type': None,
2027
+ 'amount': None,
2028
+ 'total': None,
2029
+ 'code': self.safe_string(market, 'settle'),
2030
+ 'status': None,
2031
+ 'timestamp': None,
2032
+ 'datetime': None,
2033
+ }
1835
2034
 
1836
2035
  def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
1837
2036
  """
@@ -1839,23 +2038,49 @@ class hyperliquid(Exchange, ImplicitAPI):
1839
2038
  :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#l1-usdc-transfer
1840
2039
  :param str code: unified currency code
1841
2040
  :param float amount: amount to transfer
1842
- :param str fromAccount: account to transfer from
1843
- :param str toAccount: account to transfer to
2041
+ :param str fromAccount: account to transfer from *spot, swap*
2042
+ :param str toAccount: account to transfer to *swap, spot or address*
1844
2043
  :param dict [params]: extra parameters specific to the exchange API endpoint
2044
+ :param str [params.vaultAddress]: the vault address for order
1845
2045
  :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
1846
2046
  """
1847
2047
  self.check_required_credentials()
1848
2048
  self.load_markets()
2049
+ isSandboxMode = self.safe_bool(self.options, 'sandboxMode')
2050
+ nonce = self.milliseconds()
2051
+ if self.in_array(fromAccount, ['spot', 'swap', 'perp']):
2052
+ # handle swap <> spot account transfer
2053
+ if not self.in_array(toAccount, ['spot', 'swap', 'perp']):
2054
+ raise NotSupported(self.id + 'transfer() only support spot <> swap transfer')
2055
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
2056
+ params = self.omit(params, 'vaultAddress')
2057
+ toPerp = (toAccount == 'perp') or (toAccount == 'swap')
2058
+ action = {
2059
+ 'type': 'spotUser',
2060
+ 'classTransfer': {
2061
+ 'usdc': amount,
2062
+ 'toPerp': toPerp,
2063
+ },
2064
+ }
2065
+ signature = self.sign_l1_action(action, nonce, vaultAddress)
2066
+ innerRequest = {
2067
+ 'action': self.extend(action, params),
2068
+ 'nonce': nonce,
2069
+ 'signature': signature,
2070
+ }
2071
+ if vaultAddress is not None:
2072
+ innerRequest['vaultAddress'] = vaultAddress
2073
+ transferResponse = self.privatePostExchange(innerRequest)
2074
+ return transferResponse
2075
+ # handle sub-account/different account transfer
1849
2076
  self.check_address(toAccount)
1850
2077
  if code is not None:
1851
2078
  code = code.upper()
1852
2079
  if code != 'USDC':
1853
2080
  raise NotSupported(self.id + 'withdraw() only support USDC')
1854
- isSandboxMode = self.safe_bool(self.options, 'sandboxMode')
1855
- nonce = self.milliseconds()
1856
2081
  payload = {
1857
2082
  'destination': toAccount,
1858
- 'amount': str(amount),
2083
+ 'amount': self.number_to_string(amount),
1859
2084
  'time': nonce,
1860
2085
  }
1861
2086
  sig = self.build_transfer_sig(payload)
ccxt/idex.py CHANGED
@@ -173,13 +173,15 @@ class idex(Exchange, ImplicitAPI):
173
173
  'network': 'MATIC',
174
174
  },
175
175
  'exceptions': {
176
- 'INVALID_ORDER_QUANTITY': InvalidOrder,
177
- 'INSUFFICIENT_FUNDS': InsufficientFunds,
178
- 'SERVICE_UNAVAILABLE': ExchangeNotAvailable,
179
- 'EXCEEDED_RATE_LIMIT': DDoSProtection,
180
- 'INVALID_PARAMETER': BadRequest,
181
- 'WALLET_NOT_ASSOCIATED': InvalidAddress,
182
- 'INVALID_WALLET_SIGNATURE': AuthenticationError,
176
+ 'exact': {
177
+ 'INVALID_ORDER_QUANTITY': InvalidOrder,
178
+ 'INSUFFICIENT_FUNDS': InsufficientFunds,
179
+ 'SERVICE_UNAVAILABLE': ExchangeNotAvailable,
180
+ 'EXCEEDED_RATE_LIMIT': DDoSProtection,
181
+ 'INVALID_PARAMETER': BadRequest,
182
+ 'WALLET_NOT_ASSOCIATED': InvalidAddress,
183
+ 'INVALID_WALLET_SIGNATURE': AuthenticationError,
184
+ },
183
185
  },
184
186
  'requiredCredentials': {
185
187
  'walletAddress': True,
@@ -461,7 +463,7 @@ class idex(Exchange, ImplicitAPI):
461
463
  if since is not None:
462
464
  request['start'] = since
463
465
  if limit is not None:
464
- request['limit'] = limit
466
+ request['limit'] = min(limit, 1000)
465
467
  response = self.publicGetCandles(self.extend(request, params))
466
468
  if isinstance(response, list):
467
469
  # [
@@ -1413,10 +1415,8 @@ class idex(Exchange, ImplicitAPI):
1413
1415
  def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
1414
1416
  errorCode = self.safe_string(response, 'code')
1415
1417
  message = self.safe_string(response, 'message')
1416
- if errorCode in self.exceptions:
1417
- Exception = self.exceptions[errorCode]
1418
- raise Exception(self.id + ' ' + message)
1419
1418
  if errorCode is not None:
1419
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, message)
1420
1420
  raise ExchangeError(self.id + ' ' + message)
1421
1421
  return None
1422
1422
 
ccxt/krakenfutures.py CHANGED
@@ -635,14 +635,12 @@ class krakenfutures(Exchange, ImplicitAPI):
635
635
  request['from'] = self.parse_to_int(since / 1000)
636
636
  if limit is None:
637
637
  limit = 5000
638
- elif limit > 5000:
639
- raise BadRequest(self.id + ' fetchOHLCV() limit cannot exceed 5000')
638
+ limit = min(limit, 5000)
640
639
  toTimestamp = self.sum(request['from'], limit * duration - 1)
641
640
  currentTimestamp = self.seconds()
642
641
  request['to'] = min(toTimestamp, currentTimestamp)
643
642
  elif limit is not None:
644
- if limit > 5000:
645
- raise BadRequest(self.id + ' fetchOHLCV() limit cannot exceed 5000')
643
+ limit = min(limit, 5000)
646
644
  duration = self.parse_timeframe(timeframe)
647
645
  request['to'] = self.seconds()
648
646
  request['from'] = self.parse_to_int(request['to'] - (duration * limit))
ccxt/kucoinfutures.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.kucoin import kucoin
7
7
  from ccxt.abstract.kucoinfutures import ImplicitAPI
8
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
8
+ from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
9
  from typing import List
10
10
  from ccxt.base.errors import PermissionDenied
11
11
  from ccxt.base.errors import AccountSuspended
@@ -1424,7 +1424,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
1424
1424
  #
1425
1425
  return self.safe_value(response, 'data')
1426
1426
 
1427
- def add_margin(self, symbol: str, amount, params={}):
1427
+ def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
1428
1428
  """
1429
1429
  add margin
1430
1430
  :see: https://www.kucoin.com/docs/rest/futures-trading/positions/add-margin-manually
ccxt/lbank.py CHANGED
@@ -969,6 +969,8 @@ class lbank(Exchange, ImplicitAPI):
969
969
  market = self.market(symbol)
970
970
  if limit is None:
971
971
  limit = 100
972
+ else:
973
+ limit = min(limit, 2000)
972
974
  if since is None:
973
975
  duration = self.parse_timeframe(timeframe)
974
976
  since = self.milliseconds() - duration * 1000 * limit
ccxt/mexc.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.mexc import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Balances, Currency, IndexType, Int, Leverage, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Account, Balances, Currency, IndexType, Int, Leverage, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -3778,7 +3778,7 @@ class mexc(Exchange, ImplicitAPI):
3778
3778
  # }
3779
3779
  return response
3780
3780
 
3781
- def reduce_margin(self, symbol: str, amount, params={}):
3781
+ def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
3782
3782
  """
3783
3783
  remove margin from a position
3784
3784
  :param str symbol: unified market symbol
@@ -3788,7 +3788,7 @@ class mexc(Exchange, ImplicitAPI):
3788
3788
  """
3789
3789
  return self.modify_margin_helper(symbol, amount, 'SUB', params)
3790
3790
 
3791
- def add_margin(self, symbol: str, amount, params={}):
3791
+ def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
3792
3792
  """
3793
3793
  add margin
3794
3794
  :param str symbol: unified market symbol
ccxt/oceanex.py CHANGED
@@ -750,7 +750,7 @@ class oceanex(Exchange, ImplicitAPI):
750
750
  if since is not None:
751
751
  request['timestamp'] = since
752
752
  if limit is not None:
753
- request['limit'] = limit
753
+ request['limit'] = min(limit, 10000)
754
754
  response = self.publicPostK(self.extend(request, params))
755
755
  ohlcvs = self.safe_list(response, 'data', [])
756
756
  return self.parse_ohlcvs(ohlcvs, market, timeframe, since, limit)
ccxt/okcoin.py CHANGED
@@ -1121,8 +1121,9 @@ class okcoin(Exchange, ImplicitAPI):
1121
1121
  request = {
1122
1122
  'instId': market['id'],
1123
1123
  'bar': bar,
1124
- 'limit': limit,
1125
1124
  }
1125
+ if limit is not None:
1126
+ request['limit'] = limit # default 100, max 100
1126
1127
  method = None
1127
1128
  method, params = self.handle_option_and_params(params, 'fetchOHLCV', 'method', 'publicGetMarketCandles')
1128
1129
  response = None
ccxt/okx.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.okx import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Balances, Currency, Greeks, Int, Leverage, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Account, Balances, Currency, Greeks, Int, Leverage, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -6006,7 +6006,7 @@ class okx(Exchange, ImplicitAPI):
6006
6006
  data = self.safe_value(response, 'data')
6007
6007
  return self.parse_borrow_rate_history(data, code, since, limit)
6008
6008
 
6009
- def modify_margin_helper(self, symbol: str, amount, type, params={}):
6009
+ def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
6010
6010
  self.load_markets()
6011
6011
  market = self.market(symbol)
6012
6012
  posSide = self.safe_string(params, 'posSide', 'net')
@@ -6032,29 +6032,43 @@ class okx(Exchange, ImplicitAPI):
6032
6032
  # "msg": ""
6033
6033
  # }
6034
6034
  #
6035
- return self.parse_margin_modification(response, market)
6035
+ data = self.safe_list(response, 'data', [])
6036
+ errorCode = self.safe_string(response, 'code')
6037
+ item = self.safe_dict(data, 0, {})
6038
+ return self.extend(self.parse_margin_modification(item, market), {
6039
+ 'status': 'ok' if (errorCode == '0') else 'failed',
6040
+ })
6036
6041
 
6037
- def parse_margin_modification(self, data, market: Market = None):
6038
- innerData = self.safe_value(data, 'data', [])
6039
- entry = self.safe_value(innerData, 0, {})
6040
- errorCode = self.safe_string(data, 'code')
6041
- status = 'ok' if (errorCode == '0') else 'failed'
6042
- amountRaw = self.safe_number(entry, 'amt')
6043
- typeRaw = self.safe_string(entry, 'type')
6042
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
6043
+ #
6044
+ # addMargin/reduceMargin
6045
+ #
6046
+ # {
6047
+ # "amt": "0.01",
6048
+ # "instId": "ETH-USD-SWAP",
6049
+ # "posSide": "net",
6050
+ # "type": "reduce"
6051
+ # }
6052
+ #
6053
+ amountRaw = self.safe_number(data, 'amt')
6054
+ typeRaw = self.safe_string(data, 'type')
6044
6055
  type = 'reduce' if (typeRaw == 'reduce') else 'add'
6045
- marketId = self.safe_string(entry, 'instId')
6056
+ marketId = self.safe_string(data, 'instId')
6046
6057
  responseMarket = self.safe_market(marketId, market)
6047
6058
  code = responseMarket['base'] if responseMarket['inverse'] else responseMarket['quote']
6048
6059
  return {
6049
6060
  'info': data,
6061
+ 'symbol': responseMarket['symbol'],
6050
6062
  'type': type,
6051
6063
  'amount': amountRaw,
6064
+ 'total': None,
6052
6065
  'code': code,
6053
- 'symbol': responseMarket['symbol'],
6054
- 'status': status,
6066
+ 'status': None,
6067
+ 'timestamp': None,
6068
+ 'datetime': None,
6055
6069
  }
6056
6070
 
6057
- def reduce_margin(self, symbol: str, amount, params={}):
6071
+ def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
6058
6072
  """
6059
6073
  remove margin from a position
6060
6074
  :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-increase-decrease-margin
@@ -6065,7 +6079,7 @@ class okx(Exchange, ImplicitAPI):
6065
6079
  """
6066
6080
  return self.modify_margin_helper(symbol, amount, 'reduce', params)
6067
6081
 
6068
- def add_margin(self, symbol: str, amount, params={}):
6082
+ def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
6069
6083
  """
6070
6084
  add margin
6071
6085
  :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-increase-decrease-margin
ccxt/phemex.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.phemex import ImplicitAPI
8
8
  import hashlib
9
9
  import numbers
10
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -3744,7 +3744,7 @@ class phemex(Exchange, ImplicitAPI):
3744
3744
  'previousFundingDatetime': None,
3745
3745
  }
3746
3746
 
3747
- def set_margin(self, symbol: str, amount: float, params={}):
3747
+ def set_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3748
3748
  """
3749
3749
  Either adds or reduces margin in an isolated position in order to set the margin to a specific value
3750
3750
  :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#assign-position-balance-in-isolated-marign-mode
@@ -3777,7 +3777,7 @@ class phemex(Exchange, ImplicitAPI):
3777
3777
  }
3778
3778
  return self.safe_string(statuses, status, status)
3779
3779
 
3780
- def parse_margin_modification(self, data, market: Market = None):
3780
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
3781
3781
  #
3782
3782
  # {
3783
3783
  # "code": 0,
@@ -3790,12 +3790,14 @@ class phemex(Exchange, ImplicitAPI):
3790
3790
  codeCurrency = 'base' if inverse else 'quote'
3791
3791
  return {
3792
3792
  'info': data,
3793
+ 'symbol': self.safe_symbol(None, market),
3793
3794
  'type': 'set',
3794
3795
  'amount': None,
3795
3796
  'total': None,
3796
3797
  'code': market[codeCurrency],
3797
- 'symbol': self.safe_symbol(None, market),
3798
3798
  'status': self.parse_margin_status(self.safe_string(data, 'code')),
3799
+ 'timestamp': None,
3800
+ 'datetime': None,
3799
3801
  }
3800
3802
 
3801
3803
  def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.85'
7
+ __version__ = '4.2.87'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10