ccxt 4.4.49__py2.py3-none-any.whl → 4.4.51__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 (71) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/binance.py +1 -0
  3. ccxt/abstract/binancecoinm.py +1 -0
  4. ccxt/abstract/binanceus.py +1 -0
  5. ccxt/abstract/binanceusdm.py +1 -0
  6. ccxt/alpaca.py +63 -2
  7. ccxt/async_support/__init__.py +1 -1
  8. ccxt/async_support/alpaca.py +63 -2
  9. ccxt/async_support/base/exchange.py +1 -1
  10. ccxt/async_support/binance.py +39 -20
  11. ccxt/async_support/blofin.py +5 -1
  12. ccxt/async_support/coinex.py +4 -4
  13. ccxt/async_support/coinmetro.py +16 -3
  14. ccxt/async_support/deribit.py +11 -3
  15. ccxt/async_support/gate.py +1 -1
  16. ccxt/async_support/hollaex.py +14 -17
  17. ccxt/async_support/htx.py +5 -3
  18. ccxt/async_support/kucoin.py +49 -69
  19. ccxt/async_support/mexc.py +24 -8
  20. ccxt/async_support/okcoin.py +13 -5
  21. ccxt/async_support/onetrading.py +1 -1
  22. ccxt/async_support/paradex.py +1 -1
  23. ccxt/async_support/paymium.py +42 -0
  24. ccxt/async_support/probit.py +77 -8
  25. ccxt/async_support/timex.py +67 -0
  26. ccxt/async_support/tokocrypto.py +81 -4
  27. ccxt/async_support/tradeogre.py +58 -1
  28. ccxt/async_support/vertex.py +65 -2
  29. ccxt/async_support/wavesexchange.py +73 -0
  30. ccxt/async_support/wazirx.py +59 -3
  31. ccxt/async_support/whitebit.py +79 -4
  32. ccxt/async_support/xt.py +112 -0
  33. ccxt/async_support/yobit.py +56 -0
  34. ccxt/async_support/zaif.py +55 -0
  35. ccxt/async_support/zonda.py +58 -0
  36. ccxt/base/exchange.py +72 -4
  37. ccxt/binance.py +39 -20
  38. ccxt/blofin.py +5 -1
  39. ccxt/coinex.py +4 -4
  40. ccxt/coinmetro.py +16 -3
  41. ccxt/deribit.py +11 -3
  42. ccxt/gate.py +1 -1
  43. ccxt/hollaex.py +14 -17
  44. ccxt/htx.py +5 -3
  45. ccxt/kucoin.py +49 -69
  46. ccxt/mexc.py +24 -8
  47. ccxt/okcoin.py +13 -5
  48. ccxt/onetrading.py +1 -1
  49. ccxt/paradex.py +1 -1
  50. ccxt/paymium.py +42 -0
  51. ccxt/pro/__init__.py +1 -1
  52. ccxt/pro/binance.py +2 -0
  53. ccxt/pro/blofin.py +8 -0
  54. ccxt/pro/coinex.py +4 -1
  55. ccxt/probit.py +77 -8
  56. ccxt/timex.py +67 -0
  57. ccxt/tokocrypto.py +81 -4
  58. ccxt/tradeogre.py +58 -1
  59. ccxt/vertex.py +65 -2
  60. ccxt/wavesexchange.py +73 -0
  61. ccxt/wazirx.py +59 -3
  62. ccxt/whitebit.py +79 -4
  63. ccxt/xt.py +112 -0
  64. ccxt/yobit.py +56 -0
  65. ccxt/zaif.py +55 -0
  66. ccxt/zonda.py +58 -0
  67. {ccxt-4.4.49.dist-info → ccxt-4.4.51.dist-info}/METADATA +18 -18
  68. {ccxt-4.4.49.dist-info → ccxt-4.4.51.dist-info}/RECORD +71 -71
  69. {ccxt-4.4.49.dist-info → ccxt-4.4.51.dist-info}/WHEEL +1 -1
  70. {ccxt-4.4.49.dist-info → ccxt-4.4.51.dist-info}/LICENSE.txt +0 -0
  71. {ccxt-4.4.49.dist-info → ccxt-4.4.51.dist-info}/top_level.txt +0 -0
ccxt/coinmetro.py CHANGED
@@ -219,7 +219,7 @@ class coinmetro(Exchange, ImplicitAPI):
219
219
  # exchange-specific options
220
220
  'options': {
221
221
  'currenciesByIdForParseMarket': None,
222
- 'currencyIdsListForParseMarket': None,
222
+ 'currencyIdsListForParseMarket': ['QRDO'],
223
223
  },
224
224
  'features': {
225
225
  'spot': {
@@ -407,7 +407,11 @@ class coinmetro(Exchange, ImplicitAPI):
407
407
  if self.safe_value(self.options, 'currenciesByIdForParseMarket') is None:
408
408
  currenciesById = self.index_by(result, 'id')
409
409
  self.options['currenciesByIdForParseMarket'] = currenciesById
410
- self.options['currencyIdsListForParseMarket'] = list(currenciesById.keys())
410
+ currentCurrencyIdsList = self.safe_list(self.options, 'currencyIdsListForParseMarket', [])
411
+ currencyIdsList = list(currenciesById.keys())
412
+ for i in range(0, len(currencyIdsList)):
413
+ currentCurrencyIdsList.append(currencyIdsList[i])
414
+ self.options['currencyIdsListForParseMarket'] = currentCurrencyIdsList
411
415
  return result
412
416
 
413
417
  def fetch_markets(self, params={}) -> List[Market]:
@@ -506,10 +510,19 @@ class coinmetro(Exchange, ImplicitAPI):
506
510
  baseId = None
507
511
  quoteId = None
508
512
  currencyIds = self.safe_value(self.options, 'currencyIdsListForParseMarket', [])
513
+ # Bubble sort by length(longest first)
514
+ currencyIdsLength = len(currencyIds)
515
+ for i in range(0, currencyIdsLength):
516
+ for j in range(0, currencyIdsLength - i - 1):
517
+ a = currencyIds[j]
518
+ b = currencyIds[j + 1]
519
+ if len(a) < len(b):
520
+ currencyIds[j] = b
521
+ currencyIds[j + 1] = a
509
522
  for i in range(0, len(currencyIds)):
510
523
  currencyId = currencyIds[i]
511
524
  entryIndex = marketId.find(currencyId)
512
- if entryIndex != -1:
525
+ if entryIndex == 0:
513
526
  restId = marketId.replace(currencyId, '')
514
527
  if self.in_array(restId, currencyIds):
515
528
  if entryIndex == 0:
ccxt/deribit.py CHANGED
@@ -3063,7 +3063,7 @@ class deribit(Exchange, ImplicitAPI):
3063
3063
  :param int [since]: the earliest time in ms to fetch funding rate history for
3064
3064
  :param int [limit]: the maximum number of entries to retrieve
3065
3065
  :param dict [params]: extra parameters specific to the exchange API endpoint
3066
- :param int [params.end_timestamp]: fetch funding rate ending at self timestamp
3066
+ :param int [params.until]: fetch funding rate ending at self timestamp
3067
3067
  :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3068
3068
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
3069
3069
  """
@@ -3072,16 +3072,24 @@ class deribit(Exchange, ImplicitAPI):
3072
3072
  paginate = False
3073
3073
  paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
3074
3074
  if paginate:
3075
- return self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params, 720)
3075
+ # 1h needed to fix : https://github.com/ccxt/ccxt/issues/25040
3076
+ return self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '1h', params, 720)
3076
3077
  time = self.milliseconds()
3077
3078
  month = 30 * 24 * 60 * 60 * 1000
3078
3079
  if since is None:
3079
3080
  since = time - month
3081
+ else:
3082
+ time = since + month
3080
3083
  request: dict = {
3081
3084
  'instrument_name': market['id'],
3082
3085
  'start_timestamp': since - 1,
3083
- 'end_timestamp': time,
3084
3086
  }
3087
+ until = self.safe_integer_2(params, 'until', 'end_timestamp')
3088
+ if until is not None:
3089
+ params = self.omit(params, ['until'])
3090
+ request['end_timestamp'] = until
3091
+ else:
3092
+ request['end_timestamp'] = time
3085
3093
  response = self.publicGetGetFundingRateHistory(self.extend(request, params))
3086
3094
  #
3087
3095
  # {
ccxt/gate.py CHANGED
@@ -1791,7 +1791,7 @@ class gate(Exchange, ImplicitAPI):
1791
1791
  active = listed and tradeEnabled and withdrawEnabled and depositEnabled
1792
1792
  if self.safe_value(result, code) is None:
1793
1793
  result[code] = {
1794
- 'id': code.lower(),
1794
+ 'id': currency,
1795
1795
  'code': code,
1796
1796
  'info': None,
1797
1797
  'name': None,
ccxt/hollaex.py CHANGED
@@ -829,7 +829,7 @@ class hollaex(Exchange, ImplicitAPI):
829
829
 
830
830
  def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
831
831
  """
832
- fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
832
+ hollaex has large gaps between candles, so it's recommended to specify since
833
833
 
834
834
  https://apidocs.hollaex.com/#chart
835
835
 
@@ -838,6 +838,7 @@ class hollaex(Exchange, ImplicitAPI):
838
838
  :param int [since]: timestamp in ms of the earliest candle to fetch
839
839
  :param int [limit]: the maximum amount of candles to fetch
840
840
  :param dict [params]: extra parameters specific to the exchange API endpoint
841
+ :param int [params.until]: timestamp in ms of the latest candle to fetch
841
842
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
842
843
  """
843
844
  self.load_markets()
@@ -846,22 +847,17 @@ class hollaex(Exchange, ImplicitAPI):
846
847
  'symbol': market['id'],
847
848
  'resolution': self.safe_string(self.timeframes, timeframe, timeframe),
848
849
  }
849
- duration = self.parse_timeframe(timeframe)
850
- if since is None:
851
- if limit is None:
852
- limit = 1000 # they have no defaults and can actually provide tens of thousands of bars in one request, but we should cap "default" at generous amount
853
- end = self.seconds()
854
- start = end - duration * limit
855
- request['to'] = end
856
- request['from'] = start
850
+ until = self.safe_integer(params, 'until')
851
+ end = self.seconds()
852
+ if until is not None:
853
+ end = self.parse_to_int(until / 1000)
854
+ defaultSpan = 2592000 # 30 days
855
+ if since is not None:
856
+ request['from'] = self.parse_to_int(since / 1000)
857
857
  else:
858
- if limit is None:
859
- request['from'] = self.parse_to_int(since / 1000)
860
- request['to'] = self.seconds()
861
- else:
862
- start = self.parse_to_int(since / 1000)
863
- request['from'] = start
864
- request['to'] = self.sum(start, duration * limit)
858
+ request['from'] = end - defaultSpan
859
+ request['to'] = end
860
+ params = self.omit(params, 'until')
865
861
  response = self.publicGetChart(self.extend(request, params))
866
862
  #
867
863
  # [
@@ -1916,13 +1912,14 @@ class hollaex(Exchange, ImplicitAPI):
1916
1912
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
1917
1913
 
1918
1914
  def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
1915
+ # {"message": "Invalid token"}
1919
1916
  if response is None:
1920
1917
  return None
1921
1918
  if (code >= 400) and (code <= 503):
1922
1919
  #
1923
1920
  # {"message": "Invalid token"}
1924
1921
  #
1925
- # different errors return the same code eg:
1922
+ # different errors return the same code eg
1926
1923
  #
1927
1924
  # {"message":"Error 1001 - Order rejected. Order could not be submitted order was set to a post only order."}
1928
1925
  #
ccxt/htx.py CHANGED
@@ -6991,10 +6991,12 @@ class htx(Exchange, ImplicitAPI):
6991
6991
  'AccessKeyId': self.apiKey,
6992
6992
  'Timestamp': timestamp,
6993
6993
  }
6994
- if method != 'POST':
6995
- request = self.extend(request, query)
6994
+ # sorting needs such flow exactly, before urlencoding(more at: https://github.com/ccxt/ccxt/issues/24930 )
6996
6995
  request = self.keysort(request)
6997
- auth = self.urlencode(request)
6996
+ if method != 'POST':
6997
+ sortedQuery = self.keysort(query)
6998
+ request = self.extend(request, sortedQuery)
6999
+ auth = self.urlencode(request).replace('%2c', '%2C') # in c# it manually needs to be uppercased
6998
7000
  # unfortunately, PHP demands double quotes for the escaped newline symbol
6999
7001
  payload = "\n".join([method, hostname, url, auth]) # eslint-disable-line quotes
7000
7002
  signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256, 'base64')
ccxt/kucoin.py CHANGED
@@ -1351,8 +1351,7 @@ class kucoin(Exchange, ImplicitAPI):
1351
1351
  :param dict params: extra parameters specific to the exchange API endpoint
1352
1352
  :returns dict: an associative dictionary of currencies
1353
1353
  """
1354
- promises = []
1355
- promises.append(self.publicGetCurrencies(params))
1354
+ response = self.publicGetCurrencies(params)
1356
1355
  #
1357
1356
  # {
1358
1357
  # "code":"200000",
@@ -1378,87 +1377,39 @@ class kucoin(Exchange, ImplicitAPI):
1378
1377
  # "isDepositEnabled":false,
1379
1378
  # "confirms":12,
1380
1379
  # "preConfirms":12,
1380
+ # "withdrawPrecision": 8,
1381
+ # "maxWithdraw": null,
1382
+ # "maxDeposit": null,
1383
+ # "needTag": False,
1381
1384
  # "contractAddress":"0xa6446d655a0c34bc4f05042ee88170d056cbaf45",
1382
1385
  # "depositFeeRate": "0.001", # present for some currencies/networks
1383
1386
  # }
1384
1387
  # ]
1385
1388
  # },
1386
- # }
1387
- #
1388
- promises.append(self.fetch_web_endpoint('fetchCurrencies', 'webExchangeGetCurrencyCurrencyChainInfo', True))
1389
- #
1390
- # {
1391
- # "success": True,
1392
- # "code": "200",
1393
- # "msg": "success",
1394
- # "retry": False,
1395
- # "data": [
1396
- # {
1397
- # "status": "enabled",
1398
- # "currency": "BTC",
1399
- # "isChainEnabled": "true",
1400
- # "chain": "btc",
1401
- # "chainName": "BTC",
1402
- # "chainFullName": "Bitcoin",
1403
- # "walletPrecision": "8",
1404
- # "isDepositEnabled": "true",
1405
- # "depositMinSize": "0.00005",
1406
- # "confirmationCount": "2",
1407
- # "isWithdrawEnabled": "true",
1408
- # "withdrawMinSize": "0.001",
1409
- # "withdrawMinFee": "0.0005",
1410
- # "withdrawFeeRate": "0",
1411
- # "depositDisabledTip": "Wallet Maintenance",
1412
- # "preDepositTipEnabled": "true",
1413
- # "preDepositTip": "Do not transfer from ETH network directly",
1414
- # "withdrawDisabledTip": "",
1415
- # "preWithdrawTipEnabled": "false",
1416
- # "preWithdrawTip": "",
1417
- # "orgAddress": "",
1418
- # "userAddressName": "Memo",
1419
- # },
1420
1389
  # ]
1421
1390
  # }
1422
1391
  #
1423
- responses = promises
1424
- currenciesResponse = self.safe_dict(responses, 0, {})
1425
- currenciesData = self.safe_list(currenciesResponse, 'data', [])
1426
- additionalResponse = self.safe_dict(responses, 1, {})
1427
- additionalData = self.safe_list(additionalResponse, 'data', [])
1428
- additionalDataGrouped = self.group_by(additionalData, 'currency')
1392
+ currenciesData = self.safe_list(response, 'data', [])
1429
1393
  result: dict = {}
1430
1394
  for i in range(0, len(currenciesData)):
1431
1395
  entry = currenciesData[i]
1432
1396
  id = self.safe_string(entry, 'currency')
1433
1397
  name = self.safe_string(entry, 'fullName')
1434
1398
  code = self.safe_currency_code(id)
1435
- isWithdrawEnabled = None
1436
- isDepositEnabled = None
1437
1399
  networks: dict = {}
1438
1400
  chains = self.safe_list(entry, 'chains', [])
1439
- extraChainsData = self.index_by(self.safe_list(additionalDataGrouped, id, []), 'chain')
1440
1401
  rawPrecision = self.safe_string(entry, 'precision')
1441
1402
  precision = self.parse_number(self.parse_precision(rawPrecision))
1442
1403
  chainsLength = len(chains)
1443
1404
  if not chainsLength:
1444
- # https://t.me/KuCoin_API/173118
1445
- isWithdrawEnabled = False
1446
- isDepositEnabled = False
1405
+ # one buggy coin, which doesn't contain info https://t.me/KuCoin_API/173118
1406
+ continue
1447
1407
  for j in range(0, chainsLength):
1448
1408
  chain = chains[j]
1449
1409
  chainId = self.safe_string(chain, 'chainId')
1450
1410
  networkCode = self.network_id_to_code(chainId, code)
1451
1411
  chainWithdrawEnabled = self.safe_bool(chain, 'isWithdrawEnabled', False)
1452
- if isWithdrawEnabled is None:
1453
- isWithdrawEnabled = chainWithdrawEnabled
1454
- else:
1455
- isWithdrawEnabled = isWithdrawEnabled or chainWithdrawEnabled
1456
1412
  chainDepositEnabled = self.safe_bool(chain, 'isDepositEnabled', False)
1457
- if isDepositEnabled is None:
1458
- isDepositEnabled = chainDepositEnabled
1459
- else:
1460
- isDepositEnabled = isDepositEnabled or chainDepositEnabled
1461
- chainExtraData = self.safe_dict(extraChainsData, chainId, {})
1462
1413
  networks[networkCode] = {
1463
1414
  'info': chain,
1464
1415
  'id': chainId,
@@ -1468,34 +1419,34 @@ class kucoin(Exchange, ImplicitAPI):
1468
1419
  'fee': self.safe_number(chain, 'withdrawalMinFee'),
1469
1420
  'deposit': chainDepositEnabled,
1470
1421
  'withdraw': chainWithdrawEnabled,
1471
- 'precision': self.parse_number(self.parse_precision(self.safe_string(chainExtraData, 'walletPrecision'))),
1422
+ 'precision': self.parse_number(self.parse_precision(self.safe_string(chain, 'withdrawPrecision'))),
1472
1423
  'limits': {
1473
1424
  'withdraw': {
1474
1425
  'min': self.safe_number(chain, 'withdrawalMinSize'),
1475
- 'max': None,
1426
+ 'max': self.safe_number(chain, 'maxWithdraw'),
1476
1427
  },
1477
1428
  'deposit': {
1478
1429
  'min': self.safe_number(chain, 'depositMinSize'),
1479
- 'max': None,
1430
+ 'max': self.safe_number(chain, 'maxDeposit'),
1480
1431
  },
1481
1432
  },
1482
1433
  }
1483
1434
  # kucoin has determined 'fiat' currencies with below logic
1484
1435
  isFiat = (rawPrecision == '2') and (chainsLength == 0)
1485
- result[code] = {
1436
+ result[code] = self.safe_currency_structure({
1486
1437
  'id': id,
1487
1438
  'name': name,
1488
1439
  'code': code,
1489
1440
  'type': 'fiat' if isFiat else 'crypto',
1490
1441
  'precision': precision,
1491
1442
  'info': entry,
1492
- 'active': (isDepositEnabled or isWithdrawEnabled),
1493
- 'deposit': isDepositEnabled,
1494
- 'withdraw': isWithdrawEnabled,
1495
- 'fee': None,
1496
- 'limits': self.limits,
1497
1443
  'networks': networks,
1498
- }
1444
+ 'deposit': None,
1445
+ 'withdraw': None,
1446
+ 'active': None,
1447
+ 'fee': None,
1448
+ 'limits': None,
1449
+ })
1499
1450
  return result
1500
1451
 
1501
1452
  def fetch_accounts(self, params={}) -> List[Account]:
@@ -1635,6 +1586,35 @@ class kucoin(Exchange, ImplicitAPI):
1635
1586
  # "chain": "ERC20"
1636
1587
  # }
1637
1588
  #
1589
+ if 'chains' in fee:
1590
+ # if data obtained through `currencies` endpoint
1591
+ resultNew: dict = {
1592
+ 'info': fee,
1593
+ 'withdraw': {
1594
+ 'fee': None,
1595
+ 'percentage': False,
1596
+ },
1597
+ 'deposit': {
1598
+ 'fee': None,
1599
+ 'percentage': None,
1600
+ },
1601
+ 'networks': {},
1602
+ }
1603
+ chains = self.safe_list(fee, 'chains', [])
1604
+ for i in range(0, len(chains)):
1605
+ chain = chains[i]
1606
+ networkCodeNew = self.network_id_to_code(self.safe_string(chain, 'chainId'), self.safe_string(currency, 'code'))
1607
+ resultNew['networks'][networkCodeNew] = {
1608
+ 'withdraw': {
1609
+ 'fee': self.safe_number(chain, 'withdrawMinFee'),
1610
+ 'percentage': False,
1611
+ },
1612
+ 'deposit': {
1613
+ 'fee': None,
1614
+ 'percentage': None,
1615
+ },
1616
+ }
1617
+ return resultNew
1638
1618
  minWithdrawFee = self.safe_number(fee, 'withdrawMinFee')
1639
1619
  result: dict = {
1640
1620
  'info': fee,
@@ -3120,14 +3100,14 @@ class kucoin(Exchange, ImplicitAPI):
3120
3100
  if symbol is not None:
3121
3101
  market = self.market(symbol)
3122
3102
  request['symbol'] = market['id']
3123
- if limit is not None:
3124
- request['pageSize'] = limit
3125
3103
  method = self.options['fetchMyTradesMethod']
3126
3104
  parseResponseData = False
3127
3105
  response = None
3128
3106
  request, params = self.handle_until_option('endAt', request, params)
3129
3107
  if hf:
3130
3108
  # does not return trades earlier than 2019-02-18T00:00:00Z
3109
+ if limit is not None:
3110
+ request['limit'] = limit
3131
3111
  if since is not None:
3132
3112
  # only returns trades up to one week after the since param
3133
3113
  request['startAt'] = since
ccxt/mexc.py CHANGED
@@ -1379,6 +1379,7 @@ class mexc(Exchange, ImplicitAPI):
1379
1379
  quote = self.safe_currency_code(quoteId)
1380
1380
  settle = self.safe_currency_code(settleId)
1381
1381
  state = self.safe_string(market, 'state')
1382
+ isLinear = quote == settle
1382
1383
  result.append({
1383
1384
  'id': id,
1384
1385
  'symbol': base + '/' + quote + ':' + settle,
@@ -1396,8 +1397,8 @@ class mexc(Exchange, ImplicitAPI):
1396
1397
  'option': False,
1397
1398
  'active': (state == '0'),
1398
1399
  'contract': True,
1399
- 'linear': True,
1400
- 'inverse': False,
1400
+ 'linear': isLinear,
1401
+ 'inverse': not isLinear,
1401
1402
  'taker': self.safe_number(market, 'takerFeeRate'),
1402
1403
  'maker': self.safe_number(market, 'makerFeeRate'),
1403
1404
  'contractSize': self.safe_number(market, 'contractSize'),
@@ -2233,7 +2234,7 @@ class mexc(Exchange, ImplicitAPI):
2233
2234
  :param bool [params.postOnly]: if True, the order will only be posted if it will be a maker order
2234
2235
  :param bool [params.reduceOnly]: *contract only* indicates if self order is to reduce the size of a position
2235
2236
  :param bool [params.hedged]: *swap only* True for hedged mode, False for one way mode, default is False
2236
-
2237
+ :param str [params.timeInForce]: 'IOC' or 'FOK', default is 'GTC'
2237
2238
  EXCHANGE SPECIFIC PARAMETERS
2238
2239
  :param int [params.leverage]: *contract only* leverage is necessary on isolated margin
2239
2240
  :param long [params.positionId]: *contract only* it is recommended to hasattr(self, fill) parameter when closing a position
@@ -2288,6 +2289,13 @@ class mexc(Exchange, ImplicitAPI):
2288
2289
  postOnly, params = self.handle_post_only(type == 'market', type == 'LIMIT_MAKER', params)
2289
2290
  if postOnly:
2290
2291
  request['type'] = 'LIMIT_MAKER'
2292
+ tif = self.safe_string(params, 'timeInForce')
2293
+ if tif is not None:
2294
+ params = self.omit(params, 'timeInForce')
2295
+ if tif == 'IOC':
2296
+ request['type'] = 'IMMEDIATE_OR_CANCEL'
2297
+ elif tif == 'FOK':
2298
+ request['type'] = 'FILL_OR_KILL'
2291
2299
  return self.extend(request, params)
2292
2300
 
2293
2301
  def create_spot_order(self, market, type, side, amount, price=None, marginMode=None, params={}):
@@ -5707,12 +5715,20 @@ class mexc(Exchange, ImplicitAPI):
5707
5715
  url = self.urls['api'][section][access] + '/' + path
5708
5716
  else:
5709
5717
  url = self.urls['api'][section][access] + '/api/' + self.version + '/' + path
5710
- paramsEncoded = ''
5718
+ urlParams = params
5711
5719
  if access == 'private':
5712
- params['timestamp'] = self.nonce()
5713
- params['recvWindow'] = self.safe_integer(self.options, 'recvWindow', 5000)
5714
- if params:
5715
- paramsEncoded = self.urlencode(params)
5720
+ if section == 'broker' and ((method == 'POST') or (method == 'PUT') or (method == 'DELETE')):
5721
+ urlParams = {
5722
+ 'timestamp': self.nonce(),
5723
+ 'recvWindow': self.safe_integer(self.options, 'recvWindow', 5000),
5724
+ }
5725
+ body = self.json(params)
5726
+ else:
5727
+ urlParams['timestamp'] = self.nonce()
5728
+ urlParams['recvWindow'] = self.safe_integer(self.options, 'recvWindow', 5000)
5729
+ paramsEncoded = ''
5730
+ if urlParams:
5731
+ paramsEncoded = self.urlencode(urlParams)
5716
5732
  url += '?' + paramsEncoded
5717
5733
  if access == 'private':
5718
5734
  self.check_required_credentials()
ccxt/okcoin.py CHANGED
@@ -707,12 +707,20 @@ class okcoin(Exchange, ImplicitAPI):
707
707
  """
708
708
  response = self.publicGetPublicTime(params)
709
709
  #
710
- # {
711
- # "iso": "2015-01-07T23:47:25.201Z",
712
- # "epoch": 1420674445.201
713
- # }
710
+ # {
711
+ # "code": "0",
712
+ # "data":
713
+ # [
714
+ # {
715
+ # "ts": "1737379360033"
716
+ # }
717
+ # ],
718
+ # "msg": ""
719
+ # }
714
720
  #
715
- return self.parse8601(self.safe_string(response, 'iso'))
721
+ data = self.safe_list(response, 'data')
722
+ timestamp = self.safe_dict(data, 0)
723
+ return self.safe_integer(timestamp, 'ts')
716
724
 
717
725
  def fetch_markets(self, params={}) -> List[Market]:
718
726
  """
ccxt/onetrading.py CHANGED
@@ -1200,7 +1200,7 @@ class onetrading(Exchange, ImplicitAPI):
1200
1200
  https://docs.onetrading.com/#create-order
1201
1201
 
1202
1202
  :param str symbol: unified symbol of the market to create an order in
1203
- :param str type: 'market' or 'limit'
1203
+ :param str type: 'limit'
1204
1204
  :param str side: 'buy' or 'sell'
1205
1205
  :param float amount: how much of currency you want to trade in units of base currency
1206
1206
  :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
ccxt/paradex.py CHANGED
@@ -943,7 +943,7 @@ class paradex(Exchange, ImplicitAPI):
943
943
  #
944
944
  # {
945
945
  # "symbol": "BTC-USD-PERP",
946
- # "oracle_price": "68465.17449906",
946
+ # "oracle_price": "68465.17449904",
947
947
  # "mark_price": "68465.17449906",
948
948
  # "last_traded_price": "68495.1",
949
949
  # "bid": "68477.6",
ccxt/paymium.py CHANGED
@@ -113,6 +113,48 @@ class paymium(Exchange, ImplicitAPI):
113
113
  },
114
114
  },
115
115
  'precisionMode': TICK_SIZE,
116
+ 'features': {
117
+ 'spot': {
118
+ 'sandbox': False,
119
+ 'createOrder': {
120
+ 'marginMode': False,
121
+ 'triggerPrice': False,
122
+ 'triggerDirection': False,
123
+ 'triggerPriceType': None,
124
+ 'stopLossPrice': False,
125
+ 'takeProfitPrice': False,
126
+ 'attachedStopLossTakeProfit': None,
127
+ 'timeInForce': {
128
+ 'IOC': False,
129
+ 'FOK': False,
130
+ 'PO': False,
131
+ 'GTD': False,
132
+ },
133
+ 'hedged': False,
134
+ 'trailing': False,
135
+ 'leverage': False,
136
+ 'marketBuyByCost': True, # todo
137
+ 'marketBuyRequiresPrice': False,
138
+ 'selfTradePrevention': False,
139
+ 'iceberg': False,
140
+ },
141
+ 'createOrders': None,
142
+ 'fetchMyTrades': None,
143
+ 'fetchOrder': None, # todo
144
+ 'fetchOpenOrders': None, # todo
145
+ 'fetchOrders': None, # todo
146
+ 'fetchClosedOrders': None, # todo
147
+ 'fetchOHLCV': None, # todo
148
+ },
149
+ 'swap': {
150
+ 'linear': None,
151
+ 'inverse': None,
152
+ },
153
+ 'future': {
154
+ 'linear': None,
155
+ 'inverse': None,
156
+ },
157
+ },
116
158
  })
117
159
 
118
160
  def parse_balance(self, response) -> Balances:
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.49'
7
+ __version__ = '4.4.51'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/binance.py CHANGED
@@ -2215,6 +2215,7 @@ class binance(ccxt.async_support.binance):
2215
2215
  response = None
2216
2216
  if isPortfolioMargin:
2217
2217
  response = await self.papiPostListenKey(params)
2218
+ params = self.extend(params, {'portfolioMargin': True})
2218
2219
  elif type == 'future':
2219
2220
  response = await self.fapiPrivatePostListenKey(params)
2220
2221
  elif type == 'delivery':
@@ -2259,6 +2260,7 @@ class binance(ccxt.async_support.binance):
2259
2260
  try:
2260
2261
  if isPortfolioMargin:
2261
2262
  await self.papiPutListenKey(self.extend(request, params))
2263
+ params = self.extend(params, {'portfolioMargin': True})
2262
2264
  elif type == 'future':
2263
2265
  await self.fapiPrivatePutListenKey(self.extend(request, params))
2264
2266
  elif type == 'delivery':
ccxt/pro/blofin.py CHANGED
@@ -42,6 +42,14 @@ class blofin(ccxt.async_support.blofin):
42
42
  },
43
43
  },
44
44
  },
45
+ 'test': {
46
+ 'ws': {
47
+ 'swap': {
48
+ 'public': 'wss://demo-trading-openapi.blofin.com/ws/public',
49
+ 'private': 'wss://demo-trading-openapi.blofin.com/ws/private',
50
+ },
51
+ },
52
+ },
45
53
  },
46
54
  'options': {
47
55
  'defaultType': 'swap',
ccxt/pro/coinex.py CHANGED
@@ -263,7 +263,10 @@ class coinex(ccxt.async_support.coinex):
263
263
  type, params = self.handle_market_type_and_params('watchBalance', None, params, 'spot')
264
264
  await self.authenticate(type)
265
265
  url = self.urls['api']['ws'][type]
266
- currencies = list(self.currencies_by_id.keys())
266
+ # coinex throws a closes the websocket when subscribing over 1422 currencies, therefore we filter out inactive currencies
267
+ activeCurrencies = self.filter_by(self.currencies_by_id, 'active', True)
268
+ activeCurrenciesById = self.index_by(activeCurrencies, 'id')
269
+ currencies = list(activeCurrenciesById.keys())
267
270
  if currencies is None:
268
271
  currencies = []
269
272
  messageHash = 'balances'