ccxt 4.3.63__py2.py3-none-any.whl → 4.3.65__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/kucoin.py +1 -0
  3. ccxt/abstract/kucoinfutures.py +1 -0
  4. ccxt/alpaca.py +1 -0
  5. ccxt/async_support/__init__.py +1 -1
  6. ccxt/async_support/alpaca.py +1 -0
  7. ccxt/async_support/base/exchange.py +4 -4
  8. ccxt/async_support/bingx.py +83 -1
  9. ccxt/async_support/bitfinex.py +1 -1
  10. ccxt/async_support/bitfinex2.py +1 -1
  11. ccxt/async_support/bybit.py +11 -4
  12. ccxt/async_support/independentreserve.py +103 -1
  13. ccxt/async_support/kucoin.py +2 -0
  14. ccxt/async_support/whitebit.py +1 -1
  15. ccxt/async_support/woo.py +25 -0
  16. ccxt/async_support/yobit.py +1 -1
  17. ccxt/async_support/zonda.py +1 -1
  18. ccxt/base/exchange.py +4 -4
  19. ccxt/bingx.py +83 -1
  20. ccxt/bitfinex.py +1 -1
  21. ccxt/bitfinex2.py +1 -1
  22. ccxt/bybit.py +11 -4
  23. ccxt/independentreserve.py +103 -1
  24. ccxt/kucoin.py +2 -0
  25. ccxt/pro/__init__.py +1 -1
  26. ccxt/pro/bitmart.py +3 -3
  27. ccxt/pro/gate.py +1 -1
  28. ccxt/pro/gemini.py +4 -2
  29. ccxt/pro/okx.py +1 -1
  30. ccxt/pro/onetrading.py +3 -2
  31. ccxt/pro/oxfun.py +1 -1
  32. ccxt/pro/vertex.py +3 -2
  33. ccxt/pro/woo.py +2 -1
  34. ccxt/pro/woofipro.py +2 -1
  35. ccxt/test/tests_async.py +3 -3
  36. ccxt/test/tests_helpers.py +1 -1
  37. ccxt/test/tests_init.py +3 -3
  38. ccxt/test/tests_sync.py +3 -3
  39. ccxt/whitebit.py +1 -1
  40. ccxt/woo.py +25 -0
  41. ccxt/yobit.py +1 -1
  42. ccxt/zonda.py +1 -1
  43. {ccxt-4.3.63.dist-info → ccxt-4.3.65.dist-info}/METADATA +4 -4
  44. {ccxt-4.3.63.dist-info → ccxt-4.3.65.dist-info}/RECORD +47 -47
  45. {ccxt-4.3.63.dist-info → ccxt-4.3.65.dist-info}/LICENSE.txt +0 -0
  46. {ccxt-4.3.63.dist-info → ccxt-4.3.65.dist-info}/WHEEL +0 -0
  47. {ccxt-4.3.63.dist-info → ccxt-4.3.65.dist-info}/top_level.txt +0 -0
ccxt/bybit.py CHANGED
@@ -2913,7 +2913,7 @@ class bybit(Exchange, ImplicitAPI):
2913
2913
  :see: https://bybit-exchange.github.io/docs/v5/asset/all-balance
2914
2914
  :see: https://bybit-exchange.github.io/docs/v5/account/wallet-balance
2915
2915
  :param dict [params]: extra parameters specific to the exchange API endpoint
2916
- :param str [params.type]: wallet type, ['spot', 'swap', 'fund']
2916
+ :param str [params.type]: wallet type, ['spot', 'swap', 'funding']
2917
2917
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
2918
2918
  """
2919
2919
  self.load_markets()
@@ -2921,10 +2921,17 @@ class bybit(Exchange, ImplicitAPI):
2921
2921
  enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
2922
2922
  isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
2923
2923
  type = None
2924
- type, params = self.get_bybit_type('fetchBalance', None, params)
2924
+ # don't use getBybitType here
2925
+ type, params = self.handle_market_type_and_params('fetchBalance', None, params)
2926
+ subType = None
2927
+ subType, params = self.handle_sub_type_and_params('fetchBalance', None, params)
2928
+ if (type == 'swap') or (type == 'future'):
2929
+ type = subType
2930
+ lowercaseRawType = type.lower() if (type is not None) else None
2925
2931
  isSpot = (type == 'spot')
2926
2932
  isLinear = (type == 'linear')
2927
2933
  isInverse = (type == 'inverse')
2934
+ isFunding = (lowercaseRawType == 'fund') or (lowercaseRawType == 'funding')
2928
2935
  if isUnifiedAccount:
2929
2936
  if isInverse:
2930
2937
  type = 'contract'
@@ -2940,10 +2947,10 @@ class bybit(Exchange, ImplicitAPI):
2940
2947
  response = None
2941
2948
  if isSpot and (marginMode is not None):
2942
2949
  response = self.privateGetV5SpotCrossMarginTradeAccount(self.extend(request, params))
2943
- elif unifiedType == 'FUND':
2950
+ elif isFunding:
2944
2951
  # use self endpoint only we have no other choice
2945
2952
  # because it requires transfer permission
2946
- request['accountType'] = unifiedType
2953
+ request['accountType'] = 'FUND'
2947
2954
  response = self.privateGetV5AssetTransferQueryAccountCoinsBalance(self.extend(request, params))
2948
2955
  else:
2949
2956
  request['accountType'] = unifiedType
@@ -6,8 +6,9 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.independentreserve import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, TradingFees
9
+ from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, TradingFees, Transaction
10
10
  from typing import List
11
+ from ccxt.base.errors import BadRequest
11
12
  from ccxt.base.decimal_to_precision import TICK_SIZE
12
13
  from ccxt.base.precise import Precise
13
14
 
@@ -79,6 +80,7 @@ class independentreserve(Exchange, ImplicitAPI):
79
80
  'setLeverage': False,
80
81
  'setMarginMode': False,
81
82
  'setPositionMode': False,
83
+ 'withdraw': True,
82
84
  },
83
85
  'urls': {
84
86
  'logo': 'https://user-images.githubusercontent.com/51840849/87182090-1e9e9080-c2ec-11ea-8e49-563db9a38f37.jpg',
@@ -752,6 +754,106 @@ class independentreserve(Exchange, ImplicitAPI):
752
754
  'network': None,
753
755
  }
754
756
 
757
+ def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
758
+ """
759
+ make a withdrawal
760
+ :see: https://www.independentreserve.com/features/api#WithdrawDigitalCurrency
761
+ :param str code: unified currency code
762
+ :param float amount: the amount to withdraw
763
+ :param str address: the address to withdraw to
764
+ :param str tag:
765
+ :param dict [params]: extra parameters specific to the exchange API endpoint
766
+ *
767
+ * EXCHANGE SPECIFIC PARAMETERS
768
+ :param dict [params.comment]: withdrawal comment, should not exceed 500 characters
769
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
770
+ """
771
+ tag, params = self.handle_withdraw_tag_and_params(tag, params)
772
+ self.load_markets()
773
+ currency = self.currency(code)
774
+ request: dict = {
775
+ 'primaryCurrencyCode': currency['id'],
776
+ 'withdrawalAddress': address,
777
+ 'amount': self.currency_to_precision(code, amount),
778
+ }
779
+ if tag is not None:
780
+ request['destinationTag'] = tag
781
+ networkCode = None
782
+ networkCode, params = self.handle_network_code_and_params(params)
783
+ if networkCode is not None:
784
+ raise BadRequest(self.id + ' withdraw() does not accept params["networkCode"]')
785
+ response = self.privatePostWithdrawDigitalCurrency(self.extend(request, params))
786
+ #
787
+ # {
788
+ # "TransactionGuid": "dc932e19-562b-4c50-821e-a73fd048b93b",
789
+ # "PrimaryCurrencyCode": "Bch",
790
+ # "CreatedTimestampUtc": "2020-04-01T05:26:30.5093622+00:00",
791
+ # "Amount": {
792
+ # "Total": 0.1231,
793
+ # "Fee": 0.0001
794
+ # },
795
+ # "Destination": {
796
+ # "Address": "bc1qhpqxkjpvgkckw530yfmxyr53c94q8f4273a7ez",
797
+ # "Tag": null
798
+ # },
799
+ # "Status": "Pending",
800
+ # "Transaction": null
801
+ # }
802
+ #
803
+ return self.parse_transaction(response, currency)
804
+
805
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
806
+ #
807
+ # {
808
+ # "TransactionGuid": "dc932e19-562b-4c50-821e-a73fd048b93b",
809
+ # "PrimaryCurrencyCode": "Bch",
810
+ # "CreatedTimestampUtc": "2020-04-01T05:26:30.5093622+00:00",
811
+ # "Amount": {
812
+ # "Total": 0.1231,
813
+ # "Fee": 0.0001
814
+ # },
815
+ # "Destination": {
816
+ # "Address": "bc1qhpqxkjpvgkckw530yfmxyr53c94q8f4273a7ez",
817
+ # "Tag": null
818
+ # },
819
+ # "Status": "Pending",
820
+ # "Transaction": null
821
+ # }
822
+ #
823
+ amount = self.safe_dict(transaction, 'Amount')
824
+ destination = self.safe_dict(transaction, 'Destination')
825
+ currencyId = self.safe_string(transaction, 'PrimaryCurrencyCode')
826
+ datetime = self.safe_string(transaction, 'CreatedTimestampUtc')
827
+ address = self.safe_string(destination, 'Address')
828
+ tag = self.safe_string(destination, 'Tag')
829
+ code = self.safe_currency_code(currencyId, currency)
830
+ return {
831
+ 'info': transaction,
832
+ 'id': self.safe_string(transaction, 'TransactionGuid'),
833
+ 'txid': None,
834
+ 'type': 'withdraw',
835
+ 'currency': code,
836
+ 'network': None,
837
+ 'amount': self.safe_number(amount, 'Total'),
838
+ 'status': self.safe_string(transaction, 'Status'),
839
+ 'timestamp': self.parse8601(datetime),
840
+ 'datetime': datetime,
841
+ 'address': address,
842
+ 'addressFrom': None,
843
+ 'addressTo': address,
844
+ 'tag': tag,
845
+ 'tagFrom': None,
846
+ 'tagTo': tag,
847
+ 'updated': None,
848
+ 'comment': None,
849
+ 'fee': {
850
+ 'currency': code,
851
+ 'cost': self.safe_number(amount, 'Fee'),
852
+ 'rate': None,
853
+ },
854
+ 'internal': False,
855
+ }
856
+
755
857
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
756
858
  url = self.urls['api'][api] + '/' + path
757
859
  if api == 'public':
ccxt/kucoin.py CHANGED
@@ -178,6 +178,7 @@ class kucoin(Exchange, ImplicitAPI):
178
178
  'status': 4.5, # 3PW
179
179
  # margin trading
180
180
  'mark-price/{symbol}/current': 3, # 2PW
181
+ 'mark-price/all-symbols': 3,
181
182
  'margin/config': 25, # 25SW
182
183
  },
183
184
  'post': {
@@ -663,6 +664,7 @@ class kucoin(Exchange, ImplicitAPI):
663
664
  'currencies': 'v3',
664
665
  'currencies/{currency}': 'v3',
665
666
  'symbols': 'v2',
667
+ 'mark-price/all-symbols': 'v3',
666
668
  },
667
669
  },
668
670
  'private': {
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.63'
7
+ __version__ = '4.3.65'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/bitmart.py CHANGED
@@ -707,8 +707,8 @@ class bitmart(ccxt.async_support.bitmart):
707
707
  symbol = market['symbol']
708
708
  openTimestamp = self.safe_integer(position, 'create_time')
709
709
  timestamp = self.safe_integer(position, 'update_time')
710
- side = self.safe_number(position, 'position_type')
711
- marginModeId = self.safe_number(position, 'open_type')
710
+ side = self.safe_integer(position, 'position_type')
711
+ marginModeId = self.safe_integer(position, 'open_type')
712
712
  return self.safe_position({
713
713
  'info': position,
714
714
  'id': None,
@@ -1234,7 +1234,7 @@ class bitmart(ccxt.async_support.bitmart):
1234
1234
  ob['symbol'] = symbol
1235
1235
  self.orderbooks[symbol] = ob
1236
1236
  orderbook = self.orderbooks[symbol]
1237
- way = self.safe_number(data, 'way')
1237
+ way = self.safe_integer(data, 'way')
1238
1238
  side = 'bids' if (way == 1) else 'asks'
1239
1239
  if way == 1:
1240
1240
  orderbook[side] = Bids([], limit)
ccxt/pro/gate.py CHANGED
@@ -1195,7 +1195,7 @@ class gate(ccxt.async_support.gate):
1195
1195
  elif event == 'finish':
1196
1196
  status = self.safe_string(parsed, 'status')
1197
1197
  if status is None:
1198
- left = self.safe_number(info, 'left')
1198
+ left = self.safe_integer(info, 'left')
1199
1199
  parsed['status'] = 'closed' if (left == 0) else 'canceled'
1200
1200
  stored.append(parsed)
1201
1201
  symbol = parsed['symbol']
ccxt/pro/gemini.py CHANGED
@@ -11,6 +11,7 @@ from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import NotSupported
14
+ from ccxt.base.precise import Precise
14
15
 
15
16
 
16
17
  class gemini(ccxt.async_support.gemini):
@@ -445,9 +446,10 @@ class gemini(ccxt.async_support.gemini):
445
446
  entry = rawBidAskChanges[i]
446
447
  rawSide = self.safe_string(entry, 'side')
447
448
  price = self.safe_number(entry, 'price')
448
- size = self.safe_number(entry, 'remaining')
449
- if size == 0:
449
+ sizeString = self.safe_string(entry, 'remaining')
450
+ if Precise.string_eq(sizeString, '0'):
450
451
  continue
452
+ size = self.parse_number(sizeString)
451
453
  if rawSide == 'bid':
452
454
  currentBidAsk['bid'] = price
453
455
  currentBidAsk['bidVolume'] = size
ccxt/pro/okx.py CHANGED
@@ -1645,7 +1645,7 @@ class okx(ccxt.async_support.okx):
1645
1645
  :param dict [params]: extra parameters specific to the exchange API endpoint
1646
1646
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1647
1647
  """
1648
- idsLength = len(ids)
1648
+ idsLength: number = len(ids)
1649
1649
  if idsLength > 20:
1650
1650
  raise BadRequest(self.id + ' cancelOrdersWs() accepts up to 20 ids at a time')
1651
1651
  if symbol is None:
ccxt/pro/onetrading.py CHANGED
@@ -10,6 +10,7 @@ from ccxt.async_support.base.ws.client import Client
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import NotSupported
13
+ from ccxt.base.precise import Precise
13
14
 
14
15
 
15
16
  class onetrading(ccxt.async_support.onetrading):
@@ -934,9 +935,9 @@ class onetrading(ccxt.async_support.onetrading):
934
935
  previousOrderArray = self.filter_by_array(self.orders, 'id', orderId, False)
935
936
  previousOrder = self.safe_value(previousOrderArray, 0, {})
936
937
  symbol = previousOrder['symbol']
937
- filled = self.safe_number(update, 'filled_amount')
938
+ filled = self.safe_string(update, 'filled_amount')
938
939
  status = self.parse_ws_order_status(updateType)
939
- if updateType == 'ORDER_CLOSED' and filled == 0:
940
+ if updateType == 'ORDER_CLOSED' and Precise.string_eq(filled, '0'):
940
941
  status = 'canceled'
941
942
  orderObject: dict = {
942
943
  'id': orderId,
ccxt/pro/oxfun.py CHANGED
@@ -854,7 +854,7 @@ class oxfun(ccxt.async_support.oxfun):
854
854
  :param dict [params]: extra parameters specific to the exchange API endpoint
855
855
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
856
856
  """
857
- idsLength = len(ids)
857
+ idsLength: number = len(ids)
858
858
  if idsLength > 20:
859
859
  raise BadRequest(self.id + ' cancelOrdersWs() accepts up to 20 ids at a time')
860
860
  if symbol is None:
ccxt/pro/vertex.py CHANGED
@@ -798,9 +798,10 @@ class vertex(ccxt.async_support.vertex):
798
798
  #
799
799
  marketId = self.safe_string(order, 'product_id')
800
800
  timestamp = self.parse_to_int(Precise.string_div(self.safe_string(order, 'timestamp'), '1000000'))
801
- remaining = self.parse_to_numeric(self.convertFromX18(self.safe_string(order, 'amount')))
801
+ remainingString = self.convertFromX18(self.safe_string(order, 'amount'))
802
+ remaining = self.parse_to_numeric(remainingString)
802
803
  status = self.parse_ws_order_status(self.safe_string(order, 'reason'))
803
- if remaining == 0 and status == 'open':
804
+ if Precise.string_eq(remainingString, '0') and status == 'open':
804
805
  status = 'closed'
805
806
  market = self.safe_market(marketId, market)
806
807
  symbol = market['symbol']
ccxt/pro/woo.py CHANGED
@@ -638,9 +638,10 @@ class woo(ccxt.async_support.woo):
638
638
  'cost': self.safe_string(order, 'totalFee'),
639
639
  'currency': self.safe_string(order, 'feeAsset'),
640
640
  }
641
+ priceString = self.safe_string(order, 'price')
641
642
  price = self.safe_number(order, 'price')
642
643
  avgPrice = self.safe_number(order, 'avgPrice')
643
- if (price == 0) and (avgPrice is not None):
644
+ if Precise.string_eq(priceString, '0') and (avgPrice is not None):
644
645
  price = avgPrice
645
646
  amount = self.safe_float(order, 'quantity')
646
647
  side = self.safe_string_lower(order, 'side')
ccxt/pro/woofipro.py CHANGED
@@ -686,9 +686,10 @@ class woofipro(ccxt.async_support.woofipro):
686
686
  'cost': self.safe_string(order, 'totalFee'),
687
687
  'currency': self.safe_string(order, 'feeAsset'),
688
688
  }
689
+ priceString = self.safe_string(order, 'price')
689
690
  price = self.safe_number(order, 'price')
690
691
  avgPrice = self.safe_number(order, 'avgPrice')
691
- if (price == 0) and (avgPrice is not None):
692
+ if Precise.string_eq(priceString, '0') and (avgPrice is not None):
692
693
  price = avgPrice
693
694
  amount = self.safe_string(order, 'quantity')
694
695
  side = self.safe_string_lower(order, 'side')
ccxt/test/tests_async.py CHANGED
@@ -818,7 +818,7 @@ class testMainClass(baseMainTestClass):
818
818
  new_input.append(current)
819
819
  return new_input
820
820
 
821
- async def test_method_statically(self, exchange, method, data, type, skip_keys):
821
+ async def test_request_statically(self, exchange, method, data, type, skip_keys):
822
822
  output = None
823
823
  request_url = None
824
824
  try:
@@ -850,7 +850,7 @@ class testMainClass(baseMainTestClass):
850
850
  unified_result_sync = call_exchange_method_dynamically_sync(exchange, method, self.sanitize_data_input(data['input']))
851
851
  self.assert_static_response_output(mocked_exchange, skip_keys, unified_result_sync, expected_result)
852
852
  except Exception as e:
853
- self.request_tests_failed = True
853
+ self.response_tests_failed = True
854
854
  error_message = '[' + self.lang + '][STATIC_RESPONSE_TEST_FAILURE]' + '[' + self.exchange_hint(exchange) + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
855
855
  dump('[TEST_FAILURE]' + error_message)
856
856
  set_fetch_response(exchange, None) # reset state
@@ -929,7 +929,7 @@ class testMainClass(baseMainTestClass):
929
929
  continue
930
930
  type = exchange.safe_string(exchange_data, 'outputType')
931
931
  skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
932
- await self.test_method_statically(exchange, method, result, type, skip_keys)
932
+ await self.test_request_statically(exchange, method, result, type, skip_keys)
933
933
  # reset options
934
934
  # exchange.options = exchange.deepExtend (oldExchangeOptions, {});
935
935
  exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
@@ -73,7 +73,6 @@ parser.add_argument('--requestTests', action='store_true', help='run response te
73
73
  parser.add_argument('--sync', action='store_true', help='is sync')
74
74
  parser.add_argument('--baseTests', action='store_true', help='is base tests')
75
75
  parser.add_argument('--exchangeTests', action='store_true', help='is exchange tests')
76
- parser.add_argument('--nonce', type=int, help='integer')
77
76
  parser.add_argument('exchange', type=str, help='exchange id in lowercase', nargs='?')
78
77
  parser.add_argument('symbol', type=str, help='symbol in uppercase', nargs='?')
79
78
  parser.parse_args(namespace=argv)
@@ -279,6 +278,7 @@ def set_fetch_response(exchange: ccxt.Exchange, data):
279
278
  return exchange
280
279
 
281
280
 
281
+ argvExchange = argv.exchange
282
282
  argvSymbol = argv.symbol if argv.symbol and '/' in argv.symbol else None
283
283
  # in python, we check it through "symbol" arg (as opposed to JS/PHP) because argvs were already built above
284
284
  argvMethod = 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, argv, 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
@@ -29,7 +29,7 @@ if (isBaseTests):
29
29
  # ###### exchange tests #######
30
30
  if (is_synchronous):
31
31
  from tests_sync import testMainClass as testMainClassSync
32
- testMainClassSync().init(argv.exchange, argvSymbol, argvMethod)
32
+ testMainClassSync().init(argvExchange, argvSymbol, argvMethod)
33
33
  else:
34
34
  from tests_async import testMainClass as testMainClassAsync
35
- asyncio.run(testMainClassAsync().init(argv.exchange, argvSymbol, argvMethod))
35
+ asyncio.run(testMainClassAsync().init(argvExchange, argvSymbol, argvMethod))
ccxt/test/tests_sync.py CHANGED
@@ -815,7 +815,7 @@ class testMainClass(baseMainTestClass):
815
815
  new_input.append(current)
816
816
  return new_input
817
817
 
818
- def test_method_statically(self, exchange, method, data, type, skip_keys):
818
+ def test_request_statically(self, exchange, method, data, type, skip_keys):
819
819
  output = None
820
820
  request_url = None
821
821
  try:
@@ -847,7 +847,7 @@ class testMainClass(baseMainTestClass):
847
847
  unified_result_sync = call_exchange_method_dynamically_sync(exchange, method, self.sanitize_data_input(data['input']))
848
848
  self.assert_static_response_output(mocked_exchange, skip_keys, unified_result_sync, expected_result)
849
849
  except Exception as e:
850
- self.request_tests_failed = True
850
+ self.response_tests_failed = True
851
851
  error_message = '[' + self.lang + '][STATIC_RESPONSE_TEST_FAILURE]' + '[' + self.exchange_hint(exchange) + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
852
852
  dump('[TEST_FAILURE]' + error_message)
853
853
  set_fetch_response(exchange, None) # reset state
@@ -926,7 +926,7 @@ class testMainClass(baseMainTestClass):
926
926
  continue
927
927
  type = exchange.safe_string(exchange_data, 'outputType')
928
928
  skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
929
- self.test_method_statically(exchange, method, result, type, skip_keys)
929
+ self.test_request_statically(exchange, method, result, type, skip_keys)
930
930
  # reset options
931
931
  # exchange.options = exchange.deepExtend (oldExchangeOptions, {});
932
932
  exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
ccxt/whitebit.py CHANGED
@@ -2404,7 +2404,7 @@ class whitebit(Exchange, ImplicitAPI):
2404
2404
  records = self.safe_list(response, 'records')
2405
2405
  return self.parse_transactions(records, currency, since, limit)
2406
2406
 
2407
- def is_fiat(self, currency):
2407
+ def is_fiat(self, currency: str):
2408
2408
  fiatCurrencies = self.safe_value(self.options, 'fiatCurrencies', [])
2409
2409
  return self.in_array(currency, fiatCurrencies)
2410
2410
 
ccxt/woo.py CHANGED
@@ -2481,7 +2481,21 @@ class woo(Exchange, ImplicitAPI):
2481
2481
  }
2482
2482
 
2483
2483
  def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2484
+ """
2485
+ fetch the history of funding payments paid and received on self account
2486
+ :see: https://docs.woo.org/#get-funding-fee-history
2487
+ :param str [symbol]: unified market symbol
2488
+ :param int [since]: the earliest time in ms to fetch funding history for
2489
+ :param int [limit]: the maximum number of funding history structures to retrieve
2490
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2491
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2492
+ :returns dict: a `funding history structure <https://docs.ccxt.com/#/?id=funding-history-structure>`
2493
+ """
2484
2494
  self.load_markets()
2495
+ paginate = False
2496
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingHistory', 'paginate')
2497
+ if paginate:
2498
+ return self.fetch_paginated_call_cursor('fetchFundingHistory', symbol, since, limit, params, 'page', 'page', 1, 500)
2485
2499
  request: dict = {}
2486
2500
  market: Market = None
2487
2501
  if symbol is not None:
@@ -2489,6 +2503,10 @@ class woo(Exchange, ImplicitAPI):
2489
2503
  request['symbol'] = market['id']
2490
2504
  if since is not None:
2491
2505
  request['start_t'] = since
2506
+ if limit is not None:
2507
+ request['size'] = limit
2508
+ else:
2509
+ request['size'] = 5000
2492
2510
  response = self.v1PrivateGetFundingFeeHistory(self.extend(request, params))
2493
2511
  #
2494
2512
  # {
@@ -2513,7 +2531,14 @@ class woo(Exchange, ImplicitAPI):
2513
2531
  # "success":true
2514
2532
  # }
2515
2533
  #
2534
+ meta = self.safe_dict(response, 'meta', {})
2535
+ cursor = self.safe_integer(meta, 'current_page')
2516
2536
  result = self.safe_list(response, 'rows', [])
2537
+ resultLength = len(result)
2538
+ if resultLength > 0:
2539
+ lastItem = result[resultLength - 1]
2540
+ lastItem['page'] = cursor
2541
+ result[resultLength - 1] = lastItem
2517
2542
  return self.parse_incomes(result, market, since, limit)
2518
2543
 
2519
2544
  def parse_funding_rate(self, fundingRate, market: Market = None):
ccxt/yobit.py CHANGED
@@ -558,7 +558,7 @@ class yobit(Exchange, ImplicitAPI):
558
558
  ids = self.ids
559
559
  else:
560
560
  ids = self.market_ids(symbols)
561
- idsLength = len(ids)
561
+ idsLength: number = len(ids)
562
562
  idsString = '-'.join(ids)
563
563
  maxLength = self.safe_integer(self.options, 'maxUrlLength', 2048)
564
564
  # max URL length is 2048 symbols, including http schema, hostname, tld, etc...
ccxt/zonda.py CHANGED
@@ -1467,7 +1467,7 @@ class zonda(Exchange, ImplicitAPI):
1467
1467
  # {status: "Ok", errors: []}
1468
1468
  return self.parse_order(response)
1469
1469
 
1470
- def is_fiat(self, currency):
1470
+ def is_fiat(self, currency: str):
1471
1471
  fiatCurrencies: dict = {
1472
1472
  'USD': True,
1473
1473
  'EUR': True,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.3.63
3
+ Version: 4.3.65
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
@@ -268,13 +268,13 @@ console.log(version, Object.keys(exchanges));
268
268
 
269
269
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
270
270
 
271
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.63/dist/ccxt.browser.min.js
272
- * unpkg: https://unpkg.com/ccxt@4.3.63/dist/ccxt.browser.min.js
271
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.65/dist/ccxt.browser.min.js
272
+ * unpkg: https://unpkg.com/ccxt@4.3.65/dist/ccxt.browser.min.js
273
273
 
274
274
  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.
275
275
 
276
276
  ```HTML
277
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.63/dist/ccxt.browser.min.js"></script>
277
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.65/dist/ccxt.browser.min.js"></script>
278
278
  ```
279
279
 
280
280
  Creates a global `ccxt` object: