ccxt 4.4.6__py2.py3-none-any.whl → 4.4.8__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.
@@ -55,8 +55,8 @@ class mexc(Exchange, ImplicitAPI):
55
55
  'closePosition': False,
56
56
  'createDepositAddress': True,
57
57
  'createMarketBuyOrderWithCost': True,
58
- 'createMarketOrderWithCost': False,
59
- 'createMarketSellOrderWithCost': False,
58
+ 'createMarketOrderWithCost': True,
59
+ 'createMarketSellOrderWithCost': True,
60
60
  'createOrder': True,
61
61
  'createOrders': True,
62
62
  'createPostOnlyOrder': True,
@@ -145,7 +145,7 @@ class mexc(Exchange, ImplicitAPI):
145
145
  'repayCrossMargin': False,
146
146
  'repayIsolatedMargin': False,
147
147
  'setLeverage': True,
148
- 'setMarginMode': None,
148
+ 'setMarginMode': True,
149
149
  'setPositionMode': True,
150
150
  'signIn': None,
151
151
  'transfer': None,
@@ -431,7 +431,6 @@ class mexc(Exchange, ImplicitAPI):
431
431
  'options': {
432
432
  'adjustForTimeDifference': False,
433
433
  'timeDifference': 0,
434
- 'createMarketBuyOrderRequiresPrice': True,
435
434
  'unavailableContracts': {
436
435
  'BTC/USDT:USDT': True,
437
436
  'LTC/USDT:USDT': True,
@@ -480,12 +479,14 @@ class mexc(Exchange, ImplicitAPI):
480
479
  'LTC': 'LTC',
481
480
  },
482
481
  'networks': {
482
+ 'ZKSYNC': 'ZKSYNCERA',
483
483
  'TRC20': 'TRX',
484
484
  'TON': 'TONCOIN',
485
485
  'AVAXC': 'AVAX_CCHAIN',
486
486
  'ERC20': 'ETH',
487
487
  'ACA': 'ACALA',
488
488
  'BEP20': 'BSC',
489
+ 'OPTIMISM': 'OP',
489
490
  # 'ADA': 'Cardano(ADA)',
490
491
  # 'AE': 'AE',
491
492
  # 'ALGO': 'Algorand(ALGO)',
@@ -2019,8 +2020,24 @@ class mexc(Exchange, ImplicitAPI):
2019
2020
  market = self.market(symbol)
2020
2021
  if not market['spot']:
2021
2022
  raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
2022
- params['createMarketBuyOrderRequiresPrice'] = False
2023
- return await self.create_order(symbol, 'market', 'buy', cost, None, params)
2023
+ params['cost'] = cost
2024
+ return await self.create_order(symbol, 'market', 'buy', 0, None, params)
2025
+
2026
+ async def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}):
2027
+ """
2028
+ create a market sell order by providing the symbol and cost
2029
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#new-order
2030
+ :param str symbol: unified symbol of the market to create an order in
2031
+ :param float cost: how much you want to trade in units of the quote currency
2032
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2033
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2034
+ """
2035
+ await self.load_markets()
2036
+ market = self.market(symbol)
2037
+ if not market['spot']:
2038
+ raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
2039
+ params['cost'] = cost
2040
+ return await self.create_order(symbol, 'market', 'sell', 0, None, params)
2024
2041
 
2025
2042
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2026
2043
  """
@@ -2044,6 +2061,7 @@ class mexc(Exchange, ImplicitAPI):
2044
2061
  :param long [params.positionId]: *contract only* it is recommended to hasattr(self, fill) parameter when closing a position
2045
2062
  :param str [params.externalOid]: *contract only* external order ID
2046
2063
  :param int [params.positionMode]: *contract only* 1:hedge, 2:one-way, default: the user's current config
2064
+ :param boolean [params.test]: *spot only* whether to use the test endpoint or not, default is False
2047
2065
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2048
2066
  """
2049
2067
  await self.load_markets()
@@ -2062,22 +2080,21 @@ class mexc(Exchange, ImplicitAPI):
2062
2080
  'side': orderSide,
2063
2081
  'type': type.upper(),
2064
2082
  }
2065
- if orderSide == 'BUY' and type == 'market':
2066
- createMarketBuyOrderRequiresPrice = True
2067
- createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
2083
+ if type == 'market':
2068
2084
  cost = self.safe_number_2(params, 'cost', 'quoteOrderQty')
2069
2085
  params = self.omit(params, 'cost')
2070
2086
  if cost is not None:
2071
2087
  amount = cost
2072
- elif createMarketBuyOrderRequiresPrice:
2088
+ request['quoteOrderQty'] = self.cost_to_precision(symbol, amount)
2089
+ else:
2073
2090
  if price is None:
2074
- raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend in the amount argument')
2091
+ request['quantity'] = self.amount_to_precision(symbol, amount)
2075
2092
  else:
2076
2093
  amountString = self.number_to_string(amount)
2077
2094
  priceString = self.number_to_string(price)
2078
2095
  quoteAmount = Precise.string_mul(amountString, priceString)
2079
2096
  amount = quoteAmount
2080
- request['quoteOrderQty'] = self.cost_to_precision(symbol, amount)
2097
+ request['quoteOrderQty'] = self.cost_to_precision(symbol, amount)
2081
2098
  else:
2082
2099
  request['quantity'] = self.amount_to_precision(symbol, amount)
2083
2100
  if price is not None:
@@ -2112,8 +2129,14 @@ class mexc(Exchange, ImplicitAPI):
2112
2129
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2113
2130
  """
2114
2131
  await self.load_markets()
2132
+ test = self.safe_bool(params, 'test', False)
2133
+ params = self.omit(params, 'test')
2115
2134
  request = self.create_spot_order_request(market, type, side, amount, price, marginMode, params)
2116
- response = await self.spotPrivatePostOrder(self.extend(request, params))
2135
+ response = None
2136
+ if test:
2137
+ response = await self.spotPrivatePostOrderTest(request)
2138
+ else:
2139
+ response = await self.spotPrivatePostOrder(request)
2117
2140
  #
2118
2141
  # spot
2119
2142
  #
@@ -2427,6 +2450,9 @@ class mexc(Exchange, ImplicitAPI):
2427
2450
  async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2428
2451
  """
2429
2452
  fetches information on multiple orders made by the user
2453
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
2454
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2455
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2430
2456
  :param str symbol: unified market symbol of the market orders were made in
2431
2457
  :param int [since]: the earliest time in ms to fetch orders for
2432
2458
  :param int [limit]: the maximum number of order structures to retrieve
@@ -2640,6 +2666,9 @@ class mexc(Exchange, ImplicitAPI):
2640
2666
  async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2641
2667
  """
2642
2668
  fetch all unfilled currently open orders
2669
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#current-open-orders
2670
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2671
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2643
2672
  :param str symbol: unified market symbol
2644
2673
  :param int [since]: the earliest time in ms to fetch open orders for
2645
2674
  :param int [limit]: the maximum number of open orders structures to retrieve
@@ -2722,6 +2751,9 @@ class mexc(Exchange, ImplicitAPI):
2722
2751
  async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2723
2752
  """
2724
2753
  fetches information on multiple closed orders made by the user
2754
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
2755
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2756
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2725
2757
  :param str symbol: unified market symbol of the market orders were made in
2726
2758
  :param int [since]: the earliest time in ms to fetch orders for
2727
2759
  :param int [limit]: the maximum number of order structures to retrieve
@@ -2733,6 +2765,9 @@ class mexc(Exchange, ImplicitAPI):
2733
2765
  async def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2734
2766
  """
2735
2767
  fetches information on multiple canceled orders made by the user
2768
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
2769
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2770
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2736
2771
  :param str symbol: unified market symbol of the market orders were made in
2737
2772
  :param int [since]: timestamp in ms of the earliest order, default is None
2738
2773
  :param int [limit]: max number of orders to return, default is None
@@ -5286,6 +5321,43 @@ class mexc(Exchange, ImplicitAPI):
5286
5321
  positions = self.parse_positions(data, symbols, params)
5287
5322
  return self.filter_by_since_limit(positions, since, limit)
5288
5323
 
5324
+ async def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
5325
+ """
5326
+ set margin mode to 'cross' or 'isolated'
5327
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#switch-leverage
5328
+ :param str marginMode: 'cross' or 'isolated'
5329
+ :param str [symbol]: required when there is no position, else provide params["positionId"]
5330
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5331
+ :param str [params.positionId]: required when a position is set
5332
+ :param str [params.direction]: "long" or "short" required when there is no position
5333
+ :returns dict: response from the exchange
5334
+ """
5335
+ await self.load_markets()
5336
+ market = self.market(symbol)
5337
+ if market['spot']:
5338
+ raise BadSymbol(self.id + ' setMarginMode() supports contract markets only')
5339
+ marginMode = marginMode.lower()
5340
+ if marginMode != 'isolated' and marginMode != 'cross':
5341
+ raise BadRequest(self.id + ' setMarginMode() marginMode argument should be isolated or cross')
5342
+ leverage = self.safe_integer(params, 'leverage')
5343
+ if leverage is None:
5344
+ raise ArgumentsRequired(self.id + ' setMarginMode() requires a leverage parameter')
5345
+ direction = self.safe_string_lower_2(params, 'direction', 'positionId')
5346
+ request: dict = {
5347
+ 'leverage': leverage,
5348
+ 'openType': 1 if (marginMode == 'isolated') else 2,
5349
+ }
5350
+ if symbol is not None:
5351
+ request['symbol'] = market['id']
5352
+ if direction is not None:
5353
+ request['positionType'] = 2 if (direction == 'short') else 1
5354
+ params = self.omit(params, 'direction')
5355
+ response = await self.contractPrivatePostPositionChangeLeverage(self.extend(request, params))
5356
+ #
5357
+ # {success: True, code: '0'}
5358
+ #
5359
+ return self.parse_leverage(response, market)
5360
+
5289
5361
  def nonce(self):
5290
5362
  return self.milliseconds() - self.safe_integer(self.options, 'timeDifference', 0)
5291
5363
 
ccxt/async_support/okx.py CHANGED
@@ -291,6 +291,7 @@ class okx(Exchange, ImplicitAPI):
291
291
  'copytrading/public-preference-currency': 4,
292
292
  'copytrading/public-current-subpositions': 4,
293
293
  'copytrading/public-subpositions-history': 4,
294
+ 'support/announcements-types': 20,
294
295
  },
295
296
  },
296
297
  'private': {
@@ -436,6 +437,7 @@ class okx(Exchange, ImplicitAPI):
436
437
  # affiliate
437
438
  'affiliate/invitee/detail': 1,
438
439
  'users/partner/if-rebate': 1,
440
+ 'support/announcements': 4,
439
441
  },
440
442
  'post': {
441
443
  # rfq
@@ -815,6 +817,8 @@ class okx(Exchange, ImplicitAPI):
815
817
  # SPOT/MARGIN error codes 54000-54999
816
818
  '54000': ExchangeError, # Margin transactions unavailable
817
819
  '54001': ExchangeError, # Only Multi-currency margin account can be set to borrow coins automatically
820
+ '54008': InvalidOrder, # This operation is disabled by the 'mass cancel order' endpoint. Please enable it using self endpoint.
821
+ '54009': InvalidOrder, # The range of {param0} should be [{param1}, {param2}].
818
822
  '54011': InvalidOrder, # 200 Pre-market trading contracts are only allowed to reduce the number of positions within 1 hour before delivery. Please modify or cancel the order.
819
823
  # Trading bot Error Code from 55100 to 55999
820
824
  '55100': InvalidOrder, # Take profit % should be within the range of {parameter1}-{parameter2}
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.6'
7
+ __version__ = '4.4.8'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -1734,6 +1734,9 @@ class Exchange(object):
1734
1734
  def create_safe_dictionary(self):
1735
1735
  return {}
1736
1736
 
1737
+ def rand_number(self, size):
1738
+ return int(''.join([str(random.randint(0, 9)) for _ in range(size)]))
1739
+
1737
1740
  # ########################################################################
1738
1741
  # ########################################################################
1739
1742
  # ########################################################################
@@ -2676,6 +2679,7 @@ class Exchange(object):
2676
2679
  'ETH': {'ERC20': 'ETH'},
2677
2680
  'TRX': {'TRC20': 'TRX'},
2678
2681
  'CRO': {'CRC20': 'CRONOS'},
2682
+ 'BRC20': {'BRC20': 'BTC'},
2679
2683
  },
2680
2684
  }
2681
2685
 
@@ -5946,8 +5950,17 @@ class Exchange(object):
5946
5950
  if responseLength == 0:
5947
5951
  break
5948
5952
  result = self.array_concat(result, response)
5949
- last = self.safe_value(response, responseLength - 1)
5950
- cursorValue = self.safe_value(last['info'], cursorReceived)
5953
+ last = self.safe_dict(response, responseLength - 1)
5954
+ # cursorValue = self.safe_value(last['info'], cursorReceived)
5955
+ cursorValue = None # search for the cursor
5956
+ for j in range(0, responseLength):
5957
+ index = responseLength - j - 1
5958
+ entry = self.safe_dict(response, index)
5959
+ info = self.safe_dict(entry, 'info')
5960
+ cursor = self.safe_value(info, cursorReceived)
5961
+ if cursor is not None:
5962
+ cursorValue = cursor
5963
+ break
5951
5964
  if cursorValue is None:
5952
5965
  break
5953
5966
  lastTimestamp = self.safe_integer(last, 'timestamp')
ccxt/binance.py CHANGED
@@ -1114,6 +1114,7 @@ class binance(Exchange, ImplicitAPI):
1114
1114
  'repay-futures-negative-balance': 150, # Weight(IP): 1500 => cost = 0.1 * 1500 = 150
1115
1115
  'listenKey': 1, # 1
1116
1116
  'asset-collection': 3,
1117
+ 'margin/repay-debt': 0.4, # Weight(Order): 0.4 =>(1000 / (50 * 0.4)) * 60 = 3000
1117
1118
  },
1118
1119
  'put': {
1119
1120
  'listenKey': 1, # 1
@@ -1231,6 +1232,7 @@ class binance(Exchange, ImplicitAPI):
1231
1232
  ],
1232
1233
  'fetchCurrencies': True, # self is a private call and it requires API keys
1233
1234
  # 'fetchTradesMethod': 'publicGetAggTrades', # publicGetTrades, publicGetHistoricalTrades, eapiPublicGetTrades
1235
+ # 'repayCrossMarginMethod': 'papiPostRepayLoan', # papiPostMarginRepayDebt
1234
1236
  'defaultTimeInForce': 'GTC', # 'GTC' = Good To Cancel(default), 'IOC' = Immediate Or Cancel
1235
1237
  'defaultType': 'spot', # 'spot', 'future', 'margin', 'delivery', 'option'
1236
1238
  'defaultSubType': None, # 'linear', 'inverse'
@@ -2878,7 +2880,7 @@ class binance(Exchange, ImplicitAPI):
2878
2880
  res = self.safe_value(results, i)
2879
2881
  if fetchMargins and isinstance(res, list):
2880
2882
  keysList = list(self.index_by(res, 'symbol').keys())
2881
- length = (self.options['crossMarginPairsData'])
2883
+ length = len(self.options['crossMarginPairsData'])
2882
2884
  # first one is the cross-margin promise
2883
2885
  if length == 0:
2884
2886
  self.options['crossMarginPairsData'] = keysList
@@ -11241,10 +11243,13 @@ class binance(Exchange, ImplicitAPI):
11241
11243
  repay borrowed margin and interest
11242
11244
  :see: https://developers.binance.com/docs/derivatives/portfolio-margin/trade/Margin-Account-Repay
11243
11245
  :see: https://developers.binance.com/docs/margin_trading/borrow-and-repay/Margin-Account-Borrow-Repay
11246
+ :see: https://developers.binance.com/docs/derivatives/portfolio-margin/trade/Margin-Account-Repay-Debt
11244
11247
  :param str code: unified currency code of the currency to repay
11245
11248
  :param float amount: the amount to repay
11246
11249
  :param dict [params]: extra parameters specific to the exchange API endpoint
11247
11250
  :param boolean [params.portfolioMargin]: set to True if you would like to repay margin in a portfolio margin account
11251
+ :param str [params.repayCrossMarginMethod]: *portfolio margin only* 'papiPostRepayLoan'(default), 'papiPostMarginRepayDebt'(alternative)
11252
+ :param str [params.specifyRepayAssets]: *portfolio margin papiPostMarginRepayDebt only* specific asset list to repay debt
11248
11253
  :returns dict: a `margin loan structure <https://docs.ccxt.com/#/?id=margin-loan-structure>`
11249
11254
  """
11250
11255
  self.load_markets()
@@ -11257,17 +11262,37 @@ class binance(Exchange, ImplicitAPI):
11257
11262
  isPortfolioMargin = None
11258
11263
  isPortfolioMargin, params = self.handle_option_and_params_2(params, 'repayCrossMargin', 'papi', 'portfolioMargin', False)
11259
11264
  if isPortfolioMargin:
11260
- response = self.papiPostRepayLoan(self.extend(request, params))
11265
+ method = None
11266
+ method, params = self.handle_option_and_params_2(params, 'repayCrossMargin', 'repayCrossMarginMethod', 'method')
11267
+ if method == 'papiPostMarginRepayDebt':
11268
+ response = self.papiPostMarginRepayDebt(self.extend(request, params))
11269
+ #
11270
+ # {
11271
+ # "asset": "USDC",
11272
+ # "amount": 10,
11273
+ # "specifyRepayAssets": null,
11274
+ # "updateTime": 1727170761267,
11275
+ # "success": True
11276
+ # }
11277
+ #
11278
+ else:
11279
+ response = self.papiPostRepayLoan(self.extend(request, params))
11280
+ #
11281
+ # {
11282
+ # "tranId": 108988250265,
11283
+ # "clientTag":""
11284
+ # }
11285
+ #
11261
11286
  else:
11262
11287
  request['isIsolated'] = 'FALSE'
11263
11288
  request['type'] = 'REPAY'
11264
11289
  response = self.sapiPostMarginBorrowRepay(self.extend(request, params))
11265
- #
11266
- # {
11267
- # "tranId": 108988250265,
11268
- # "clientTag":""
11269
- # }
11270
- #
11290
+ #
11291
+ # {
11292
+ # "tranId": 108988250265,
11293
+ # "clientTag":""
11294
+ # }
11295
+ #
11271
11296
  return self.parse_margin_loan(response, currency)
11272
11297
 
11273
11298
  def repay_isolated_margin(self, symbol: str, code: str, amount, params={}):
@@ -11369,13 +11394,25 @@ class binance(Exchange, ImplicitAPI):
11369
11394
  # "clientTag":""
11370
11395
  # }
11371
11396
  #
11397
+ # repayCrossMargin alternative endpoint
11398
+ #
11399
+ # {
11400
+ # "asset": "USDC",
11401
+ # "amount": 10,
11402
+ # "specifyRepayAssets": null,
11403
+ # "updateTime": 1727170761267,
11404
+ # "success": True
11405
+ # }
11406
+ #
11407
+ currencyId = self.safe_string(info, 'asset')
11408
+ timestamp = self.safe_integer(info, 'updateTime')
11372
11409
  return {
11373
11410
  'id': self.safe_integer(info, 'tranId'),
11374
- 'currency': self.safe_currency_code(None, currency),
11375
- 'amount': None,
11411
+ 'currency': self.safe_currency_code(currencyId, currency),
11412
+ 'amount': self.safe_number(info, 'amount'),
11376
11413
  'symbol': None,
11377
- 'timestamp': None,
11378
- 'datetime': None,
11414
+ 'timestamp': timestamp,
11415
+ 'datetime': self.iso8601(timestamp),
11379
11416
  'info': info,
11380
11417
  }
11381
11418
 
ccxt/bingx.py CHANGED
@@ -503,6 +503,9 @@ class bingx(Exchange, ImplicitAPI):
503
503
  'BTC': 'BTC',
504
504
  'LTC': 'LTC',
505
505
  },
506
+ 'networks': {
507
+ 'ARB': 'ARBITRUM',
508
+ },
506
509
  },
507
510
  })
508
511
 
ccxt/bitget.py CHANGED
@@ -1436,11 +1436,13 @@ class bitget(Exchange, ImplicitAPI):
1436
1436
  'networks': {
1437
1437
  'TRX': 'TRC20',
1438
1438
  'ETH': 'ERC20',
1439
- 'BSC': 'BEP20',
1439
+ 'BEP20': 'BSC',
1440
+ 'ZKSYNC': 'zkSyncEra',
1441
+ 'STARKNET': 'Starknet',
1442
+ 'OPTIMISM': 'Optimism',
1443
+ 'ARBITRUM': 'Arbitrum',
1440
1444
  },
1441
1445
  'networksById': {
1442
- 'TRC20': 'TRX',
1443
- 'BSC': 'BEP20',
1444
1446
  },
1445
1447
  'fetchPositions': {
1446
1448
  'method': 'privateMixGetV2MixPositionAllPosition', # or privateMixGetV2MixPositionHistoryPosition
@@ -1839,7 +1841,9 @@ class bitget(Exchange, ImplicitAPI):
1839
1841
  for j in range(0, len(chains)):
1840
1842
  chain = chains[j]
1841
1843
  networkId = self.safe_string(chain, 'chain')
1842
- network = self.safe_currency_code(networkId)
1844
+ network = self.network_id_to_code(networkId, code)
1845
+ if network is not None:
1846
+ network = network.upper()
1843
1847
  withdrawEnabled = self.safe_string(chain, 'withdrawable')
1844
1848
  canWithdraw = withdrawEnabled == 'true'
1845
1849
  withdraw = canWithdraw if (canWithdraw) else withdraw
ccxt/bitmart.py CHANGED
@@ -2206,7 +2206,7 @@ class bitmart(Exchange, ImplicitAPI):
2206
2206
 
2207
2207
  def parse_order(self, order: dict, market: Market = None) -> Order:
2208
2208
  #
2209
- # createOrder
2209
+ # createOrder, editOrder
2210
2210
  #
2211
2211
  # {
2212
2212
  # "order_id": 2707217580
@@ -4466,6 +4466,114 @@ class bitmart(Exchange, ImplicitAPI):
4466
4466
  'datetime': self.iso8601(timestamp),
4467
4467
  })
4468
4468
 
4469
+ def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
4470
+ """
4471
+ edits an open order
4472
+ :see: https://developer-pro.bitmart.com/en/futuresv2/#modify-plan-order-signed
4473
+ :see: https://developer-pro.bitmart.com/en/futuresv2/#modify-tp-sl-order-signed
4474
+ :see: https://developer-pro.bitmart.com/en/futuresv2/#modify-preset-plan-order-signed
4475
+ :param str id: order id
4476
+ :param str symbol: unified symbol of the market to edit an order in
4477
+ :param str type: 'market' or 'limit'
4478
+ :param str side: 'buy' or 'sell'
4479
+ :param float [amount]: how much you want to trade in units of the base currency
4480
+ :param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
4481
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4482
+ :param str [params.triggerPrice]: *swap only* the price to trigger a stop order
4483
+ :param str [params.stopLossPrice]: *swap only* the price to trigger a stop-loss order
4484
+ :param str [params.takeProfitPrice]: *swap only* the price to trigger a take-profit order
4485
+ :param str [params.stopLoss.triggerPrice]: *swap only* the price to trigger a preset stop-loss order
4486
+ :param str [params.takeProfit.triggerPrice]: *swap only* the price to trigger a preset take-profit order
4487
+ :param str [params.clientOrderId]: client order id of the order
4488
+ :param int [params.price_type]: *swap only* 1: last price, 2: fair price, default is 1
4489
+ :param int [params.plan_category]: *swap tp/sl only* 1: tp/sl, 2: position tp/sl, default is 1
4490
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4491
+ """
4492
+ self.load_markets()
4493
+ market = self.market(symbol)
4494
+ if not market['swap']:
4495
+ raise NotSupported(self.id + ' editOrder() does not support ' + market['type'] + ' markets, only swap markets are supported')
4496
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
4497
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
4498
+ triggerPrice = self.safe_string_n(params, ['triggerPrice', 'stopPrice', 'trigger_price'])
4499
+ stopLoss = self.safe_dict(params, 'stopLoss', {})
4500
+ takeProfit = self.safe_dict(params, 'takeProfit', {})
4501
+ presetStopLoss = self.safe_string(stopLoss, 'triggerPrice')
4502
+ presetTakeProfit = self.safe_string(takeProfit, 'triggerPrice')
4503
+ isTriggerOrder = triggerPrice is not None
4504
+ isStopLoss = stopLossPrice is not None
4505
+ isTakeProfit = takeProfitPrice is not None
4506
+ isPresetStopLoss = presetStopLoss is not None
4507
+ isPresetTakeProfit = presetTakeProfit is not None
4508
+ request: dict = {
4509
+ 'symbol': market['id'],
4510
+ }
4511
+ clientOrderId = self.safe_string(params, 'clientOrderId')
4512
+ if clientOrderId is not None:
4513
+ params = self.omit(params, 'clientOrderId')
4514
+ request['client_order_id'] = clientOrderId
4515
+ if id is not None:
4516
+ request['order_id'] = id
4517
+ params = self.omit(params, ['triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit'])
4518
+ response = None
4519
+ if isTriggerOrder or isStopLoss or isTakeProfit:
4520
+ request['price_type'] = self.safe_integer(params, 'price_type', 1)
4521
+ if price is not None:
4522
+ request['executive_price'] = self.price_to_precision(symbol, price)
4523
+ if isTriggerOrder:
4524
+ request['type'] = type
4525
+ request['trigger_price'] = self.price_to_precision(symbol, triggerPrice)
4526
+ response = self.privatePostContractPrivateModifyPlanOrder(self.extend(request, params))
4527
+ #
4528
+ # {
4529
+ # "code": 1000,
4530
+ # "message": "Ok",
4531
+ # "data": {
4532
+ # "order_id": "3000023150003503"
4533
+ # },
4534
+ # "trace": "324523453245.108.1734567125596324575"
4535
+ # }
4536
+ #
4537
+ elif isStopLoss or isTakeProfit:
4538
+ request['category'] = type
4539
+ if isStopLoss:
4540
+ request['trigger_price'] = self.price_to_precision(symbol, stopLossPrice)
4541
+ else:
4542
+ request['trigger_price'] = self.price_to_precision(symbol, takeProfitPrice)
4543
+ response = self.privatePostContractPrivateModifyTpSlOrder(self.extend(request, params))
4544
+ #
4545
+ # {
4546
+ # "code": 1000,
4547
+ # "message": "Ok",
4548
+ # "data": {
4549
+ # "order_id": "3000023150003480"
4550
+ # },
4551
+ # "trace": "23452345.104.1724536582682345459"
4552
+ # }
4553
+ #
4554
+ elif isPresetStopLoss or isPresetTakeProfit:
4555
+ if isPresetStopLoss:
4556
+ request['preset_stop_loss_price_type'] = self.safe_integer(params, 'price_type', 1)
4557
+ request['preset_stop_loss_price'] = self.price_to_precision(symbol, presetStopLoss)
4558
+ else:
4559
+ request['preset_take_profit_price_type'] = self.safe_integer(params, 'price_type', 1)
4560
+ request['preset_take_profit_price'] = self.price_to_precision(symbol, presetTakeProfit)
4561
+ response = self.privatePostContractPrivateModifyPresetPlanOrder(self.extend(request, params))
4562
+ #
4563
+ # {
4564
+ # "code": 1000,
4565
+ # "message": "Ok",
4566
+ # "data": {
4567
+ # "order_id": "3000023150003496"
4568
+ # },
4569
+ # "trace": "a5c3234534534a836bc476a203.123452.172716624359200197"
4570
+ # }
4571
+ #
4572
+ else:
4573
+ raise NotSupported(self.id + ' editOrder() only supports trigger, stop loss and take profit orders')
4574
+ data = self.safe_dict(response, 'data', {})
4575
+ return self.parse_order(data, market)
4576
+
4469
4577
  def nonce(self):
4470
4578
  return self.milliseconds()
4471
4579