ccxt 4.4.12__py2.py3-none-any.whl → 4.4.14__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/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/abstract/cryptocom.py +1 -0
  7. ccxt/async_support/__init__.py +1 -1
  8. ccxt/async_support/base/exchange.py +37 -1
  9. ccxt/async_support/bigone.py +2 -0
  10. ccxt/async_support/binance.py +113 -12
  11. ccxt/async_support/bingx.py +69 -3
  12. ccxt/async_support/bitget.py +102 -3
  13. ccxt/async_support/bitmex.py +1 -0
  14. ccxt/async_support/bitrue.py +1 -7
  15. ccxt/async_support/bitvavo.py +1 -3
  16. ccxt/async_support/bybit.py +2 -0
  17. ccxt/async_support/coinbaseinternational.py +2 -0
  18. ccxt/async_support/coinex.py +15 -1
  19. ccxt/async_support/cryptocom.py +1 -0
  20. ccxt/async_support/delta.py +2 -0
  21. ccxt/async_support/deribit.py +2 -0
  22. ccxt/async_support/digifinex.py +15 -1
  23. ccxt/async_support/gate.py +2 -0
  24. ccxt/async_support/htx.py +2 -2
  25. ccxt/async_support/huobijp.py +1 -3
  26. ccxt/async_support/krakenfutures.py +2 -0
  27. ccxt/async_support/kucoin.py +36 -1
  28. ccxt/async_support/kucoinfutures.py +56 -3
  29. ccxt/async_support/mexc.py +52 -8
  30. ccxt/async_support/okx.py +48 -0
  31. ccxt/async_support/oxfun.py +1 -0
  32. ccxt/async_support/paradex.py +1 -0
  33. ccxt/async_support/poloniex.py +1 -0
  34. ccxt/async_support/poloniexfutures.py +35 -11
  35. ccxt/async_support/woo.py +12 -0
  36. ccxt/async_support/woofipro.py +12 -0
  37. ccxt/async_support/xt.py +12 -0
  38. ccxt/base/exchange.py +44 -2
  39. ccxt/base/types.py +2 -0
  40. ccxt/bigone.py +2 -0
  41. ccxt/binance.py +113 -12
  42. ccxt/bingx.py +69 -3
  43. ccxt/bitget.py +102 -3
  44. ccxt/bitmex.py +1 -0
  45. ccxt/bitrue.py +1 -7
  46. ccxt/bitvavo.py +1 -3
  47. ccxt/bybit.py +2 -0
  48. ccxt/coinbaseinternational.py +2 -0
  49. ccxt/coinex.py +15 -1
  50. ccxt/cryptocom.py +1 -0
  51. ccxt/delta.py +2 -0
  52. ccxt/deribit.py +2 -0
  53. ccxt/digifinex.py +15 -1
  54. ccxt/gate.py +2 -0
  55. ccxt/htx.py +2 -2
  56. ccxt/huobijp.py +1 -3
  57. ccxt/krakenfutures.py +2 -0
  58. ccxt/kucoin.py +36 -1
  59. ccxt/kucoinfutures.py +56 -3
  60. ccxt/mexc.py +52 -8
  61. ccxt/okx.py +48 -0
  62. ccxt/oxfun.py +1 -0
  63. ccxt/paradex.py +1 -0
  64. ccxt/poloniex.py +1 -0
  65. ccxt/poloniexfutures.py +35 -11
  66. ccxt/pro/__init__.py +1 -1
  67. ccxt/pro/binance.py +72 -5
  68. ccxt/pro/bitfinex.py +8 -8
  69. ccxt/pro/krakenfutures.py +2 -0
  70. ccxt/pro/okx.py +38 -0
  71. ccxt/pro/phemex.py +2 -0
  72. ccxt/pro/woo.py +69 -0
  73. ccxt/test/tests_async.py +76 -48
  74. ccxt/test/tests_helpers.py +27 -36
  75. ccxt/test/tests_init.py +6 -2
  76. ccxt/test/tests_sync.py +76 -48
  77. ccxt/woo.py +12 -0
  78. ccxt/woofipro.py +12 -0
  79. ccxt/xt.py +12 -0
  80. {ccxt-4.4.12.dist-info → ccxt-4.4.14.dist-info}/METADATA +4 -5
  81. {ccxt-4.4.12.dist-info → ccxt-4.4.14.dist-info}/RECORD +84 -84
  82. {ccxt-4.4.12.dist-info → ccxt-4.4.14.dist-info}/LICENSE.txt +0 -0
  83. {ccxt-4.4.12.dist-info → ccxt-4.4.14.dist-info}/WHEEL +0 -0
  84. {ccxt-4.4.12.dist-info → ccxt-4.4.14.dist-info}/top_level.txt +0 -0
ccxt/pro/woo.py CHANGED
@@ -27,6 +27,7 @@ class woo(ccxt.async_support.woo):
27
27
  'watchOrders': True,
28
28
  'watchTicker': True,
29
29
  'watchTickers': True,
30
+ 'watchBidsAsks': True,
30
31
  'watchTrades': True,
31
32
  'watchTradesForSymbols': False,
32
33
  'watchPositions': True,
@@ -383,6 +384,73 @@ class woo(ccxt.async_support.woo):
383
384
  result.append(ticker)
384
385
  client.resolve(result, topic)
385
386
 
387
+ async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
388
+ """
389
+ :see: https://docs.woox.io/#bbos
390
+ watches best bid & ask for symbols
391
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
392
+ :param dict [params]: extra parameters specific to the exchange API endpoint
393
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
394
+ """
395
+ await self.load_markets()
396
+ symbols = self.market_symbols(symbols, None, False)
397
+ name = 'bbos'
398
+ topic = name
399
+ request: dict = {
400
+ 'event': 'subscribe',
401
+ 'topic': topic,
402
+ }
403
+ message = self.extend(request, params)
404
+ tickers = await self.watch_public(topic, message)
405
+ if self.newUpdates:
406
+ return tickers
407
+ return self.filter_by_array(self.bidsasks, 'symbol', symbols)
408
+
409
+ def handle_bid_ask(self, client: Client, message):
410
+ #
411
+ # {
412
+ # "topic": "bbos",
413
+ # "ts": 1618822376000,
414
+ # "data": [
415
+ # {
416
+ # "symbol": "SPOT_FIL_USDT",
417
+ # "ask": 159.0318,
418
+ # "askSize": 370.43,
419
+ # "bid": 158.9158,
420
+ # "bidSize": 16
421
+ # }
422
+ # ]
423
+ # }
424
+ #
425
+ topic = self.safe_string(message, 'topic')
426
+ data = self.safe_list(message, 'data', [])
427
+ timestamp = self.safe_integer(message, 'ts')
428
+ result: dict = {}
429
+ for i in range(0, len(data)):
430
+ ticker = self.safe_dict(data, i)
431
+ ticker['ts'] = timestamp
432
+ parsedTicker = self.parse_ws_bid_ask(ticker)
433
+ symbol = parsedTicker['symbol']
434
+ self.bidsasks[symbol] = parsedTicker
435
+ result[symbol] = parsedTicker
436
+ client.resolve(result, topic)
437
+
438
+ def parse_ws_bid_ask(self, ticker, market=None):
439
+ marketId = self.safe_string(ticker, 'symbol')
440
+ market = self.safe_market(marketId, market)
441
+ symbol = self.safe_string(market, 'symbol')
442
+ timestamp = self.safe_integer(ticker, 'ts')
443
+ return self.safe_ticker({
444
+ 'symbol': symbol,
445
+ 'timestamp': timestamp,
446
+ 'datetime': self.iso8601(timestamp),
447
+ 'ask': self.safe_string(ticker, 'ask'),
448
+ 'askVolume': self.safe_string(ticker, 'askSize'),
449
+ 'bid': self.safe_string(ticker, 'bid'),
450
+ 'bidVolume': self.safe_string(ticker, 'bidSize'),
451
+ 'info': ticker,
452
+ }, market)
453
+
386
454
  async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
387
455
  """
388
456
  watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
@@ -1101,6 +1169,7 @@ class woo(ccxt.async_support.woo):
1101
1169
  'trade': self.handle_trade,
1102
1170
  'balance': self.handle_balance,
1103
1171
  'position': self.handle_positions,
1172
+ 'bbos': self.handle_bid_ask,
1104
1173
  }
1105
1174
  event = self.safe_string(message, 'event')
1106
1175
  method = self.safe_value(methods, event)
ccxt/test/tests_async.py CHANGED
@@ -3,10 +3,34 @@
3
3
  import asyncio
4
4
 
5
5
 
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, get_root_exception, 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
-
8
- class testMainClass(baseMainTestClass):
9
- def parse_cli_args(self):
6
+ from tests_helpers import AuthenticationError, NotSupported, InvalidProxySettings, ExchangeNotAvailable, OperationFailed, OnMaintenance, get_cli_arg_value, get_root_dir, is_sync, 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, get_root_exception, 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, get_env_vars, get_lang, get_ext # noqa: F401
7
+
8
+ class testMainClass:
9
+ id_tests = False
10
+ request_tests_failed = False
11
+ response_tests_failed = False
12
+ request_tests = False
13
+ ws_tests = False
14
+ response_tests = False
15
+ static_tests = False
16
+ info = False
17
+ verbose = False
18
+ debug = False
19
+ private_test = False
20
+ private_test_only = False
21
+ load_keys = False
22
+ sandbox = False
23
+ only_specific_tests = []
24
+ skipped_settings_for_exchange = {}
25
+ skipped_methods = {}
26
+ checked_public_tests = {}
27
+ test_files = {}
28
+ public_tests = {}
29
+ ext = ''
30
+ lang = ''
31
+ proxy_test_file_name = 'proxies'
32
+
33
+ def parse_cli_args_and_props(self):
10
34
  self.response_tests = get_cli_arg_value('--responseTests')
11
35
  self.id_tests = get_cli_arg_value('--idTests')
12
36
  self.request_tests = get_cli_arg_value('--requestTests')
@@ -18,9 +42,11 @@ class testMainClass(baseMainTestClass):
18
42
  self.sandbox = get_cli_arg_value('--sandbox')
19
43
  self.load_keys = get_cli_arg_value('--loadKeys')
20
44
  self.ws_tests = get_cli_arg_value('--ws')
45
+ self.lang = get_lang()
46
+ self.ext = get_ext()
21
47
 
22
48
  async def init(self, exchange_id, symbol_argv, method_argv):
23
- self.parse_cli_args()
49
+ self.parse_cli_args_and_props()
24
50
  if self.request_tests and self.response_tests:
25
51
  await self.run_static_request_tests(exchange_id, symbol_argv)
26
52
  await self.run_static_response_tests(exchange_id, symbol_argv)
@@ -34,12 +60,13 @@ class testMainClass(baseMainTestClass):
34
60
  if self.id_tests:
35
61
  await self.run_broker_id_tests()
36
62
  return
37
- dump(self.new_line + '' + self.new_line + '' + '[INFO] TESTING ', self.ext, {
63
+ new_line = '\n'
64
+ dump(new_line + '' + new_line + '' + '[INFO] TESTING ', self.ext, {
38
65
  'exchange': exchange_id,
39
66
  'symbol': symbol_argv,
40
67
  'method': method_argv,
41
68
  'isWs': self.ws_tests,
42
- }, self.new_line)
69
+ }, new_line)
43
70
  exchange_args = {
44
71
  'verbose': self.verbose,
45
72
  'debug': self.debug,
@@ -72,7 +99,7 @@ class testMainClass(baseMainTestClass):
72
99
  async def import_files(self, exchange):
73
100
  properties = list(exchange.has.keys())
74
101
  properties.append('loadMarkets')
75
- if self.is_synchronous:
102
+ if is_sync():
76
103
  self.test_files = get_test_files_sync(properties, self.ws_tests)
77
104
  else:
78
105
  self.test_files = await get_test_files(properties, self.ws_tests)
@@ -87,14 +114,15 @@ class testMainClass(baseMainTestClass):
87
114
  if is_required and get_exchange_prop(exchange, credential) is None:
88
115
  full_key = exchange_id + '_' + credential
89
116
  credential_env_name = full_key.upper() # example: KRAKEN_APIKEY
90
- credential_value = self.env_vars[credential_env_name] if (credential_env_name in self.env_vars) else None
117
+ env_vars = get_env_vars()
118
+ credential_value = env_vars[credential_env_name] if (credential_env_name in env_vars) else None
91
119
  if credential_value:
92
120
  set_exchange_prop(exchange, credential, credential_value)
93
121
 
94
122
  def expand_settings(self, exchange):
95
123
  exchange_id = exchange.id
96
- keys_global = self.root_dir + 'keys.json'
97
- keys_local = self.root_dir + 'keys.local.json'
124
+ keys_global = get_root_dir() + 'keys.json'
125
+ keys_local = get_root_dir() + 'keys.local.json'
98
126
  keys_global_exists = io_file_exists(keys_global)
99
127
  keys_local_exists = io_file_exists(keys_local)
100
128
  global_settings = io_file_read(keys_global) if keys_global_exists else {}
@@ -117,7 +145,7 @@ class testMainClass(baseMainTestClass):
117
145
  if self.load_keys:
118
146
  self.load_credentials_from_env(exchange)
119
147
  # skipped tests
120
- skipped_file = self.root_dir_for_skips + 'skip-tests.json'
148
+ skipped_file = get_root_dir() + 'skip-tests.json'
121
149
  skipped_settings = io_file_read(skipped_file)
122
150
  self.skipped_settings_for_exchange = exchange.safe_value(skipped_settings, exchange_id, {})
123
151
  skipped_settings_for_exchange = self.skipped_settings_for_exchange
@@ -178,7 +206,7 @@ class testMainClass(baseMainTestClass):
178
206
  if self.info:
179
207
  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"
180
208
  dump(self.add_padding('[INFO] TESTING', 25), name, method_name, args_stringified)
181
- if self.is_synchronous:
209
+ if is_sync():
182
210
  call_method_sync(self.test_files, method_name, exchange, skipped_properties_for_method, args)
183
211
  else:
184
212
  await call_method(self.test_files, method_name, exchange, skipped_properties_for_method, args)
@@ -561,7 +589,7 @@ class testMainClass(baseMainTestClass):
561
589
  # these tests should be synchronously executed, because of conflicting nature of proxy settings
562
590
  proxy_test_name = self.proxy_test_file_name
563
591
  # todo: temporary skip for sync py
564
- if self.ext == 'py' and self.is_synchronous:
592
+ if self.ext == 'py' and is_sync():
565
593
  return
566
594
  # try proxy several times
567
595
  max_retries = 3
@@ -589,7 +617,7 @@ class testMainClass(baseMainTestClass):
589
617
  try:
590
618
  result = await self.load_exchange(exchange)
591
619
  if not result:
592
- if not self.is_synchronous:
620
+ if not is_sync():
593
621
  await close(exchange)
594
622
  return
595
623
  # if (exchange.id === 'binance') {
@@ -597,10 +625,10 @@ class testMainClass(baseMainTestClass):
597
625
  # # await this.testProxies (exchange);
598
626
  # }
599
627
  await self.test_exchange(exchange, symbol)
600
- if not self.is_synchronous:
628
+ if not is_sync():
601
629
  await close(exchange)
602
630
  except Exception as e:
603
- if not self.is_synchronous:
631
+ if not is_sync():
604
632
  await close(exchange)
605
633
  raise e
606
634
 
@@ -620,12 +648,12 @@ class testMainClass(baseMainTestClass):
620
648
  # to make this test as fast as possible
621
649
  # and basically independent from the exchange
622
650
  # so we can run it offline
623
- filename = self.root_dir + './ts/src/test/static/markets/' + id + '.json'
651
+ filename = get_root_dir() + './ts/src/test/static/markets/' + id + '.json'
624
652
  content = io_file_read(filename)
625
653
  return content
626
654
 
627
655
  def load_currencies_from_file(self, id):
628
- filename = self.root_dir + './ts/src/test/static/currencies/' + id + '.json'
656
+ filename = get_root_dir() + './ts/src/test/static/currencies/' + id + '.json'
629
657
  content = io_file_read(filename)
630
658
  return content
631
659
 
@@ -815,7 +843,7 @@ class testMainClass(baseMainTestClass):
815
843
  output = None
816
844
  request_url = None
817
845
  try:
818
- if not self.is_synchronous:
846
+ if not is_sync():
819
847
  await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
820
848
  else:
821
849
  call_exchange_method_dynamically_sync(exchange, method, self.sanitize_data_input(data['input']))
@@ -836,7 +864,7 @@ class testMainClass(baseMainTestClass):
836
864
  expected_result = exchange.safe_value(data, 'parsedResponse')
837
865
  mocked_exchange = set_fetch_response(exchange, data['httpResponse'])
838
866
  try:
839
- if not self.is_synchronous:
867
+ if not is_sync():
840
868
  unified_result = await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
841
869
  self.assert_static_response_output(mocked_exchange, skip_keys, unified_result, expected_result)
842
870
  else:
@@ -932,7 +960,7 @@ class testMainClass(baseMainTestClass):
932
960
  # reset options
933
961
  # exchange.options = exchange.deepExtend (oldExchangeOptions, {});
934
962
  exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
935
- if not self.is_synchronous:
963
+ if not is_sync():
936
964
  await close(exchange)
937
965
  return True # in c# methods that will be used with promiseAll need to return something
938
966
 
@@ -982,7 +1010,7 @@ class testMainClass(baseMainTestClass):
982
1010
  # reset options
983
1011
  # exchange.options = exchange.deepExtend (oldExchangeOptions, {});
984
1012
  exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
985
- if not self.is_synchronous:
1013
+ if not is_sync():
986
1014
  await close(exchange)
987
1015
  return True # in c# methods that will be used with promiseAll need to return something
988
1016
 
@@ -1003,7 +1031,7 @@ class testMainClass(baseMainTestClass):
1003
1031
  await self.run_static_tests('request', target_exchange, test_name)
1004
1032
 
1005
1033
  async def run_static_tests(self, type, target_exchange=None, test_name=None):
1006
- folder = self.root_dir + './ts/src/test/static/' + type + '/'
1034
+ folder = get_root_dir() + './ts/src/test/static/' + type + '/'
1007
1035
  static_data = self.load_static_data(folder, target_exchange)
1008
1036
  if static_data is None:
1009
1037
  return
@@ -1028,7 +1056,7 @@ class testMainClass(baseMainTestClass):
1028
1056
  if self.request_tests_failed or self.response_tests_failed:
1029
1057
  exit_script(1)
1030
1058
  else:
1031
- prefix = '[SYNC]' if (self.is_synchronous) else ''
1059
+ prefix = '[SYNC]' if (is_sync()) else ''
1032
1060
  success_message = '[' + self.lang + ']' + prefix + '[TEST_SUCCESS] ' + str(sum) + ' static ' + type + ' tests passed.'
1033
1061
  dump('[INFO]' + success_message)
1034
1062
 
@@ -1075,7 +1103,7 @@ class testMainClass(baseMainTestClass):
1075
1103
  assert client_order_id_swap.startswith(swap_id_string), 'binance - swap clientOrderId: ' + client_order_id_swap + ' does not start with swapId' + swap_id_string
1076
1104
  client_order_id_inverse = swap_inverse_order_request['newClientOrderId']
1077
1105
  assert client_order_id_inverse.startswith(swap_id_string), 'binance - swap clientOrderIdInverse: ' + client_order_id_inverse + ' does not start with swapId' + swap_id_string
1078
- if not self.is_synchronous:
1106
+ if not is_sync():
1079
1107
  await close(exchange)
1080
1108
  return True
1081
1109
 
@@ -1101,7 +1129,7 @@ class testMainClass(baseMainTestClass):
1101
1129
  assert client_order_id_swap.startswith(id_string), 'okx - swap clientOrderId: ' + client_order_id_swap + ' does not start with id: ' + id_string
1102
1130
  swap_tag = swap_order_request[0]['tag']
1103
1131
  assert swap_tag == id, 'okx - id: ' + id + ' different from swap tag: ' + swap_tag
1104
- if not self.is_synchronous:
1132
+ if not is_sync():
1105
1133
  await close(exchange)
1106
1134
  return True
1107
1135
 
@@ -1116,7 +1144,7 @@ class testMainClass(baseMainTestClass):
1116
1144
  request = json_parse(exchange.last_request_body)
1117
1145
  broker_id = request['params']['broker_id']
1118
1146
  assert broker_id == id, 'cryptocom - id: ' + id + ' different from broker_id: ' + broker_id
1119
- if not self.is_synchronous:
1147
+ if not is_sync():
1120
1148
  await close(exchange)
1121
1149
  return True
1122
1150
 
@@ -1131,7 +1159,7 @@ class testMainClass(baseMainTestClass):
1131
1159
  # we expect an error here, we're only interested in the headers
1132
1160
  req_headers = exchange.last_request_headers
1133
1161
  assert req_headers['Referer'] == id, 'bybit - id: ' + id + ' not in headers.'
1134
- if not self.is_synchronous:
1162
+ if not is_sync():
1135
1163
  await close(exchange)
1136
1164
  return True
1137
1165
 
@@ -1149,7 +1177,7 @@ class testMainClass(baseMainTestClass):
1149
1177
  req_headers = exchange.last_request_headers
1150
1178
  id = 'ccxt'
1151
1179
  assert req_headers['KC-API-PARTNER'] == id, 'kucoin - id: ' + id + ' not in headers.'
1152
- if not self.is_synchronous:
1180
+ if not is_sync():
1153
1181
  await close(exchange)
1154
1182
  return True
1155
1183
 
@@ -1166,7 +1194,7 @@ class testMainClass(baseMainTestClass):
1166
1194
  except Exception as e:
1167
1195
  req_headers = exchange.last_request_headers
1168
1196
  assert req_headers['KC-API-PARTNER'] == id, 'kucoinfutures - id: ' + id + ' not in headers.'
1169
- if not self.is_synchronous:
1197
+ if not is_sync():
1170
1198
  await close(exchange)
1171
1199
  return True
1172
1200
 
@@ -1180,7 +1208,7 @@ class testMainClass(baseMainTestClass):
1180
1208
  except Exception as e:
1181
1209
  req_headers = exchange.last_request_headers
1182
1210
  assert req_headers['X-CHANNEL-API-CODE'] == id, 'bitget - id: ' + id + ' not in headers.'
1183
- if not self.is_synchronous:
1211
+ if not is_sync():
1184
1212
  await close(exchange)
1185
1213
  return True
1186
1214
 
@@ -1195,7 +1223,7 @@ class testMainClass(baseMainTestClass):
1195
1223
  except Exception as e:
1196
1224
  req_headers = exchange.last_request_headers
1197
1225
  assert req_headers['source'] == id, 'mexc - id: ' + id + ' not in headers.'
1198
- if not self.is_synchronous:
1226
+ if not is_sync():
1199
1227
  await close(exchange)
1200
1228
  return True
1201
1229
 
@@ -1226,7 +1254,7 @@ class testMainClass(baseMainTestClass):
1226
1254
  assert client_order_id_swap.startswith(id_string), 'htx - swap channel_code ' + client_order_id_swap + ' does not start with id: ' + id_string
1227
1255
  client_order_id_inverse = swap_inverse_order_request['channel_code']
1228
1256
  assert client_order_id_inverse.startswith(id_string), 'htx - swap inverse channel_code ' + client_order_id_inverse + ' does not start with id: ' + id_string
1229
- if not self.is_synchronous:
1257
+ if not is_sync():
1230
1258
  await close(exchange)
1231
1259
  return True
1232
1260
 
@@ -1252,7 +1280,7 @@ class testMainClass(baseMainTestClass):
1252
1280
  stop_order_request = json_parse(exchange.last_request_body)
1253
1281
  client_order_id_stop = stop_order_request['brokerId']
1254
1282
  assert client_order_id_stop.startswith(id_string), 'woo - brokerId: ' + client_order_id_stop + ' does not start with id: ' + id_string
1255
- if not self.is_synchronous:
1283
+ if not is_sync():
1256
1284
  await close(exchange)
1257
1285
  return True
1258
1286
 
@@ -1267,7 +1295,7 @@ class testMainClass(baseMainTestClass):
1267
1295
  except Exception as e:
1268
1296
  req_headers = exchange.last_request_headers
1269
1297
  assert req_headers['X-BM-BROKER-ID'] == id, 'bitmart - id: ' + id + ' not in headers'
1270
- if not self.is_synchronous:
1298
+ if not is_sync():
1271
1299
  await close(exchange)
1272
1300
  return True
1273
1301
 
@@ -1283,7 +1311,7 @@ class testMainClass(baseMainTestClass):
1283
1311
  client_order_id = spot_order_request['client_id']
1284
1312
  id_string = str(id)
1285
1313
  assert client_order_id.startswith(id_string), 'coinex - clientOrderId: ' + client_order_id + ' does not start with id: ' + id_string
1286
- if not self.is_synchronous:
1314
+ if not is_sync():
1287
1315
  await close(exchange)
1288
1316
  return True
1289
1317
 
@@ -1298,7 +1326,7 @@ class testMainClass(baseMainTestClass):
1298
1326
  # we expect an error here, we're only interested in the headers
1299
1327
  req_headers = exchange.last_request_headers
1300
1328
  assert req_headers['X-SOURCE-KEY'] == id, 'bingx - id: ' + id + ' not in headers.'
1301
- if not self.is_synchronous:
1329
+ if not is_sync():
1302
1330
  await close(exchange)
1303
1331
 
1304
1332
  async def test_phemex(self):
@@ -1312,7 +1340,7 @@ class testMainClass(baseMainTestClass):
1312
1340
  client_order_id = request['clOrdID']
1313
1341
  id_string = str(id)
1314
1342
  assert client_order_id.startswith(id_string), 'phemex - clOrdID: ' + client_order_id + ' does not start with id: ' + id_string
1315
- if not self.is_synchronous:
1343
+ if not is_sync():
1316
1344
  await close(exchange)
1317
1345
 
1318
1346
  async def test_blofin(self):
@@ -1326,7 +1354,7 @@ class testMainClass(baseMainTestClass):
1326
1354
  broker_id = request['brokerId']
1327
1355
  id_string = str(id)
1328
1356
  assert broker_id.startswith(id_string), 'blofin - brokerId: ' + broker_id + ' does not start with id: ' + id_string
1329
- if not self.is_synchronous:
1357
+ if not is_sync():
1330
1358
  await close(exchange)
1331
1359
 
1332
1360
  async def test_hyperliquid(self):
@@ -1339,7 +1367,7 @@ class testMainClass(baseMainTestClass):
1339
1367
  request = json_parse(exchange.last_request_body)
1340
1368
  broker_id = str((request['action']['brokerCode']))
1341
1369
  assert broker_id == id, 'hyperliquid - brokerId: ' + broker_id + ' does not start with id: ' + id
1342
- if not self.is_synchronous:
1370
+ if not is_sync():
1343
1371
  await close(exchange)
1344
1372
 
1345
1373
  async def test_coinbaseinternational(self):
@@ -1354,7 +1382,7 @@ class testMainClass(baseMainTestClass):
1354
1382
  request = json_parse(exchange.last_request_body)
1355
1383
  client_order_id = request['client_order_id']
1356
1384
  assert client_order_id.startswith(str(id)), 'clientOrderId does not start with id'
1357
- if not self.is_synchronous:
1385
+ if not is_sync():
1358
1386
  await close(exchange)
1359
1387
  return True
1360
1388
 
@@ -1369,7 +1397,7 @@ class testMainClass(baseMainTestClass):
1369
1397
  request = json_parse(exchange.last_request_body)
1370
1398
  client_order_id = request['client_order_id']
1371
1399
  assert client_order_id.startswith(str(id)), 'clientOrderId does not start with id'
1372
- if not self.is_synchronous:
1400
+ if not is_sync():
1373
1401
  await close(exchange)
1374
1402
  return True
1375
1403
 
@@ -1385,7 +1413,7 @@ class testMainClass(baseMainTestClass):
1385
1413
  request = json_parse(exchange.last_request_body)
1386
1414
  broker_id = request['order_tag']
1387
1415
  assert broker_id == id, 'woofipro - id: ' + id + ' different from broker_id: ' + broker_id
1388
- if not self.is_synchronous:
1416
+ if not is_sync():
1389
1417
  await close(exchange)
1390
1418
  return True
1391
1419
 
@@ -1422,7 +1450,7 @@ class testMainClass(baseMainTestClass):
1422
1450
  swap_order_request = json_parse(exchange.last_request_body)
1423
1451
  swap_media = swap_order_request['clientMedia']
1424
1452
  assert swap_media == id, 'xt - id: ' + id + ' different from swap tag: ' + swap_media
1425
- if not self.is_synchronous:
1453
+ if not is_sync():
1426
1454
  await close(exchange)
1427
1455
  return True
1428
1456
 
@@ -1445,7 +1473,7 @@ class testMainClass(baseMainTestClass):
1445
1473
  order = request['place_order']
1446
1474
  broker_id = order['id']
1447
1475
  assert broker_id == id, 'vertex - id: ' + str(id) + ' different from broker_id: ' + str(broker_id)
1448
- if not self.is_synchronous:
1476
+ if not is_sync():
1449
1477
  await close(exchange)
1450
1478
  return True
1451
1479
 
@@ -1487,7 +1515,7 @@ class testMainClass(baseMainTestClass):
1487
1515
  except Exception as e:
1488
1516
  req_headers = exchange.last_request_headers
1489
1517
  assert req_headers['PARADEX-PARTNER'] == id, 'paradex - id: ' + id + ' not in headers'
1490
- if not self.is_synchronous:
1518
+ if not is_sync():
1491
1519
  await close(exchange)
1492
1520
  return True
1493
1521
 
@@ -1501,6 +1529,6 @@ class testMainClass(baseMainTestClass):
1501
1529
  # we expect an error here, we're only interested in the headers
1502
1530
  req_headers = exchange.last_request_headers
1503
1531
  assert req_headers['INPUT-SOURCE'] == id, 'hashkey - id: ' + id + ' not in headers.'
1504
- if not self.is_synchronous:
1532
+ if not is_sync():
1505
1533
  await close(exchange)
1506
1534
  return True
@@ -105,14 +105,15 @@ sys.excepthook = handle_all_unhandled_exceptions
105
105
 
106
106
  # non-transpiled part, but shared names among langs
107
107
 
108
- is_synchronous = argv.sync # 'async' not in os.path.basename(__file__)
109
-
110
- rootDir = DIR_NAME + '/../../../'
111
- rootDirForSkips = DIR_NAME + '/../../../'
112
- envVars = os.environ
108
+ EXT = 'py'
109
+ LANG = 'PY'
110
+ IS_SYNCHRONOUS = argv.sync # 'async' not in os.path.basename(__file__)
111
+ PROXY_TEST_FILE_NAME = 'proxies'
112
+ ROOT_DIR = DIR_NAME + '/../../../'
113
+ ENV_VARS = os.environ
114
+ NEW_LINE = '\n'
113
115
  LOG_CHARS_LENGTH = 10000
114
- ext = 'py'
115
- proxyTestFileName = 'proxies'
116
+
116
117
 
117
118
 
118
119
  def get_cli_arg_value(arg):
@@ -125,30 +126,6 @@ def get_cli_arg_value(arg):
125
126
 
126
127
  isWsTests = get_cli_arg_value('--ws')
127
128
 
128
-
129
- class baseMainTestClass():
130
- lang = 'PY'
131
- is_synchronous = is_synchronous
132
- request_tests_failed = False
133
- response_tests_failed = False
134
- response_tests = False
135
- ws_tests = False
136
- load_keys = False
137
- skipped_settings_for_exchange = {}
138
- skipped_methods = {}
139
- check_public_tests = {}
140
- test_files = {}
141
- public_tests = {}
142
- new_line = '\n'
143
- root_dir = rootDir
144
- env_vars = envVars
145
- ext = ext
146
- root_dir_for_skips = rootDirForSkips
147
- only_specific_tests = []
148
- proxy_test_file_name = proxyTestFileName
149
- pass
150
-
151
-
152
129
  def dump(*args):
153
130
  print(' '.join([str(arg) for arg in args]))
154
131
 
@@ -240,7 +217,7 @@ def set_exchange_prop(exchange, prop, value):
240
217
 
241
218
 
242
219
  def init_exchange(exchangeId, args, is_ws=False):
243
- if is_synchronous:
220
+ if IS_SYNCHRONOUS:
244
221
  return getattr(ccxt_sync, exchangeId)(args)
245
222
  if (is_ws):
246
223
  return getattr(ccxtpro, exchangeId)(args)
@@ -249,11 +226,11 @@ def init_exchange(exchangeId, args, is_ws=False):
249
226
 
250
227
  def get_test_files_sync(properties, ws=False):
251
228
  tests = {}
252
- finalPropList = properties + [proxyTestFileName]
229
+ finalPropList = properties + [PROXY_TEST_FILE_NAME]
253
230
  for i in range(0, len(finalPropList)):
254
231
  methodName = finalPropList[i]
255
232
  name_snake_case = convert_to_snake_case(methodName)
256
- prefix = 'async' if not is_synchronous else 'sync'
233
+ prefix = 'async' if not IS_SYNCHRONOUS else 'sync'
257
234
  dir_to_test = DIR_NAME + '/exchange/' + prefix + '/'
258
235
  module_string = 'ccxt.test.exchange.' + prefix + '.test_' + name_snake_case
259
236
  if (ws):
@@ -270,14 +247,14 @@ async def get_test_files(properties, ws=False):
270
247
  return get_test_files_sync(properties, ws)
271
248
 
272
249
  async def close(exchange):
273
- if (not is_synchronous and hasattr(exchange, 'close')):
250
+ if (not IS_SYNCHRONOUS and hasattr(exchange, 'close')):
274
251
  await exchange.close()
275
252
 
276
253
  def is_null_value(value):
277
254
  return value is None
278
255
 
279
256
  def set_fetch_response(exchange: ccxt.Exchange, data):
280
- if (is_synchronous):
257
+ if (IS_SYNCHRONOUS):
281
258
  def fetch(url, method='GET', headers=None, body=None):
282
259
  return data
283
260
  exchange.fetch = fetch
@@ -287,6 +264,20 @@ def set_fetch_response(exchange: ccxt.Exchange, data):
287
264
  exchange.fetch = fetch
288
265
  return exchange
289
266
 
267
+ def get_lang():
268
+ return LANG
269
+
270
+ def get_ext():
271
+ return EXT
272
+
273
+ def get_root_dir():
274
+ return ROOT_DIR
275
+
276
+ def get_env_vars():
277
+ return ENV_VARS
278
+
279
+ def is_sync():
280
+ return IS_SYNCHRONOUS
290
281
 
291
282
  argvExchange = argv.exchange
292
283
  argvSymbol = argv.symbol if argv.symbol and '/' in argv.symbol else None
ccxt/test/tests_init.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- from tests_helpers import get_cli_arg_value, is_synchronous, argvExchange, argvSymbol, argvMethod
3
+ from tests_helpers import get_cli_arg_value, IS_SYNCHRONOUS, argvExchange, argvSymbol, argvMethod
4
4
 
5
5
  try:
6
6
  import asyncio
@@ -10,6 +10,10 @@ except ImportError:
10
10
  from base.tests_init import base_tests_init # noqa: F401
11
11
  from ccxt.pro.test.base.tests_init import test_base_init_ws # noqa: F401
12
12
 
13
+ # fix : https://github.com/aio-libs/aiodns/issues/86
14
+ import sys
15
+ if sys.platform == 'win32':
16
+ asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
13
17
 
14
18
  # ########### args ###########
15
19
  isWs = get_cli_arg_value('--ws')
@@ -27,7 +31,7 @@ if (isBaseTests):
27
31
  exit(0)
28
32
 
29
33
  # ###### exchange tests #######
30
- if (is_synchronous):
34
+ if (IS_SYNCHRONOUS):
31
35
  from tests_sync import testMainClass as testMainClassSync
32
36
  testMainClassSync().init(argvExchange, argvSymbol, argvMethod)
33
37
  else: