ccxt 4.2.21__py2.py3-none-any.whl → 4.2.22__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.

Potentially problematic release.


This version of ccxt might be problematic. Click here for more details.

Files changed (47) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/binance.py +3 -0
  3. ccxt/abstract/binancecoinm.py +3 -0
  4. ccxt/abstract/binanceus.py +16 -12
  5. ccxt/abstract/binanceusdm.py +3 -0
  6. ccxt/async_support/__init__.py +1 -1
  7. ccxt/async_support/base/exchange.py +1 -1
  8. ccxt/async_support/bigone.py +1 -0
  9. ccxt/async_support/binance.py +14 -3
  10. ccxt/async_support/bitget.py +11 -1
  11. ccxt/async_support/bitrue.py +1 -0
  12. ccxt/async_support/bybit.py +49 -10
  13. ccxt/async_support/coinbasepro.py +1 -0
  14. ccxt/async_support/coinex.py +34 -12
  15. ccxt/async_support/deribit.py +145 -0
  16. ccxt/async_support/okcoin.py +3 -0
  17. ccxt/async_support/phemex.py +5 -2
  18. ccxt/async_support/poloniex.py +1 -0
  19. ccxt/async_support/woo.py +1 -1
  20. ccxt/base/exchange.py +1 -1
  21. ccxt/bigone.py +1 -0
  22. ccxt/binance.py +14 -3
  23. ccxt/bitget.py +11 -1
  24. ccxt/bitrue.py +1 -0
  25. ccxt/bybit.py +49 -10
  26. ccxt/coinbasepro.py +1 -0
  27. ccxt/coinex.py +34 -12
  28. ccxt/deribit.py +145 -0
  29. ccxt/okcoin.py +3 -0
  30. ccxt/phemex.py +5 -2
  31. ccxt/poloniex.py +1 -0
  32. ccxt/pro/__init__.py +1 -1
  33. ccxt/pro/bequant.py +7 -1
  34. ccxt/pro/binance.py +7 -4
  35. ccxt/pro/binancecoinm.py +7 -1
  36. ccxt/pro/binanceus.py +7 -1
  37. ccxt/pro/bitcoincom.py +7 -1
  38. ccxt/pro/bitget.py +1 -1
  39. ccxt/pro/bitrue.py +5 -1
  40. ccxt/pro/okx.py +10 -2
  41. ccxt/test/test_async.py +14 -1
  42. ccxt/test/test_sync.py +14 -1
  43. ccxt/woo.py +1 -1
  44. {ccxt-4.2.21.dist-info → ccxt-4.2.22.dist-info}/METADATA +4 -4
  45. {ccxt-4.2.21.dist-info → ccxt-4.2.22.dist-info}/RECORD +47 -47
  46. {ccxt-4.2.21.dist-info → ccxt-4.2.22.dist-info}/WHEEL +0 -0
  47. {ccxt-4.2.21.dist-info → ccxt-4.2.22.dist-info}/top_level.txt +0 -0
ccxt/deribit.py CHANGED
@@ -415,6 +415,151 @@ class deribit(Exchange, ImplicitAPI):
415
415
  },
416
416
  })
417
417
 
418
+ def convert_expire_date(self, date):
419
+ # parse YYMMDD to timestamp
420
+ year = date[0:2]
421
+ month = date[2:4]
422
+ day = date[4:6]
423
+ reconstructedDate = '20' + year + '-' + month + '-' + day + 'T00:00:00Z'
424
+ return reconstructedDate
425
+
426
+ def convert_market_id_expire_date(self, date):
427
+ # parse 19JAN24 to 240119
428
+ monthMappping = {
429
+ 'JAN': '01',
430
+ 'FEB': '02',
431
+ 'MAR': '03',
432
+ 'APR': '04',
433
+ 'MAY': '05',
434
+ 'JUN': '06',
435
+ 'JUL': '07',
436
+ 'AUG': '08',
437
+ 'SEP': '09',
438
+ 'OCT': '10',
439
+ 'NOV': '11',
440
+ 'DEC': '12',
441
+ }
442
+ year = date[0:2]
443
+ monthName = date[2:5]
444
+ month = self.safe_string(monthMappping, monthName)
445
+ day = date[5:7]
446
+ reconstructedDate = day + month + year
447
+ return reconstructedDate
448
+
449
+ def convert_expire_date_to_market_id_date(self, date):
450
+ # parse 240119 to 19JAN24
451
+ year = date[0:2]
452
+ monthRaw = date[2:4]
453
+ month = None
454
+ day = date[4:6]
455
+ if monthRaw == '01':
456
+ month = 'JAN'
457
+ elif monthRaw == '02':
458
+ month = 'FEB'
459
+ elif monthRaw == '03':
460
+ month = 'MAR'
461
+ elif monthRaw == '04':
462
+ month = 'APR'
463
+ elif monthRaw == '05':
464
+ month = 'MAY'
465
+ elif monthRaw == '06':
466
+ month = 'JUN'
467
+ elif monthRaw == '07':
468
+ month = 'JUL'
469
+ elif monthRaw == '08':
470
+ month = 'AUG'
471
+ elif monthRaw == '09':
472
+ month = 'SEP'
473
+ elif monthRaw == '10':
474
+ month = 'OCT'
475
+ elif monthRaw == '11':
476
+ month = 'NOV'
477
+ elif monthRaw == '12':
478
+ month = 'DEC'
479
+ reconstructedDate = day + month + year
480
+ return reconstructedDate
481
+
482
+ def create_expired_option_market(self, symbol):
483
+ # support expired option contracts
484
+ quote = 'USD'
485
+ settle = None
486
+ optionParts = symbol.split('-')
487
+ symbolBase = symbol.split('/')
488
+ base = None
489
+ expiry = None
490
+ if symbol.find('/') > -1:
491
+ base = self.safe_string(symbolBase, 0)
492
+ expiry = self.safe_string(optionParts, 1)
493
+ if symbol.find('USDC') > -1:
494
+ base = base + '_USDC'
495
+ else:
496
+ base = self.safe_string(optionParts, 0)
497
+ expiry = self.convert_market_id_expire_date(self.safe_string(optionParts, 1))
498
+ if symbol.find('USDC') > -1:
499
+ quote = 'USDC'
500
+ settle = 'USDC'
501
+ else:
502
+ settle = base
503
+ splitBase = base
504
+ if base.find('_') > -1:
505
+ splitSymbol = base.split('_')
506
+ splitBase = self.safe_string(splitSymbol, 0)
507
+ strike = self.safe_string(optionParts, 2)
508
+ optionType = self.safe_string(optionParts, 3)
509
+ datetime = self.convert_expire_date(expiry)
510
+ timestamp = self.parse8601(datetime)
511
+ return {
512
+ 'id': base + '-' + self.convert_expire_date_to_market_id_date(expiry) + '-' + strike + '-' + optionType,
513
+ 'symbol': splitBase + '/' + quote + ':' + settle + '-' + expiry + '-' + strike + '-' + optionType,
514
+ 'base': base,
515
+ 'quote': quote,
516
+ 'settle': settle,
517
+ 'baseId': base,
518
+ 'quoteId': quote,
519
+ 'settleId': settle,
520
+ 'active': False,
521
+ 'type': 'option',
522
+ 'linear': None,
523
+ 'inverse': None,
524
+ 'spot': False,
525
+ 'swap': False,
526
+ 'future': False,
527
+ 'option': True,
528
+ 'margin': False,
529
+ 'contract': True,
530
+ 'contractSize': None,
531
+ 'expiry': timestamp,
532
+ 'expiryDatetime': datetime,
533
+ 'optionType': 'call' if (optionType == 'C') else 'put',
534
+ 'strike': self.parse_number(strike),
535
+ 'precision': {
536
+ 'amount': None,
537
+ 'price': None,
538
+ },
539
+ 'limits': {
540
+ 'amount': {
541
+ 'min': None,
542
+ 'max': None,
543
+ },
544
+ 'price': {
545
+ 'min': None,
546
+ 'max': None,
547
+ },
548
+ 'cost': {
549
+ 'min': None,
550
+ 'max': None,
551
+ },
552
+ },
553
+ 'info': None,
554
+ }
555
+
556
+ def safe_market(self, marketId=None, market=None, delimiter=None, marketType=None):
557
+ isOption = (marketId is not None) and ((marketId.endswith('-C')) or (marketId.endswith('-P')))
558
+ if isOption and not (marketId in self.markets_by_id):
559
+ # handle expired option contracts
560
+ return self.create_expired_option_market(marketId)
561
+ return super(deribit, self).safe_market(marketId, market, delimiter, marketType)
562
+
418
563
  def fetch_time(self, params={}):
419
564
  """
420
565
  fetches the current integer timestamp in milliseconds from the exchange server
ccxt/okcoin.py CHANGED
@@ -67,6 +67,9 @@ class okcoin(Exchange, ImplicitAPI):
67
67
  'fetchCurrencies': True, # see below
68
68
  'fetchDepositAddress': True,
69
69
  'fetchDeposits': True,
70
+ 'fetchFundingHistory': False,
71
+ 'fetchFundingRate': False,
72
+ 'fetchFundingRateHistory': False,
70
73
  'fetchLedger': True,
71
74
  'fetchMarkets': True,
72
75
  'fetchMyTrades': True,
ccxt/phemex.py CHANGED
@@ -1850,23 +1850,26 @@ class phemex(Exchange, ImplicitAPI):
1850
1850
  def fetch_balance(self, params={}) -> Balances:
1851
1851
  """
1852
1852
  query for balance and get the amount of funds available for trading or funds locked in orders
1853
+ :see: https://phemex-docs.github.io/#query-wallets
1853
1854
  :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
1855
+ :see: https://phemex-docs.github.io/#query-trading-account-and-positions
1854
1856
  :param dict [params]: extra parameters specific to the exchange API endpoint
1855
1857
  :param str [params.type]: spot or swap
1858
+ :param str [params.code]: *swap only* currency code of the balance to query(USD, USDT, etc), default is USDT
1856
1859
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1857
1860
  """
1858
1861
  self.load_markets()
1859
1862
  type = None
1860
1863
  type, params = self.handle_market_type_and_params('fetchBalance', None, params)
1861
1864
  code = self.safe_string(params, 'code')
1862
- params = self.omit(params, ['type', 'code'])
1865
+ params = self.omit(params, ['code'])
1863
1866
  response = None
1864
1867
  request = {}
1865
1868
  if (type != 'spot') and (type != 'swap'):
1866
1869
  raise BadRequest(self.id + ' does not support ' + type + ' markets, only spot and swap')
1867
1870
  if type == 'swap':
1868
1871
  settle = None
1869
- settle, params = self.handle_option_and_params(params, 'fetchBalance', 'settle')
1872
+ settle, params = self.handle_option_and_params(params, 'fetchBalance', 'settle', 'USDT')
1870
1873
  if code is not None or settle is not None:
1871
1874
  coin = None
1872
1875
  if code is not None:
ccxt/poloniex.py CHANGED
@@ -60,6 +60,7 @@ class poloniex(Exchange, ImplicitAPI):
60
60
  'fetchDepositsWithdrawals': True,
61
61
  'fetchDepositWithdrawFee': 'emulated',
62
62
  'fetchDepositWithdrawFees': True,
63
+ 'fetchFundingRate': False,
63
64
  'fetchMarginMode': False,
64
65
  'fetchMarkets': True,
65
66
  'fetchMyTrades': True,
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.21'
7
+ __version__ = '4.2.22'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/bequant.py CHANGED
@@ -5,11 +5,17 @@
5
5
 
6
6
  from ccxt.pro.hitbtc import hitbtc
7
7
 
8
+ import ccxt.async_support.bequant as bequantRest
9
+
8
10
 
9
11
  class bequant(hitbtc):
10
12
 
11
13
  def describe(self):
12
- return self.deep_extend(super(bequant, self).describe(), {
14
+ # eslint-disable-next-line new-cap
15
+ restInstance = bequantRest()
16
+ restDescribe = restInstance.describe()
17
+ extended = self.deep_extend(super(bequant, self).describe(), restDescribe)
18
+ return self.deep_extend(extended, {
13
19
  'id': 'bequant',
14
20
  'name': 'Bequant',
15
21
  'countries': ['MT'], # Malta
ccxt/pro/binance.py CHANGED
@@ -49,7 +49,7 @@ class binance(ccxt.async_support.binance):
49
49
  'ws': {
50
50
  'spot': 'wss://testnet.binance.vision/ws',
51
51
  'margin': 'wss://testnet.binance.vision/ws',
52
- 'future': 'wss://stream.binancefuture.com/ws',
52
+ 'future': 'wss://fstream.binancefuture.com/ws',
53
53
  'delivery': 'wss://dstream.binancefuture.com/ws',
54
54
  'ws': 'wss://testnet.binance.vision/ws-api/v3',
55
55
  },
@@ -1811,12 +1811,13 @@ class binance(ccxt.async_support.binance):
1811
1811
 
1812
1812
  async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1813
1813
  """
1814
- :see: https://binance-docs.github.io/apidocs/spot/en/#payload-order-update
1815
1814
  watches information on multiple orders made by the user
1816
- :param str symbol: unified market symbol of the market orders were made in
1815
+ :see: https://binance-docs.github.io/apidocs/spot/en/#payload-order-update
1816
+ :param str symbol: unified market symbol of the market the orders were made in
1817
1817
  :param int [since]: the earliest time in ms to fetch orders for
1818
1818
  :param int [limit]: the maximum number of order structures to retrieve
1819
1819
  :param dict [params]: extra parameters specific to the exchange API endpoint
1820
+ :param str|None [params.marginMode]: 'cross' or 'isolated', for spot margin
1820
1821
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1821
1822
  """
1822
1823
  await self.load_markets()
@@ -1836,8 +1837,10 @@ class binance(ccxt.async_support.binance):
1836
1837
  type = 'delivery'
1837
1838
  params = self.extend(params, {'type': type, 'symbol': symbol}) # needed inside authenticate for isolated margin
1838
1839
  await self.authenticate(params)
1840
+ marginMode = None
1841
+ marginMode, params = self.handle_margin_mode_and_params('watchOrders', params)
1839
1842
  urlType = type
1840
- if type == 'margin':
1843
+ if (type == 'margin') or ((type == 'spot') and (marginMode is not None)):
1841
1844
  urlType = 'spot' # spot-margin shares the same stream spot
1842
1845
  url = self.urls['api']['ws'][urlType] + '/' + self.options[type]['listenKey']
1843
1846
  client = self.client(url)
ccxt/pro/binancecoinm.py CHANGED
@@ -5,11 +5,17 @@
5
5
 
6
6
  from ccxt.pro.binance import binance
7
7
 
8
+ import ccxt.async_support.binancecoinm as binancecoinmRest
9
+
8
10
 
9
11
  class binancecoinm(binance):
10
12
 
11
13
  def describe(self):
12
- return self.deep_extend(super(binancecoinm, self).describe(), {
14
+ # eslint-disable-next-line new-cap
15
+ restInstance = binancecoinmRest()
16
+ restDescribe = restInstance.describe()
17
+ extended = self.deep_extend(super(binancecoinm, self).describe(), restDescribe)
18
+ return self.deep_extend(extended, {
13
19
  'id': 'binancecoinm',
14
20
  'name': 'Binance COIN-M',
15
21
  'urls': {
ccxt/pro/binanceus.py CHANGED
@@ -5,11 +5,17 @@
5
5
 
6
6
  from ccxt.pro.binance import binance
7
7
 
8
+ import ccxt.async_support.binanceus as binanceusRest
9
+
8
10
 
9
11
  class binanceus(binance):
10
12
 
11
13
  def describe(self):
12
- return self.deep_extend(super(binanceus, self).describe(), {
14
+ # eslint-disable-next-line new-cap
15
+ restInstance = binanceusRest()
16
+ restDescribe = restInstance.describe()
17
+ extended = self.deep_extend(super(binanceus, self).describe(), restDescribe)
18
+ return self.deep_extend(extended, {
13
19
  'id': 'binanceus',
14
20
  'name': 'Binance US',
15
21
  'countries': ['US'], # US
ccxt/pro/bitcoincom.py CHANGED
@@ -5,11 +5,17 @@
5
5
 
6
6
  from ccxt.pro.hitbtc import hitbtc
7
7
 
8
+ import ccxt.async_support.bequant as bequantRest
9
+
8
10
 
9
11
  class bitcoincom(hitbtc):
10
12
 
11
13
  def describe(self):
12
- return self.deep_extend(super(bitcoincom, self).describe(), {
14
+ # eslint-disable-next-line new-cap
15
+ restInstance = bequantRest()
16
+ restDescribe = restInstance.describe()
17
+ extended = self.deep_extend(super(bitcoincom, self).describe(), restDescribe)
18
+ return self.deep_extend(extended, {
13
19
  'id': 'bitcoincom',
14
20
  'name': 'bitcoin.com',
15
21
  'countries': ['KN'],
ccxt/pro/bitget.py CHANGED
@@ -1184,7 +1184,7 @@ class bitget(ccxt.async_support.bitget):
1184
1184
  'price': self.safe_string(order, 'price'),
1185
1185
  'stopPrice': triggerPrice,
1186
1186
  'triggerPrice': triggerPrice,
1187
- 'amount': self.safe_string_2(order, 'size', 'baseSize'),
1187
+ 'amount': self.safe_string(order, 'baseVolume'),
1188
1188
  'cost': self.safe_string_n(order, ['notional', 'notionalUsd', 'quoteSize']),
1189
1189
  'average': self.omit_zero(self.safe_string_2(order, 'priceAvg', 'fillPrice')),
1190
1190
  'filled': self.safe_string_2(order, 'accBaseVolume', 'baseVolume'),
ccxt/pro/bitrue.py CHANGED
@@ -341,7 +341,11 @@ class bitrue(ccxt.async_support.bitrue):
341
341
  symbol = market['symbol']
342
342
  timestamp = self.safe_integer(message, 'ts')
343
343
  tick = self.safe_value(message, 'tick', {})
344
- orderbook = self.parse_order_book(tick, symbol, timestamp, 'buys', 'asks')
344
+ orderbook = self.safe_value(self.orderbooks, symbol)
345
+ if orderbook is None:
346
+ orderbook = self.order_book()
347
+ snapshot = self.parse_order_book(tick, symbol, timestamp, 'buys', 'asks')
348
+ orderbook.reset(snapshot)
345
349
  self.orderbooks[symbol] = orderbook
346
350
  messageHash = 'orderbook:' + symbol
347
351
  client.resolve(orderbook, messageHash)
ccxt/pro/okx.py CHANGED
@@ -949,17 +949,20 @@ class okx(ccxt.async_support.okx):
949
949
 
950
950
  async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
951
951
  """
952
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-order-channel
953
952
  watches information on multiple orders made by the user
954
- :param str [symbol]: unified market symbol of the market orders were made in
953
+ :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-order-channel
954
+ :param str [symbol]: unified market symbol of the market the orders were made in
955
955
  :param int [since]: the earliest time in ms to fetch orders for
956
956
  :param int [limit]: the maximum number of order structures to retrieve
957
957
  :param dict [params]: extra parameters specific to the exchange API endpoint
958
958
  :param bool [params.stop]: True if fetching trigger or conditional orders
959
+ :param str [params.type]: 'spot', 'swap', 'future', 'option', 'ANY', 'SPOT', 'MARGIN', 'SWAP', 'FUTURES' or 'OPTION'
960
+ :param str [params.marginMode]: 'cross' or 'isolated', for automatically setting the type to spot margin
959
961
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
960
962
  """
961
963
  type = None
962
964
  # By default, receive order updates from any instrument type
965
+ type, params = self.handle_option_and_params(params, 'watchOrders', 'defaultType')
963
966
  type, params = self.handle_option_and_params(params, 'watchOrders', 'type', 'ANY')
964
967
  isStop = self.safe_value_2(params, 'stop', 'trigger', False)
965
968
  params = self.omit(params, ['stop', 'trigger'])
@@ -973,6 +976,11 @@ class okx(ccxt.async_support.okx):
973
976
  if type == 'future':
974
977
  type = 'futures'
975
978
  uppercaseType = type.upper()
979
+ marginMode = None
980
+ marginMode, params = self.handle_margin_mode_and_params('watchOrders', params)
981
+ if uppercaseType == 'SPOT':
982
+ if marginMode is not None:
983
+ uppercaseType = 'MARGIN'
976
984
  request = {
977
985
  'instType': uppercaseType,
978
986
  }
ccxt/test/test_async.py CHANGED
@@ -274,6 +274,10 @@ class testMainClass(baseMainTestClass):
274
274
 
275
275
  async def init(self, exchange_id, symbol_argv):
276
276
  self.parse_cli_args()
277
+ if self.request_tests and self.response_tests:
278
+ await self.run_static_request_tests(exchange_id, symbol_argv)
279
+ await self.run_static_response_tests(exchange_id, symbol_argv)
280
+ return
277
281
  if self.response_tests:
278
282
  await self.run_static_response_tests(exchange_id, symbol_argv)
279
283
  return
@@ -1053,6 +1057,9 @@ class testMainClass(baseMainTestClass):
1053
1057
  results = methods[method]
1054
1058
  for j in range(0, len(results)):
1055
1059
  result = results[j]
1060
+ old_exchange_options = exchange.options # snapshot options;
1061
+ test_exchange_options = exchange.safe_value(result, 'options', {})
1062
+ exchange.options = exchange.deep_extend(old_exchange_options, test_exchange_options) # custom options to be used in the tests
1056
1063
  description = exchange.safe_value(result, 'description')
1057
1064
  if (test_name is not None) and (test_name != description):
1058
1065
  continue
@@ -1062,6 +1069,8 @@ class testMainClass(baseMainTestClass):
1062
1069
  type = exchange.safe_string(exchange_data, 'outputType')
1063
1070
  skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
1064
1071
  await self.test_method_statically(exchange, method, result, type, skip_keys)
1072
+ # reset options
1073
+ exchange.options = old_exchange_options
1065
1074
  await close(exchange)
1066
1075
 
1067
1076
  async def test_exchange_response_statically(self, exchange_name, exchange_data, test_name=None):
@@ -1076,6 +1085,9 @@ class testMainClass(baseMainTestClass):
1076
1085
  for j in range(0, len(results)):
1077
1086
  result = results[j]
1078
1087
  description = exchange.safe_value(result, 'description')
1088
+ old_exchange_options = exchange.options # snapshot options;
1089
+ test_exchange_options = exchange.safe_value(result, 'options', {})
1090
+ exchange.options = exchange.deep_extend(old_exchange_options, test_exchange_options) # custom options to be used in the tests
1079
1091
  is_disabled = exchange.safe_value(result, 'disabled', False)
1080
1092
  if is_disabled:
1081
1093
  continue
@@ -1086,6 +1098,8 @@ class testMainClass(baseMainTestClass):
1086
1098
  continue
1087
1099
  skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
1088
1100
  await self.test_response_statically(exchange, method, skip_keys, result)
1101
+ # reset options
1102
+ exchange.options = old_exchange_options
1089
1103
  await close(exchange)
1090
1104
 
1091
1105
  def get_number_of_tests_from_exchange(self, exchange, exchange_data):
@@ -1130,7 +1144,6 @@ class testMainClass(baseMainTestClass):
1130
1144
  else:
1131
1145
  success_message = '[' + self.lang + '][TEST_SUCCESS] ' + str(sum) + ' static ' + type + ' tests passed.'
1132
1146
  dump('[INFO]' + success_message)
1133
- exit_script(0)
1134
1147
 
1135
1148
  async def run_static_response_tests(self, exchange_name=None, test=None):
1136
1149
  # -----------------------------------------------------------------------------
ccxt/test/test_sync.py CHANGED
@@ -273,6 +273,10 @@ class testMainClass(baseMainTestClass):
273
273
 
274
274
  def init(self, exchange_id, symbol_argv):
275
275
  self.parse_cli_args()
276
+ if self.request_tests and self.response_tests:
277
+ self.run_static_request_tests(exchange_id, symbol_argv)
278
+ self.run_static_response_tests(exchange_id, symbol_argv)
279
+ return
276
280
  if self.response_tests:
277
281
  self.run_static_response_tests(exchange_id, symbol_argv)
278
282
  return
@@ -1052,6 +1056,9 @@ class testMainClass(baseMainTestClass):
1052
1056
  results = methods[method]
1053
1057
  for j in range(0, len(results)):
1054
1058
  result = results[j]
1059
+ old_exchange_options = exchange.options # snapshot options;
1060
+ test_exchange_options = exchange.safe_value(result, 'options', {})
1061
+ exchange.options = exchange.deep_extend(old_exchange_options, test_exchange_options) # custom options to be used in the tests
1055
1062
  description = exchange.safe_value(result, 'description')
1056
1063
  if (test_name is not None) and (test_name != description):
1057
1064
  continue
@@ -1061,6 +1068,8 @@ class testMainClass(baseMainTestClass):
1061
1068
  type = exchange.safe_string(exchange_data, 'outputType')
1062
1069
  skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
1063
1070
  self.test_method_statically(exchange, method, result, type, skip_keys)
1071
+ # reset options
1072
+ exchange.options = old_exchange_options
1064
1073
  close(exchange)
1065
1074
 
1066
1075
  def test_exchange_response_statically(self, exchange_name, exchange_data, test_name=None):
@@ -1075,6 +1084,9 @@ class testMainClass(baseMainTestClass):
1075
1084
  for j in range(0, len(results)):
1076
1085
  result = results[j]
1077
1086
  description = exchange.safe_value(result, 'description')
1087
+ old_exchange_options = exchange.options # snapshot options;
1088
+ test_exchange_options = exchange.safe_value(result, 'options', {})
1089
+ exchange.options = exchange.deep_extend(old_exchange_options, test_exchange_options) # custom options to be used in the tests
1078
1090
  is_disabled = exchange.safe_value(result, 'disabled', False)
1079
1091
  if is_disabled:
1080
1092
  continue
@@ -1085,6 +1097,8 @@ class testMainClass(baseMainTestClass):
1085
1097
  continue
1086
1098
  skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
1087
1099
  self.test_response_statically(exchange, method, skip_keys, result)
1100
+ # reset options
1101
+ exchange.options = old_exchange_options
1088
1102
  close(exchange)
1089
1103
 
1090
1104
  def get_number_of_tests_from_exchange(self, exchange, exchange_data):
@@ -1129,7 +1143,6 @@ class testMainClass(baseMainTestClass):
1129
1143
  else:
1130
1144
  success_message = '[' + self.lang + '][TEST_SUCCESS] ' + str(sum) + ' static ' + type + ' tests passed.'
1131
1145
  dump('[INFO]' + success_message)
1132
- exit_script(0)
1133
1146
 
1134
1147
  def run_static_response_tests(self, exchange_name=None, test=None):
1135
1148
  # -----------------------------------------------------------------------------
ccxt/woo.py CHANGED
@@ -66,7 +66,7 @@ class woo(Exchange, ImplicitAPI):
66
66
  'fetchClosedOrder': False,
67
67
  'fetchClosedOrders': False,
68
68
  'fetchCurrencies': True,
69
- 'fetchDepositAddress': False,
69
+ 'fetchDepositAddress': True,
70
70
  'fetchDeposits': True,
71
71
  'fetchDepositsWithdrawals': True,
72
72
  'fetchFundingHistory': True,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.2.21
3
+ Version: 4.2.22
4
4
  Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges
5
5
  Home-page: https://ccxt.com
6
6
  Author: Igor Kroitor
@@ -258,13 +258,13 @@ console.log(version, Object.keys(exchanges));
258
258
 
259
259
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
260
260
 
261
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.2.21/dist/ccxt.browser.js
262
- * unpkg: https://unpkg.com/ccxt@4.2.21/dist/ccxt.browser.js
261
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.2.22/dist/ccxt.browser.js
262
+ * unpkg: https://unpkg.com/ccxt@4.2.22/dist/ccxt.browser.js
263
263
 
264
264
  CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
265
265
 
266
266
  ```HTML
267
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.2.21/dist/ccxt.browser.js"></script>
267
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.2.22/dist/ccxt.browser.js"></script>
268
268
  ```
269
269
 
270
270
  Creates a global `ccxt` object: