ccxt 4.5.26 → 4.5.28

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 (60) hide show
  1. package/README.md +6 -5
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +4 -1
  4. package/dist/cjs/src/abstract/zebpay.js +11 -0
  5. package/dist/cjs/src/base/Exchange.js +2 -2
  6. package/dist/cjs/src/binance.js +18 -7
  7. package/dist/cjs/src/bingx.js +5 -5
  8. package/dist/cjs/src/bitget.js +18 -17
  9. package/dist/cjs/src/bitmex.js +5 -1
  10. package/dist/cjs/src/blofin.js +5 -5
  11. package/dist/cjs/src/bybit.js +58 -29
  12. package/dist/cjs/src/coincatch.js +9 -9
  13. package/dist/cjs/src/coinex.js +93 -0
  14. package/dist/cjs/src/coinmate.js +20 -0
  15. package/dist/cjs/src/coinsph.js +23 -0
  16. package/dist/cjs/src/cryptocom.js +7 -0
  17. package/dist/cjs/src/gate.js +2 -0
  18. package/dist/cjs/src/hyperliquid.js +12 -15
  19. package/dist/cjs/src/pro/binance.js +1 -1
  20. package/dist/cjs/src/pro/bybit.js +1 -1
  21. package/dist/cjs/src/whitebit.js +4 -2
  22. package/dist/cjs/src/zebpay.js +1908 -0
  23. package/js/ccxt.d.ts +5 -2
  24. package/js/ccxt.js +4 -2
  25. package/js/src/abstract/binance.d.ts +3 -1
  26. package/js/src/abstract/binancecoinm.d.ts +3 -1
  27. package/js/src/abstract/binanceus.d.ts +3 -1
  28. package/js/src/abstract/binanceusdm.d.ts +3 -1
  29. package/js/src/abstract/coinex.d.ts +16 -0
  30. package/js/src/abstract/coinmate.d.ts +3 -0
  31. package/js/src/abstract/coinsph.d.ts +21 -0
  32. package/js/src/abstract/cryptocom.d.ts +7 -0
  33. package/js/src/abstract/gate.d.ts +2 -0
  34. package/js/src/abstract/gateio.d.ts +2 -0
  35. package/js/src/abstract/zebpay.d.ts +49 -0
  36. package/js/src/abstract/zebpay.js +11 -0
  37. package/js/src/base/Exchange.js +2 -2
  38. package/js/src/binance.d.ts +1 -0
  39. package/js/src/binance.js +18 -7
  40. package/js/src/bingx.js +5 -5
  41. package/js/src/bitget.js +19 -18
  42. package/js/src/bitmex.js +5 -1
  43. package/js/src/blofin.js +5 -5
  44. package/js/src/bybit.d.ts +3 -0
  45. package/js/src/bybit.js +58 -29
  46. package/js/src/coincatch.js +9 -9
  47. package/js/src/coinex.d.ts +11 -0
  48. package/js/src/coinex.js +93 -0
  49. package/js/src/coinmate.d.ts +9 -0
  50. package/js/src/coinmate.js +20 -0
  51. package/js/src/coinsph.js +23 -0
  52. package/js/src/cryptocom.js +7 -0
  53. package/js/src/gate.js +2 -0
  54. package/js/src/hyperliquid.js +12 -15
  55. package/js/src/pro/binance.js +1 -1
  56. package/js/src/pro/bybit.js +1 -1
  57. package/js/src/whitebit.js +4 -2
  58. package/js/src/zebpay.d.ts +361 -0
  59. package/js/src/zebpay.js +1907 -0
  60. package/package.json +1 -1
package/js/src/bitget.js CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import Exchange from './abstract/bitget.js';
9
- import { ExchangeError, ExchangeNotAvailable, NotSupported, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, BadSymbol, RateLimitExceeded } from './base/errors.js';
9
+ import { ExchangeError, ExchangeNotAvailable, NotSupported, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, BadSymbol, RateLimitExceeded, RestrictedLocation } from './base/errors.js';
10
10
  import { Precise } from './base/Precise.js';
11
11
  import { TICK_SIZE } from './base/functions/number.js';
12
12
  import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
@@ -1411,6 +1411,7 @@ export default class bitget extends Exchange {
1411
1411
  'invalid end time': BadRequest,
1412
1412
  '20003': ExchangeError,
1413
1413
  '01001': ExchangeError,
1414
+ '40024': RestrictedLocation,
1414
1415
  '43111': PermissionDenied, // {"code":"43111","msg":"参数错误 address not in address book","requestTime":1665394201164,"data":null}
1415
1416
  },
1416
1417
  'broad': {
@@ -5182,8 +5183,8 @@ export default class bitget extends Exchange {
5182
5183
  const takeProfitTriggerPrice = this.safeNumber(params, 'takeProfitPrice');
5183
5184
  const stopLoss = this.safeValue(params, 'stopLoss');
5184
5185
  const takeProfit = this.safeValue(params, 'takeProfit');
5185
- const isStopLoss = stopLoss !== undefined;
5186
- const isTakeProfit = takeProfit !== undefined;
5186
+ const hasStopLoss = stopLoss !== undefined;
5187
+ const hasTakeProfit = takeProfit !== undefined;
5187
5188
  const isStopLossTrigger = stopLossTriggerPrice !== undefined;
5188
5189
  const isTakeProfitTrigger = takeProfitTriggerPrice !== undefined;
5189
5190
  const isStopLossOrTakeProfitTrigger = isStopLossTrigger || isTakeProfitTrigger;
@@ -5215,7 +5216,7 @@ export default class bitget extends Exchange {
5215
5216
  params = this.omit(params, ['stopLossPrice', 'takeProfitPrice']);
5216
5217
  }
5217
5218
  else {
5218
- if (isStopLoss) {
5219
+ if (hasStopLoss) {
5219
5220
  const slTriggerPrice = this.safeNumber2(stopLoss, 'triggerPrice', 'stopPrice');
5220
5221
  const slLimitPrice = this.safeNumber(stopLoss, 'price');
5221
5222
  request['stopLoss'] = this.priceToPrecision(symbol, slTriggerPrice);
@@ -5227,7 +5228,7 @@ export default class bitget extends Exchange {
5227
5228
  request['slOrderType'] = this.safeString(params, 'slOrderType', 'market');
5228
5229
  }
5229
5230
  }
5230
- if (isTakeProfit) {
5231
+ if (hasTakeProfit) {
5231
5232
  const tpTriggerPrice = this.safeNumber2(takeProfit, 'triggerPrice', 'stopPrice');
5232
5233
  const tpLimitPrice = this.safeNumber(takeProfit, 'price');
5233
5234
  request['takeProfit'] = this.priceToPrecision(symbol, tpTriggerPrice);
@@ -5310,10 +5311,10 @@ export default class bitget extends Exchange {
5310
5311
  const isTriggerOrder = triggerPrice !== undefined;
5311
5312
  const isStopLossTriggerOrder = stopLossTriggerPrice !== undefined;
5312
5313
  const isTakeProfitTriggerOrder = takeProfitTriggerPrice !== undefined;
5313
- const isStopLoss = stopLoss !== undefined;
5314
- const isTakeProfit = takeProfit !== undefined;
5314
+ const hasStopLoss = stopLoss !== undefined;
5315
+ const hasTakeProfit = takeProfit !== undefined;
5315
5316
  const isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder || isTakeProfitTriggerOrder;
5316
- const isStopLossOrTakeProfit = isStopLoss || isTakeProfit;
5317
+ const isStopLossOrTakeProfit = hasStopLoss || hasTakeProfit;
5317
5318
  const trailingTriggerPrice = this.safeString(params, 'trailingTriggerPrice', this.numberToString(price));
5318
5319
  const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRatio');
5319
5320
  const isTrailingPercentOrder = trailingPercent !== undefined;
@@ -5373,7 +5374,7 @@ export default class bitget extends Exchange {
5373
5374
  if (price !== undefined) {
5374
5375
  request['executePrice'] = this.priceToPrecision(symbol, price);
5375
5376
  }
5376
- if (isStopLoss) {
5377
+ if (hasStopLoss) {
5377
5378
  const slTriggerPrice = this.safeString2(stopLoss, 'triggerPrice', 'stopPrice');
5378
5379
  request['stopLossTriggerPrice'] = this.priceToPrecision(symbol, slTriggerPrice);
5379
5380
  const slPrice = this.safeString(stopLoss, 'price');
@@ -5381,7 +5382,7 @@ export default class bitget extends Exchange {
5381
5382
  const slType = this.safeString(stopLoss, 'type', 'mark_price');
5382
5383
  request['stopLossTriggerType'] = slType;
5383
5384
  }
5384
- if (isTakeProfit) {
5385
+ if (hasTakeProfit) {
5385
5386
  const tpTriggerPrice = this.safeString2(takeProfit, 'triggerPrice', 'stopPrice');
5386
5387
  request['stopSurplusTriggerPrice'] = this.priceToPrecision(symbol, tpTriggerPrice);
5387
5388
  const tpPrice = this.safeString(takeProfit, 'price');
@@ -5410,11 +5411,11 @@ export default class bitget extends Exchange {
5410
5411
  }
5411
5412
  }
5412
5413
  else {
5413
- if (isStopLoss) {
5414
+ if (hasStopLoss) {
5414
5415
  const slTriggerPrice = this.safeValue2(stopLoss, 'triggerPrice', 'stopPrice');
5415
5416
  request['presetStopLossPrice'] = this.priceToPrecision(symbol, slTriggerPrice);
5416
5417
  }
5417
- if (isTakeProfit) {
5418
+ if (hasTakeProfit) {
5418
5419
  const tpTriggerPrice = this.safeValue2(takeProfit, 'triggerPrice', 'stopPrice');
5419
5420
  request['presetStopSurplusPrice'] = this.priceToPrecision(symbol, tpTriggerPrice);
5420
5421
  }
@@ -5733,8 +5734,8 @@ export default class bitget extends Exchange {
5733
5734
  const isTakeProfitOrder = takeProfitPrice !== undefined;
5734
5735
  const stopLoss = this.safeValue(params, 'stopLoss');
5735
5736
  const takeProfit = this.safeValue(params, 'takeProfit');
5736
- const isStopLoss = stopLoss !== undefined;
5737
- const isTakeProfit = takeProfit !== undefined;
5737
+ const hasStopLoss = stopLoss !== undefined;
5738
+ const hasTakeProfit = takeProfit !== undefined;
5738
5739
  const trailingTriggerPrice = this.safeString(params, 'trailingTriggerPrice', this.numberToString(price));
5739
5740
  const trailingPercent = this.safeString2(params, 'trailingPercent', 'newCallbackRatio');
5740
5741
  const isTrailingPercentOrder = trailingPercent !== undefined;
@@ -5858,7 +5859,7 @@ export default class bitget extends Exchange {
5858
5859
  }
5859
5860
  else if (isTriggerOrder) {
5860
5861
  request['newTriggerPrice'] = this.priceToPrecision(symbol, triggerPrice);
5861
- if (isStopLoss) {
5862
+ if (hasStopLoss) {
5862
5863
  const slTriggerPrice = this.safeNumber2(stopLoss, 'triggerPrice', 'stopPrice');
5863
5864
  request['newStopLossTriggerPrice'] = this.priceToPrecision(symbol, slTriggerPrice);
5864
5865
  const slPrice = this.safeNumber(stopLoss, 'price');
@@ -5866,7 +5867,7 @@ export default class bitget extends Exchange {
5866
5867
  const slType = this.safeString(stopLoss, 'type', 'mark_price');
5867
5868
  request['newStopLossTriggerType'] = slType;
5868
5869
  }
5869
- if (isTakeProfit) {
5870
+ if (hasTakeProfit) {
5870
5871
  const tpTriggerPrice = this.safeNumber2(takeProfit, 'triggerPrice', 'stopPrice');
5871
5872
  request['newSurplusTriggerPrice'] = this.priceToPrecision(symbol, tpTriggerPrice);
5872
5873
  const tpPrice = this.safeNumber(takeProfit, 'price');
@@ -5881,11 +5882,11 @@ export default class bitget extends Exchange {
5881
5882
  const newClientOrderId = this.safeString2(params, 'newClientOid', 'newClientOrderId', defaultNewClientOrderId);
5882
5883
  params = this.omit(params, 'newClientOrderId');
5883
5884
  request['newClientOid'] = newClientOrderId;
5884
- if (isStopLoss) {
5885
+ if (hasStopLoss) {
5885
5886
  const slTriggerPrice = this.safeValue2(stopLoss, 'triggerPrice', 'stopPrice');
5886
5887
  request['newPresetStopLossPrice'] = this.priceToPrecision(symbol, slTriggerPrice);
5887
5888
  }
5888
- if (isTakeProfit) {
5889
+ if (hasTakeProfit) {
5889
5890
  const tpTriggerPrice = this.safeValue2(takeProfit, 'triggerPrice', 'stopPrice');
5890
5891
  request['newPresetStopSurplusPrice'] = this.priceToPrecision(symbol, tpTriggerPrice);
5891
5892
  }
package/js/src/bitmex.js CHANGED
@@ -707,7 +707,7 @@ export default class bitmex extends Exchange {
707
707
  // 'positionCurrency' may be empty ("", as Bitmex currently returns for ETHUSD)
708
708
  // so let's take the settlCurrency first and then adjust if needed
709
709
  const typ = this.safeString(market, 'typ'); // type definitions at: https://www.bitmex.com/api/explorer/#!/Instrument/Instrument_get
710
- let type;
710
+ let type = undefined;
711
711
  let swap = false;
712
712
  let spot = false;
713
713
  let future = false;
@@ -730,6 +730,10 @@ export default class bitmex extends Exchange {
730
730
  type = 'future';
731
731
  future = true;
732
732
  }
733
+ else if (typ === 'FFSCSX') {
734
+ type = 'swap';
735
+ swap = true;
736
+ }
733
737
  const base = this.safeCurrencyCode(baseId);
734
738
  const quote = this.safeCurrencyCode(quoteId);
735
739
  const contract = swap || future;
package/js/src/blofin.js CHANGED
@@ -1192,16 +1192,16 @@ export default class blofin extends Exchange {
1192
1192
  const stopLoss = this.safeDict(params, 'stopLoss');
1193
1193
  const takeProfit = this.safeDict(params, 'takeProfit');
1194
1194
  params = this.omit(params, ['stopLoss', 'takeProfit', 'hedged']);
1195
- const isStopLoss = stopLoss !== undefined;
1196
- const isTakeProfit = takeProfit !== undefined;
1197
- if (isStopLoss || isTakeProfit) {
1198
- if (isStopLoss) {
1195
+ const hasStopLoss = stopLoss !== undefined;
1196
+ const hasTakeProfit = takeProfit !== undefined;
1197
+ if (hasStopLoss || hasTakeProfit) {
1198
+ if (hasStopLoss) {
1199
1199
  const slTriggerPrice = this.safeString2(stopLoss, 'triggerPrice', 'stopPrice');
1200
1200
  request['slTriggerPrice'] = this.priceToPrecision(symbol, slTriggerPrice);
1201
1201
  const slOrderPrice = this.safeString(stopLoss, 'price', '-1');
1202
1202
  request['slOrderPrice'] = this.priceToPrecision(symbol, slOrderPrice);
1203
1203
  }
1204
- if (isTakeProfit) {
1204
+ if (hasTakeProfit) {
1205
1205
  const tpTriggerPrice = this.safeString2(takeProfit, 'triggerPrice', 'stopPrice');
1206
1206
  request['tpTriggerPrice'] = this.priceToPrecision(symbol, tpTriggerPrice);
1207
1207
  const tpPrice = this.safeString(takeProfit, 'price', '-1');
package/js/src/bybit.d.ts CHANGED
@@ -237,13 +237,16 @@ export default class bybit extends Exchange {
237
237
  * @param {string} [params.triggerDirection] *contract only* the direction for trigger orders, 'ascending' or 'descending'
238
238
  * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
239
239
  * @param {float} [params.stopLossPrice] The price at which a stop loss order is triggered at
240
+ * @param {float} [params.stopLossLimitPrice] The limit price for a stoploss order (only when used in OCO with takeProfitPrice)
240
241
  * @param {float} [params.takeProfitPrice] The price at which a take profit order is triggered at
242
+ * @param {float} [params.takeProfitLimitPrice] The limit price for a takeprofit order (only when used in OCO combination with stopLossPrice)
241
243
  * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered
242
244
  * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
243
245
  * @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered
244
246
  * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
245
247
  * @param {string} [params.trailingAmount] the quote amount to trail away from the current market price
246
248
  * @param {string} [params.trailingTriggerPrice] the price to trigger a trailing order, default uses the price argument
249
+ * @param {boolean} [params.tradingStopEndpoint] whether to enforce using the tradingStop (https://bybit-exchange.github.io/docs/v5/position/trading-stop) endpoint, makes difference when submitting single tp/sl order
247
250
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
248
251
  */
249
252
  createOrder(symbol: string, type: OrderType, side: OrderSide, amount: number, price?: Num, params?: {}): Promise<Order>;
package/js/src/bybit.js CHANGED
@@ -3988,13 +3988,16 @@ export default class bybit extends Exchange {
3988
3988
  * @param {string} [params.triggerDirection] *contract only* the direction for trigger orders, 'ascending' or 'descending'
3989
3989
  * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
3990
3990
  * @param {float} [params.stopLossPrice] The price at which a stop loss order is triggered at
3991
+ * @param {float} [params.stopLossLimitPrice] The limit price for a stoploss order (only when used in OCO with takeProfitPrice)
3991
3992
  * @param {float} [params.takeProfitPrice] The price at which a take profit order is triggered at
3993
+ * @param {float} [params.takeProfitLimitPrice] The limit price for a takeprofit order (only when used in OCO combination with stopLossPrice)
3992
3994
  * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered
3993
3995
  * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
3994
3996
  * @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered
3995
3997
  * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
3996
3998
  * @param {string} [params.trailingAmount] the quote amount to trail away from the current market price
3997
3999
  * @param {string} [params.trailingTriggerPrice] the price to trigger a trailing order, default uses the price argument
4000
+ * @param {boolean} [params.tradingStopEndpoint] whether to enforce using the tradingStop (https://bybit-exchange.github.io/docs/v5/position/trading-stop) endpoint, makes difference when submitting single tp/sl order
3998
4001
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
3999
4002
  */
4000
4003
  async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
@@ -4006,8 +4009,9 @@ export default class bybit extends Exchange {
4006
4009
  const isStopLossOrder = this.safeString(params, 'stopLossPrice') !== undefined;
4007
4010
  const isTakeProfitOrder = this.safeString(params, 'takeProfitPrice') !== undefined;
4008
4011
  const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params, enableUnifiedAccount);
4012
+ const switchToOco = (isStopLossOrder && isTakeProfitOrder) || this.safeBool(params, 'tradingStopEndpoint', false);
4009
4013
  let defaultMethod = undefined;
4010
- if ((isTrailingOrder || isStopLossOrder || isTakeProfitOrder) && !market['spot']) {
4014
+ if ((isTrailingOrder || switchToOco) && !market['spot']) {
4011
4015
  defaultMethod = 'privatePostV5PositionTradingStop';
4012
4016
  }
4013
4017
  else {
@@ -4020,7 +4024,7 @@ export default class bybit extends Exchange {
4020
4024
  response = await this.privatePostV5PositionTradingStop(orderRequest);
4021
4025
  }
4022
4026
  else {
4023
- response = await this.privatePostV5OrderCreate(orderRequest); // already extended inside createOrderRequest
4027
+ response = await this.privatePostV5OrderCreate(orderRequest);
4024
4028
  }
4025
4029
  //
4026
4030
  // {
@@ -4041,9 +4045,6 @@ export default class bybit extends Exchange {
4041
4045
  const market = this.market(symbol);
4042
4046
  symbol = market['symbol'];
4043
4047
  const lowerCaseType = type.toLowerCase();
4044
- if ((price === undefined) && (lowerCaseType === 'limit')) {
4045
- throw new ArgumentsRequired(this.id + ' createOrder requires a price argument for limit orders');
4046
- }
4047
4048
  const request = {
4048
4049
  'symbol': market['id'],
4049
4050
  // 'side': this.capitalize (side),
@@ -4083,12 +4084,13 @@ export default class bybit extends Exchange {
4083
4084
  const isStopLossOrder = stopLossTriggerPrice !== undefined;
4084
4085
  const isTakeProfitOrder = takeProfitTriggerPrice !== undefined;
4085
4086
  const hasStopLoss = stopLoss !== undefined;
4086
- const isTakeProfit = takeProfit !== undefined;
4087
+ const hasTakeProfit = takeProfit !== undefined;
4087
4088
  const isMarket = lowerCaseType === 'market';
4088
4089
  const isLimit = lowerCaseType === 'limit';
4089
4090
  const isBuy = side === 'buy';
4091
+ const switchToOco = (isStopLossOrder && isTakeProfitOrder) || this.safeBool(params, 'tradingStopEndpoint', false);
4090
4092
  let defaultMethod = undefined;
4091
- if ((isTrailingOrder || isStopLossOrder || isTakeProfitOrder) && !market['spot']) {
4093
+ if (isTrailingOrder || switchToOco) {
4092
4094
  defaultMethod = 'privatePostV5PositionTradingStop';
4093
4095
  }
4094
4096
  else {
@@ -4097,40 +4099,67 @@ export default class bybit extends Exchange {
4097
4099
  let method = undefined;
4098
4100
  [method, params] = this.handleOptionAndParams(params, 'createOrder', 'method', defaultMethod);
4099
4101
  const endpointIsTradingStop = method === 'privatePostV5PositionTradingStop';
4100
- const amountString = this.getAmount(symbol, amount);
4102
+ if ((price === undefined) && (lowerCaseType === 'limit') && !endpointIsTradingStop) {
4103
+ throw new ArgumentsRequired(this.id + ' createOrder requires a price argument for limit orders');
4104
+ }
4105
+ // workaround, bcz for some langs we have to allow 0.0 as input (bcz of type)
4106
+ if (!Precise.stringGt(this.numberToString(amount), '0')) {
4107
+ amount = undefined;
4108
+ }
4109
+ const amountString = (amount !== undefined) ? this.getAmount(symbol, amount) : undefined;
4101
4110
  const priceString = (price !== undefined) ? this.getPrice(symbol, this.numberToString(price)) : undefined;
4102
- if (isTrailingOrder || endpointIsTradingStop) {
4103
- if (hasStopLoss || isTakeProfit || isTriggerOrder || market['spot']) {
4111
+ if (endpointIsTradingStop) {
4112
+ if (hasStopLoss || hasTakeProfit || isTriggerOrder || market['spot']) {
4104
4113
  throw new InvalidOrder(this.id + ' the API endpoint used only supports contract trailingAmount, stopLossPrice and takeProfitPrice orders');
4105
4114
  }
4106
4115
  if (isStopLossOrder || isTakeProfitOrder) {
4107
- const tpslMode = this.safeString(params, 'tpslMode', 'Partial');
4108
- const isFullTpsl = tpslMode === 'Full';
4109
- const isPartialTpsl = tpslMode === 'Partial';
4110
- if (isLimit && isFullTpsl) {
4111
- throw new InvalidOrder(this.id + ' tpsl orders with "full" tpslMode only support "market" type');
4112
- }
4113
- request['tpslMode'] = tpslMode;
4116
+ let tpslModeSl = undefined;
4117
+ let tpslModeTp = undefined;
4114
4118
  if (isStopLossOrder) {
4115
4119
  request['stopLoss'] = this.getPrice(symbol, stopLossTriggerPrice);
4116
- if (isPartialTpsl) {
4120
+ const stopLossLimitPrice = this.safeString2(params, 'stopLossLimitPrice', 'slLimitPrice');
4121
+ if (stopLossLimitPrice !== undefined) {
4122
+ tpslModeSl = 'Partial';
4123
+ request['slOrderType'] = 'Limit';
4124
+ request['slLimitPrice'] = stopLossLimitPrice;
4117
4125
  request['slSize'] = amountString;
4118
4126
  }
4119
- if (isLimit) {
4120
- request['slOrderType'] = 'Limit';
4121
- request['slLimitPrice'] = priceString;
4127
+ else {
4128
+ request['slOrderType'] = 'Market';
4129
+ if (amountString !== undefined) {
4130
+ request['slSize'] = amountString;
4131
+ tpslModeSl = 'Partial';
4132
+ }
4133
+ else {
4134
+ tpslModeSl = 'Full';
4135
+ }
4122
4136
  }
4123
4137
  }
4124
- else if (isTakeProfitOrder) {
4138
+ if (isTakeProfitOrder) {
4125
4139
  request['takeProfit'] = this.getPrice(symbol, takeProfitTriggerPrice);
4126
- if (isPartialTpsl) {
4140
+ const takeProfitLimitPrice = this.safeString2(params, 'takeProfitLimitPrice', 'tpLimitPrice');
4141
+ if (takeProfitLimitPrice !== undefined) {
4142
+ tpslModeTp = 'Partial';
4143
+ request['tpOrderType'] = 'Limit';
4144
+ request['tpLimitPrice'] = takeProfitLimitPrice;
4127
4145
  request['tpSize'] = amountString;
4128
4146
  }
4129
- if (isLimit) {
4130
- request['tpOrderType'] = 'Limit';
4131
- request['tpLimitPrice'] = priceString;
4147
+ else {
4148
+ request['tpOrderType'] = 'Market';
4149
+ if (amountString !== undefined) {
4150
+ request['tpSize'] = amountString;
4151
+ tpslModeTp = 'Partial';
4152
+ }
4153
+ else {
4154
+ tpslModeTp = 'Full';
4155
+ }
4132
4156
  }
4133
4157
  }
4158
+ if (tpslModeSl !== tpslModeTp) {
4159
+ throw new InvalidOrder(this.id + ' createOrder() requires both stopLoss and takeProfit to be full or partial when using as OCO combination');
4160
+ }
4161
+ request['tpslMode'] = tpslModeSl; // same as tpslModeTp
4162
+ params = this.omit(params, ['stopLossLimitPrice', 'takeProfitLimitPrice']);
4134
4163
  }
4135
4164
  }
4136
4165
  else {
@@ -4265,7 +4294,7 @@ export default class bybit extends Exchange {
4265
4294
  request['triggerPrice'] = this.getPrice(symbol, triggerPrice);
4266
4295
  request['reduceOnly'] = true;
4267
4296
  }
4268
- if ((hasStopLoss || isTakeProfit) && !endpointIsTradingStop) {
4297
+ if ((hasStopLoss || hasTakeProfit) && !endpointIsTradingStop) {
4269
4298
  if (hasStopLoss) {
4270
4299
  const slTriggerPrice = this.safeValue2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss);
4271
4300
  request['stopLoss'] = this.getPrice(symbol, slTriggerPrice);
@@ -4286,7 +4315,7 @@ export default class bybit extends Exchange {
4286
4315
  throw new InvalidOrder(this.id + ' createOrder(): attached stopLoss is not supported for spot market orders');
4287
4316
  }
4288
4317
  }
4289
- if (isTakeProfit) {
4318
+ if (hasTakeProfit) {
4290
4319
  const tpTriggerPrice = this.safeValue2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit);
4291
4320
  request['takeProfit'] = this.getPrice(symbol, tpTriggerPrice);
4292
4321
  const tpLimitPrice = this.safeValue(takeProfit, 'price');
@@ -4314,7 +4343,7 @@ export default class bybit extends Exchange {
4314
4343
  }
4315
4344
  request['positionIdx'] = (side === 'buy') ? 1 : 2;
4316
4345
  }
4317
- params = this.omit(params, ['stopPrice', 'timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingAmount', 'trailingTriggerPrice', 'hedged', 'tpslMode']);
4346
+ params = this.omit(params, ['stopPrice', 'timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingAmount', 'trailingTriggerPrice', 'hedged']);
4318
4347
  return this.extend(request, params);
4319
4348
  }
4320
4349
  /**
@@ -1148,7 +1148,7 @@ export default class coincatch extends Exchange {
1148
1148
  await this.loadMarkets();
1149
1149
  symbols = this.marketSymbols(symbols, undefined, true, true);
1150
1150
  const market = this.getMarketFromSymbols(symbols);
1151
- let marketType = 'spot';
1151
+ let marketType = undefined;
1152
1152
  [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
1153
1153
  let response = undefined;
1154
1154
  if (marketType === 'spot') {
@@ -2655,22 +2655,22 @@ export default class coincatch extends Exchange {
2655
2655
  let stopLossPrice = this.safeString(params, 'stopLossPrice');
2656
2656
  let takeProfitPrice = this.safeString(params, 'takeProfitPrice');
2657
2657
  let requestTriggerPrice = undefined;
2658
- const takeProfitParams = this.safeDict(params, 'takeProfit');
2659
- const stopLossParams = this.safeDict(params, 'stopLoss');
2658
+ const takeProfit = this.safeDict(params, 'takeProfit');
2659
+ const stopLoss = this.safeDict(params, 'stopLoss');
2660
2660
  const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
2661
2661
  const isTrigger = (triggerPrice !== undefined);
2662
2662
  const trailingPercent = this.safeString(params, 'trailingPercent');
2663
2663
  const trailingTriggerPrice = this.safeString(params, 'trailingTriggerPrice');
2664
2664
  let hasTPPrice = (takeProfitPrice !== undefined);
2665
2665
  let hasSLPrice = (stopLossPrice !== undefined);
2666
- const hasTPParams = (takeProfitParams !== undefined);
2667
- if (hasTPParams && !hasTPPrice) {
2668
- takeProfitPrice = this.safeString(takeProfitParams, 'triggerPrice');
2666
+ const hasTakeProfit = (takeProfit !== undefined);
2667
+ if (hasTakeProfit && !hasTPPrice) {
2668
+ takeProfitPrice = this.safeString(takeProfit, 'triggerPrice');
2669
2669
  hasTPPrice = (takeProfitPrice !== undefined);
2670
2670
  }
2671
- const hasSLParams = (stopLossParams !== undefined);
2672
- if (hasSLParams && !hasSLPrice) {
2673
- stopLossPrice = this.safeString(stopLossParams, 'triggerPrice');
2671
+ const hasStopLoss = (stopLoss !== undefined);
2672
+ if (hasStopLoss && !hasSLPrice) {
2673
+ stopLossPrice = this.safeString(stopLoss, 'triggerPrice');
2674
2674
  hasSLPrice = (stopLossPrice !== undefined);
2675
2675
  }
2676
2676
  const hasBothTPAndSL = hasTPPrice && hasSLPrice;
@@ -227,6 +227,17 @@ export default class coinex extends Exchange {
227
227
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
228
228
  */
229
229
  editOrder(id: string, symbol: string, type: OrderType, side: OrderSide, amount?: Num, price?: Num, params?: {}): Promise<Order>;
230
+ /**
231
+ * @method
232
+ * @name coinex#editOrders
233
+ * @description edit a list of trade orders
234
+ * @see https://docs.coinex.com/api/v2/spot/order/http/edit-multi-order
235
+ * @see https://docs.coinex.com/api/v2/futures/order/http/edit-multi-order
236
+ * @param {Array} orders list of orders to edit, each object should contain the parameters required by editOrder, namely id, symbol, amount, price and params
237
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
238
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
239
+ */
240
+ editOrders(orders: OrderRequest[], params?: {}): Promise<Order[]>;
230
241
  /**
231
242
  * @method
232
243
  * @name coinex#cancelOrder
package/js/src/coinex.js CHANGED
@@ -62,6 +62,7 @@ export default class coinex extends Exchange {
62
62
  'createTakeProfitOrder': true,
63
63
  'createTriggerOrder': true,
64
64
  'editOrder': true,
65
+ 'editOrders': true,
65
66
  'fetchBalance': true,
66
67
  'fetchBorrowInterest': true,
67
68
  'fetchBorrowRateHistories': false,
@@ -320,6 +321,7 @@ export default class coinex extends Exchange {
320
321
  'futures/index': 1,
321
322
  'futures/funding-rate': 1,
322
323
  'futures/funding-rate-history': 1,
324
+ 'futures/premium-index-history': 1,
323
325
  'futures/position-level': 1,
324
326
  'futures/liquidation-history': 1,
325
327
  'futures/basis-history': 1,
@@ -334,20 +336,26 @@ export default class coinex extends Exchange {
334
336
  'account/subs/info': 1,
335
337
  'account/subs/api': 40,
336
338
  'account/subs/transfer-history': 40,
339
+ 'account/subs/balance': 1,
337
340
  'account/subs/spot-balance': 1,
338
341
  'account/trade-fee-rate': 40,
342
+ 'account/futures-market-settings': 1,
343
+ 'account/info': 1,
339
344
  'assets/spot/balance': 40,
340
345
  'assets/futures/balance': 40,
341
346
  'assets/margin/balance': 1,
342
347
  'assets/financial/balance': 40,
343
348
  'assets/amm/liquidity': 40,
344
349
  'assets/credit/info': 40,
350
+ 'assets/spot/transcation-history': 1,
345
351
  'assets/margin/borrow-history': 40,
346
352
  'assets/margin/interest-limit': 1,
347
353
  'assets/deposit-address': 40,
348
354
  'assets/deposit-history': 40,
349
355
  'assets/withdraw': 40,
350
356
  'assets/transfer-history': 40,
357
+ 'assets/amm/liquidity-pool': 40,
358
+ 'assets/amm/income-history': 40,
351
359
  'spot/order-status': 8,
352
360
  'spot/batch-order-status': 8,
353
361
  'spot/pending-order': 8,
@@ -370,6 +378,12 @@ export default class coinex extends Exchange {
370
378
  'futures/position-funding-history': 40,
371
379
  'futures/position-adl-history': 1,
372
380
  'futures/position-settle-history': 1,
381
+ 'refer/referee': 1,
382
+ 'refer/referee-rebate/record': 1,
383
+ 'refer/referee-rebate/detail': 1,
384
+ 'refer/agent-referee': 1,
385
+ 'refer/agent-rebate/record': 1,
386
+ 'refer/agent-rebate/detail': 1,
373
387
  },
374
388
  'post': {
375
389
  'account/subs': 40,
@@ -380,6 +394,7 @@ export default class coinex extends Exchange {
380
394
  'account/subs/delete-api': 40,
381
395
  'account/subs/transfer': 40,
382
396
  'account/settings': 40,
397
+ 'account/futures-market-settings': 40,
383
398
  'assets/margin/borrow': 40,
384
399
  'assets/margin/repay': 40,
385
400
  'assets/renewal-deposit-address': 40,
@@ -394,6 +409,7 @@ export default class coinex extends Exchange {
394
409
  'spot/batch-stop-order': 1,
395
410
  'spot/modify-order': 13.334,
396
411
  'spot/modify-stop-order': 13.334,
412
+ 'spot/batch-modify-order': 13.334,
397
413
  'spot/cancel-all-order': 1,
398
414
  'spot/cancel-order': 6.667,
399
415
  'spot/cancel-stop-order': 6.667,
@@ -407,6 +423,7 @@ export default class coinex extends Exchange {
407
423
  'futures/batch-stop-order': 1,
408
424
  'futures/modify-order': 20,
409
425
  'futures/modify-stop-order': 20,
426
+ 'futures/batch-modify-order': 20,
410
427
  'futures/cancel-all-order': 1,
411
428
  'futures/cancel-order': 10,
412
429
  'futures/cancel-stop-order': 10,
@@ -3040,6 +3057,82 @@ export default class coinex extends Exchange {
3040
3057
  const data = this.safeDict(response, 'data', {});
3041
3058
  return this.parseOrder(data, market);
3042
3059
  }
3060
+ /**
3061
+ * @method
3062
+ * @name coinex#editOrders
3063
+ * @description edit a list of trade orders
3064
+ * @see https://docs.coinex.com/api/v2/spot/order/http/edit-multi-order
3065
+ * @see https://docs.coinex.com/api/v2/futures/order/http/edit-multi-order
3066
+ * @param {Array} orders list of orders to edit, each object should contain the parameters required by editOrder, namely id, symbol, amount, price and params
3067
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3068
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
3069
+ */
3070
+ async editOrders(orders, params = {}) {
3071
+ await this.loadMarkets();
3072
+ const ordersRequests = [];
3073
+ let orderSymbols = [];
3074
+ for (let i = 0; i < orders.length; i++) {
3075
+ const rawOrder = orders[i];
3076
+ const marketId = this.safeString(rawOrder, 'symbol');
3077
+ const market = this.market(marketId);
3078
+ orderSymbols.push(marketId);
3079
+ const id = this.safeString(rawOrder, 'id');
3080
+ const amount = this.safeValue(rawOrder, 'amount');
3081
+ const price = this.safeValue(rawOrder, 'price');
3082
+ let orderParams = this.safeDict(rawOrder, 'params', {});
3083
+ let marginMode = undefined;
3084
+ [marginMode, orderParams] = this.handleMarginModeAndParams('editOrders', orderParams);
3085
+ let market_type = 'SPOT';
3086
+ if (market['swap']) {
3087
+ market_type = 'FUTURES';
3088
+ }
3089
+ else if (marginMode !== undefined) {
3090
+ market_type = 'MARGIN';
3091
+ }
3092
+ const orderRequest = {
3093
+ 'order_id': this.parseToNumeric(id),
3094
+ 'market': market['id'],
3095
+ 'market_type': market_type,
3096
+ };
3097
+ if (amount !== undefined) {
3098
+ orderRequest['amount'] = this.amountToPrecision(marketId, amount);
3099
+ }
3100
+ if (price !== undefined) {
3101
+ orderRequest['price'] = this.priceToPrecision(marketId, price);
3102
+ }
3103
+ ordersRequests.push(this.extend(orderRequest, orderParams));
3104
+ }
3105
+ orderSymbols = this.marketSymbols(orderSymbols, undefined, false, true, true);
3106
+ const firstSymbol = this.safeString(orderSymbols, 0);
3107
+ const firstMarket = this.market(firstSymbol);
3108
+ const request = {
3109
+ 'orders': ordersRequests,
3110
+ };
3111
+ let response = undefined;
3112
+ if (firstMarket['spot']) {
3113
+ response = await this.v2PrivatePostSpotBatchModifyOrder(this.extend(request, params));
3114
+ }
3115
+ else {
3116
+ response = await this.v2PrivatePostFuturesBatchModifyOrder(this.extend(request, params));
3117
+ }
3118
+ const data = this.safeList(response, 'data', []);
3119
+ const result = [];
3120
+ for (let i = 0; i < data.length; i++) {
3121
+ const entry = data[i];
3122
+ const code = this.safeString(entry, 'code');
3123
+ const message = this.safeString(entry, 'message');
3124
+ if ((code !== '0') || ((message !== 'Success') && (message !== 'Succeeded') && (message.toLowerCase() !== 'ok') && !data)) {
3125
+ const feedback = this.id + ' ' + message;
3126
+ this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
3127
+ this.throwExactlyMatchedException(this.exceptions['exact'], code, feedback);
3128
+ throw new ExchangeError(feedback);
3129
+ }
3130
+ const item = this.safeDict(entry, 'data', {});
3131
+ const order = this.parseOrder(item);
3132
+ result.push(order);
3133
+ }
3134
+ return result;
3135
+ }
3043
3136
  /**
3044
3137
  * @method
3045
3138
  * @name coinex#cancelOrder
@@ -6,6 +6,15 @@ import type { Balances, Currency, Dict, Int, Market, Num, Order, OrderBook, Orde
6
6
  */
7
7
  export default class coinmate extends Exchange {
8
8
  describe(): any;
9
+ /**
10
+ * @method
11
+ * @name coinmate#fetchTime
12
+ * @description fetches the current integer timestamp in milliseconds from the bingx server
13
+ * @see https://coinmate.docs.apiary.io/#reference/system/get-server-time/get
14
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
15
+ * @returns {int} the current integer timestamp in milliseconds from the bingx server
16
+ */
17
+ fetchTime(params?: {}): Promise<Int>;
9
18
  /**
10
19
  * @method
11
20
  * @name coinmate#fetchMarkets