ccxt 4.2.63__py2.py3-none-any.whl → 4.2.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 (59) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/blofin.py +1 -0
  3. ccxt/abstract/krakenfutures.py +1 -0
  4. ccxt/abstract/kucoin.py +10 -0
  5. ccxt/abstract/kucoinfutures.py +10 -0
  6. ccxt/async_support/__init__.py +1 -1
  7. ccxt/async_support/base/exchange.py +2 -2
  8. ccxt/async_support/binance.py +32 -13
  9. ccxt/async_support/bingx.py +56 -49
  10. ccxt/async_support/bitget.py +66 -2
  11. ccxt/async_support/bitmex.py +2 -1
  12. ccxt/async_support/blofin.py +45 -12
  13. ccxt/async_support/btcmarkets.py +9 -0
  14. ccxt/async_support/bybit.py +90 -6
  15. ccxt/async_support/coinbase.py +9 -2
  16. ccxt/async_support/delta.py +92 -2
  17. ccxt/async_support/gate.py +1 -1
  18. ccxt/async_support/gemini.py +9 -5
  19. ccxt/async_support/hitbtc.py +1 -1
  20. ccxt/async_support/krakenfutures.py +1 -0
  21. ccxt/async_support/kucoin.py +85 -61
  22. ccxt/async_support/okx.py +1 -1
  23. ccxt/async_support/woo.py +1 -1
  24. ccxt/async_support/yobit.py +15 -15
  25. ccxt/base/exchange.py +14 -3
  26. ccxt/binance.py +32 -13
  27. ccxt/bingx.py +56 -49
  28. ccxt/bitget.py +66 -2
  29. ccxt/bitmex.py +2 -1
  30. ccxt/blofin.py +45 -12
  31. ccxt/btcmarkets.py +9 -0
  32. ccxt/bybit.py +90 -6
  33. ccxt/coinbase.py +9 -2
  34. ccxt/delta.py +92 -2
  35. ccxt/gate.py +1 -1
  36. ccxt/gemini.py +9 -5
  37. ccxt/hitbtc.py +1 -1
  38. ccxt/krakenfutures.py +1 -0
  39. ccxt/kucoin.py +85 -61
  40. ccxt/okx.py +1 -1
  41. ccxt/pro/__init__.py +1 -1
  42. ccxt/pro/bitget.py +4 -3
  43. ccxt/pro/coinex.py +4 -4
  44. ccxt/pro/currencycom.py +1 -1
  45. ccxt/pro/lbank.py +1 -1
  46. ccxt/static_dependencies/ethereum/utils/__init__.py +0 -6
  47. ccxt/static_dependencies/ethereum/utils/curried/__init__.py +0 -4
  48. ccxt/test/base/test_shared_methods.py +1 -1
  49. ccxt/test/test_async.py +13 -1
  50. ccxt/test/test_sync.py +13 -1
  51. ccxt/woo.py +1 -1
  52. ccxt/yobit.py +15 -15
  53. {ccxt-4.2.63.dist-info → ccxt-4.2.65.dist-info}/METADATA +4 -4
  54. {ccxt-4.2.63.dist-info → ccxt-4.2.65.dist-info}/RECORD +56 -59
  55. ccxt/static_dependencies/ethereum/utils/__json/eth_networks.json +0 -1
  56. ccxt/static_dependencies/ethereum/utils/network.py +0 -88
  57. ccxt-4.2.63.data/data/ccxt/eth_networks.json +0 -1
  58. {ccxt-4.2.63.dist-info → ccxt-4.2.65.dist-info}/WHEEL +0 -0
  59. {ccxt-4.2.63.dist-info → ccxt-4.2.65.dist-info}/top_level.txt +0 -0
ccxt/bitget.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bitget import ImplicitAPI
8
8
  import hashlib
9
9
  import json
10
- from ccxt.base.types import Balances, Currency, Int, Liquidation, Leverage, Market, Order, TransferEntry, OrderBook, OrderRequest, OrderSide, OrderType, Position, FundingHistory, Str, Strings, Ticker, Tickers, Trade, Transaction
10
+ from ccxt.base.types import Balances, Currency, Int, Liquidation, Leverage, MarginMode, Market, Order, TransferEntry, OrderBook, OrderRequest, OrderSide, OrderType, Position, FundingHistory, Str, Strings, Ticker, Tickers, Trade, Transaction
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -105,7 +105,7 @@ class bitget(Exchange, ImplicitAPI):
105
105
  'fetchLeverage': True,
106
106
  'fetchLeverageTiers': False,
107
107
  'fetchLiquidations': False,
108
- 'fetchMarginMode': False,
108
+ 'fetchMarginMode': True,
109
109
  'fetchMarketLeverageTiers': True,
110
110
  'fetchMarkets': True,
111
111
  'fetchMarkOHLCV': True,
@@ -7726,6 +7726,70 @@ class bitget(Exchange, ImplicitAPI):
7726
7726
  orderInfo = self.safe_value(data, 'successList', [])
7727
7727
  return self.parse_positions(orderInfo, None, params)
7728
7728
 
7729
+ def fetch_margin_mode(self, symbol: str, params={}) -> MarginMode:
7730
+ """
7731
+ fetches the margin mode of a trading pair
7732
+ :see: https://www.bitget.com/api-doc/contract/account/Get-Single-Account
7733
+ :param str symbol: unified symbol of the market to fetch the margin mode for
7734
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7735
+ :returns dict: a `margin mode structure <https://docs.ccxt.com/#/?id=margin-mode-structure>`
7736
+ """
7737
+ self.load_markets()
7738
+ sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
7739
+ market = None
7740
+ if sandboxMode:
7741
+ sandboxSymbol = self.convert_symbol_for_sandbox(symbol)
7742
+ market = self.market(sandboxSymbol)
7743
+ else:
7744
+ market = self.market(symbol)
7745
+ productType = None
7746
+ productType, params = self.handle_product_type_and_params(market, params)
7747
+ request = {
7748
+ 'symbol': market['id'],
7749
+ 'marginCoin': market['settleId'],
7750
+ 'productType': productType,
7751
+ }
7752
+ response = self.privateMixGetV2MixAccountAccount(self.extend(request, params))
7753
+ #
7754
+ # {
7755
+ # "code": "00000",
7756
+ # "msg": "success",
7757
+ # "requestTime": 1709791216652,
7758
+ # "data": {
7759
+ # "marginCoin": "USDT",
7760
+ # "locked": "0",
7761
+ # "available": "19.88811074",
7762
+ # "crossedMaxAvailable": "19.88811074",
7763
+ # "isolatedMaxAvailable": "19.88811074",
7764
+ # "maxTransferOut": "19.88811074",
7765
+ # "accountEquity": "19.88811074",
7766
+ # "usdtEquity": "19.888110749166",
7767
+ # "btcEquity": "0.000302183391",
7768
+ # "crossedRiskRate": "0",
7769
+ # "crossedMarginLeverage": 20,
7770
+ # "isolatedLongLever": 20,
7771
+ # "isolatedShortLever": 20,
7772
+ # "marginMode": "crossed",
7773
+ # "posMode": "hedge_mode",
7774
+ # "unrealizedPL": "0",
7775
+ # "coupon": "0",
7776
+ # "crossedUnrealizedPL": "0",
7777
+ # "isolatedUnrealizedPL": ""
7778
+ # }
7779
+ # }
7780
+ #
7781
+ data = self.safe_dict(response, 'data', {})
7782
+ return self.parse_margin_mode(data, market)
7783
+
7784
+ def parse_margin_mode(self, marginMode, market=None) -> MarginMode:
7785
+ marginType = self.safe_string(marginMode, 'marginMode')
7786
+ marginType = 'cross' if (marginType == 'crossed') else marginType
7787
+ return {
7788
+ 'info': marginMode,
7789
+ 'symbol': market['symbol'],
7790
+ 'marginMode': marginType,
7791
+ }
7792
+
7729
7793
  def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
7730
7794
  if not response:
7731
7795
  return None # fallback to default error handler
ccxt/bitmex.py CHANGED
@@ -2388,7 +2388,8 @@ class bitmex(Exchange, ImplicitAPI):
2388
2388
  params = self.omit(params, ['until', 'till'])
2389
2389
  if until is not None:
2390
2390
  request['endTime'] = self.iso8601(until)
2391
- request['reverse'] = True
2391
+ if (since is None) and (until is None):
2392
+ request['reverse'] = True
2392
2393
  response = self.publicGetFunding(self.extend(request, params))
2393
2394
  #
2394
2395
  # [
ccxt/blofin.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.blofin import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Leverage, Leverages, Market, Order, TransferEntry, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction
9
+ from ccxt.base.types import Balances, Currency, Int, Leverage, Leverages, MarginMode, Market, Order, TransferEntry, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
@@ -91,6 +91,8 @@ class blofin(Exchange, ImplicitAPI):
91
91
  'fetchLeverage': True,
92
92
  'fetchLeverages': True,
93
93
  'fetchLeverageTiers': False,
94
+ 'fetchMarginMode': True,
95
+ 'fetchMarginModes': False,
94
96
  'fetchMarketLeverageTiers': False,
95
97
  'fetchMarkets': True,
96
98
  'fetchMarkOHLCV': False,
@@ -194,6 +196,7 @@ class blofin(Exchange, ImplicitAPI):
194
196
  'account/balance': 1,
195
197
  'account/positions': 1,
196
198
  'account/leverage-info': 1,
199
+ 'account/margin-mode': 1,
197
200
  'account/batch-leverage-info': 1,
198
201
  'trade/orders-tpsl-pending': 1,
199
202
  'trade/orders-history': 1,
@@ -384,7 +387,7 @@ class blofin(Exchange, ImplicitAPI):
384
387
  strikePrice = None
385
388
  optionType = None
386
389
  tickSize = self.safe_string(market, 'tickSize')
387
- fees = self.safe_value_2(self.fees, type, 'trading', {})
390
+ fees = self.safe_dict_2(self.fees, type, 'trading', {})
388
391
  taker = self.safe_number(fees, 'taker')
389
392
  maker = self.safe_number(fees, 'maker')
390
393
  maxLeverage = self.safe_string(market, 'maxLeverage', '100')
@@ -482,7 +485,7 @@ class blofin(Exchange, ImplicitAPI):
482
485
  # }
483
486
  #
484
487
  data = self.safe_list(response, 'data', [])
485
- first = self.safe_value(data, 0, {})
488
+ first = self.safe_dict(data, 0, {})
486
489
  timestamp = self.safe_integer(first, 'ts')
487
490
  return self.parse_order_book(first, symbol, timestamp)
488
491
 
@@ -536,7 +539,7 @@ class blofin(Exchange, ImplicitAPI):
536
539
  }
537
540
  response = self.publicGetMarketTickers(self.extend(request, params))
538
541
  data = self.safe_list(response, 'data', [])
539
- first = self.safe_value(data, 0, {})
542
+ first = self.safe_dict(data, 0, {})
540
543
  return self.parse_ticker(first, market)
541
544
 
542
545
  def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
@@ -961,8 +964,8 @@ class blofin(Exchange, ImplicitAPI):
961
964
  postOnly, params = self.handle_post_only(isMarketOrder, type == 'post_only', params)
962
965
  if postOnly:
963
966
  request['type'] = 'post_only'
964
- stopLoss = self.safe_value(params, 'stopLoss')
965
- takeProfit = self.safe_value(params, 'takeProfit')
967
+ stopLoss = self.safe_dict(params, 'stopLoss')
968
+ takeProfit = self.safe_dict(params, 'takeProfit')
966
969
  params = self.omit(params, ['stopLoss', 'takeProfit'])
967
970
  isStopLoss = stopLoss is not None
968
971
  isTakeProfit = takeProfit is not None
@@ -1227,7 +1230,7 @@ class blofin(Exchange, ImplicitAPI):
1227
1230
  side = self.safe_string(rawOrder, 'side')
1228
1231
  amount = self.safe_value(rawOrder, 'amount')
1229
1232
  price = self.safe_value(rawOrder, 'price')
1230
- orderParams = self.safe_value(rawOrder, 'params', {})
1233
+ orderParams = self.safe_dict(rawOrder, 'params', {})
1231
1234
  extendedParams = self.extend(orderParams, params) # the request does not accept extra params since it's a list, so we're extending each order with the common params
1232
1235
  orderRequest = self.create_order_request(marketId, type, side, amount, price, extendedParams)
1233
1236
  ordersRequests.append(orderRequest)
@@ -1261,7 +1264,7 @@ class blofin(Exchange, ImplicitAPI):
1261
1264
  request['instId'] = market['id']
1262
1265
  if limit is not None:
1263
1266
  request['limit'] = limit # default 100, max 100
1264
- isStop = self.safe_value_n(params, ['stop', 'trigger', 'tpsl', 'TPSL'], False)
1267
+ isStop = self.safe_bool_n(params, ['stop', 'trigger', 'tpsl', 'TPSL'], False)
1265
1268
  method: str = None
1266
1269
  method, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'method', 'privateGetTradeOrdersPending')
1267
1270
  query = self.omit(params, ['method', 'stop', 'trigger', 'tpsl', 'TPSL'])
@@ -1560,7 +1563,7 @@ class blofin(Exchange, ImplicitAPI):
1560
1563
  self.load_markets()
1561
1564
  market = self.market(symbol)
1562
1565
  request = []
1563
- options = self.safe_value(self.options, 'cancelOrders', {})
1566
+ options = self.safe_dict(self.options, 'cancelOrders', {})
1564
1567
  defaultMethod = self.safe_string(options, 'method', 'privatePostTradeCancelBatchOrders')
1565
1568
  method = self.safe_string(params, 'method', defaultMethod)
1566
1569
  clientOrderIds = self.parse_ids(self.safe_value(params, 'clientOrderId'))
@@ -1614,7 +1617,7 @@ class blofin(Exchange, ImplicitAPI):
1614
1617
  """
1615
1618
  self.load_markets()
1616
1619
  currency = self.currency(code)
1617
- accountsByType = self.safe_value(self.options, 'accountsByType', {})
1620
+ accountsByType = self.safe_dict(self.options, 'accountsByType', {})
1618
1621
  fromId = self.safe_string(accountsByType, fromAccount, fromAccount)
1619
1622
  toId = self.safe_string(accountsByType, toAccount, toAccount)
1620
1623
  request = {
@@ -1912,7 +1915,7 @@ class blofin(Exchange, ImplicitAPI):
1912
1915
  if clientOrderId is not None:
1913
1916
  request['clientOrderId'] = clientOrderId
1914
1917
  response = self.privatePostTradeClosePosition(self.extend(request, params))
1915
- return self.safe_value(response, 'data')
1918
+ return self.safe_dict(response, 'data')
1916
1919
 
1917
1920
  def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1918
1921
  """
@@ -1942,7 +1945,7 @@ class blofin(Exchange, ImplicitAPI):
1942
1945
  request['limit'] = limit # default 100, max 100
1943
1946
  if since is not None:
1944
1947
  request['begin'] = since
1945
- isStop = self.safe_value_n(params, ['stop', 'trigger', 'tpsl', 'TPSL'], False)
1948
+ isStop = self.safe_bool_n(params, ['stop', 'trigger', 'tpsl', 'TPSL'], False)
1946
1949
  method: str = None
1947
1950
  method, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'method', 'privateGetTradeOrdersHistory')
1948
1951
  query = self.omit(params, ['method', 'stop', 'trigger', 'tpsl', 'TPSL'])
@@ -1954,6 +1957,36 @@ class blofin(Exchange, ImplicitAPI):
1954
1957
  data = self.safe_list(response, 'data', [])
1955
1958
  return self.parse_orders(data, market, since, limit)
1956
1959
 
1960
+ def fetch_margin_mode(self, symbol: str, params={}) -> MarginMode:
1961
+ """
1962
+ fetches the margin mode of a trading pair
1963
+ :see: https://docs.blofin.com/index.html#get-margin-mode
1964
+ :param str symbol: unified symbol of the market to fetch the margin mode for
1965
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1966
+ :returns dict: a `margin mode structure <https://docs.ccxt.com/#/?id=margin-mode-structure>`
1967
+ """
1968
+ self.load_markets()
1969
+ market = self.market(symbol)
1970
+ response = self.privateGetAccountMarginMode(params)
1971
+ #
1972
+ # {
1973
+ # "code": "0",
1974
+ # "msg": "success",
1975
+ # "data": {
1976
+ # "marginMode": "cross"
1977
+ # }
1978
+ # }
1979
+ #
1980
+ data = self.safe_dict(response, 'data', {})
1981
+ return self.parse_margin_mode(data, market)
1982
+
1983
+ def parse_margin_mode(self, marginMode, market=None) -> MarginMode:
1984
+ return {
1985
+ 'info': marginMode,
1986
+ 'symbol': market['symbol'],
1987
+ 'marginMode': self.safe_string(marginMode, 'marginMode'),
1988
+ }
1989
+
1957
1990
  def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
1958
1991
  if response is None:
1959
1992
  return None # fallback to default error handler
ccxt/btcmarkets.py CHANGED
@@ -870,6 +870,15 @@ class btcmarkets(Exchange, ImplicitAPI):
870
870
  return self.privateDeleteOrdersId(self.extend(request, params))
871
871
 
872
872
  def calculate_fee(self, symbol, type, side, amount, price, takerOrMaker='taker', params={}):
873
+ """
874
+ calculates the presumptive fee that would be charged for an order
875
+ :param str symbol: unified market symbol
876
+ :param str type: not used by btcmarkets.calculate_fee :param string side: not used by btcmarkets.calculate_fee :param float amount: how much you want to trade, in units of the base currency on most exchanges, or number of contracts
877
+ :param float price: the price for the order to be filled at, in units of the quote currency
878
+ :param str takerOrMaker: 'taker' or 'maker'
879
+ :param dict params:
880
+ :returns dict: contains the rate, the percentage multiplied to the order amount to obtain the fee amount, and cost, the total value of the fee in units of the quote currency, for the order
881
+ """
873
882
  market = self.markets[symbol]
874
883
  currency = None
875
884
  cost = None
ccxt/bybit.py CHANGED
@@ -3563,8 +3563,8 @@ class bybit(Exchange, ImplicitAPI):
3563
3563
  market = self.market(symbols[0])
3564
3564
  category = None
3565
3565
  category, params = self.get_bybit_type('createOrders', market, params)
3566
- if (category == 'spot') or (category == 'inverse'):
3567
- raise NotSupported(self.id + ' createOrders does not allow spot or inverse orders')
3566
+ if category == 'inverse':
3567
+ raise NotSupported(self.id + ' createOrders does not allow inverse orders')
3568
3568
  request = {
3569
3569
  'category': category,
3570
3570
  'request': ordersRequests,
@@ -3985,6 +3985,81 @@ class bybit(Exchange, ImplicitAPI):
3985
3985
  result = self.safe_value(response, 'result', {})
3986
3986
  return self.parse_order(result, market)
3987
3987
 
3988
+ def cancel_orders(self, ids, symbol: Str = None, params={}):
3989
+ """
3990
+ cancel multiple orders
3991
+ :see: https://bybit-exchange.github.io/docs/v5/order/batch-cancel
3992
+ :param str[] ids: order ids
3993
+ :param str symbol: unified symbol of the market the order was made in
3994
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3995
+ :param str[] [params.clientOrderIds]: client order ids
3996
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
3997
+ """
3998
+ if symbol is None:
3999
+ raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
4000
+ self.load_markets()
4001
+ market = self.market(symbol)
4002
+ category = None
4003
+ category, params = self.get_bybit_type('cancelOrders', market, params)
4004
+ if category == 'inverse':
4005
+ raise NotSupported(self.id + ' cancelOrders does not allow inverse orders')
4006
+ ordersRequests = []
4007
+ clientOrderIds = self.safe_list_2(params, 'clientOrderIds', 'clientOids', [])
4008
+ params = self.omit(params, ['clientOrderIds', 'clientOids'])
4009
+ for i in range(0, len(clientOrderIds)):
4010
+ ordersRequests.append({
4011
+ 'symbol': market['id'],
4012
+ 'orderLinkId': self.safe_string(clientOrderIds, i),
4013
+ })
4014
+ for i in range(0, len(ids)):
4015
+ ordersRequests.append({
4016
+ 'symbol': market['id'],
4017
+ 'orderId': self.safe_string(ids, i),
4018
+ })
4019
+ request = {
4020
+ 'category': category,
4021
+ 'request': ordersRequests,
4022
+ }
4023
+ response = self.privatePostV5OrderCancelBatch(self.extend(request, params))
4024
+ #
4025
+ # {
4026
+ # "retCode": "0",
4027
+ # "retMsg": "OK",
4028
+ # "result": {
4029
+ # "list": [
4030
+ # {
4031
+ # "category": "spot",
4032
+ # "symbol": "BTCUSDT",
4033
+ # "orderId": "1636282505818800896",
4034
+ # "orderLinkId": "1636282505818800897"
4035
+ # },
4036
+ # {
4037
+ # "category": "spot",
4038
+ # "symbol": "BTCUSDT",
4039
+ # "orderId": "1636282505818800898",
4040
+ # "orderLinkId": "1636282505818800899"
4041
+ # }
4042
+ # ]
4043
+ # },
4044
+ # "retExtInfo": {
4045
+ # "list": [
4046
+ # {
4047
+ # "code": "0",
4048
+ # "msg": "OK"
4049
+ # },
4050
+ # {
4051
+ # "code": "0",
4052
+ # "msg": "OK"
4053
+ # }
4054
+ # ]
4055
+ # },
4056
+ # "time": "1709796158501"
4057
+ # }
4058
+ #
4059
+ result = self.safe_dict(response, 'result', {})
4060
+ row = self.safe_list(result, 'list', [])
4061
+ return self.parse_orders(row, market)
4062
+
3988
4063
  def cancel_all_usdc_orders(self, symbol: Str = None, params={}):
3989
4064
  if symbol is None:
3990
4065
  raise ArgumentsRequired(self.id + ' cancelAllUsdcOrders() requires a symbol argument')
@@ -6714,7 +6789,8 @@ class bybit(Exchange, ImplicitAPI):
6714
6789
  # }
6715
6790
  #
6716
6791
  marketId = self.safe_string(fee, 'symbol')
6717
- symbol = self.safe_symbol(marketId, None, None, 'contract')
6792
+ defaultType = market['type'] if (market is not None) else 'contract'
6793
+ symbol = self.safe_symbol(marketId, market, None, defaultType)
6718
6794
  return {
6719
6795
  'info': fee,
6720
6796
  'symbol': symbol,
@@ -6732,11 +6808,19 @@ class bybit(Exchange, ImplicitAPI):
6732
6808
  """
6733
6809
  self.load_markets()
6734
6810
  market = self.market(symbol)
6735
- if market['spot']:
6736
- raise NotSupported(self.id + ' fetchTradingFee() is not supported for spot market')
6737
6811
  request = {
6738
6812
  'symbol': market['id'],
6739
6813
  }
6814
+ category = None
6815
+ if market['linear']:
6816
+ category = 'linear'
6817
+ elif market['inverse']:
6818
+ category = 'inverse'
6819
+ elif market['spot']:
6820
+ category = 'spot'
6821
+ else:
6822
+ category = 'option'
6823
+ request['category'] = category
6740
6824
  response = self.privateGetV5AccountFeeRate(self.extend(request, params))
6741
6825
  #
6742
6826
  # {
@@ -6758,7 +6842,7 @@ class bybit(Exchange, ImplicitAPI):
6758
6842
  result = self.safe_value(response, 'result', {})
6759
6843
  fees = self.safe_value(result, 'list', [])
6760
6844
  first = self.safe_value(fees, 0, {})
6761
- return self.parse_trading_fee(first)
6845
+ return self.parse_trading_fee(first, market)
6762
6846
 
6763
6847
  def fetch_trading_fees(self, params={}):
6764
6848
  """
ccxt/coinbase.py CHANGED
@@ -3521,7 +3521,8 @@ class coinbase(Exchange, ImplicitAPI):
3521
3521
  def sign(self, path, api=[], method='GET', params={}, headers=None, body=None):
3522
3522
  version = api[0]
3523
3523
  signed = api[1] == 'private'
3524
- pathPart = 'api/v3' if (version == 'v3') else 'v2'
3524
+ isV3 = version == 'v3'
3525
+ pathPart = 'api/v3' if (isV3) else 'v2'
3525
3526
  fullPath = '/' + pathPart + '/' + self.implode_params(path, params)
3526
3527
  query = self.omit(params, self.extract_params(path))
3527
3528
  savedPath = fullPath
@@ -3555,8 +3556,14 @@ class coinbase(Exchange, ImplicitAPI):
3555
3556
  if query:
3556
3557
  body = self.json(query)
3557
3558
  payload = body
3558
- # 'GET' doesn't need payload in the signature. inside url is enough
3559
+ else:
3560
+ if not isV3:
3561
+ if query:
3562
+ payload += '?' + self.urlencode(query)
3563
+ # v3: 'GET' doesn't need payload in the signature. inside url is enough
3559
3564
  # https://docs.cloud.coinbase.com/advanced-trade-api/docs/auth#example-request
3565
+ # v2: 'GET' require payload in the signature
3566
+ # https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-key-authentication
3560
3567
  auth = timestampString + method + savedPath + payload
3561
3568
  signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256)
3562
3569
  headers = {
ccxt/delta.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.delta import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Greeks, Int, Leverage, Market, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
9
+ from ccxt.base.types import Balances, Currency, Greeks, Int, Leverage, MarginMode, Market, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
@@ -61,7 +61,8 @@ class delta(Exchange, ImplicitAPI):
61
61
  'fetchLedger': True,
62
62
  'fetchLeverage': True,
63
63
  'fetchLeverageTiers': False, # An infinite number of tiers, see examples/js/delta-maintenance-margin-rate-max-leverage.js
64
- 'fetchMarginMode': False,
64
+ 'fetchMarginMode': True,
65
+ 'fetchMarginModes': False,
65
66
  'fetchMarketLeverageTiers': False,
66
67
  'fetchMarkets': True,
67
68
  'fetchMarkOHLCV': True,
@@ -3088,6 +3089,95 @@ class delta(Exchange, ImplicitAPI):
3088
3089
  position = self.parse_position(self.safe_value(response, 'result', {}))
3089
3090
  return [position]
3090
3091
 
3092
+ def fetch_margin_mode(self, symbol: str, params={}) -> MarginMode:
3093
+ """
3094
+ fetches the margin mode of a trading pair
3095
+ :see: https://docs.delta.exchange/#get-user
3096
+ :param str symbol: unified symbol of the market to fetch the margin mode for
3097
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3098
+ :returns dict: a `margin mode structure <https://docs.ccxt.com/#/?id=margin-mode-structure>`
3099
+ """
3100
+ self.load_markets()
3101
+ market = None
3102
+ if symbol is not None:
3103
+ market = self.market(symbol)
3104
+ response = self.privateGetProfile(params)
3105
+ #
3106
+ # {
3107
+ # "result": {
3108
+ # "is_password_set": True,
3109
+ # "kyc_expiry_date": null,
3110
+ # "phishing_code": "12345",
3111
+ # "preferences": {
3112
+ # "favorites": []
3113
+ # },
3114
+ # "is_kyc_provisioned": False,
3115
+ # "country": "Canada",
3116
+ # "margin_mode": "isolated",
3117
+ # "mfa_updated_at": "2023-07-19T01:04:43Z",
3118
+ # "last_name": "",
3119
+ # "oauth_apple_active": False,
3120
+ # "pf_index_symbol": null,
3121
+ # "proof_of_identity_status": "approved",
3122
+ # "dob": null,
3123
+ # "email": "abc_123@gmail.com",
3124
+ # "force_change_password": False,
3125
+ # "nick_name": "still-breeze-123",
3126
+ # "oauth_google_active": False,
3127
+ # "phone_verification_status": "verified",
3128
+ # "id": 12345678,
3129
+ # "last_seen": null,
3130
+ # "is_withdrawal_enabled": True,
3131
+ # "force_change_mfa": False,
3132
+ # "enable_bots": False,
3133
+ # "kyc_verified_on": null,
3134
+ # "created_at": "2023-07-19T01:02:32Z",
3135
+ # "withdrawal_blocked_till": null,
3136
+ # "proof_of_address_status": "approved",
3137
+ # "is_password_change_blocked": False,
3138
+ # "is_mfa_enabled": True,
3139
+ # "is_kyc_done": True,
3140
+ # "oauth": null,
3141
+ # "account_name": "Main",
3142
+ # "sub_account_permissions": null,
3143
+ # "phone_number": null,
3144
+ # "tracking_info": {
3145
+ # "ga_cid": "1234.4321",
3146
+ # "is_kyc_gtm_tracked": True,
3147
+ # "sub_account_config": {
3148
+ # "cross": 2,
3149
+ # "isolated": 2,
3150
+ # "portfolio": 2
3151
+ # }
3152
+ # },
3153
+ # "first_name": "",
3154
+ # "phone_verified_on": null,
3155
+ # "seen_intro": False,
3156
+ # "password_updated_at": null,
3157
+ # "is_login_enabled": True,
3158
+ # "registration_date": "2023-07-19T01:02:32Z",
3159
+ # "permissions": {},
3160
+ # "max_sub_accounts_limit": 2,
3161
+ # "country_calling_code": null,
3162
+ # "is_sub_account": False,
3163
+ # "is_kyc_refresh_required": False
3164
+ # },
3165
+ # "success": True
3166
+ # }
3167
+ #
3168
+ result = self.safe_dict(response, 'result', {})
3169
+ return self.parse_margin_mode(result, market)
3170
+
3171
+ def parse_margin_mode(self, marginMode, market=None) -> MarginMode:
3172
+ symbol = None
3173
+ if market is not None:
3174
+ symbol = market['symbol']
3175
+ return {
3176
+ 'info': marginMode,
3177
+ 'symbol': symbol,
3178
+ 'marginMode': self.safe_string(marginMode, 'margin_mode'),
3179
+ }
3180
+
3091
3181
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
3092
3182
  requestPath = '/' + self.version + '/' + self.implode_params(path, params)
3093
3183
  url = self.urls['api'][api] + requestPath
ccxt/gate.py CHANGED
@@ -879,7 +879,7 @@ class gate(Exchange, ImplicitAPI):
879
879
  },
880
880
  })
881
881
 
882
- def set_sandbox_mode(self, enable):
882
+ def set_sandbox_mode(self, enable: bool):
883
883
  super(gate, self).set_sandbox_mode(enable)
884
884
  self.options['sandboxMode'] = enable
885
885
 
ccxt/gemini.py CHANGED
@@ -266,7 +266,7 @@ class gemini(Exchange, ImplicitAPI):
266
266
  },
267
267
  },
268
268
  'options': {
269
- 'fetchMarketsMethod': 'fetch_markets_from_web',
269
+ 'fetchMarketsMethod': 'fetch_markets_from_web', # fetch_markets_from_api, fetch_markets_from_web
270
270
  'fetchMarketFromWebRetries': 10,
271
271
  'fetchMarketsFromAPI': {
272
272
  'fetchDetailsForAllSymbols': False,
@@ -276,12 +276,12 @@ class gemini(Exchange, ImplicitAPI):
276
276
  'webApiEnable': True, # fetches from WEB
277
277
  'webApiRetries': 10,
278
278
  },
279
+ 'fetchUsdtMarkets': ['btcusdt', 'ethusdt'], # self is only used if markets-fetch is set from "web"; keep self list updated(not available trough web api)
279
280
  'fetchCurrencies': {
280
281
  'webApiEnable': True, # fetches from WEB
281
282
  'webApiRetries': 5,
282
283
  'webApiMuteFailure': True,
283
284
  },
284
- 'fetchUsdtMarkets': ['btcusdt', 'ethusdt'], # keep self list updated(not available trough web api)
285
285
  'fetchTickerMethod': 'fetchTickerV1', # fetchTickerV1, fetchTickerV2, fetchTickerV1AndV2
286
286
  'networks': {
287
287
  'BTC': 'bitcoin',
@@ -410,9 +410,11 @@ class gemini(Exchange, ImplicitAPI):
410
410
  """
411
411
  method = self.safe_value(self.options, 'fetchMarketsMethod', 'fetch_markets_from_api')
412
412
  if method == 'fetch_markets_from_web':
413
- usdMarkets = self.fetch_markets_from_web(params) # get usd markets
414
- usdtMarkets = self.fetch_usdt_markets(params) # get usdt markets
415
- return self.array_concat(usdMarkets, usdtMarkets)
413
+ promises = []
414
+ promises.append(self.fetch_markets_from_web(params)) # get usd markets
415
+ promises.append(self.fetch_usdt_markets(params)) # get usdt markets
416
+ promisesResult = promises
417
+ return self.array_concat(promisesResult[0], promisesResult[1])
416
418
  return self.fetch_markets_from_api(params)
417
419
 
418
420
  def fetch_markets_from_web(self, params={}):
@@ -515,6 +517,8 @@ class gemini(Exchange, ImplicitAPI):
515
517
  'post_only': True,
516
518
  'limit_only': True,
517
519
  }
520
+ if status is None:
521
+ return True # below
518
522
  return self.safe_bool(statuses, status, True)
519
523
 
520
524
  def fetch_usdt_markets(self, params={}):
ccxt/hitbtc.py CHANGED
@@ -2339,7 +2339,7 @@ class hitbtc(Exchange, ImplicitAPI):
2339
2339
  :see: https://api.hitbtc.com/#get-futures-position-parameters
2340
2340
  :param str symbol: unified symbol of the market the order was made in
2341
2341
  :param dict [params]: extra parameters specific to the exchange API endpoint
2342
- :returns dict: Struct of MarginMode
2342
+ :returns dict: a list of `margin mode structures <https://docs.ccxt.com/#/?id=margin-mode-structure>`
2343
2343
  """
2344
2344
  self.load_markets()
2345
2345
  market = None
ccxt/krakenfutures.py CHANGED
@@ -161,6 +161,7 @@ class krakenfutures(Exchange, ImplicitAPI):
161
161
  'executions',
162
162
  'triggers',
163
163
  'accountlogcsv',
164
+ 'account-log',
164
165
  'market/{symbol}/orders',
165
166
  'market/{symbol}/executions',
166
167
  ],