ccxt 4.4.94__py2.py3-none-any.whl → 4.4.96__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 (92) hide show
  1. ccxt/__init__.py +3 -1
  2. ccxt/abstract/bingx.py +3 -0
  3. ccxt/abstract/foxbit.py +26 -0
  4. ccxt/abstract/hyperliquid.py +1 -1
  5. ccxt/abstract/woo.py +59 -4
  6. ccxt/apex.py +3 -3
  7. ccxt/ascendex.py +2 -2
  8. ccxt/async_support/__init__.py +3 -1
  9. ccxt/async_support/apex.py +3 -3
  10. ccxt/async_support/ascendex.py +2 -2
  11. ccxt/async_support/base/exchange.py +5 -3
  12. ccxt/async_support/base/ws/future.py +5 -1
  13. ccxt/async_support/bingx.py +129 -92
  14. ccxt/async_support/bitget.py +31 -144
  15. ccxt/async_support/bitmart.py +2 -2
  16. ccxt/async_support/bitrue.py +13 -8
  17. ccxt/async_support/bitstamp.py +2 -0
  18. ccxt/async_support/blofin.py +6 -1
  19. ccxt/async_support/bybit.py +15 -6
  20. ccxt/async_support/coinbase.py +36 -0
  21. ccxt/async_support/coinbaseexchange.py +4 -2
  22. ccxt/async_support/coinbaseinternational.py +2 -2
  23. ccxt/async_support/coinmate.py +34 -0
  24. ccxt/async_support/coinone.py +34 -0
  25. ccxt/async_support/coinsph.py +29 -0
  26. ccxt/async_support/coinspot.py +36 -1
  27. ccxt/async_support/cryptocom.py +2 -1
  28. ccxt/async_support/cryptomus.py +41 -1
  29. ccxt/async_support/defx.py +1 -1
  30. ccxt/async_support/derive.py +1 -1
  31. ccxt/async_support/ellipx.py +40 -0
  32. ccxt/async_support/foxbit.py +1935 -0
  33. ccxt/async_support/gate.py +1 -1
  34. ccxt/async_support/hyperliquid.py +3 -2
  35. ccxt/async_support/kucoin.py +1 -1
  36. ccxt/async_support/kucoinfutures.py +3 -2
  37. ccxt/async_support/mexc.py +28 -13
  38. ccxt/async_support/modetrade.py +3 -3
  39. ccxt/async_support/okcoin.py +1 -1
  40. ccxt/async_support/okx.py +10 -3
  41. ccxt/async_support/onetrading.py +1 -1
  42. ccxt/async_support/oxfun.py +2 -1
  43. ccxt/async_support/paradex.py +2 -2
  44. ccxt/async_support/vertex.py +3 -2
  45. ccxt/async_support/woo.py +1255 -875
  46. ccxt/async_support/woofipro.py +2 -2
  47. ccxt/base/exchange.py +8 -5
  48. ccxt/bingx.py +129 -92
  49. ccxt/bitget.py +31 -144
  50. ccxt/bitmart.py +2 -2
  51. ccxt/bitrue.py +13 -8
  52. ccxt/bitstamp.py +2 -0
  53. ccxt/blofin.py +6 -1
  54. ccxt/bybit.py +15 -6
  55. ccxt/coinbase.py +36 -0
  56. ccxt/coinbaseexchange.py +4 -2
  57. ccxt/coinbaseinternational.py +2 -2
  58. ccxt/coinmate.py +34 -0
  59. ccxt/coinone.py +34 -0
  60. ccxt/coinsph.py +29 -0
  61. ccxt/coinspot.py +36 -1
  62. ccxt/cryptocom.py +2 -1
  63. ccxt/cryptomus.py +41 -1
  64. ccxt/defx.py +1 -1
  65. ccxt/derive.py +1 -1
  66. ccxt/ellipx.py +40 -0
  67. ccxt/foxbit.py +1935 -0
  68. ccxt/gate.py +1 -1
  69. ccxt/hyperliquid.py +3 -2
  70. ccxt/kucoin.py +1 -1
  71. ccxt/kucoinfutures.py +3 -2
  72. ccxt/mexc.py +28 -13
  73. ccxt/modetrade.py +3 -3
  74. ccxt/okcoin.py +1 -1
  75. ccxt/okx.py +10 -3
  76. ccxt/onetrading.py +1 -1
  77. ccxt/oxfun.py +2 -1
  78. ccxt/paradex.py +2 -2
  79. ccxt/pro/__init__.py +1 -1
  80. ccxt/pro/hyperliquid.py +6 -6
  81. ccxt/pro/kraken.py +17 -16
  82. ccxt/pro/mexc.py +10 -10
  83. ccxt/test/tests_async.py +17 -2
  84. ccxt/test/tests_sync.py +17 -2
  85. ccxt/vertex.py +3 -2
  86. ccxt/woo.py +1255 -875
  87. ccxt/woofipro.py +2 -2
  88. {ccxt-4.4.94.dist-info → ccxt-4.4.96.dist-info}/METADATA +8 -8
  89. {ccxt-4.4.94.dist-info → ccxt-4.4.96.dist-info}/RECORD +92 -89
  90. {ccxt-4.4.94.dist-info → ccxt-4.4.96.dist-info}/LICENSE.txt +0 -0
  91. {ccxt-4.4.94.dist-info → ccxt-4.4.96.dist-info}/WHEEL +0 -0
  92. {ccxt-4.4.94.dist-info → ccxt-4.4.96.dist-info}/top_level.txt +0 -0
ccxt/gate.py CHANGED
@@ -3754,7 +3754,7 @@ class gate(Exchange, ImplicitAPI):
3754
3754
  start = self.parse_to_int(since / 1000)
3755
3755
  request['from'] = start
3756
3756
  request['to'] = self.sum(start, 30 * 24 * 60 * 60)
3757
- request, params = self.handle_until_option('to', request, params)
3757
+ request, params = self.handle_until_option('to', request, params, 0.001)
3758
3758
  response = self.privateWalletGetDeposits(self.extend(request, params))
3759
3759
  return self.parse_transactions(response, currency)
3760
3760
 
ccxt/hyperliquid.py CHANGED
@@ -173,6 +173,7 @@ class hyperliquid(Exchange, ImplicitAPI):
173
173
  'orderStatus': 2,
174
174
  'spotClearinghouseState': 2,
175
175
  'exchangeStatus': 2,
176
+ 'candleSnapshot': 4,
176
177
  },
177
178
  },
178
179
  },
@@ -1809,7 +1810,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1809
1810
  # }
1810
1811
  # }
1811
1812
  #
1812
- return response
1813
+ return [self.safe_order({'info': response})]
1813
1814
 
1814
1815
  def cancel_all_orders_after(self, timeout: Int, params={}):
1815
1816
  """
@@ -3599,7 +3600,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3599
3600
  def coin_to_market_id(self, coin: Str):
3600
3601
  if coin.find('/') > -1 or coin.find('@') > -1:
3601
3602
  return coin # spot
3602
- return coin + '/USDC:USDC'
3603
+ return self.safe_currency_code(coin) + '/USDC:USDC'
3603
3604
 
3604
3605
  def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
3605
3606
  if not response:
ccxt/kucoin.py CHANGED
@@ -2646,7 +2646,7 @@ class kucoin(Exchange, ImplicitAPI):
2646
2646
  response = self.privateDeleteHfOrders(self.extend(request, query))
2647
2647
  else:
2648
2648
  response = self.privateDeleteOrders(self.extend(request, query))
2649
- return response
2649
+ return [self.safe_order({'info': response})]
2650
2650
 
2651
2651
  def fetch_orders_by_status(self, status, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2652
2652
  """
ccxt/kucoinfutures.py CHANGED
@@ -1719,7 +1719,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
1719
1719
  # },
1720
1720
  # }
1721
1721
  #
1722
- return self.safe_value(response, 'data')
1722
+ return self.safe_order({'info': response})
1723
1723
 
1724
1724
  def cancel_orders(self, ids, symbol: Str = None, params={}):
1725
1725
  """
@@ -1811,7 +1811,8 @@ class kucoinfutures(kucoin, ImplicitAPI):
1811
1811
  # },
1812
1812
  # }
1813
1813
  #
1814
- return self.safe_value(response, 'data')
1814
+ data = self.safe_dict(response, 'data')
1815
+ return [self.safe_order({'info': data})]
1815
1816
 
1816
1817
  def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
1817
1818
  """
ccxt/mexc.py CHANGED
@@ -4651,11 +4651,14 @@ class mexc(Exchange, ImplicitAPI):
4651
4651
  # "network": "TRX",
4652
4652
  # "status": "5",
4653
4653
  # "address": "TSMcEDDvkqY9dz8RkFnrS86U59GwEZjfvh",
4654
- # "txId": "51a8f49e6f03f2c056e71fe3291aa65e1032880be855b65cecd0595a1b8af95b",
4654
+ # "txId": "51a8f49e6f03f2c056e71fe3291aa65e1032880be855b65cecd0595a1b8af95b:0",
4655
4655
  # "insertTime": "1664805021000",
4656
4656
  # "unlockConfirm": "200",
4657
4657
  # "confirmTimes": "203",
4658
- # "memo": "xxyy1122"
4658
+ # "memo": "xxyy1122",
4659
+ # "transHash": "51a8f49e6f03f2c056e71fe3291aa65e1032880be855b65cecd0595a1b8af95b",
4660
+ # "updateTime": "1664805621000",
4661
+ # "netWork: "TRX"
4659
4662
  # }
4660
4663
  # ]
4661
4664
  #
@@ -4696,7 +4699,7 @@ class mexc(Exchange, ImplicitAPI):
4696
4699
  # [
4697
4700
  # {
4698
4701
  # "id": "adcd1c8322154de691b815eedcd10c42",
4699
- # "txId": "0xc8c918cd69b2246db493ef6225a72ffdc664f15b08da3e25c6879b271d05e9d0",
4702
+ # "txId": "0xc8c918cd69b2246db493ef6225a72ffdc664f15b08da3e25c6879b271d05e9d0:0",
4700
4703
  # "coin": "USDC-MATIC",
4701
4704
  # "network": "MATIC",
4702
4705
  # "address": "0xeE6C7a415995312ED52c53a0f8f03e165e0A5D62",
@@ -4707,7 +4710,11 @@ class mexc(Exchange, ImplicitAPI):
4707
4710
  # "confirmNo": null,
4708
4711
  # "applyTime": "1664882739000",
4709
4712
  # "remark": '',
4710
- # "memo": null
4713
+ # "memo": null,
4714
+ # "explorerUrl": "https://etherscan.io/tx/0xc8c918cd69b2246db493ef6225a72ffdc664f15b08da3e25c6879b271d05e9d0",
4715
+ # "transHash": "0xc8c918cd69b2246db493ef6225a72ffdc664f15b08da3e25c6879b271d05e9d0",
4716
+ # "updateTime": "1664882799000",
4717
+ # "netWork: "MATIC"
4711
4718
  # }
4712
4719
  # ]
4713
4720
  #
@@ -4723,18 +4730,21 @@ class mexc(Exchange, ImplicitAPI):
4723
4730
  # "network": "TRX",
4724
4731
  # "status": "5",
4725
4732
  # "address": "TSMcEDDvkqY9dz8RkFnrS86U59GwEZjfvh",
4726
- # "txId": "51a8f49e6f03f2c056e71fe3291aa65e1032880be855b65cecd0595a1b8af95b",
4733
+ # "txId": "51a8f49e6f03f2c056e71fe3291aa65e1032880be855b65cecd0595a1b8af95b:0",
4727
4734
  # "insertTime": "1664805021000",
4728
4735
  # "unlockConfirm": "200",
4729
4736
  # "confirmTimes": "203",
4730
- # "memo": "xxyy1122"
4737
+ # "memo": "xxyy1122",
4738
+ # "transHash": "51a8f49e6f03f2c056e71fe3291aa65e1032880be855b65cecd0595a1b8af95b",
4739
+ # "updateTime": "1664805621000",
4740
+ # "netWork: "TRX"
4731
4741
  # }
4732
4742
  #
4733
4743
  # fetchWithdrawals
4734
4744
  #
4735
4745
  # {
4736
4746
  # "id": "adcd1c8322154de691b815eedcd10c42",
4737
- # "txId": "0xc8c918cd69b2246db493ef6225a72ffdc664f15b08da3e25c6879b271d05e9d0",
4747
+ # "txId": "0xc8c918cd69b2246db493ef6225a72ffdc664f15b08da3e25c6879b271d05e9d0:0",
4738
4748
  # "coin": "USDC-MATIC",
4739
4749
  # "network": "MATIC",
4740
4750
  # "address": "0xeE6C7a415995312ED52c53a0f8f03e165e0A5D62",
@@ -4744,8 +4754,12 @@ class mexc(Exchange, ImplicitAPI):
4744
4754
  # "transactionFee": "1",
4745
4755
  # "confirmNo": null,
4746
4756
  # "applyTime": "1664882739000",
4747
- # "remark": '',
4748
- # "memo": null
4757
+ # "remark": "",
4758
+ # "memo": null,
4759
+ # "explorerUrl": "https://etherscan.io/tx/0xc8c918cd69b2246db493ef6225a72ffdc664f15b08da3e25c6879b271d05e9d0",
4760
+ # "transHash": "0xc8c918cd69b2246db493ef6225a72ffdc664f15b08da3e25c6879b271d05e9d0",
4761
+ # "updateTime": "1664882799000",
4762
+ # "netWork: "MATIC"
4749
4763
  # }
4750
4764
  #
4751
4765
  # withdraw
@@ -4757,6 +4771,7 @@ class mexc(Exchange, ImplicitAPI):
4757
4771
  id = self.safe_string(transaction, 'id')
4758
4772
  type = 'deposit' if (id is None) else 'withdrawal'
4759
4773
  timestamp = self.safe_integer_2(transaction, 'insertTime', 'applyTime')
4774
+ updated = self.safe_integer(transaction, 'updateTime')
4760
4775
  currencyId = None
4761
4776
  currencyWithNetwork = self.safe_string(transaction, 'coin')
4762
4777
  if currencyWithNetwork is not None:
@@ -4769,7 +4784,7 @@ class mexc(Exchange, ImplicitAPI):
4769
4784
  status = self.parse_transaction_status_by_type(self.safe_string(transaction, 'status'), type)
4770
4785
  amountString = self.safe_string(transaction, 'amount')
4771
4786
  address = self.safe_string(transaction, 'address')
4772
- txid = self.safe_string(transaction, 'txId')
4787
+ txid = self.safe_string_2(transaction, 'transHash', 'txId')
4773
4788
  fee = None
4774
4789
  feeCostString = self.safe_string(transaction, 'transactionFee')
4775
4790
  if feeCostString is not None:
@@ -4797,8 +4812,8 @@ class mexc(Exchange, ImplicitAPI):
4797
4812
  'amount': self.parse_number(amountString),
4798
4813
  'currency': code,
4799
4814
  'status': status,
4800
- 'updated': None,
4801
- 'comment': None,
4815
+ 'updated': updated,
4816
+ 'comment': self.safe_string(transaction, 'remark'),
4802
4817
  'internal': None,
4803
4818
  'fee': fee,
4804
4819
  }
@@ -5704,7 +5719,7 @@ class mexc(Exchange, ImplicitAPI):
5704
5719
  #
5705
5720
  # {success: True, code: '0'}
5706
5721
  #
5707
- return self.parse_leverage(response, market)
5722
+ return self.parse_leverage(response, market) # tmp revert type
5708
5723
 
5709
5724
  def nonce(self):
5710
5725
  return self.milliseconds() - self.safe_integer(self.options, 'timeDifference', 0)
ccxt/modetrade.py CHANGED
@@ -29,7 +29,7 @@ class modetrade(Exchange, ImplicitAPI):
29
29
  'countries': ['KY'], # Cayman Islands
30
30
  'rateLimit': 100,
31
31
  'version': 'v1',
32
- 'certified': True,
32
+ 'certified': False,
33
33
  'pro': True,
34
34
  'dex': True,
35
35
  'hostname': 'trade.mode.network',
@@ -1750,9 +1750,9 @@ class modetrade(Exchange, ImplicitAPI):
1750
1750
  # }
1751
1751
  #
1752
1752
  return [
1753
- {
1753
+ self.safe_order({
1754
1754
  'info': response,
1755
- },
1755
+ }),
1756
1756
  ]
1757
1757
 
1758
1758
  def fetch_order(self, id: str, symbol: Str = None, params={}):
ccxt/okcoin.py CHANGED
@@ -1650,7 +1650,7 @@ class okcoin(Exchange, ImplicitAPI):
1650
1650
  advanced = self.safe_value(params, 'advanced')
1651
1651
  if trigger or advanced:
1652
1652
  orderInner = self.cancel_orders([id], symbol, params)
1653
- return self.safe_value(orderInner, 0)
1653
+ return self.safe_dict(orderInner, 0)
1654
1654
  market = self.market(symbol)
1655
1655
  request: dict = {
1656
1656
  'instId': market['id'],
ccxt/okx.py CHANGED
@@ -1172,7 +1172,9 @@ class okx(Exchange, ImplicitAPI):
1172
1172
  },
1173
1173
  'createOrder': 'privatePostTradeBatchOrders', # or 'privatePostTradeOrder' or 'privatePostTradeOrderAlgo'
1174
1174
  'createMarketBuyOrderRequiresPrice': False,
1175
- 'fetchMarkets': ['spot', 'future', 'swap', 'option'], # spot, future, swap, option
1175
+ 'fetchMarkets': {
1176
+ 'types': ['spot', 'future', 'swap', 'option'], # spot, future, swap, option
1177
+ },
1176
1178
  'timeDifference': 0, # the difference between system clock and exchange server clock
1177
1179
  'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
1178
1180
  'defaultType': 'spot', # 'funding', 'spot', 'margin', 'future', 'swap', 'option'
@@ -1558,7 +1560,12 @@ class okx(Exchange, ImplicitAPI):
1558
1560
  """
1559
1561
  if self.options['adjustForTimeDifference']:
1560
1562
  self.load_time_difference()
1561
- types = self.safe_list(self.options, 'fetchMarkets', [])
1563
+ types = ['spot', 'future', 'swap', 'option']
1564
+ fetchMarketsOption = self.safe_dict(self.options, 'fetchMarkets')
1565
+ if fetchMarketsOption is not None:
1566
+ types = self.safe_list(fetchMarketsOption, 'types', types)
1567
+ else:
1568
+ types = self.safe_list(self.options, 'fetchMarkets', types) # backward-support
1562
1569
  promises = []
1563
1570
  result = []
1564
1571
  for i in range(0, len(types)):
@@ -3324,7 +3331,7 @@ class okx(Exchange, ImplicitAPI):
3324
3331
  trailing = self.safe_bool(params, 'trailing', False)
3325
3332
  if trigger or trailing:
3326
3333
  orderInner = self.cancel_orders([id], symbol, params)
3327
- return self.safe_value(orderInner, 0)
3334
+ return self.safe_dict(orderInner, 0)
3328
3335
  self.load_markets()
3329
3336
  market = self.market(symbol)
3330
3337
  request: dict = {
ccxt/onetrading.py CHANGED
@@ -1321,7 +1321,7 @@ class onetrading(Exchange, ImplicitAPI):
1321
1321
  # "a10e9bd1-8f72-4cfe-9f1b-7f1c8a9bd8ee"
1322
1322
  # ]
1323
1323
  #
1324
- return response
1324
+ return [self.safe_order({'info': response})]
1325
1325
 
1326
1326
  def cancel_orders(self, ids, symbol: Str = None, params={}):
1327
1327
  """
ccxt/oxfun.py CHANGED
@@ -2584,7 +2584,8 @@ class oxfun(Exchange, ImplicitAPI):
2584
2584
  # "data": {"notice": "No working orders found"}
2585
2585
  # }
2586
2586
  #
2587
- return self.privateDeleteV3OrdersCancelAll(self.extend(request, params))
2587
+ response = self.privateDeleteV3OrdersCancelAll(self.extend(request, params))
2588
+ return [self.safe_order({'info': response})]
2588
2589
 
2589
2590
  def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
2590
2591
  """
ccxt/paradex.py CHANGED
@@ -1249,7 +1249,7 @@ class paradex(Exchange, ImplicitAPI):
1249
1249
  cancelReason = self.safe_string(order, 'cancel_reason')
1250
1250
  status = self.safe_string(order, 'status')
1251
1251
  if cancelReason is not None:
1252
- if cancelReason == 'NOT_ENOUGH_MARGIN':
1252
+ if cancelReason == 'NOT_ENOUGH_MARGIN' or cancelReason == 'ORDER_EXCEEDS_POSITION_LIMIT':
1253
1253
  status = 'rejected'
1254
1254
  else:
1255
1255
  status = 'canceled'
@@ -1527,7 +1527,7 @@ class paradex(Exchange, ImplicitAPI):
1527
1527
  #
1528
1528
  # if success, no response...
1529
1529
  #
1530
- return response
1530
+ return [self.safe_order({'info': response})]
1531
1531
 
1532
1532
  def fetch_order(self, id: str, symbol: Str = None, params={}):
1533
1533
  """
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.94'
7
+ __version__ = '4.4.96'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/hyperliquid.py CHANGED
@@ -170,7 +170,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
170
170
  'method': 'subscribe',
171
171
  'subscription': {
172
172
  'type': 'l2Book',
173
- 'coin': market['base'] if market['swap'] else market['id'],
173
+ 'coin': market['baseName'] if market['swap'] else market['id'],
174
174
  },
175
175
  }
176
176
  message = self.extend(request, params)
@@ -199,7 +199,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
199
199
  'method': 'unsubscribe',
200
200
  'subscription': {
201
201
  'type': 'l2Book',
202
- 'coin': market['base'] if market['swap'] else market['id'],
202
+ 'coin': market['baseName'] if market['swap'] else market['id'],
203
203
  },
204
204
  }
205
205
  message = self.extend(request, params)
@@ -500,7 +500,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
500
500
  'method': 'subscribe',
501
501
  'subscription': {
502
502
  'type': 'trades',
503
- 'coin': market['base'] if market['swap'] else market['id'],
503
+ 'coin': market['baseName'] if market['swap'] else market['id'],
504
504
  },
505
505
  }
506
506
  message = self.extend(request, params)
@@ -529,7 +529,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
529
529
  'method': 'unsubscribe',
530
530
  'subscription': {
531
531
  'type': 'trades',
532
- 'coin': market['base'] if market['swap'] else market['id'],
532
+ 'coin': market['baseName'] if market['swap'] else market['id'],
533
533
  },
534
534
  }
535
535
  message = self.extend(request, params)
@@ -653,7 +653,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
653
653
  'method': 'subscribe',
654
654
  'subscription': {
655
655
  'type': 'candle',
656
- 'coin': market['base'] if market['swap'] else market['id'],
656
+ 'coin': market['baseName'] if market['swap'] else market['id'],
657
657
  'interval': timeframe,
658
658
  },
659
659
  }
@@ -683,7 +683,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
683
683
  'method': 'unsubscribe',
684
684
  'subscription': {
685
685
  'type': 'candle',
686
- 'coin': market['base'] if market['swap'] else market['id'],
686
+ 'coin': market['baseName'] if market['swap'] else market['id'],
687
687
  'interval': timeframe,
688
688
  },
689
689
  }
ccxt/pro/kraken.py CHANGED
@@ -745,15 +745,13 @@ class kraken(ccxt.async_support.kraken):
745
745
  :param dict [params]: extra parameters specific to the exchange API endpoint
746
746
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
747
747
  """
748
- request: dict = {}
748
+ requiredParams: dict = {}
749
749
  if limit is not None:
750
750
  if self.in_array(limit, [10, 25, 100, 500, 1000]):
751
- request['params'] = {
752
- 'depth': limit, # default 10, valid options 10, 25, 100, 500, 1000
753
- }
751
+ requiredParams['depth'] = limit # default 10, valid options 10, 25, 100, 500, 1000
754
752
  else:
755
753
  raise NotSupported(self.id + ' watchOrderBook accepts limit values of 10, 25, 100, 500 and 1000 only')
756
- orderbook = await self.watch_multi_helper('orderbook', 'book', symbols, {'limit': limit}, self.extend(request, params))
754
+ orderbook = await self.watch_multi_helper('orderbook', 'book', symbols, {'limit': limit}, self.extend(requiredParams, params))
757
755
  return orderbook.limit()
758
756
 
759
757
  async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
@@ -1614,17 +1612,20 @@ class kraken(ccxt.async_support.kraken):
1614
1612
  #
1615
1613
  errorMessage = self.safe_string_2(message, 'errorMessage', 'error')
1616
1614
  if errorMessage is not None:
1617
- requestId = self.safe_value_2(message, 'reqid', 'req_id')
1618
- if requestId is not None:
1619
- broad = self.exceptions['ws']['broad']
1620
- broadKey = self.find_broadly_matched_key(broad, errorMessage)
1621
- exception = None
1622
- if broadKey is None:
1623
- exception = ExchangeError(errorMessage) # c# requirement to convert the errorMessage to string
1624
- else:
1625
- exception = broad[broadKey](errorMessage)
1626
- client.reject(exception, requestId)
1627
- return False
1615
+ # requestId = self.safe_value_2(message, 'reqid', 'req_id')
1616
+ broad = self.exceptions['ws']['broad']
1617
+ broadKey = self.find_broadly_matched_key(broad, errorMessage)
1618
+ exception = None
1619
+ if broadKey is None:
1620
+ exception = ExchangeError(errorMessage) # c# requirement to convert the errorMessage to string
1621
+ else:
1622
+ exception = broad[broadKey](errorMessage)
1623
+ # if requestId is not None:
1624
+ # client.reject(exception, requestId)
1625
+ # else:
1626
+ client.reject(exception)
1627
+ # }
1628
+ return False
1628
1629
  return True
1629
1630
 
1630
1631
  def handle_message(self, client: Client, message):
ccxt/pro/mexc.py CHANGED
@@ -1377,14 +1377,14 @@ class mexc(ccxt.async_support.mexc):
1377
1377
  channel = 'spot@public.bookTicker.v3.api@' + market['id']
1378
1378
  url = self.urls['api']['ws']['spot']
1379
1379
  params['unsubscribed'] = True
1380
- self.watch_spot_public(channel, messageHash, params)
1380
+ await self.watch_spot_public(channel, messageHash, params)
1381
1381
  else:
1382
1382
  channel = 'unsub.ticker'
1383
1383
  requestParams: dict = {
1384
1384
  'symbol': market['id'],
1385
1385
  }
1386
1386
  url = self.urls['api']['ws']['swap']
1387
- self.watch_swap_public(channel, messageHash, requestParams, params)
1387
+ await self.watch_swap_public(channel, messageHash, requestParams, params)
1388
1388
  client = self.client(url)
1389
1389
  self.handle_unsubscriptions(client, [messageHash])
1390
1390
  return None
@@ -1435,7 +1435,7 @@ class mexc(ccxt.async_support.mexc):
1435
1435
  request['params'] = {}
1436
1436
  messageHashes.append('unsubscribe:ticker')
1437
1437
  client = self.client(url)
1438
- self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
1438
+ await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
1439
1439
  self.handle_unsubscriptions(client, messageHashes)
1440
1440
  return None
1441
1441
 
@@ -1469,7 +1469,7 @@ class mexc(ccxt.async_support.mexc):
1469
1469
  'params': topics,
1470
1470
  }
1471
1471
  client = self.client(url)
1472
- self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
1472
+ await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
1473
1473
  self.handle_unsubscriptions(client, messageHashes)
1474
1474
  return None
1475
1475
 
@@ -1493,7 +1493,7 @@ class mexc(ccxt.async_support.mexc):
1493
1493
  url = self.urls['api']['ws']['spot']
1494
1494
  channel = 'spot@public.kline.v3.api@' + market['id'] + '@' + timeframeId
1495
1495
  params['unsubscribed'] = True
1496
- self.watch_spot_public(channel, messageHash, params)
1496
+ await self.watch_spot_public(channel, messageHash, params)
1497
1497
  else:
1498
1498
  url = self.urls['api']['ws']['swap']
1499
1499
  channel = 'unsub.kline'
@@ -1501,7 +1501,7 @@ class mexc(ccxt.async_support.mexc):
1501
1501
  'symbol': market['id'],
1502
1502
  'interval': timeframeId,
1503
1503
  }
1504
- self.watch_swap_public(channel, messageHash, requestParams, params)
1504
+ await self.watch_swap_public(channel, messageHash, requestParams, params)
1505
1505
  client = self.client(url)
1506
1506
  self.handle_unsubscriptions(client, [messageHash])
1507
1507
  return None
@@ -1522,14 +1522,14 @@ class mexc(ccxt.async_support.mexc):
1522
1522
  url = self.urls['api']['ws']['spot']
1523
1523
  channel = 'spot@public.increase.depth.v3.api@' + market['id']
1524
1524
  params['unsubscribed'] = True
1525
- self.watch_spot_public(channel, messageHash, params)
1525
+ await self.watch_spot_public(channel, messageHash, params)
1526
1526
  else:
1527
1527
  url = self.urls['api']['ws']['swap']
1528
1528
  channel = 'unsub.depth'
1529
1529
  requestParams: dict = {
1530
1530
  'symbol': market['id'],
1531
1531
  }
1532
- self.watch_swap_public(channel, messageHash, requestParams, params)
1532
+ await self.watch_swap_public(channel, messageHash, requestParams, params)
1533
1533
  client = self.client(url)
1534
1534
  self.handle_unsubscriptions(client, [messageHash])
1535
1535
  return None
@@ -1551,14 +1551,14 @@ class mexc(ccxt.async_support.mexc):
1551
1551
  url = self.urls['api']['ws']['spot']
1552
1552
  channel = 'spot@public.deals.v3.api@' + market['id']
1553
1553
  params['unsubscribed'] = True
1554
- self.watch_spot_public(channel, messageHash, params)
1554
+ await self.watch_spot_public(channel, messageHash, params)
1555
1555
  else:
1556
1556
  url = self.urls['api']['ws']['swap']
1557
1557
  channel = 'unsub.deal'
1558
1558
  requestParams: dict = {
1559
1559
  'symbol': market['id'],
1560
1560
  }
1561
- self.watch_swap_public(channel, messageHash, requestParams, params)
1561
+ await self.watch_swap_public(channel, messageHash, requestParams, params)
1562
1562
  client = self.client(url)
1563
1563
  self.handle_unsubscriptions(client, [messageHash])
1564
1564
  return None
ccxt/test/tests_async.py CHANGED
@@ -622,18 +622,33 @@ class testMainClass:
622
622
  def check_constructor(self, exchange):
623
623
  # todo: this might be moved in base tests later
624
624
  if exchange.id == 'binance':
625
- assert exchange.hostname is None, 'binance.com hostname should be empty'
625
+ assert exchange.hostname is None or exchange.hostname == '', 'binance.com hostname should be empty'
626
626
  assert exchange.urls['api']['public'] == 'https://api.binance.com/api/v3', 'https://api.binance.com/api/v3 does not match: ' + exchange.urls['api']['public']
627
627
  assert ('lending/union/account' in exchange.api['sapi']['get']), 'SAPI should contain the endpoint lending/union/account, ' + json_stringify(exchange.api['sapi']['get'])
628
628
  elif exchange.id == 'binanceus':
629
629
  assert exchange.hostname == 'binance.us', 'binance.us hostname does not match ' + exchange.hostname
630
630
  assert exchange.urls['api']['public'] == 'https://api.binance.us/api/v3', 'https://api.binance.us/api/v3 does not match: ' + exchange.urls['api']['public']
631
631
 
632
+ async def test_return_response_headers(self, exchange):
633
+ if exchange.id != 'binance':
634
+ return False # this test is only for binance exchange for now
635
+ exchange.return_response_headers = True
636
+ ticker = await exchange.fetch_ticker('BTC/USDT')
637
+ info = ticker['info']
638
+ headers = info['responseHeaders']
639
+ headers_keys = list(headers.keys())
640
+ assert len(headers_keys) > 0, 'Response headers should not be empty'
641
+ header_values = list(headers.values())
642
+ assert len(header_values) > 0, 'Response headers values should not be empty'
643
+ exchange.return_response_headers = False
644
+ return True
645
+
632
646
  async def start_test(self, exchange, symbol):
633
647
  # we do not need to test aliases
634
648
  if exchange.alias:
635
649
  return True
636
650
  self.check_constructor(exchange)
651
+ # await this.testReturnResponseHeaders (exchange);
637
652
  if self.sandbox or get_exchange_prop(exchange, 'sandbox'):
638
653
  exchange.set_sandbox_mode(True)
639
654
  try:
@@ -1395,7 +1410,7 @@ class testMainClass:
1395
1410
  try:
1396
1411
  await exchange.create_order('BTC/USDT', 'limit', 'buy', 1, 20000)
1397
1412
  except Exception as e:
1398
- spot_order_request = self.urlencoded_to_dict(exchange.last_request_body)
1413
+ spot_order_request = json_parse(exchange.last_request_body)
1399
1414
  broker_id = spot_order_request['broker_id']
1400
1415
  id_string = str(id)
1401
1416
  assert broker_id.startswith(id_string), 'woo - broker_id: ' + broker_id + ' does not start with id: ' + id_string
ccxt/test/tests_sync.py CHANGED
@@ -619,18 +619,33 @@ class testMainClass:
619
619
  def check_constructor(self, exchange):
620
620
  # todo: this might be moved in base tests later
621
621
  if exchange.id == 'binance':
622
- assert exchange.hostname is None, 'binance.com hostname should be empty'
622
+ assert exchange.hostname is None or exchange.hostname == '', 'binance.com hostname should be empty'
623
623
  assert exchange.urls['api']['public'] == 'https://api.binance.com/api/v3', 'https://api.binance.com/api/v3 does not match: ' + exchange.urls['api']['public']
624
624
  assert ('lending/union/account' in exchange.api['sapi']['get']), 'SAPI should contain the endpoint lending/union/account, ' + json_stringify(exchange.api['sapi']['get'])
625
625
  elif exchange.id == 'binanceus':
626
626
  assert exchange.hostname == 'binance.us', 'binance.us hostname does not match ' + exchange.hostname
627
627
  assert exchange.urls['api']['public'] == 'https://api.binance.us/api/v3', 'https://api.binance.us/api/v3 does not match: ' + exchange.urls['api']['public']
628
628
 
629
+ def test_return_response_headers(self, exchange):
630
+ if exchange.id != 'binance':
631
+ return False # this test is only for binance exchange for now
632
+ exchange.return_response_headers = True
633
+ ticker = exchange.fetch_ticker('BTC/USDT')
634
+ info = ticker['info']
635
+ headers = info['responseHeaders']
636
+ headers_keys = list(headers.keys())
637
+ assert len(headers_keys) > 0, 'Response headers should not be empty'
638
+ header_values = list(headers.values())
639
+ assert len(header_values) > 0, 'Response headers values should not be empty'
640
+ exchange.return_response_headers = False
641
+ return True
642
+
629
643
  def start_test(self, exchange, symbol):
630
644
  # we do not need to test aliases
631
645
  if exchange.alias:
632
646
  return True
633
647
  self.check_constructor(exchange)
648
+ # this.testReturnResponseHeaders (exchange);
634
649
  if self.sandbox or get_exchange_prop(exchange, 'sandbox'):
635
650
  exchange.set_sandbox_mode(True)
636
651
  try:
@@ -1392,7 +1407,7 @@ class testMainClass:
1392
1407
  try:
1393
1408
  exchange.create_order('BTC/USDT', 'limit', 'buy', 1, 20000)
1394
1409
  except Exception as e:
1395
- spot_order_request = self.urlencoded_to_dict(exchange.last_request_body)
1410
+ spot_order_request = json_parse(exchange.last_request_body)
1396
1411
  broker_id = spot_order_request['broker_id']
1397
1412
  id_string = str(id)
1398
1413
  assert broker_id.startswith(id_string), 'woo - broker_id: ' + broker_id + ' does not start with id: ' + id_string
ccxt/vertex.py CHANGED
@@ -2351,7 +2351,7 @@ class vertex(Exchange, ImplicitAPI):
2351
2351
  # "request_type": "execute_cancel_product_orders"
2352
2352
  # }
2353
2353
  #
2354
- return response
2354
+ return [self.safe_order({'info': response})]
2355
2355
 
2356
2356
  def cancel_order(self, id: str, symbol: Str = None, params={}):
2357
2357
  """
@@ -2365,7 +2365,8 @@ class vertex(Exchange, ImplicitAPI):
2365
2365
  :param dict [params]: extra parameters specific to the exchange API endpoint
2366
2366
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2367
2367
  """
2368
- return self.cancel_orders([id], symbol, params)
2368
+ order = self.cancel_orders([id], symbol, params)
2369
+ return self.safe_order({'info': order})
2369
2370
 
2370
2371
  def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
2371
2372
  """