ccxt 4.2.77__py2.py3-none-any.whl → 4.2.79__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 (51) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/bingx.py +1 -0
  3. ccxt/abstract/gate.py +1 -0
  4. ccxt/abstract/gateio.py +1 -0
  5. ccxt/async_support/__init__.py +1 -1
  6. ccxt/async_support/base/exchange.py +1 -1
  7. ccxt/async_support/base/ws/functions.py +1 -1
  8. ccxt/async_support/bingx.py +37 -5
  9. ccxt/async_support/bitstamp.py +20 -26
  10. ccxt/async_support/bybit.py +97 -2
  11. ccxt/async_support/coinbase.py +20 -9
  12. ccxt/async_support/coinbaseinternational.py +2 -2
  13. ccxt/async_support/gate.py +4 -1
  14. ccxt/async_support/htx.py +34 -27
  15. ccxt/async_support/hyperliquid.py +6 -4
  16. ccxt/async_support/kucoin.py +52 -0
  17. ccxt/async_support/okcoin.py +27 -1
  18. ccxt/async_support/okx.py +18 -0
  19. ccxt/async_support/woo.py +43 -3
  20. ccxt/base/exchange.py +5 -5
  21. ccxt/bingx.py +37 -5
  22. ccxt/bitstamp.py +20 -26
  23. ccxt/bybit.py +97 -2
  24. ccxt/coinbase.py +20 -9
  25. ccxt/coinbaseinternational.py +2 -2
  26. ccxt/gate.py +4 -1
  27. ccxt/htx.py +34 -27
  28. ccxt/hyperliquid.py +6 -4
  29. ccxt/kucoin.py +52 -0
  30. ccxt/okcoin.py +27 -1
  31. ccxt/okx.py +18 -0
  32. ccxt/pro/__init__.py +1 -1
  33. ccxt/pro/alpaca.py +1 -1
  34. ccxt/pro/bitfinex2.py +1 -1
  35. ccxt/pro/bitget.py +1 -1
  36. ccxt/pro/bitmart.py +1 -1
  37. ccxt/pro/bitmex.py +1 -1
  38. ccxt/pro/blockchaincom.py +1 -1
  39. ccxt/pro/bybit.py +14 -1
  40. ccxt/pro/cex.py +9 -5
  41. ccxt/pro/cryptocom.py +1 -1
  42. ccxt/pro/hitbtc.py +1 -1
  43. ccxt/pro/htx.py +1 -1
  44. ccxt/pro/okcoin.py +1 -1
  45. ccxt/pro/onetrading.py +1 -1
  46. ccxt/pro/woo.py +30 -0
  47. ccxt/woo.py +43 -3
  48. {ccxt-4.2.77.dist-info → ccxt-4.2.79.dist-info}/METADATA +6 -6
  49. {ccxt-4.2.77.dist-info → ccxt-4.2.79.dist-info}/RECORD +51 -51
  50. {ccxt-4.2.77.dist-info → ccxt-4.2.79.dist-info}/WHEEL +0 -0
  51. {ccxt-4.2.77.dist-info → ccxt-4.2.79.dist-info}/top_level.txt +0 -0
@@ -465,6 +465,56 @@ class kucoin(Exchange, ImplicitAPI):
465
465
  '130202': ExchangeError, # The system is renewing the loan automatically. Please try again later
466
466
  '130203': InsufficientFunds, # Insufficient account balance
467
467
  '130204': BadRequest, # As the total lending amount for platform leverage reaches the platform's maximum position limit, the system suspends the borrowing function of leverage
468
+ '130301': InsufficientFunds, # Insufficient account balance
469
+ '130302': PermissionDenied, # Your relevant permission rights have been restricted, you can contact customer service for processing
470
+ '130303': NotSupported, # The current trading pair does not support isolated positions
471
+ '130304': NotSupported, # The trading function of the current trading pair is not enabled
472
+ '130305': NotSupported, # The current trading pair does not support cross position
473
+ '130306': NotSupported, # The account has not opened leveraged trading
474
+ '130307': NotSupported, # Please reopen the leverage agreement
475
+ '130308': InvalidOrder, # Position renewal freeze
476
+ '130309': InvalidOrder, # Position forced liquidation freeze
477
+ '130310': ExchangeError, # Abnormal leverage account status
478
+ '130311': InvalidOrder, # Failed to place an order, triggering buy limit
479
+ '130312': InvalidOrder, # Trigger global position limit, suspend buying
480
+ '130313': InvalidOrder, # Trigger global position limit, suspend selling
481
+ '130314': InvalidOrder, # Trigger the global position limit and prompt the remaining quantity available for purchase
482
+ '130315': NotSupported, # This feature has been suspended due to country restrictions
483
+ '126000': ExchangeError, # Abnormal margin trading
484
+ '126001': NotSupported, # Users currently do not support high frequency
485
+ '126002': ExchangeError, # There is a risk problem in your account and transactions are temporarily not allowed!
486
+ '126003': InvalidOrder, # The commission amount is less than the minimum transaction amount for a single commission
487
+ '126004': ExchangeError, # Trading pair does not exist or is prohibited
488
+ '126005': PermissionDenied, # This trading pair requires advanced KYC certification before trading
489
+ '126006': ExchangeError, # Trading pair is not available
490
+ '126007': ExchangeError, # Trading pair suspended
491
+ '126009': ExchangeError, # Trading pair is suspended from creating orders
492
+ '126010': ExchangeError, # Trading pair suspended order cancellation
493
+ '126011': ExchangeError, # There are too many orders in the order
494
+ '126013': InsufficientFunds, # Insufficient account balance
495
+ '126015': ExchangeError, # It is prohibited to place orders on self trading pair
496
+ '126021': NotSupported, # This digital asset does not support user participation in your region, thank you for your understanding!
497
+ '126022': InvalidOrder, # The final transaction price of your order will trigger the price protection strategy. To protect the price from deviating too much, please place an order again.
498
+ '126027': InvalidOrder, # Only limit orders are supported
499
+ '126028': InvalidOrder, # Only limit orders are supported before the specified time
500
+ '126029': InvalidOrder, # The maximum order price is: xxx
501
+ '126030': InvalidOrder, # The minimum order price is: xxx
502
+ '126033': InvalidOrder, # Duplicate order
503
+ '126034': InvalidOrder, # Failed to create take profit and stop loss order
504
+ '126036': InvalidOrder, # Failed to create margin order
505
+ '126037': ExchangeError, # Due to country and region restrictions, self function has been suspended!
506
+ '126038': ExchangeError, # Third-party service call failed(internal exception)
507
+ '126039': ExchangeError, # Third-party service call failed, reason: xxx
508
+ '126041': ExchangeError, # clientTimestamp parameter error
509
+ '126042': ExchangeError, # Exceeded maximum position limit
510
+ '126043': OrderNotFound, # Order does not exist
511
+ '126044': InvalidOrder, # clientOid duplicate
512
+ '126045': NotSupported, # This digital asset does not support user participation in your region, thank you for your understanding!
513
+ '126046': NotSupported, # This digital asset does not support your IP region, thank you for your understanding!
514
+ '126047': PermissionDenied, # Please complete identity verification
515
+ '126048': PermissionDenied, # Please complete authentication for the master account
516
+ '135005': ExchangeError, # Margin order query business abnormality
517
+ '135018': ExchangeError, # Margin order query service abnormality
468
518
  '200004': InsufficientFunds,
469
519
  '210014': InvalidOrder, # {"code":"210014","msg":"Exceeds the max. borrowing amount, the remaining amount you can borrow: 0USDT"}
470
520
  '210021': InsufficientFunds, # {"code":"210021","msg":"Balance not enough"}
@@ -486,10 +536,12 @@ class kucoin(Exchange, ImplicitAPI):
486
536
  '400350': InvalidOrder, # {"code":"400350","msg":"Upper limit for holding: 10,000USDT, you can still buy 10,000USDT worth of coin."}
487
537
  '400370': InvalidOrder, # {"code":"400370","msg":"Max. price: 0.02500000000000000000"}
488
538
  '400400': BadRequest, # Parameter error
539
+ '400401': AuthenticationError, # User is not logged in
489
540
  '400500': InvalidOrder, # {"code":"400500","msg":"Your located country/region is currently not supported for the trading of self token"}
490
541
  '400600': BadSymbol, # {"code":"400600","msg":"validation.createOrder.symbolNotAvailable"}
491
542
  '400760': InvalidOrder, # {"code":"400760","msg":"order price should be more than XX"}
492
543
  '401000': BadRequest, # {"code":"401000","msg":"The interface has been deprecated"}
544
+ '408000': BadRequest, # Network timeout, please try again later
493
545
  '411100': AccountSuspended,
494
546
  '415000': BadRequest, # {"code":"415000","msg":"Unsupported Media Type"}
495
547
  '400303': PermissionDenied, # {"msg":"To enjoy the full range of our products and services, we kindly request you complete the identity verification process.","code":"400303"}
@@ -266,6 +266,16 @@ class okcoin(Exchange, ImplicitAPI):
266
266
  '50026': ExchangeNotAvailable, # System error, please try again later.
267
267
  '50027': PermissionDenied, # The account is restricted from trading
268
268
  '50028': ExchangeError, # Unable to take the order, please reach out to support center for details
269
+ '50029': ExchangeError, # This instrument({0}) is unavailable at present due to risk management. Please contact customer service for help.
270
+ '50030': PermissionDenied, # No permission to use self API
271
+ '50032': AccountSuspended, # This asset is blocked, allow its trading and try again
272
+ '50033': AccountSuspended, # This instrument is blocked, allow its trading and try again
273
+ '50035': BadRequest, # This endpoint requires that APIKey must be bound to IP
274
+ '50036': BadRequest, # Invalid expTime
275
+ '50037': BadRequest, # Order expired
276
+ '50038': ExchangeError, # This feature is temporarily unavailable in demo trading
277
+ '50039': ExchangeError, # The before parameter is not available for implementing timestamp pagination
278
+ '50041': ExchangeError, # You are not currently on the whitelist, please contact customer service
269
279
  '50044': BadRequest, # Must select one broker type
270
280
  # API Class
271
281
  '50100': ExchangeError, # API frozen, please contact customer service
@@ -309,9 +319,25 @@ class okcoin(Exchange, ImplicitAPI):
309
319
  '51024': AccountSuspended, # Unified accountblocked
310
320
  '51025': ExchangeError, # Order count exceeds the limit
311
321
  '51026': BadSymbol, # Instrument type does not match underlying index
322
+ '51030': InvalidOrder, # Funding fee is being settled.
323
+ '51031': InvalidOrder, # This order price is not within the closing price range
324
+ '51032': InvalidOrder, # Closing all positions at market price.
325
+ '51033': InvalidOrder, # The total amount per order for self pair has reached the upper limit.
326
+ '51037': InvalidOrder, # The current account risk status only supports you to place IOC orders that can reduce the risk of your account.
327
+ '51038': InvalidOrder, # There is already an IOC order under the current risk module that reduces the risk of the account.
328
+ '51044': InvalidOrder, # The order type {0}, {1} is not allowed to set stop loss and take profit
312
329
  '51046': InvalidOrder, # The take profit trigger price must be higher than the order price
313
330
  '51047': InvalidOrder, # The stop loss trigger price must be lower than the order price
314
- '51031': InvalidOrder, # This order price is not within the closing price range
331
+ '51048': InvalidOrder, # The take profit trigger price should be lower than the order price
332
+ '51049': InvalidOrder, # The stop loss trigger price should be higher than the order price
333
+ '51050': InvalidOrder, # The take profit trigger price should be higher than the best ask price
334
+ '51051': InvalidOrder, # The stop loss trigger price should be lower than the best ask price
335
+ '51052': InvalidOrder, # The take profit trigger price should be lower than the best bid price
336
+ '51053': InvalidOrder, # The stop loss trigger price should be higher than the best bid price
337
+ '51054': BadRequest, # Getting information timed out, please try again later
338
+ '51056': InvalidOrder, # Action not allowed
339
+ '51058': InvalidOrder, # No available position for self algo order
340
+ '51059': InvalidOrder, # Strategy for the current state does not support self operation
315
341
  '51100': InvalidOrder, # Trading amount does not meet the min tradable amount
316
342
  '51102': InvalidOrder, # Entered amount exceeds the max pending count
317
343
  '51103': InvalidOrder, # Entered amount exceeds the max pending order count of the underlying asset
ccxt/async_support/okx.py CHANGED
@@ -596,6 +596,7 @@ class okx(Exchange, ImplicitAPI):
596
596
  '50027': PermissionDenied, # The account is restricted from trading
597
597
  '50028': ExchangeError, # Unable to take the order, please reach out to support center for details
598
598
  '50044': BadRequest, # Must select one broker type
599
+ '50061': ExchangeError, # You've reached the maximum order rate limit for self account.
599
600
  '50062': ExchangeError, # This feature is currently unavailable.
600
601
  # API Class
601
602
  '50100': ExchangeError, # API frozen, please contact customer service
@@ -783,6 +784,15 @@ class okx(Exchange, ImplicitAPI):
783
784
  # SPOT/MARGIN error codes 54000-54999
784
785
  '54000': ExchangeError, # Margin transactions unavailable
785
786
  '54001': ExchangeError, # Only Multi-currency margin account can be set to borrow coins automatically
787
+ # Trading bot Error Code from 55100 to 55999
788
+ '55100': InvalidOrder, # Take profit % should be within the range of {parameter1}-{parameter2}
789
+ '55101': InvalidOrder, # Stop loss % should be within the range of {parameter1}-{parameter2}
790
+ '55102': InvalidOrder, # Take profit % should be greater than the current bot’s PnL%
791
+ '55103': InvalidOrder, # Stop loss % should be less than the current bot’s PnL%
792
+ '55104': InvalidOrder, # Only futures grid supports take profit or stop loss based on profit percentage
793
+ '55111': InvalidOrder, # This signal name is in use, please try a new name
794
+ '55112': InvalidOrder, # This signal does not exist
795
+ '55113': InvalidOrder, # Create signal strategies with leverage greater than the maximum leverage of the instruments
786
796
  # FUNDING error codes 58000-58999
787
797
  '58000': ExchangeError, # Account type {0} does not supported when getting the sub-account balance
788
798
  '58001': AuthenticationError, # Incorrect trade password
@@ -4700,6 +4710,14 @@ class okx(Exchange, ImplicitAPI):
4700
4710
  '3': 'pending',
4701
4711
  '4': 'pending',
4702
4712
  '5': 'pending',
4713
+ '6': 'pending',
4714
+ '7': 'pending',
4715
+ '8': 'pending',
4716
+ '9': 'pending',
4717
+ '10': 'pending',
4718
+ '12': 'pending',
4719
+ '15': 'pending',
4720
+ '16': 'pending',
4703
4721
  }
4704
4722
  return self.safe_string(statuses, status, status)
4705
4723
 
ccxt/async_support/woo.py CHANGED
@@ -65,7 +65,7 @@ class woo(Exchange, ImplicitAPI):
65
65
  'fetchBalance': True,
66
66
  'fetchCanceledOrders': False,
67
67
  'fetchClosedOrder': False,
68
- 'fetchClosedOrders': False,
68
+ 'fetchClosedOrders': True,
69
69
  'fetchCurrencies': True,
70
70
  'fetchDepositAddress': True,
71
71
  'fetchDeposits': True,
@@ -84,7 +84,7 @@ class woo(Exchange, ImplicitAPI):
84
84
  'fetchOHLCV': True,
85
85
  'fetchOpenInterestHistory': False,
86
86
  'fetchOpenOrder': False,
87
- 'fetchOpenOrders': False,
87
+ 'fetchOpenOrders': True,
88
88
  'fetchOrder': True,
89
89
  'fetchOrderBook': True,
90
90
  'fetchOrders': True,
@@ -1341,7 +1341,47 @@ class woo(Exchange, ImplicitAPI):
1341
1341
  #
1342
1342
  data = self.safe_value(response, 'data', response)
1343
1343
  orders = self.safe_list(data, 'rows')
1344
- return self.parse_orders(orders, market, since, limit, params)
1344
+ return self.parse_orders(orders, market, since, limit)
1345
+
1346
+ async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1347
+ """
1348
+ fetches information on multiple orders made by the user
1349
+ :see: https://docs.woo.org/#get-orders
1350
+ :see: https://docs.woo.org/#get-algo-orders
1351
+ :param str symbol: unified market symbol of the market orders were made in
1352
+ :param int [since]: the earliest time in ms to fetch orders for
1353
+ :param int [limit]: the maximum number of order structures to retrieve
1354
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1355
+ :param boolean [params.stop]: whether the order is a stop/algo order
1356
+ :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1357
+ :param str [params.side]: 'buy' or 'sell'
1358
+ :param boolean [params.trailing]: set to True if you want to fetch trailing orders
1359
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1360
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1361
+ """
1362
+ await self.load_markets()
1363
+ extendedParams = self.extend(params, {'status': 'INCOMPLETE'})
1364
+ return await self.fetch_orders(symbol, since, limit, extendedParams)
1365
+
1366
+ async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1367
+ """
1368
+ fetches information on multiple orders made by the user
1369
+ :see: https://docs.woo.org/#get-orders
1370
+ :see: https://docs.woo.org/#get-algo-orders
1371
+ :param str symbol: unified market symbol of the market orders were made in
1372
+ :param int [since]: the earliest time in ms to fetch orders for
1373
+ :param int [limit]: the maximum number of order structures to retrieve
1374
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1375
+ :param boolean [params.stop]: whether the order is a stop/algo order
1376
+ :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1377
+ :param str [params.side]: 'buy' or 'sell'
1378
+ :param boolean [params.trailing]: set to True if you want to fetch trailing orders
1379
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1380
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1381
+ """
1382
+ await self.load_markets()
1383
+ extendedParams = self.extend(params, {'status': 'COMPLETED'})
1384
+ return await self.fetch_orders(symbol, since, limit, extendedParams)
1345
1385
 
1346
1386
  def parse_time_in_force(self, timeInForce):
1347
1387
  timeInForces = {
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.77'
7
+ __version__ = '4.2.79'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -1171,7 +1171,7 @@ class Exchange(object):
1171
1171
  return None
1172
1172
 
1173
1173
  try:
1174
- utc = datetime.datetime.utcfromtimestamp(timestamp // 1000)
1174
+ utc = datetime.datetime.fromtimestamp(timestamp // 1000, datetime.timezone.utc)
1175
1175
  return utc.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-6] + "{:03d}".format(int(timestamp) % 1000) + 'Z'
1176
1176
  except (TypeError, OverflowError, OSError):
1177
1177
  return None
@@ -1187,13 +1187,13 @@ class Exchange(object):
1187
1187
 
1188
1188
  @staticmethod
1189
1189
  def dmy(timestamp, infix='-'):
1190
- utc_datetime = datetime.datetime.utcfromtimestamp(int(round(timestamp / 1000)))
1190
+ utc_datetime = datetime.datetime.fromtimestamp(int(round(timestamp / 1000)), datetime.timezone.utc)
1191
1191
  return utc_datetime.strftime('%m' + infix + '%d' + infix + '%Y')
1192
1192
 
1193
1193
  @staticmethod
1194
1194
  def ymd(timestamp, infix='-', fullYear=True):
1195
1195
  year_format = '%Y' if fullYear else '%y'
1196
- utc_datetime = datetime.datetime.utcfromtimestamp(int(round(timestamp / 1000)))
1196
+ utc_datetime = datetime.datetime.fromtimestamp(int(round(timestamp / 1000)), datetime.timezone.utc)
1197
1197
  return utc_datetime.strftime(year_format + infix + '%m' + infix + '%d')
1198
1198
 
1199
1199
  @staticmethod
@@ -1206,7 +1206,7 @@ class Exchange(object):
1206
1206
 
1207
1207
  @staticmethod
1208
1208
  def ymdhms(timestamp, infix=' '):
1209
- utc_datetime = datetime.datetime.utcfromtimestamp(int(round(timestamp / 1000)))
1209
+ utc_datetime = datetime.datetime.fromtimestamp(int(round(timestamp / 1000)), datetime.timezone.utc)
1210
1210
  return utc_datetime.strftime('%Y-%m-%d' + infix + '%H:%M:%S')
1211
1211
 
1212
1212
  @staticmethod
ccxt/bingx.py CHANGED
@@ -195,6 +195,7 @@ class bingx(Exchange, ImplicitAPI):
195
195
  'post': {
196
196
  'trade/cancelReplace': 1,
197
197
  'positionSide/dual': 1,
198
+ 'trade/closePosition': 1,
198
199
  },
199
200
  },
200
201
  },
@@ -2031,6 +2032,8 @@ class bingx(Exchange, ImplicitAPI):
2031
2032
  'SELL': 'sell',
2032
2033
  'SHORT': 'sell',
2033
2034
  'LONG': 'buy',
2035
+ 'ask': 'sell',
2036
+ 'bid': 'buy',
2034
2037
  }
2035
2038
  return self.safe_string(sides, side, side)
2036
2039
 
@@ -3655,14 +3658,43 @@ class bingx(Exchange, ImplicitAPI):
3655
3658
  :param str symbol: Unified CCXT market symbol
3656
3659
  :param str [side]: not used by bingx
3657
3660
  :param dict [params]: extra parameters specific to the bingx api endpoint
3661
+ :param str|None [params.positionId]: it is recommended to hasattr(self, fill) parameter when closing a position
3658
3662
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3659
3663
  """
3660
3664
  self.load_markets()
3661
- market = self.market(symbol)
3662
- request: dict = {
3663
- 'symbol': market['id'],
3664
- }
3665
- response = self.swapV2PrivatePostTradeCloseAllPositions(self.extend(request, params))
3665
+ positionId = self.safe_string(params, 'positionId')
3666
+ params = self.omit(params, 'positionId')
3667
+ response = None
3668
+ if positionId is not None:
3669
+ request: dict = {
3670
+ 'positionId': positionId,
3671
+ }
3672
+ response = self.swapV1PrivatePostTradeClosePosition(self.extend(request, params))
3673
+ else:
3674
+ market = self.market(symbol)
3675
+ request: dict = {
3676
+ 'symbol': market['id'],
3677
+ }
3678
+ response = self.swapV2PrivatePostTradeCloseAllPositions(self.extend(request, params))
3679
+ #
3680
+ # swapV1PrivatePostTradeClosePosition
3681
+ #
3682
+ # {
3683
+ # "code": 0,
3684
+ # "msg": "",
3685
+ # "timestamp": 1710992264190,
3686
+ # "data": {
3687
+ # "orderId": 1770656007907930112,
3688
+ # "positionId": "1751667128353910784",
3689
+ # "symbol": "LTC-USDT",
3690
+ # "side": "Ask",
3691
+ # "type": "MARKET",
3692
+ # "positionSide": "Long",
3693
+ # "origQty": "0.2"
3694
+ # }
3695
+ # }
3696
+ #
3697
+ # swapV2PrivatePostTradeCloseAllPositions
3666
3698
  #
3667
3699
  # {
3668
3700
  # "code": 0,
ccxt/bitstamp.py CHANGED
@@ -1082,16 +1082,17 @@ class bitstamp(Exchange, ImplicitAPI):
1082
1082
  'timestamp': None,
1083
1083
  'datetime': None,
1084
1084
  }
1085
- codes = list(self.currencies.keys())
1086
- for i in range(0, len(codes)):
1087
- code = codes[i]
1088
- currency = self.currency(code)
1089
- currencyId = currency['id']
1085
+ if response is None:
1086
+ response = []
1087
+ for i in range(0, len(response)):
1088
+ currencyBalance = response[i]
1089
+ currencyId = self.safe_string(currencyBalance, 'currency')
1090
+ currencyCode = self.safe_currency_code(currencyId)
1090
1091
  account = self.account()
1091
- account['free'] = self.safe_string(response, currencyId + '_available')
1092
- account['used'] = self.safe_string(response, currencyId + '_reserved')
1093
- account['total'] = self.safe_string(response, currencyId + '_balance')
1094
- result[code] = account
1092
+ account['free'] = self.safe_string(currencyBalance, 'available')
1093
+ account['used'] = self.safe_string(currencyBalance, 'reserved')
1094
+ account['total'] = self.safe_string(currencyBalance, 'total')
1095
+ result[currencyCode] = account
1095
1096
  return self.safe_balance(result)
1096
1097
 
1097
1098
  def fetch_balance(self, params={}) -> Balances:
@@ -1102,24 +1103,17 @@ class bitstamp(Exchange, ImplicitAPI):
1102
1103
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1103
1104
  """
1104
1105
  self.load_markets()
1105
- response = self.privatePostBalance(params)
1106
+ response = self.privatePostAccountBalances(params)
1106
1107
  #
1107
- # {
1108
- # "aave_available": "0.00000000",
1109
- # "aave_balance": "0.00000000",
1110
- # "aave_reserved": "0.00000000",
1111
- # "aave_withdrawal_fee": "0.07000000",
1112
- # "aavebtc_fee": "0.000",
1113
- # "aaveeur_fee": "0.000",
1114
- # "aaveusd_fee": "0.000",
1115
- # "bat_available": "0.00000000",
1116
- # "bat_balance": "0.00000000",
1117
- # "bat_reserved": "0.00000000",
1118
- # "bat_withdrawal_fee": "5.00000000",
1119
- # "batbtc_fee": "0.000",
1120
- # "bateur_fee": "0.000",
1121
- # "batusd_fee": "0.000",
1122
- # }
1108
+ # [
1109
+ # {
1110
+ # "currency": "usdt",
1111
+ # "total": "7.00000",
1112
+ # "available": "7.00000",
1113
+ # "reserved": "0.00000"
1114
+ # },
1115
+ # ...
1116
+ # ]
1123
1117
  #
1124
1118
  return self.parse_balance(response)
1125
1119
 
ccxt/bybit.py CHANGED
@@ -84,6 +84,7 @@ class bybit(Exchange, ImplicitAPI):
84
84
  'fetchDeposits': True,
85
85
  'fetchDepositWithdrawFee': 'emulated',
86
86
  'fetchDepositWithdrawFees': True,
87
+ 'fetchFundingHistory': True,
87
88
  'fetchFundingRate': True, # emulated in exchange
88
89
  'fetchFundingRateHistory': True,
89
90
  'fetchFundingRates': True,
@@ -7525,17 +7526,111 @@ class bybit(Exchange, ImplicitAPI):
7525
7526
  tier = info[i]
7526
7527
  marketId = self.safe_string(info, 'symbol')
7527
7528
  market = self.safe_market(marketId)
7529
+ minNotional = self.parse_number('0')
7530
+ if i != 0:
7531
+ minNotional = self.safe_number(info[i - 1], 'riskLimitValue')
7528
7532
  tiers.append({
7529
7533
  'tier': self.safe_integer(tier, 'id'),
7530
7534
  'currency': market['settle'],
7531
- 'minNotional': None,
7532
- 'maxNotional': None,
7535
+ 'minNotional': minNotional,
7536
+ 'maxNotional': self.safe_number(tier, 'riskLimitValue'),
7533
7537
  'maintenanceMarginRate': self.safe_number(tier, 'maintenanceMargin'),
7534
7538
  'maxLeverage': self.safe_number(tier, 'maxLeverage'),
7535
7539
  'info': tier,
7536
7540
  })
7537
7541
  return tiers
7538
7542
 
7543
+ def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
7544
+ """
7545
+ fetch the history of funding payments paid and received on self account
7546
+ :see: https://bybit-exchange.github.io/docs/api-explorer/v5/position/execution
7547
+ :param str [symbol]: unified market symbol
7548
+ :param int [since]: the earliest time in ms to fetch funding history for
7549
+ :param int [limit]: the maximum number of funding history structures to retrieve
7550
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7551
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
7552
+ :returns dict: a `funding history structure <https://docs.ccxt.com/#/?id=funding-history-structure>`
7553
+ """
7554
+ self.load_markets()
7555
+ paginate = False
7556
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingHistory', 'paginate')
7557
+ if paginate:
7558
+ return self.fetch_paginated_call_cursor('fetchFundingHistory', symbol, since, limit, params, 'nextPageCursor', 'cursor', None, 100)
7559
+ request = {
7560
+ 'execType': 'Funding',
7561
+ }
7562
+ market: Market = None
7563
+ if symbol is not None:
7564
+ market = self.market(symbol)
7565
+ request['symbol'] = market['id']
7566
+ type = None
7567
+ type, params = self.get_bybit_type('fetchFundingHistory', market, params)
7568
+ request['category'] = type
7569
+ if symbol is not None:
7570
+ request['symbol'] = market['id']
7571
+ if since is not None:
7572
+ request['startTime'] = since
7573
+ if limit is not None:
7574
+ request['size'] = limit
7575
+ else:
7576
+ request['size'] = 100
7577
+ request, params = self.handle_until_option('endTime', request, params)
7578
+ response = self.privateGetV5ExecutionList(self.extend(request, params))
7579
+ fundings = self.add_pagination_cursor_to_result(response)
7580
+ return self.parse_incomes(fundings, market, since, limit)
7581
+
7582
+ def parse_income(self, income, market: Market = None):
7583
+ #
7584
+ # {
7585
+ # "symbol": "XMRUSDT",
7586
+ # "orderType": "UNKNOWN",
7587
+ # "underlyingPrice": "",
7588
+ # "orderLinkId": "",
7589
+ # "orderId": "a11e5fe2-1dbf-4bab-a9b2-af80a14efc5d",
7590
+ # "stopOrderType": "UNKNOWN",
7591
+ # "execTime": "1710950400000",
7592
+ # "feeCurrency": "",
7593
+ # "createType": "",
7594
+ # "feeRate": "-0.000761",
7595
+ # "tradeIv": "",
7596
+ # "blockTradeId": "",
7597
+ # "markPrice": "136.79",
7598
+ # "execPrice": "137.11",
7599
+ # "markIv": "",
7600
+ # "orderQty": "0",
7601
+ # "orderPrice": "0",
7602
+ # "execValue": "134.3678",
7603
+ # "closedSize": "0",
7604
+ # "execType": "Funding",
7605
+ # "seq": "28097658790",
7606
+ # "side": "Sell",
7607
+ # "indexPrice": "",
7608
+ # "leavesQty": "0",
7609
+ # "isMaker": False,
7610
+ # "execFee": "-0.10232512",
7611
+ # "execId": "8d1ef156-4ec6-4445-9a6c-1c0c24dbd046",
7612
+ # "marketUnit": "",
7613
+ # "execQty": "0.98",
7614
+ # "nextPageCursor": "5774437%3A0%2C5771289%3A0"
7615
+ # }
7616
+ #
7617
+ marketId = self.safe_string(income, 'symbol')
7618
+ market = self.safe_market(marketId, market, None, 'contract')
7619
+ code = 'USDT'
7620
+ if market['inverse']:
7621
+ code = market['quote']
7622
+ timestamp = self.safe_integer(income, 'execTime')
7623
+ return {
7624
+ 'info': income,
7625
+ 'symbol': self.safe_symbol(marketId, market, '-', 'swap'),
7626
+ 'code': code,
7627
+ 'timestamp': timestamp,
7628
+ 'datetime': self.iso8601(timestamp),
7629
+ 'id': self.safe_string(income, 'execId'),
7630
+ 'amount': self.safe_number(income, 'execQty'),
7631
+ 'rate': self.safe_number(income, 'feeRate'),
7632
+ }
7633
+
7539
7634
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
7540
7635
  url = self.implode_hostname(self.urls['api'][api]) + '/' + path
7541
7636
  if api == 'public':
ccxt/coinbase.py CHANGED
@@ -1040,7 +1040,9 @@ class coinbase(Exchange, ImplicitAPI):
1040
1040
  :returns dict[]: an array of objects representing market data
1041
1041
  """
1042
1042
  method = self.safe_string(self.options, 'fetchMarkets', 'fetchMarketsV3')
1043
- return getattr(self, method)(params)
1043
+ if method == 'fetchMarketsV3':
1044
+ return self.fetch_markets_v3(params)
1045
+ return self.fetch_markets_v2(params)
1044
1046
 
1045
1047
  def fetch_markets_v2(self, params={}):
1046
1048
  response = self.fetch_currencies_from_cache(params)
@@ -1112,7 +1114,13 @@ class coinbase(Exchange, ImplicitAPI):
1112
1114
  return result
1113
1115
 
1114
1116
  def fetch_markets_v3(self, params={}):
1115
- response = self.v3PrivateGetBrokerageProducts(params)
1117
+ promisesUnresolved = [
1118
+ self.v3PrivateGetBrokerageProducts(params),
1119
+ self.v3PrivateGetBrokerageTransactionSummary(params),
1120
+ ]
1121
+ # response = self.v3PrivateGetBrokerageProducts(params)
1122
+ promises = promisesUnresolved
1123
+ response = self.safe_dict(promises, 0, {})
1116
1124
  #
1117
1125
  # [
1118
1126
  # {
@@ -1147,7 +1155,8 @@ class coinbase(Exchange, ImplicitAPI):
1147
1155
  # ...
1148
1156
  # ]
1149
1157
  #
1150
- fees = self.v3PrivateGetBrokerageTransactionSummary(params)
1158
+ # fees = self.v3PrivateGetBrokerageTransactionSummary(params)
1159
+ fees = self.safe_dict(promises, 1, {})
1151
1160
  #
1152
1161
  # {
1153
1162
  # "total_volume": 0,
@@ -1831,6 +1840,8 @@ class coinbase(Exchange, ImplicitAPI):
1831
1840
  response = self.v2PrivateGetAccountsAccountIdTransactions(self.extend(request, params))
1832
1841
  ledger = self.parse_ledger(response['data'], currency, since, limit)
1833
1842
  length = len(ledger)
1843
+ if length == 0:
1844
+ return ledger
1834
1845
  lastIndex = length - 1
1835
1846
  last = self.safe_dict(ledger, lastIndex)
1836
1847
  pagination = self.safe_dict(response, 'pagination', {})
@@ -2164,9 +2175,9 @@ class coinbase(Exchange, ImplicitAPI):
2164
2175
  'fee': fee,
2165
2176
  }
2166
2177
 
2167
- def find_account_id(self, code):
2178
+ def find_account_id(self, code, params={}):
2168
2179
  self.load_markets()
2169
- self.load_accounts()
2180
+ self.load_accounts(False, params)
2170
2181
  for i in range(0, len(self.accounts)):
2171
2182
  account = self.accounts[i]
2172
2183
  if account['code'] == code:
@@ -2190,7 +2201,7 @@ class coinbase(Exchange, ImplicitAPI):
2190
2201
  if accountId is None:
2191
2202
  if code is None:
2192
2203
  raise ArgumentsRequired(self.id + ' prepareAccountRequestWithCurrencyCode() method requires an account_id(or accountId) parameter OR a currency code argument')
2193
- accountId = self.find_account_id(code)
2204
+ accountId = self.find_account_id(code, params)
2194
2205
  if accountId is None:
2195
2206
  raise ExchangeError(self.id + ' prepareAccountRequestWithCurrencyCode() could not find account id for ' + code)
2196
2207
  request = {
@@ -3219,7 +3230,7 @@ class coinbase(Exchange, ImplicitAPI):
3219
3230
  if accountId is None:
3220
3231
  if code is None:
3221
3232
  raise ArgumentsRequired(self.id + ' withdraw() requires an account_id(or accountId) parameter OR a currency code argument')
3222
- accountId = self.find_account_id(code)
3233
+ accountId = self.find_account_id(code, params)
3223
3234
  if accountId is None:
3224
3235
  raise ExchangeError(self.id + ' withdraw() could not find account id for ' + code)
3225
3236
  request = {
@@ -3436,7 +3447,7 @@ class coinbase(Exchange, ImplicitAPI):
3436
3447
  if accountId is None:
3437
3448
  if code is None:
3438
3449
  raise ArgumentsRequired(self.id + ' deposit() requires an account_id(or accountId) parameter OR a currency code argument')
3439
- accountId = self.find_account_id(code)
3450
+ accountId = self.find_account_id(code, params)
3440
3451
  if accountId is None:
3441
3452
  raise ExchangeError(self.id + ' deposit() could not find account id for ' + code)
3442
3453
  request = {
@@ -3501,7 +3512,7 @@ class coinbase(Exchange, ImplicitAPI):
3501
3512
  if accountId is None:
3502
3513
  if code is None:
3503
3514
  raise ArgumentsRequired(self.id + ' fetchDeposit() requires an account_id(or accountId) parameter OR a currency code argument')
3504
- accountId = self.find_account_id(code)
3515
+ accountId = self.find_account_id(code, params)
3505
3516
  if accountId is None:
3506
3517
  raise ExchangeError(self.id + ' fetchDeposit() could not find account id for ' + code)
3507
3518
  request = {
@@ -126,10 +126,10 @@ class coinbaseinternational(Exchange, ImplicitAPI):
126
126
  },
127
127
  'www': 'https://international.coinbase.com',
128
128
  'doc': [
129
- 'https://docs.cloud.coinbaseinternational.com/intx/docs',
129
+ 'https://docs.cloud.coinbase.com/intx/docs',
130
130
  ],
131
131
  'fees': [
132
- 'https://help.coinbaseinternational.com/en/international-exchange/trading-deposits-withdrawals/international-exchange-fees',
132
+ 'https://help.coinbase.com/en/international-exchange/trading-deposits-withdrawals/international-exchange-fees',
133
133
  ],
134
134
  'referral': '',
135
135
  },