ccxt 4.4.64__py2.py3-none-any.whl → 4.4.68__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 (55) hide show
  1. ccxt/__init__.py +5 -3
  2. ccxt/abstract/cryptomus.py +20 -0
  3. ccxt/abstract/derive.py +117 -0
  4. ccxt/abstract/tradeogre.py +1 -0
  5. ccxt/abstract/whitebit.py +16 -0
  6. ccxt/async_support/__init__.py +5 -3
  7. ccxt/async_support/base/exchange.py +6 -5
  8. ccxt/async_support/binance.py +5 -3
  9. ccxt/async_support/bitget.py +22 -12
  10. ccxt/async_support/bitrue.py +6 -3
  11. ccxt/async_support/bybit.py +1 -1
  12. ccxt/async_support/coinbase.py +73 -2
  13. ccxt/async_support/cryptocom.py +2 -0
  14. ccxt/async_support/cryptomus.py +1041 -0
  15. ccxt/async_support/derive.py +2530 -0
  16. ccxt/async_support/gate.py +5 -1
  17. ccxt/async_support/htx.py +19 -5
  18. ccxt/async_support/hyperliquid.py +108 -68
  19. ccxt/async_support/luno.py +113 -1
  20. ccxt/async_support/paradex.py +51 -12
  21. ccxt/async_support/tradeogre.py +132 -13
  22. ccxt/async_support/whitebit.py +276 -2
  23. ccxt/base/errors.py +0 -6
  24. ccxt/base/exchange.py +13 -4
  25. ccxt/binance.py +5 -3
  26. ccxt/bitget.py +22 -12
  27. ccxt/bitrue.py +6 -3
  28. ccxt/bybit.py +1 -1
  29. ccxt/coinbase.py +73 -2
  30. ccxt/cryptocom.py +2 -0
  31. ccxt/cryptomus.py +1041 -0
  32. ccxt/derive.py +2529 -0
  33. ccxt/gate.py +5 -1
  34. ccxt/htx.py +19 -5
  35. ccxt/hyperliquid.py +108 -68
  36. ccxt/luno.py +113 -1
  37. ccxt/paradex.py +51 -12
  38. ccxt/pro/__init__.py +3 -3
  39. ccxt/pro/bybit.py +3 -2
  40. ccxt/pro/derive.py +704 -0
  41. ccxt/pro/gate.py +5 -2
  42. ccxt/pro/hyperliquid.py +3 -3
  43. ccxt/test/tests_async.py +36 -3
  44. ccxt/test/tests_sync.py +36 -3
  45. ccxt/tradeogre.py +132 -13
  46. ccxt/whitebit.py +276 -2
  47. {ccxt-4.4.64.dist-info → ccxt-4.4.68.dist-info}/METADATA +16 -12
  48. {ccxt-4.4.64.dist-info → ccxt-4.4.68.dist-info}/RECORD +51 -48
  49. ccxt/abstract/currencycom.py +0 -68
  50. ccxt/async_support/currencycom.py +0 -2070
  51. ccxt/currencycom.py +0 -2070
  52. ccxt/pro/currencycom.py +0 -536
  53. {ccxt-4.4.64.dist-info → ccxt-4.4.68.dist-info}/LICENSE.txt +0 -0
  54. {ccxt-4.4.64.dist-info → ccxt-4.4.68.dist-info}/WHEEL +0 -0
  55. {ccxt-4.4.64.dist-info → ccxt-4.4.68.dist-info}/top_level.txt +0 -0
ccxt/bitget.py CHANGED
@@ -2338,16 +2338,16 @@ class bitget(Exchange, ImplicitAPI):
2338
2338
  paginate, params = self.handle_option_and_params(params, 'fetchDeposits', 'paginate')
2339
2339
  if paginate:
2340
2340
  return self.fetch_paginated_call_cursor('fetchDeposits', None, since, limit, params, 'idLessThan', 'idLessThan', None, 100)
2341
- if code is None:
2342
- raise ArgumentsRequired(self.id + ' fetchDeposits() requires a `code` argument')
2343
- currency = self.currency(code)
2344
2341
  if since is None:
2345
2342
  since = self.milliseconds() - 7776000000 # 90 days
2346
2343
  request: dict = {
2347
- 'coin': currency['id'],
2348
2344
  'startTime': since,
2349
2345
  'endTime': self.milliseconds(),
2350
2346
  }
2347
+ currency = None
2348
+ if code is not None:
2349
+ currency = self.currency(code)
2350
+ request['coin'] = currency['id']
2351
2351
  if limit is not None:
2352
2352
  request['limit'] = limit
2353
2353
  request, params = self.handle_until_option('endTime', request, params)
@@ -2376,7 +2376,7 @@ class bitget(Exchange, ImplicitAPI):
2376
2376
  # }
2377
2377
  #
2378
2378
  rawTransactions = self.safe_list(response, 'data', [])
2379
- return self.parse_transactions(rawTransactions, currency, since, limit)
2379
+ return self.parse_transactions(rawTransactions, None, since, limit)
2380
2380
 
2381
2381
  def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
2382
2382
  """
@@ -4669,7 +4669,8 @@ class bitget(Exchange, ImplicitAPI):
4669
4669
  elif isTakeProfitOrder or isStopLossOrder:
4670
4670
  request['marginCoin'] = market['settleId']
4671
4671
  request['size'] = self.amount_to_precision(symbol, amount)
4672
- request['executePrice'] = self.price_to_precision(symbol, price)
4672
+ if price is not None:
4673
+ request['executePrice'] = self.price_to_precision(symbol, price)
4673
4674
  if isStopLossOrder:
4674
4675
  request['triggerPrice'] = self.price_to_precision(symbol, stopLossPrice)
4675
4676
  elif isTakeProfitOrder:
@@ -5450,10 +5451,11 @@ class bitget(Exchange, ImplicitAPI):
5450
5451
  :param int [since]: timestamp in ms of the earliest order
5451
5452
  :param int [limit]: the max number of closed orders to return
5452
5453
  :param dict [params]: extra parameters specific to the exchange API endpoint
5453
- :param int [params.until]: the latest time in ms to fetch entries for
5454
+ :param int [params.until]: the latest time in ms to fetch orders for
5455
+ :param str [params.planType]: *contract stop only* 'normal_plan': average trigger order, 'profit_loss': opened tp/sl orders, 'track_plan': trailing stop order, default is 'normal_plan'
5456
+ :param boolean [params.trigger]: set to True for fetching trigger orders
5454
5457
  :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)
5455
5458
  :param str [params.isPlan]: *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
5456
- :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
5457
5459
  :param boolean [params.trailing]: set to True if you want to fetch trailing orders
5458
5460
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5459
5461
  """
@@ -5476,10 +5478,11 @@ class bitget(Exchange, ImplicitAPI):
5476
5478
  :param int [since]: timestamp in ms of the earliest order
5477
5479
  :param int [limit]: the max number of canceled orders to return
5478
5480
  :param dict [params]: extra parameters specific to the exchange API endpoint
5479
- :param int [params.until]: the latest time in ms to fetch entries for
5481
+ :param int [params.until]: the latest time in ms to fetch orders for
5482
+ :param str [params.planType]: *contract stop only* 'normal_plan': average trigger order, 'profit_loss': opened tp/sl orders, 'track_plan': trailing stop order, default is 'normal_plan'
5483
+ :param boolean [params.trigger]: set to True for fetching trigger orders
5480
5484
  :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)
5481
5485
  :param str [params.isPlan]: *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
5482
- :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
5483
5486
  :param boolean [params.trailing]: set to True if you want to fetch trailing orders
5484
5487
  :returns dict: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5485
5488
  """
@@ -5502,6 +5505,12 @@ class bitget(Exchange, ImplicitAPI):
5502
5505
  :param int [since]: the earliest time in ms to fetch orders for
5503
5506
  :param int [limit]: the maximum number of order structures to retrieve
5504
5507
  :param dict [params]: extra parameters specific to the exchange API endpoint
5508
+ :param int [params.until]: the latest time in ms to fetch orders for
5509
+ :param str [params.planType]: *contract stop only* 'normal_plan': average trigger order, 'profit_loss': opened tp/sl orders, 'track_plan': trailing stop order, default is 'normal_plan'
5510
+ :param boolean [params.trigger]: set to True for fetching trigger orders
5511
+ :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)
5512
+ :param str [params.isPlan]: *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
5513
+ :param boolean [params.trailing]: set to True if you want to fetch trailing orders
5505
5514
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5506
5515
  """
5507
5516
  self.load_markets()
@@ -5530,7 +5539,7 @@ class bitget(Exchange, ImplicitAPI):
5530
5539
  cursorReceived = 'endId'
5531
5540
  return self.fetch_paginated_call_cursor('fetchCanceledAndClosedOrders', symbol, since, limit, params, cursorReceived, 'idLessThan')
5532
5541
  response = None
5533
- trailing = self.safe_value(params, 'trailing')
5542
+ trailing = self.safe_bool(params, 'trailing')
5534
5543
  trigger = self.safe_bool_2(params, 'stop', 'trigger')
5535
5544
  params = self.omit(params, ['stop', 'trigger', 'trailing'])
5536
5545
  request, params = self.handle_until_option('endTime', request, params)
@@ -5570,11 +5579,12 @@ class bitget(Exchange, ImplicitAPI):
5570
5579
  productType = None
5571
5580
  productType, params = self.handle_product_type_and_params(market, params)
5572
5581
  request['productType'] = productType
5582
+ planTypeDefined = self.safe_string(params, 'planType') is not None
5573
5583
  if trailing:
5574
5584
  planType = self.safe_string(params, 'planType', 'track_plan')
5575
5585
  request['planType'] = planType
5576
5586
  response = self.privateMixGetV2MixOrderOrdersPlanHistory(self.extend(request, params))
5577
- elif trigger:
5587
+ elif trigger or planTypeDefined:
5578
5588
  planType = self.safe_string(params, 'planType', 'normal_plan')
5579
5589
  request['planType'] = planType
5580
5590
  response = self.privateMixGetV2MixOrderOrdersPlanHistory(self.extend(request, params))
ccxt/bitrue.py CHANGED
@@ -1385,6 +1385,7 @@ class bitrue(Exchange, ImplicitAPI):
1385
1385
  :param int [since]: timestamp in ms of the earliest candle to fetch
1386
1386
  :param int [limit]: the maximum amount of candles to fetch
1387
1387
  :param dict [params]: extra parameters specific to the exchange API endpoint
1388
+ :param int [params.until]: the latest time in ms to fetch transfers for
1388
1389
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
1389
1390
  """
1390
1391
  self.load_markets()
@@ -1415,8 +1416,10 @@ class bitrue(Exchange, ImplicitAPI):
1415
1416
  }
1416
1417
  if limit is not None:
1417
1418
  request['limit'] = limit
1418
- if since is not None:
1419
- request['fromIdx'] = since
1419
+ until = self.safe_integer(params, 'until')
1420
+ if until is not None:
1421
+ params = self.omit(params, 'until')
1422
+ request['fromIdx'] = until
1420
1423
  response = self.spotV1PublicGetMarketKline(self.extend(request, params))
1421
1424
  data = self.safe_list(response, 'data', [])
1422
1425
  else:
@@ -1630,7 +1633,7 @@ class bitrue(Exchange, ImplicitAPI):
1630
1633
  tickers: dict = {}
1631
1634
  for i in range(0, len(data)):
1632
1635
  ticker = self.safe_dict(data, i, {})
1633
- market = self.market(self.safe_value(ticker, 'symbol'))
1636
+ market = self.safe_market(self.safe_string(ticker, 'symbol'))
1634
1637
  tickers[market['id']] = ticker
1635
1638
  return self.parse_tickers(tickers, symbols)
1636
1639
 
ccxt/bybit.py CHANGED
@@ -8825,7 +8825,7 @@ classic accounts only/ spot not supported* fetches information on an order made
8825
8825
  feedback = self.id + ' private api uses /user/v3/private/query-api to check if you have a unified account. The API key of user id must own one of permissions: "Account Transfer", "Subaccount Transfer", "Withdrawal" ' + body
8826
8826
  else:
8827
8827
  feedback = self.id + ' ' + body
8828
- if body.find('Withdraw address chain or destination tag are not equal'):
8828
+ if body.find('Withdraw address chain or destination tag are not equal') > -1:
8829
8829
  feedback = feedback + '; You might also need to ensure the address is whitelisted'
8830
8830
  self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
8831
8831
  self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
ccxt/coinbase.py CHANGED
@@ -4126,7 +4126,8 @@ class coinbase(Exchange, ImplicitAPI):
4126
4126
  # }
4127
4127
  # }
4128
4128
  #
4129
- data = self.safe_dict(response, 'data', {})
4129
+ # https://github.com/ccxt/ccxt/issues/25484
4130
+ data = self.safe_dict_2(response, 'data', 'transfer', {})
4130
4131
  return self.parse_transaction(data)
4131
4132
 
4132
4133
  def fetch_deposit(self, id: str, code: Str = None, params={}):
@@ -4191,7 +4192,8 @@ class coinbase(Exchange, ImplicitAPI):
4191
4192
  # }
4192
4193
  # }
4193
4194
  #
4194
- data = self.safe_dict(response, 'data', {})
4195
+ # https://github.com/ccxt/ccxt/issues/25484
4196
+ data = self.safe_dict_2(response, 'data', 'transfer', {})
4195
4197
  return self.parse_transaction(data)
4196
4198
 
4197
4199
  def fetch_deposit_method_ids(self, params={}):
@@ -4669,6 +4671,75 @@ class coinbase(Exchange, ImplicitAPI):
4669
4671
  }
4670
4672
  return result
4671
4673
 
4674
+ def fetch_portfolio_details(self, portfolioUuid: str, params={}) -> List[Any]:
4675
+ """
4676
+ Fetch details for a specific portfolio by UUID
4677
+
4678
+ https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getportfolios
4679
+
4680
+ :param str portfolioUuid: The unique identifier of the portfolio to fetch
4681
+ :param Dict [params]: Extra parameters specific to the exchange API endpoint
4682
+ :returns any[]: An account structure <https://docs.ccxt.com/#/?id=account-structure>
4683
+ """
4684
+ self.load_markets()
4685
+ request = {
4686
+ 'portfolio_uuid': portfolioUuid,
4687
+ }
4688
+ response = self.v3PrivateGetBrokeragePortfoliosPortfolioUuid(self.extend(request, params))
4689
+ result = self.parse_portfolio_details(response)
4690
+ return result
4691
+
4692
+ def parse_portfolio_details(self, portfolioData: dict):
4693
+ """
4694
+ Parse a Coinbase portfolio JSON object and extract relevant trading information.
4695
+ :param Dict portfolioData: The JSON response containing portfolio details
4696
+ :returns any[]: List of dictionaries with parsed portfolio position data
4697
+ """
4698
+ breakdown = portfolioData['breakdown']
4699
+ portfolioInfo = self.safe_dict(breakdown, 'portfolio', {})
4700
+ portfolioName = self.safe_string(portfolioInfo, 'name', 'Unknown')
4701
+ portfolioUuid = self.safe_string(portfolioInfo, 'uuid', '')
4702
+ spotPositions = self.safe_list(breakdown, 'spot_positions', [])
4703
+ parsedPositions = []
4704
+ for i in range(0, len(spotPositions)):
4705
+ position: dict = spotPositions[i]
4706
+ currencyCode = self.safe_string(position, 'asset', 'Unknown')
4707
+ availableBalanceStr = self.safe_string(position, 'available_to_trade_fiat', '0')
4708
+ availableBalance = self.parse_number(availableBalanceStr)
4709
+ totalBalanceFiatStr = self.safe_string(position, 'total_balance_fiat', '0')
4710
+ totalBalanceFiat = self.parse_number(totalBalanceFiatStr)
4711
+ holdAmount = totalBalanceFiat - availableBalance
4712
+ costBasisDict = self.safe_dict(position, 'cost_basis', {})
4713
+ costBasisStr = self.safe_string(costBasisDict, 'value', '0')
4714
+ averageEntryPriceDict = self.safe_dict(position, 'average_entry_price', {})
4715
+ averageEntryPriceStr = self.safe_string(averageEntryPriceDict, 'value', '0')
4716
+ positionData: dict = {
4717
+ 'currency': currencyCode,
4718
+ 'available_balance': availableBalance,
4719
+ 'hold_amount': holdAmount > holdAmount if 0 else 0,
4720
+ 'wallet_name': portfolioName,
4721
+ 'account_id': portfolioUuid,
4722
+ 'account_uuid': self.safe_string(position, 'account_uuid', ''),
4723
+ 'total_balance_fiat': totalBalanceFiat,
4724
+ 'total_balance_crypto': self.parse_number(self.safe_string(position, 'total_balance_crypto', '0')),
4725
+ 'available_to_trade_fiat': self.parse_number(self.safe_string(position, 'available_to_trade_fiat', '0')),
4726
+ 'available_to_trade_crypto': self.parse_number(self.safe_string(position, 'available_to_trade_crypto', '0')),
4727
+ 'available_to_transfer_fiat': self.parse_number(self.safe_string(position, 'available_to_transfer_fiat', '0')),
4728
+ 'available_to_transfer_crypto': self.parse_number(self.safe_string(position, 'available_to_trade_crypto', '0')),
4729
+ 'allocation': self.parse_number(self.safe_string(position, 'allocation', '0')),
4730
+ 'cost_basis': self.parse_number(costBasisStr),
4731
+ 'cost_basis_currency': self.safe_string(costBasisDict, 'currency', 'USD'),
4732
+ 'is_cash': self.safe_bool(position, 'is_cash', False),
4733
+ 'average_entry_price': self.parse_number(averageEntryPriceStr),
4734
+ 'average_entry_price_currency': self.safe_string(averageEntryPriceDict, 'currency', 'USD'),
4735
+ 'asset_uuid': self.safe_string(position, 'asset_uuid', ''),
4736
+ 'unrealized_pnl': self.parse_number(self.safe_string(position, 'unrealized_pnl', '0')),
4737
+ 'asset_color': self.safe_string(position, 'asset_color', ''),
4738
+ 'account_type': self.safe_string(position, 'account_type', ''),
4739
+ }
4740
+ parsedPositions.append(positionData)
4741
+ return parsedPositions
4742
+
4672
4743
  def create_auth_token(self, seconds: Int, method: Str = None, url: Str = None):
4673
4744
  # it may not work for v2
4674
4745
  uri = None
ccxt/cryptocom.py CHANGED
@@ -471,6 +471,8 @@ class cryptocom(Exchange, ImplicitAPI):
471
471
  'exact': {
472
472
  '219': InvalidOrder,
473
473
  '314': InvalidOrder, # {"id" : 1700xxx, "method" : "private/create-order", "code" : 314, "message" : "EXCEEDS_MAX_ORDER_SIZE", "result" : {"client_oid" : "1700xxx", "order_id" : "6530xxx"}}
474
+ '325': InvalidOrder, # {"id" : 1741xxx, "method" : "private/create-order", "code" : 325, "message" : "EXCEED_DAILY_VOL_LIMIT", "result" : {"client_oid" : "1741xxx", "order_id" : "6530xxx"}}
475
+ '415': InvalidOrder, # {"id" : 1741xxx, "method" : "private/create-order", "code" : 415, "message" : "BELOW_MIN_ORDER_SIZE", "result" : {"client_oid" : "1741xxx", "order_id" : "6530xxx"}}
474
476
  '10001': ExchangeError,
475
477
  '10002': PermissionDenied,
476
478
  '10003': PermissionDenied,