ccxt 4.3.65__py2.py3-none-any.whl → 4.3.67__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.
ccxt/pro/currencycom.py CHANGED
@@ -56,7 +56,7 @@ class currencycom(ccxt.async_support.currencycom):
56
56
  },
57
57
  })
58
58
 
59
- def ping(self, client):
59
+ def ping(self, client: Client):
60
60
  # custom ping-pong
61
61
  requestId = str(self.request_id())
62
62
  return {
ccxt/pro/hollaex.py CHANGED
@@ -546,7 +546,7 @@ class hollaex(ccxt.async_support.hollaex):
546
546
  if method is not None:
547
547
  method(client, message)
548
548
 
549
- def ping(self, client):
549
+ def ping(self, client: Client):
550
550
  # hollaex does not support built-in ws protocol-level ping-pong
551
551
  return {'op': 'ping'}
552
552
 
ccxt/pro/hyperliquid.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  import ccxt.async_support
7
7
  from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
8
- from ccxt.base.types import Int, Market, Order, OrderBook, Str, Trade
8
+ from ccxt.base.types import Int, Market, Order, OrderBook, Str, Strings, Ticker, Tickers, Trade
9
9
  from ccxt.async_support.base.ws.client import Client
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
@@ -23,7 +23,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
23
23
  'watchOrderBook': True,
24
24
  'watchOrders': True,
25
25
  'watchTicker': False,
26
- 'watchTickers': False,
26
+ 'watchTickers': True,
27
27
  'watchTrades': True,
28
28
  'watchPosition': False,
29
29
  },
@@ -123,6 +123,29 @@ class hyperliquid(ccxt.async_support.hyperliquid):
123
123
  messageHash = 'orderbook:' + symbol
124
124
  client.resolve(orderbook, messageHash)
125
125
 
126
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
127
+ """
128
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
129
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
130
+ :param dict [params]: extra parameters specific to the exchange API endpoint
131
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
132
+ """
133
+ await self.load_markets()
134
+ symbols = self.market_symbols(symbols, None, True)
135
+ messageHash = 'tickers'
136
+ url = self.urls['api']['ws']['public']
137
+ request: dict = {
138
+ 'method': 'subscribe',
139
+ 'subscription': {
140
+ 'type': 'webData2', # allMids
141
+ 'user': '0x0000000000000000000000000000000000000000',
142
+ },
143
+ }
144
+ tickers = await self.watch(url, messageHash, self.extend(request, params), messageHash)
145
+ if self.newUpdates:
146
+ return self.filter_by_array_tickers(tickers, 'symbol', symbols)
147
+ return self.tickers
148
+
126
149
  async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
127
150
  """
128
151
  watches information on multiple trades made by the user
@@ -154,6 +177,82 @@ class hyperliquid(ccxt.async_support.hyperliquid):
154
177
  limit = trades.getLimit(symbol, limit)
155
178
  return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
156
179
 
180
+ def handle_ws_tickers(self, client: Client, message):
181
+ #
182
+ # {
183
+ # "channel": "webData2",
184
+ # "data": {
185
+ # "meta": {
186
+ # "universe": [
187
+ # {
188
+ # "szDecimals": 5,
189
+ # "name": "BTC",
190
+ # "maxLeverage": 50,
191
+ # "onlyIsolated": False
192
+ # },
193
+ # ...
194
+ # ],
195
+ # },
196
+ # "assetCtxs": [
197
+ # {
198
+ # "funding": "0.00003005",
199
+ # "openInterest": "2311.50778",
200
+ # "prevDayPx": "63475.0",
201
+ # "dayNtlVlm": "468043329.64289033",
202
+ # "premium": "0.00094264",
203
+ # "oraclePx": "64712.0",
204
+ # "markPx": "64774.0",
205
+ # "midPx": "64773.5",
206
+ # "impactPxs": [
207
+ # "64773.0",
208
+ # "64774.0"
209
+ # ]
210
+ # },
211
+ # ...
212
+ # ],
213
+ # "spotAssetCtxs": [
214
+ # {
215
+ # "prevDayPx": "0.20937",
216
+ # "dayNtlVlm": "11188888.61984999",
217
+ # "markPx": "0.19722",
218
+ # "midPx": "0.197145",
219
+ # "circulatingSupply": "598760557.12072003",
220
+ # "coin": "PURR/USDC"
221
+ # },
222
+ # ...
223
+ # ],
224
+ # }
225
+ # }
226
+ #
227
+ # spot
228
+ rawData = self.safe_dict(message, 'data', {})
229
+ spotAssets = self.safe_list(rawData, 'spotAssetCtxs', [])
230
+ parsedTickers = []
231
+ for i in range(0, len(spotAssets)):
232
+ assetObject = spotAssets[i]
233
+ marketId = self.safe_string(assetObject, 'coin')
234
+ market = self.safe_market(marketId, None, None, 'spot')
235
+ ticker = self.parse_ws_ticker(assetObject, market)
236
+ parsedTickers.append(ticker)
237
+ # perpetuals
238
+ meta = self.safe_dict(rawData, 'meta', {})
239
+ universe = self.safe_list(meta, 'universe', [])
240
+ assetCtxs = self.safe_list(rawData, 'assetCtxs', [])
241
+ for i in range(0, len(universe)):
242
+ data = self.extend(
243
+ self.safe_dict(universe, i, {}),
244
+ self.safe_dict(assetCtxs, i, {})
245
+ )
246
+ id = data['name'] + '/USDC:USDC'
247
+ market = self.safe_market(id, None, None, 'swap')
248
+ ticker = self.parse_ws_ticker(data, market)
249
+ parsedTickers.append(ticker)
250
+ tickers = self.index_by(parsedTickers, 'symbol')
251
+ client.resolve(tickers, 'tickers')
252
+
253
+ def parse_ws_ticker(self, rawTicker, market: Market = None) -> Ticker:
254
+ return self.parse_ticker(rawTicker, market)
255
+
157
256
  def handle_my_trades(self, client: Client, message):
158
257
  #
159
258
  # {
@@ -497,6 +596,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
497
596
  'candle': self.handle_ohlcv,
498
597
  'orderUpdates': self.handle_order,
499
598
  'userFills': self.handle_my_trades,
599
+ 'webData2': self.handle_ws_tickers,
500
600
  }
501
601
  exacMethod = self.safe_value(methods, topic)
502
602
  if exacMethod is not None:
@@ -510,7 +610,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
510
610
  method(client, message)
511
611
  return
512
612
 
513
- def ping(self, client):
613
+ def ping(self, client: Client):
514
614
  return {
515
615
  'method': 'ping',
516
616
  }
ccxt/pro/kucoin.py CHANGED
@@ -1155,7 +1155,7 @@ class kucoin(ccxt.async_support.kucoin):
1155
1155
  if method is not None:
1156
1156
  method(client, message)
1157
1157
 
1158
- def ping(self, client):
1158
+ def ping(self, client: Client):
1159
1159
  # kucoin does not support built-in ws protocol-level ping-pong
1160
1160
  # instead it requires a custom json-based text ping-pong
1161
1161
  # https://docs.kucoin.com/#ping
ccxt/pro/kucoinfutures.py CHANGED
@@ -1035,7 +1035,7 @@ class kucoinfutures(ccxt.async_support.kucoinfutures):
1035
1035
  else:
1036
1036
  return elementName + 's@all'
1037
1037
 
1038
- def ping(self, client):
1038
+ def ping(self, client: Client):
1039
1039
  # kucoin does not support built-in ws protocol-level ping-pong
1040
1040
  # instead it requires a custom json-based text ping-pong
1041
1041
  # https://docs.kucoin.com/#ping
ccxt/pro/mexc.py CHANGED
@@ -1118,5 +1118,5 @@ class mexc(ccxt.async_support.mexc):
1118
1118
  method = methods[channel]
1119
1119
  method(client, message)
1120
1120
 
1121
- def ping(self, client):
1121
+ def ping(self, client: Client):
1122
1122
  return {'method': 'ping'}
ccxt/pro/okcoin.py CHANGED
@@ -573,7 +573,7 @@ class okcoin(ccxt.async_support.okcoin):
573
573
  client.resolve(message, 'authenticated')
574
574
  return message
575
575
 
576
- def ping(self, client):
576
+ def ping(self, client: Client):
577
577
  # okex does not support built-in ws protocol-level ping-pong
578
578
  # instead it requires custom text-based ping-pong
579
579
  return 'ping'
ccxt/pro/okx.py CHANGED
@@ -13,6 +13,7 @@ from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
14
14
  from ccxt.base.errors import ArgumentsRequired
15
15
  from ccxt.base.errors import BadRequest
16
+ from ccxt.base.errors import InvalidNonce
16
17
  from ccxt.base.errors import ChecksumError
17
18
 
18
19
 
@@ -836,7 +837,7 @@ class okx(ccxt.async_support.okx):
836
837
  for i in range(0, len(deltas)):
837
838
  self.handle_delta(bookside, deltas[i])
838
839
 
839
- def handle_order_book_message(self, client: Client, message, orderbook, messageHash):
840
+ def handle_order_book_message(self, client: Client, message, orderbook, messageHash, market=None):
840
841
  #
841
842
  # {
842
843
  # "asks": [
@@ -851,6 +852,9 @@ class okx(ccxt.async_support.okx):
851
852
  # ],
852
853
  # "instId": "BTC-USDT",
853
854
  # "ts": "1626537446491"
855
+ # "checksum": -855196043,
856
+ # "prevSeqId": 123456,
857
+ # "seqId": 123457
854
858
  # }
855
859
  #
856
860
  asks = self.safe_value(message, 'asks', [])
@@ -860,9 +864,12 @@ class okx(ccxt.async_support.okx):
860
864
  self.handle_deltas(storedAsks, asks)
861
865
  self.handle_deltas(storedBids, bids)
862
866
  marketId = self.safe_string(message, 'instId')
863
- symbol = self.safe_symbol(marketId)
867
+ symbol = self.safe_symbol(marketId, market)
864
868
  checksum = self.handle_option('watchOrderBook', 'checksum', True)
869
+ seqId = self.safe_integer(message, 'seqId')
865
870
  if checksum:
871
+ prevSeqId = self.safe_integer(message, 'prevSeqId')
872
+ nonce = orderbook['nonce']
866
873
  asksLength = len(storedAsks)
867
874
  bidsLength = len(storedBids)
868
875
  payloadArray = []
@@ -876,12 +883,17 @@ class okx(ccxt.async_support.okx):
876
883
  payload = ':'.join(payloadArray)
877
884
  responseChecksum = self.safe_integer(message, 'checksum')
878
885
  localChecksum = self.crc32(payload, True)
886
+ error = None
887
+ if prevSeqId != -1 and nonce != prevSeqId:
888
+ error = InvalidNonce(self.id + ' watchOrderBook received invalid nonce')
879
889
  if responseChecksum != localChecksum:
880
890
  error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
891
+ if error is not None:
881
892
  del client.subscriptions[messageHash]
882
893
  del self.orderbooks[symbol]
883
894
  client.reject(error, messageHash)
884
895
  timestamp = self.safe_integer(message, 'ts')
896
+ orderbook['nonce'] = seqId
885
897
  orderbook['timestamp'] = timestamp
886
898
  orderbook['datetime'] = self.iso8601(timestamp)
887
899
  return orderbook
@@ -1001,7 +1013,7 @@ class okx(ccxt.async_support.okx):
1001
1013
  orderbook = self.orderbooks[symbol]
1002
1014
  for i in range(0, len(data)):
1003
1015
  update = data[i]
1004
- self.handle_order_book_message(client, update, orderbook, messageHash)
1016
+ self.handle_order_book_message(client, update, orderbook, messageHash, market)
1005
1017
  client.resolve(orderbook, messageHash)
1006
1018
  elif (channel == 'books5') or (channel == 'bbo-tbt'):
1007
1019
  if not (symbol in self.orderbooks):
@@ -1528,7 +1540,7 @@ class okx(ccxt.async_support.okx):
1528
1540
  await self.load_markets()
1529
1541
  await self.authenticate()
1530
1542
  url = self.get_url('private', 'private')
1531
- messageHash = str(self.nonce())
1543
+ messageHash = str(self.milliseconds())
1532
1544
  op = None
1533
1545
  op, params = self.handle_option_and_params(params, 'createOrderWs', 'op', 'batch-orders')
1534
1546
  args = self.create_order_request(symbol, type, side, amount, price, params)
@@ -1593,7 +1605,7 @@ class okx(ccxt.async_support.okx):
1593
1605
  await self.load_markets()
1594
1606
  await self.authenticate()
1595
1607
  url = self.get_url('private', 'private')
1596
- messageHash = str(self.nonce())
1608
+ messageHash = str(self.milliseconds())
1597
1609
  op = None
1598
1610
  op, params = self.handle_option_and_params(params, 'editOrderWs', 'op', 'amend-order')
1599
1611
  args = self.edit_order_request(id, symbol, type, side, amount, price, params)
@@ -1619,7 +1631,7 @@ class okx(ccxt.async_support.okx):
1619
1631
  await self.load_markets()
1620
1632
  await self.authenticate()
1621
1633
  url = self.get_url('private', 'private')
1622
- messageHash = str(self.nonce())
1634
+ messageHash = str(self.milliseconds())
1623
1635
  clientOrderId = self.safe_string_2(params, 'clOrdId', 'clientOrderId')
1624
1636
  params = self.omit(params, ['clientOrderId', 'clOrdId'])
1625
1637
  arg: dict = {
@@ -1653,7 +1665,7 @@ class okx(ccxt.async_support.okx):
1653
1665
  await self.load_markets()
1654
1666
  await self.authenticate()
1655
1667
  url = self.get_url('private', 'private')
1656
- messageHash = str(self.nonce())
1668
+ messageHash = str(self.milliseconds())
1657
1669
  args = []
1658
1670
  for i in range(0, idsLength):
1659
1671
  arg: dict = {
@@ -1684,7 +1696,7 @@ class okx(ccxt.async_support.okx):
1684
1696
  if market['type'] != 'option':
1685
1697
  raise BadRequest(self.id + 'cancelAllOrdersWs is only applicable to Option in Portfolio Margin mode, and MMP privilege is required.')
1686
1698
  url = self.get_url('private', 'private')
1687
- messageHash = str(self.nonce())
1699
+ messageHash = str(self.milliseconds())
1688
1700
  request: dict = {
1689
1701
  'id': messageHash,
1690
1702
  'op': 'mass-cancel',
@@ -1728,7 +1740,7 @@ class okx(ccxt.async_support.okx):
1728
1740
  future = self.safe_value(client.futures, 'authenticated')
1729
1741
  future.resolve(True)
1730
1742
 
1731
- def ping(self, client):
1743
+ def ping(self, client: Client):
1732
1744
  # OKX does not support the built-in WebSocket protocol-level ping-pong.
1733
1745
  # Instead, it requires a custom text-based ping-pong mechanism.
1734
1746
  return 'ping'
ccxt/pro/oxfun.py CHANGED
@@ -914,7 +914,7 @@ class oxfun(ccxt.async_support.oxfun):
914
914
  if messageHash in client.subscriptions:
915
915
  del client.subscriptions[messageHash]
916
916
 
917
- def ping(self, client):
917
+ def ping(self, client: Client):
918
918
  return 'ping'
919
919
 
920
920
  def handle_pong(self, client: Client, message):
ccxt/pro/p2b.py CHANGED
@@ -388,7 +388,7 @@ class p2b(ccxt.async_support.p2b):
388
388
  raise ExchangeError(self.id + ' error: ' + self.json(error))
389
389
  return False
390
390
 
391
- def ping(self, client):
391
+ def ping(self, client: Client):
392
392
  """
393
393
  :see: https://github.com/P2B-team/P2B-WSS-Public/blob/main/wss_documentation.md#ping
394
394
  * @param client
ccxt/pro/poloniex.py CHANGED
@@ -1160,7 +1160,7 @@ class poloniex(ccxt.async_support.poloniex):
1160
1160
  del client.subscriptions[messageHash]
1161
1161
  return message
1162
1162
 
1163
- def ping(self, client):
1163
+ def ping(self, client: Client):
1164
1164
  return {
1165
1165
  'event': 'ping',
1166
1166
  }
ccxt/pro/whitebit.py CHANGED
@@ -856,7 +856,7 @@ class whitebit(ccxt.async_support.whitebit):
856
856
  client.lastPong = self.milliseconds()
857
857
  return message
858
858
 
859
- def ping(self, client):
859
+ def ping(self, client: Client):
860
860
  return {
861
861
  'id': 0,
862
862
  'method': 'ping',
ccxt/test/tests_async.py CHANGED
@@ -3,7 +3,7 @@
3
3
  import asyncio
4
4
 
5
5
 
6
- from tests_helpers import get_cli_arg_value, dump, exit_script, get_test_files, init_exchange, set_exchange_prop, call_method, exception_message, io_file_exists, io_file_read, baseMainTestClass, AuthenticationError, NotSupported, OperationFailed, OnMaintenance, ExchangeNotAvailable, InvalidProxySettings, get_exchange_prop, close, json_parse, json_stringify, is_null_value, io_dir_read, convert_ascii, call_exchange_method_dynamically, set_fetch_response, call_exchange_method_dynamically_sync # noqa: F401
6
+ from tests_helpers import AuthenticationError, NotSupported, InvalidProxySettings, ExchangeNotAvailable, OperationFailed, OnMaintenance, get_cli_arg_value, baseMainTestClass, dump, json_parse, json_stringify, convert_ascii, io_file_exists, io_file_read, io_dir_read, call_method, call_method_sync, call_exchange_method_dynamically, call_exchange_method_dynamically_sync, exception_message, exit_script, get_exchange_prop, set_exchange_prop, init_exchange, get_test_files_sync, get_test_files, set_fetch_response, is_null_value, close # noqa: F401
7
7
 
8
8
  class testMainClass(baseMainTestClass):
9
9
  def parse_cli_args(self):
@@ -72,7 +72,10 @@ class testMainClass(baseMainTestClass):
72
72
  async def import_files(self, exchange):
73
73
  properties = list(exchange.has.keys())
74
74
  properties.append('loadMarkets')
75
- self.test_files = await get_test_files(properties, self.ws_tests)
75
+ if self.is_synchronous:
76
+ self.test_files = get_test_files_sync(properties, self.ws_tests)
77
+ else:
78
+ self.test_files = await get_test_files(properties, self.ws_tests)
76
79
 
77
80
  def load_credentials_from_env(self, exchange):
78
81
  exchange_id = exchange.id
@@ -192,7 +195,10 @@ class testMainClass(baseMainTestClass):
192
195
  if self.info:
193
196
  args_stringified = '(' + exchange.json(args) + ')' # args.join() breaks when we provide a list of symbols or multidimensional array; "args.toString()" breaks bcz of "array to string conversion"
194
197
  dump(self.add_padding('[INFO] TESTING', 25), self.exchange_hint(exchange), method_name, args_stringified)
195
- await call_method(self.test_files, method_name, exchange, skipped_properties_for_method, args)
198
+ if self.is_synchronous:
199
+ call_method_sync(self.test_files, method_name, exchange, skipped_properties_for_method, args)
200
+ else:
201
+ await call_method(self.test_files, method_name, exchange, skipped_properties_for_method, args)
196
202
  if self.info:
197
203
  dump(self.add_padding('[INFO] TESTING DONE', 25), self.exchange_hint(exchange), method_name)
198
204
  # add to the list of successed tests
@@ -587,7 +593,7 @@ class testMainClass(baseMainTestClass):
587
593
  if exception is not None:
588
594
  error_message = '[TEST_FAILURE] Failed ' + proxy_test_name + ' : ' + exception_message(exception)
589
595
  # temporary comment the below, because c# transpilation failure
590
- # throw new ExchangeError (errorMessage.toString ());
596
+ # throw new Exchange Error (errorMessage.toString ());
591
597
  dump('[TEST_WARNING]' + str(error_message))
592
598
 
593
599
  async def start_test(self, exchange, symbol):
@@ -599,16 +605,19 @@ class testMainClass(baseMainTestClass):
599
605
  try:
600
606
  result = await self.load_exchange(exchange)
601
607
  if not result:
602
- await close(exchange)
608
+ if not self.is_synchronous:
609
+ await close(exchange)
603
610
  return
604
611
  # if (exchange.id === 'binance') {
605
612
  # # we test proxies functionality just for one random exchange on each build, because proxy functionality is not exchange-specific, instead it's all done from base methods, so just one working sample would mean it works for all ccxt exchanges
606
613
  # # await this.testProxies (exchange);
607
614
  # }
608
615
  await self.test_exchange(exchange, symbol)
609
- await close(exchange)
616
+ if not self.is_synchronous:
617
+ await close(exchange)
610
618
  except Exception as e:
611
- await close(exchange)
619
+ if not self.is_synchronous:
620
+ await close(exchange)
612
621
  raise e
613
622
 
614
623
  def assert_static_error(self, cond, message, calculated_output, stored_output, key=None):
@@ -1076,7 +1085,8 @@ class testMainClass(baseMainTestClass):
1076
1085
  assert client_order_id_swap.startswith(swap_id_string), 'binance - swap clientOrderId: ' + client_order_id_swap + ' does not start with swapId' + swap_id_string
1077
1086
  client_order_id_inverse = swap_inverse_order_request['newClientOrderId']
1078
1087
  assert client_order_id_inverse.startswith(swap_id_string), 'binance - swap clientOrderIdInverse: ' + client_order_id_inverse + ' does not start with swapId' + swap_id_string
1079
- await close(exchange)
1088
+ if not self.is_synchronous:
1089
+ await close(exchange)
1080
1090
  return True
1081
1091
 
1082
1092
  async def test_okx(self):
@@ -1101,7 +1111,8 @@ class testMainClass(baseMainTestClass):
1101
1111
  assert client_order_id_swap.startswith(id_string), 'okx - swap clientOrderId: ' + client_order_id_swap + ' does not start with id: ' + id_string
1102
1112
  swap_tag = swap_order_request[0]['tag']
1103
1113
  assert swap_tag == id, 'okx - id: ' + id + ' different from swap tag: ' + swap_tag
1104
- await close(exchange)
1114
+ if not self.is_synchronous:
1115
+ await close(exchange)
1105
1116
  return True
1106
1117
 
1107
1118
  async def test_cryptocom(self):
@@ -1115,7 +1126,8 @@ class testMainClass(baseMainTestClass):
1115
1126
  request = json_parse(exchange.last_request_body)
1116
1127
  broker_id = request['params']['broker_id']
1117
1128
  assert broker_id == id, 'cryptocom - id: ' + id + ' different from broker_id: ' + broker_id
1118
- await close(exchange)
1129
+ if not self.is_synchronous:
1130
+ await close(exchange)
1119
1131
  return True
1120
1132
 
1121
1133
  async def test_bybit(self):
@@ -1129,7 +1141,8 @@ class testMainClass(baseMainTestClass):
1129
1141
  # we expect an error here, we're only interested in the headers
1130
1142
  req_headers = exchange.last_request_headers
1131
1143
  assert req_headers['Referer'] == id, 'bybit - id: ' + id + ' not in headers.'
1132
- await close(exchange)
1144
+ if not self.is_synchronous:
1145
+ await close(exchange)
1133
1146
  return True
1134
1147
 
1135
1148
  async def test_kucoin(self):
@@ -1146,7 +1159,8 @@ class testMainClass(baseMainTestClass):
1146
1159
  req_headers = exchange.last_request_headers
1147
1160
  id = 'ccxt'
1148
1161
  assert req_headers['KC-API-PARTNER'] == id, 'kucoin - id: ' + id + ' not in headers.'
1149
- await close(exchange)
1162
+ if not self.is_synchronous:
1163
+ await close(exchange)
1150
1164
  return True
1151
1165
 
1152
1166
  async def test_kucoinfutures(self):
@@ -1162,7 +1176,8 @@ class testMainClass(baseMainTestClass):
1162
1176
  except Exception as e:
1163
1177
  req_headers = exchange.last_request_headers
1164
1178
  assert req_headers['KC-API-PARTNER'] == id, 'kucoinfutures - id: ' + id + ' not in headers.'
1165
- await close(exchange)
1179
+ if not self.is_synchronous:
1180
+ await close(exchange)
1166
1181
  return True
1167
1182
 
1168
1183
  async def test_bitget(self):
@@ -1175,7 +1190,8 @@ class testMainClass(baseMainTestClass):
1175
1190
  except Exception as e:
1176
1191
  req_headers = exchange.last_request_headers
1177
1192
  assert req_headers['X-CHANNEL-API-CODE'] == id, 'bitget - id: ' + id + ' not in headers.'
1178
- await close(exchange)
1193
+ if not self.is_synchronous:
1194
+ await close(exchange)
1179
1195
  return True
1180
1196
 
1181
1197
  async def test_mexc(self):
@@ -1189,7 +1205,8 @@ class testMainClass(baseMainTestClass):
1189
1205
  except Exception as e:
1190
1206
  req_headers = exchange.last_request_headers
1191
1207
  assert req_headers['source'] == id, 'mexc - id: ' + id + ' not in headers.'
1192
- await close(exchange)
1208
+ if not self.is_synchronous:
1209
+ await close(exchange)
1193
1210
  return True
1194
1211
 
1195
1212
  async def test_htx(self):
@@ -1219,7 +1236,8 @@ class testMainClass(baseMainTestClass):
1219
1236
  assert client_order_id_swap.startswith(id_string), 'htx - swap channel_code ' + client_order_id_swap + ' does not start with id: ' + id_string
1220
1237
  client_order_id_inverse = swap_inverse_order_request['channel_code']
1221
1238
  assert client_order_id_inverse.startswith(id_string), 'htx - swap inverse channel_code ' + client_order_id_inverse + ' does not start with id: ' + id_string
1222
- await close(exchange)
1239
+ if not self.is_synchronous:
1240
+ await close(exchange)
1223
1241
  return True
1224
1242
 
1225
1243
  async def test_woo(self):
@@ -1244,7 +1262,8 @@ class testMainClass(baseMainTestClass):
1244
1262
  stop_order_request = json_parse(exchange.last_request_body)
1245
1263
  client_order_id_stop = stop_order_request['brokerId']
1246
1264
  assert client_order_id_stop.startswith(id_string), 'woo - brokerId: ' + client_order_id_stop + ' does not start with id: ' + id_string
1247
- await close(exchange)
1265
+ if not self.is_synchronous:
1266
+ await close(exchange)
1248
1267
  return True
1249
1268
 
1250
1269
  async def test_bitmart(self):
@@ -1258,7 +1277,8 @@ class testMainClass(baseMainTestClass):
1258
1277
  except Exception as e:
1259
1278
  req_headers = exchange.last_request_headers
1260
1279
  assert req_headers['X-BM-BROKER-ID'] == id, 'bitmart - id: ' + id + ' not in headers'
1261
- await close(exchange)
1280
+ if not self.is_synchronous:
1281
+ await close(exchange)
1262
1282
  return True
1263
1283
 
1264
1284
  async def test_coinex(self):
@@ -1273,7 +1293,8 @@ class testMainClass(baseMainTestClass):
1273
1293
  client_order_id = spot_order_request['client_id']
1274
1294
  id_string = str(id)
1275
1295
  assert client_order_id.startswith(id_string), 'coinex - clientOrderId: ' + client_order_id + ' does not start with id: ' + id_string
1276
- await close(exchange)
1296
+ if not self.is_synchronous:
1297
+ await close(exchange)
1277
1298
  return True
1278
1299
 
1279
1300
  async def test_bingx(self):
@@ -1287,7 +1308,8 @@ class testMainClass(baseMainTestClass):
1287
1308
  # we expect an error here, we're only interested in the headers
1288
1309
  req_headers = exchange.last_request_headers
1289
1310
  assert req_headers['X-SOURCE-KEY'] == id, 'bingx - id: ' + id + ' not in headers.'
1290
- await close(exchange)
1311
+ if not self.is_synchronous:
1312
+ await close(exchange)
1291
1313
 
1292
1314
  async def test_phemex(self):
1293
1315
  exchange = self.init_offline_exchange('phemex')
@@ -1300,7 +1322,8 @@ class testMainClass(baseMainTestClass):
1300
1322
  client_order_id = request['clOrdID']
1301
1323
  id_string = str(id)
1302
1324
  assert client_order_id.startswith(id_string), 'phemex - clOrdID: ' + client_order_id + ' does not start with id: ' + id_string
1303
- await close(exchange)
1325
+ if not self.is_synchronous:
1326
+ await close(exchange)
1304
1327
 
1305
1328
  async def test_blofin(self):
1306
1329
  exchange = self.init_offline_exchange('blofin')
@@ -1313,7 +1336,8 @@ class testMainClass(baseMainTestClass):
1313
1336
  broker_id = request['brokerId']
1314
1337
  id_string = str(id)
1315
1338
  assert broker_id.startswith(id_string), 'blofin - brokerId: ' + broker_id + ' does not start with id: ' + id_string
1316
- await close(exchange)
1339
+ if not self.is_synchronous:
1340
+ await close(exchange)
1317
1341
 
1318
1342
  async def test_hyperliquid(self):
1319
1343
  exchange = self.init_offline_exchange('hyperliquid')
@@ -1325,7 +1349,8 @@ class testMainClass(baseMainTestClass):
1325
1349
  request = json_parse(exchange.last_request_body)
1326
1350
  broker_id = str((request['action']['brokerCode']))
1327
1351
  assert broker_id == id, 'hyperliquid - brokerId: ' + broker_id + ' does not start with id: ' + id
1328
- await close(exchange)
1352
+ if not self.is_synchronous:
1353
+ await close(exchange)
1329
1354
 
1330
1355
  async def test_coinbaseinternational(self):
1331
1356
  exchange = self.init_offline_exchange('coinbaseinternational')
@@ -1339,7 +1364,8 @@ class testMainClass(baseMainTestClass):
1339
1364
  request = json_parse(exchange.last_request_body)
1340
1365
  client_order_id = request['client_order_id']
1341
1366
  assert client_order_id.startswith(str(id)), 'clientOrderId does not start with id'
1342
- await close(exchange)
1367
+ if not self.is_synchronous:
1368
+ await close(exchange)
1343
1369
  return True
1344
1370
 
1345
1371
  async def test_coinbase_advanced(self):
@@ -1353,7 +1379,8 @@ class testMainClass(baseMainTestClass):
1353
1379
  request = json_parse(exchange.last_request_body)
1354
1380
  client_order_id = request['client_order_id']
1355
1381
  assert client_order_id.startswith(str(id)), 'clientOrderId does not start with id'
1356
- await close(exchange)
1382
+ if not self.is_synchronous:
1383
+ await close(exchange)
1357
1384
  return True
1358
1385
 
1359
1386
  async def test_woofi_pro(self):
@@ -1368,7 +1395,8 @@ class testMainClass(baseMainTestClass):
1368
1395
  request = json_parse(exchange.last_request_body)
1369
1396
  broker_id = request['order_tag']
1370
1397
  assert broker_id == id, 'woofipro - id: ' + id + ' different from broker_id: ' + broker_id
1371
- await close(exchange)
1398
+ if not self.is_synchronous:
1399
+ await close(exchange)
1372
1400
  return True
1373
1401
 
1374
1402
  async def test_oxfun(self):
@@ -1404,7 +1432,8 @@ class testMainClass(baseMainTestClass):
1404
1432
  swap_order_request = json_parse(exchange.last_request_body)
1405
1433
  swap_media = swap_order_request['clientMedia']
1406
1434
  assert swap_media == id, 'xt - id: ' + id + ' different from swap tag: ' + swap_media
1407
- await close(exchange)
1435
+ if not self.is_synchronous:
1436
+ await close(exchange)
1408
1437
  return True
1409
1438
 
1410
1439
  async def test_vertex(self):
@@ -1426,5 +1455,6 @@ class testMainClass(baseMainTestClass):
1426
1455
  order = request['place_order']
1427
1456
  broker_id = order['id']
1428
1457
  assert broker_id == id, 'vertex - id: ' + str(id) + ' different from broker_id: ' + str(broker_id)
1429
- await close(exchange)
1458
+ if not self.is_synchronous:
1459
+ await close(exchange)
1430
1460
  return True
@@ -191,6 +191,10 @@ def io_dir_read(path):
191
191
  return os.listdir(path)
192
192
 
193
193
 
194
+ def call_method_sync(test_files, methodName, exchange, skippedProperties, args):
195
+ methodNameToCall = 'test_' + convert_to_snake_case(methodName)
196
+ return getattr(test_files[methodName], methodNameToCall)(exchange, skippedProperties, *args)
197
+
194
198
  async def call_method(test_files, methodName, exchange, skippedProperties, args):
195
199
  methodNameToCall = 'test_' + convert_to_snake_case(methodName)
196
200
  return await getattr(test_files[methodName], methodNameToCall)(exchange, skippedProperties, *args)
@@ -240,7 +244,7 @@ def init_exchange(exchangeId, args, is_ws=False):
240
244
  return getattr(ccxt, exchangeId)(args)
241
245
 
242
246
 
243
- async def get_test_files(properties, ws=False):
247
+ def get_test_files_sync(properties, ws=False):
244
248
  tests = {}
245
249
  finalPropList = properties + [proxyTestFileName]
246
250
  for i in range(0, len(finalPropList)):
@@ -259,6 +263,9 @@ async def get_test_files(properties, ws=False):
259
263
  tests[methodName] = imp # getattr(imp, finalName)
260
264
  return tests
261
265
 
266
+ async def get_test_files(properties, ws=False):
267
+ return get_test_files_sync(properties, ws)
268
+
262
269
  async def close(exchange):
263
270
  if (not is_synchronous and hasattr(exchange, 'close')):
264
271
  await exchange.close()