ccxt 4.2.5 → 4.2.6

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.
package/dist/cjs/ccxt.js CHANGED
@@ -169,7 +169,7 @@ var woo$1 = require('./src/pro/woo.js');
169
169
 
170
170
  //-----------------------------------------------------------------------------
171
171
  // this is updated by vss.js when building
172
- const version = '4.2.5';
172
+ const version = '4.2.6';
173
173
  Exchange["default"].ccxtVersion = version;
174
174
  const exchanges = {
175
175
  'ace': ace,
@@ -1231,10 +1231,15 @@ class Exchange {
1231
1231
  const closedClients = [];
1232
1232
  for (let i = 0; i < clients.length; i++) {
1233
1233
  const client = clients[i];
1234
- delete this.clients[client.url];
1234
+ client.error = new errors.ExchangeClosedByUser(this.id + ' closedByUser');
1235
1235
  closedClients.push(client.close());
1236
1236
  }
1237
- return Promise.all(closedClients);
1237
+ await Promise.all(closedClients);
1238
+ for (let i = 0; i < clients.length; i++) {
1239
+ const client = clients[i];
1240
+ delete this.clients[client.url];
1241
+ }
1242
+ return;
1238
1243
  }
1239
1244
  async loadOrderBook(client, messageHash, symbol, limit = undefined, params = {}) {
1240
1245
  if (!(symbol in this.orderbooks)) {
@@ -46,6 +46,12 @@ class ExchangeError extends Error {
46
46
  this.name = 'ExchangeError';
47
47
  }
48
48
  }
49
+ class ExchangeClosedByUser extends Error {
50
+ constructor(message) {
51
+ super(message);
52
+ this.name = 'ExchangeClosedByUser';
53
+ }
54
+ }
49
55
  class AuthenticationError extends ExchangeError {
50
56
  constructor(message) {
51
57
  super(message);
@@ -252,7 +258,7 @@ class RequestTimeout extends NetworkError {
252
258
  // // Derived class hierarchy
253
259
  // errorHierarchy
254
260
  // )
255
- const errors = { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
261
+ const errors = { BaseError, ExchangeClosedByUser, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
256
262
 
257
263
  exports.AccountNotEnabled = AccountNotEnabled;
258
264
  exports.AccountSuspended = AccountSuspended;
@@ -267,6 +273,7 @@ exports.CancelPending = CancelPending;
267
273
  exports.ContractUnavailable = ContractUnavailable;
268
274
  exports.DDoSProtection = DDoSProtection;
269
275
  exports.DuplicateOrderId = DuplicateOrderId;
276
+ exports.ExchangeClosedByUser = ExchangeClosedByUser;
270
277
  exports.ExchangeError = ExchangeError;
271
278
  exports.ExchangeNotAvailable = ExchangeNotAvailable;
272
279
  exports.InsufficientFunds = InsufficientFunds;
@@ -209,6 +209,9 @@ class Client {
209
209
  // todo: exception types for server-side disconnects
210
210
  this.reset(new errors.NetworkError('connection closed by remote server, closing code ' + String(event.code)));
211
211
  }
212
+ if (this.error instanceof errors.ExchangeClosedByUser) {
213
+ this.reset(this.error);
214
+ }
212
215
  if (this.disconnected !== undefined) {
213
216
  this.disconnected.resolve(true);
214
217
  }
@@ -229,6 +232,7 @@ class Client {
229
232
  const future = Future.Future();
230
233
  if (platform.isNode) {
231
234
  /* eslint-disable no-inner-declarations */
235
+ /* eslint-disable jsdoc/require-jsdoc */
232
236
  function onSendComplete(error) {
233
237
  if (error) {
234
238
  future.reject(error);
@@ -2231,6 +2231,7 @@ class bingx extends bingx$1 {
2231
2231
  * @param {string} id order id
2232
2232
  * @param {string} symbol unified symbol of the market the order was made in
2233
2233
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2234
+ * @param {string} [params.clientOrderId] a unique id for the order
2234
2235
  * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2235
2236
  */
2236
2237
  if (symbol === undefined) {
@@ -2240,8 +2241,15 @@ class bingx extends bingx$1 {
2240
2241
  const market = this.market(symbol);
2241
2242
  const request = {
2242
2243
  'symbol': market['id'],
2243
- 'orderId': id,
2244
2244
  };
2245
+ const clientOrderId = this.safeString2(params, 'clientOrderId', 'clientOrderID');
2246
+ params = this.omit(params, ['clientOrderId']);
2247
+ if (clientOrderId !== undefined) {
2248
+ request['clientOrderID'] = clientOrderId;
2249
+ }
2250
+ else {
2251
+ request['orderId'] = id;
2252
+ }
2245
2253
  let response = undefined;
2246
2254
  const [marketType, query] = this.handleMarketTypeAndParams('cancelOrder', market, params);
2247
2255
  if (marketType === 'spot') {
@@ -1827,14 +1827,15 @@ class bitmex extends bitmex$1 {
1827
1827
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1828
1828
  * @param {object} [params.triggerPrice] the price at which a trigger order is triggered at
1829
1829
  * @param {object} [params.triggerDirection] the direction whenever the trigger happens with relation to price - 'above' or 'below'
1830
+ * @param {float} [params.trailingAmount] the quote amount to trail away from the current market price
1830
1831
  * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1831
1832
  */
1832
1833
  await this.loadMarkets();
1833
1834
  const market = this.market(symbol);
1834
- const orderType = this.capitalize(type);
1835
+ let orderType = this.capitalize(type);
1835
1836
  const reduceOnly = this.safeValue(params, 'reduceOnly');
1836
1837
  if (reduceOnly !== undefined) {
1837
- if ((market['type'] !== 'swap') && (market['type'] !== 'future')) {
1838
+ if ((!market['swap']) && (!market['future'])) {
1838
1839
  throw new errors.InvalidOrder(this.id + ' createOrder() does not support reduceOnly for ' + market['type'] + ' orders, reduceOnly orders are supported for swap and future markets only');
1839
1840
  }
1840
1841
  }
@@ -1847,44 +1848,54 @@ class bitmex extends bitmex$1 {
1847
1848
  'ordType': orderType,
1848
1849
  'text': brokerId,
1849
1850
  };
1850
- const customTriggerType = (orderType === 'Stop') || (orderType === 'StopLimit') || (orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched');
1851
1851
  // support for unified trigger format
1852
1852
  const triggerPrice = this.safeNumberN(params, ['triggerPrice', 'stopPx', 'stopPrice']);
1853
- if ((triggerPrice !== undefined) && !customTriggerType) {
1854
- request['stopPx'] = parseFloat(this.priceToPrecision(symbol, triggerPrice));
1853
+ let trailingAmount = this.safeString2(params, 'trailingAmount', 'pegOffsetValue');
1854
+ const isTriggerOrder = triggerPrice !== undefined;
1855
+ const isTrailingAmountOrder = trailingAmount !== undefined;
1856
+ if (isTriggerOrder || isTrailingAmountOrder) {
1855
1857
  const triggerDirection = this.safeString(params, 'triggerDirection');
1856
- params = this.omit(params, ['triggerPrice', 'stopPrice', 'stopPx', 'triggerDirection']);
1857
1858
  const triggerAbove = (triggerDirection === 'above');
1858
- this.checkRequiredArgument('createOrder', triggerDirection, 'triggerDirection', ['above', 'below']);
1859
- this.checkRequiredArgument('createOrder', side, 'side', ['buy', 'sell']);
1859
+ if ((type === 'limit') || (type === 'market')) {
1860
+ this.checkRequiredArgument('createOrder', triggerDirection, 'triggerDirection', ['above', 'below']);
1861
+ }
1860
1862
  if (type === 'limit') {
1861
- request['price'] = parseFloat(this.priceToPrecision(symbol, price));
1862
1863
  if (side === 'buy') {
1863
- request['ordType'] = triggerAbove ? 'StopLimit' : 'LimitIfTouched';
1864
+ orderType = triggerAbove ? 'StopLimit' : 'LimitIfTouched';
1864
1865
  }
1865
1866
  else {
1866
- request['ordType'] = triggerAbove ? 'LimitIfTouched' : 'StopLimit';
1867
+ orderType = triggerAbove ? 'LimitIfTouched' : 'StopLimit';
1867
1868
  }
1868
1869
  }
1869
1870
  else if (type === 'market') {
1870
1871
  if (side === 'buy') {
1871
- request['ordType'] = triggerAbove ? 'Stop' : 'MarketIfTouched';
1872
+ orderType = triggerAbove ? 'Stop' : 'MarketIfTouched';
1872
1873
  }
1873
1874
  else {
1874
- request['ordType'] = triggerAbove ? 'MarketIfTouched' : 'Stop';
1875
+ orderType = triggerAbove ? 'MarketIfTouched' : 'Stop';
1875
1876
  }
1876
1877
  }
1877
- }
1878
- else if (customTriggerType) {
1879
- if (triggerPrice === undefined) {
1880
- // if exchange specific trigger types were provided
1881
- throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a triggerPrice (stopPx|stopPrice) parameter for the ' + orderType + ' order type');
1878
+ if (isTrailingAmountOrder) {
1879
+ const isStopSellOrder = (side === 'sell') && ((orderType === 'Stop') || (orderType === 'StopLimit'));
1880
+ const isBuyIfTouchedOrder = (side === 'buy') && ((orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched'));
1881
+ if (isStopSellOrder || isBuyIfTouchedOrder) {
1882
+ trailingAmount = '-' + trailingAmount;
1883
+ }
1884
+ request['pegOffsetValue'] = this.parseToNumeric(trailingAmount);
1885
+ request['pegPriceType'] = 'TrailingStopPeg';
1886
+ }
1887
+ else {
1888
+ if (triggerPrice === undefined) {
1889
+ // if exchange specific trigger types were provided
1890
+ throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a triggerPrice (stopPx|stopPrice) parameter for the ' + orderType + ' order type');
1891
+ }
1892
+ request['stopPx'] = this.parseToNumeric(this.priceToPrecision(symbol, triggerPrice));
1882
1893
  }
1883
- params = this.omit(params, ['triggerPrice', 'stopPrice', 'stopPx']);
1884
- request['stopPx'] = parseFloat(this.priceToPrecision(symbol, triggerPrice));
1894
+ request['ordType'] = orderType;
1895
+ params = this.omit(params, ['triggerPrice', 'stopPrice', 'stopPx', 'triggerDirection', 'trailingAmount']);
1885
1896
  }
1886
1897
  if ((orderType === 'Limit') || (orderType === 'StopLimit') || (orderType === 'LimitIfTouched')) {
1887
- request['price'] = parseFloat(this.priceToPrecision(symbol, price));
1898
+ request['price'] = this.parseToNumeric(this.priceToPrecision(symbol, price));
1888
1899
  }
1889
1900
  const clientOrderId = this.safeString2(params, 'clOrdID', 'clientOrderId');
1890
1901
  if (clientOrderId !== undefined) {
@@ -1897,6 +1908,39 @@ class bitmex extends bitmex$1 {
1897
1908
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
1898
1909
  await this.loadMarkets();
1899
1910
  const request = {};
1911
+ let trailingAmount = this.safeString2(params, 'trailingAmount', 'pegOffsetValue');
1912
+ const isTrailingAmountOrder = trailingAmount !== undefined;
1913
+ if (isTrailingAmountOrder) {
1914
+ const triggerDirection = this.safeString(params, 'triggerDirection');
1915
+ const triggerAbove = (triggerDirection === 'above');
1916
+ if ((type === 'limit') || (type === 'market')) {
1917
+ this.checkRequiredArgument('createOrder', triggerDirection, 'triggerDirection', ['above', 'below']);
1918
+ }
1919
+ let orderType = undefined;
1920
+ if (type === 'limit') {
1921
+ if (side === 'buy') {
1922
+ orderType = triggerAbove ? 'StopLimit' : 'LimitIfTouched';
1923
+ }
1924
+ else {
1925
+ orderType = triggerAbove ? 'LimitIfTouched' : 'StopLimit';
1926
+ }
1927
+ }
1928
+ else if (type === 'market') {
1929
+ if (side === 'buy') {
1930
+ orderType = triggerAbove ? 'Stop' : 'MarketIfTouched';
1931
+ }
1932
+ else {
1933
+ orderType = triggerAbove ? 'MarketIfTouched' : 'Stop';
1934
+ }
1935
+ }
1936
+ const isStopSellOrder = (side === 'sell') && ((orderType === 'Stop') || (orderType === 'StopLimit'));
1937
+ const isBuyIfTouchedOrder = (side === 'buy') && ((orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched'));
1938
+ if (isStopSellOrder || isBuyIfTouchedOrder) {
1939
+ trailingAmount = '-' + trailingAmount;
1940
+ }
1941
+ request['pegOffsetValue'] = this.parseToNumeric(trailingAmount);
1942
+ params = this.omit(params, ['triggerDirection', 'trailingAmount']);
1943
+ }
1900
1944
  const origClOrdID = this.safeString2(params, 'origClOrdID', 'clientOrderId');
1901
1945
  if (origClOrdID !== undefined) {
1902
1946
  request['origClOrdID'] = origClOrdID;
@@ -120,7 +120,7 @@ class htx extends htx$1 {
120
120
  'repayIsolatedMargin': true,
121
121
  'setLeverage': true,
122
122
  'setMarginMode': false,
123
- 'setPositionMode': false,
123
+ 'setPositionMode': true,
124
124
  'signIn': undefined,
125
125
  'transfer': true,
126
126
  'withdraw': true,
@@ -8957,6 +8957,71 @@ class htx extends htx$1 {
8957
8957
  'datetime': this.iso8601(timestamp),
8958
8958
  });
8959
8959
  }
8960
+ async setPositionMode(hedged, symbol = undefined, params = {}) {
8961
+ /**
8962
+ * @method
8963
+ * @name htx#setPositionMode
8964
+ * @description set hedged to true or false
8965
+ * @see https://huobiapi.github.io/docs/usdt_swap/v1/en/#isolated-switch-position-mode
8966
+ * @see https://huobiapi.github.io/docs/usdt_swap/v1/en/#cross-switch-position-mode
8967
+ * @param {bool} hedged set to true to for hedged mode, must be set separately for each market in isolated margin mode, only valid for linear markets
8968
+ * @param {string} [symbol] unified market symbol, required for isolated margin mode
8969
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
8970
+ * @param {string} [params.marginMode] "cross" (default) or "isolated"
8971
+ * @returns {object} response from the exchange
8972
+ */
8973
+ await this.loadMarkets();
8974
+ const posMode = hedged ? 'dual_side' : 'single_side';
8975
+ let market = undefined;
8976
+ if (symbol !== undefined) {
8977
+ market = this.market(symbol);
8978
+ }
8979
+ let marginMode = undefined;
8980
+ [marginMode, params] = this.handleMarginModeAndParams('setPositionMode', params, 'cross');
8981
+ const request = {
8982
+ 'position_mode': posMode,
8983
+ };
8984
+ let response = undefined;
8985
+ if ((market !== undefined) && (market['inverse'])) {
8986
+ throw new errors.BadRequest(this.id + ' setPositionMode can only be used for linear markets');
8987
+ }
8988
+ if (marginMode === 'isolated') {
8989
+ if (symbol === undefined) {
8990
+ throw new errors.ArgumentsRequired(this.id + ' setPositionMode requires a symbol argument for isolated margin mode');
8991
+ }
8992
+ request['margin_account'] = market['id'];
8993
+ response = await this.contractPrivatePostLinearSwapApiV1SwapSwitchPositionMode(this.extend(request, params));
8994
+ //
8995
+ // {
8996
+ // "status": "ok",
8997
+ // "data": [
8998
+ // {
8999
+ // "margin_account": "BTC-USDT",
9000
+ // "position_mode": "single_side"
9001
+ // }
9002
+ // ],
9003
+ // "ts": 1566899973811
9004
+ // }
9005
+ //
9006
+ }
9007
+ else {
9008
+ request['margin_account'] = 'USDT';
9009
+ response = await this.contractPrivatePostLinearSwapApiV1SwapCrossSwitchPositionMode(this.extend(request, params));
9010
+ //
9011
+ // {
9012
+ // "status": "ok",
9013
+ // "data": [
9014
+ // {
9015
+ // "margin_account": "USDT",
9016
+ // "position_mode": "single_side"
9017
+ // }
9018
+ // ],
9019
+ // "ts": 1566899973811
9020
+ // }
9021
+ //
9022
+ }
9023
+ return response;
9024
+ }
8960
9025
  }
8961
9026
 
8962
9027
  module.exports = htx;
@@ -765,9 +765,9 @@ class woo extends woo$1 {
765
765
  /**
766
766
  * @method
767
767
  * @name woo#createOrder
768
+ * @description create a trade order
768
769
  * @see https://docs.woo.org/#send-order
769
770
  * @see https://docs.woo.org/#send-algo-order
770
- * @description create a trade order
771
771
  * @param {string} symbol unified symbol of the market to create an order in
772
772
  * @param {string} type 'market' or 'limit'
773
773
  * @param {string} side 'buy' or 'sell'
@@ -781,6 +781,9 @@ class woo extends woo$1 {
781
781
  * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
782
782
  * @param {float} [params.algoType] 'STOP'or 'TRAILING_STOP' or 'OCO' or 'CLOSE_POSITION'
783
783
  * @param {float} [params.cost] *spot market buy only* the quote quantity that can be used as an alternative for the amount
784
+ * @param {string} [params.trailingAmount] the quote amount to trail away from the current market price
785
+ * @param {string} [params.trailingPercent] the percent to trail away from the current market price
786
+ * @param {string} [params.trailingTriggerPrice] the price to trigger a trailing order, default uses the price argument
784
787
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
785
788
  */
786
789
  const reduceOnly = this.safeValue2(params, 'reduceOnly', 'reduce_only');
@@ -797,7 +800,13 @@ class woo extends woo$1 {
797
800
  const stopLoss = this.safeValue(params, 'stopLoss');
798
801
  const takeProfit = this.safeValue(params, 'takeProfit');
799
802
  const algoType = this.safeString(params, 'algoType');
800
- const isStop = stopPrice !== undefined || stopLoss !== undefined || takeProfit !== undefined || (this.safeValue(params, 'childOrders') !== undefined);
803
+ const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activatedPrice', price);
804
+ const trailingAmount = this.safeString2(params, 'trailingAmount', 'callbackValue');
805
+ const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
806
+ const isTrailingAmountOrder = trailingAmount !== undefined;
807
+ const isTrailingPercentOrder = trailingPercent !== undefined;
808
+ const isTrailing = isTrailingAmountOrder || isTrailingPercentOrder;
809
+ const isStop = isTrailing || stopPrice !== undefined || stopLoss !== undefined || takeProfit !== undefined || (this.safeValue(params, 'childOrders') !== undefined);
801
810
  const isMarket = orderType === 'MARKET';
802
811
  const timeInForce = this.safeStringLower(params, 'timeInForce');
803
812
  const postOnly = this.isPostOnly(isMarket, undefined, params);
@@ -862,7 +871,21 @@ class woo extends woo$1 {
862
871
  if (clientOrderId !== undefined) {
863
872
  request[clientOrderIdKey] = clientOrderId;
864
873
  }
865
- if (stopPrice !== undefined) {
874
+ if (isTrailing) {
875
+ if (trailingTriggerPrice === undefined) {
876
+ throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a trailingTriggerPrice parameter for trailing orders');
877
+ }
878
+ request['activatedPrice'] = this.priceToPrecision(symbol, trailingTriggerPrice);
879
+ request['algoType'] = 'TRAILING_STOP';
880
+ if (isTrailingAmountOrder) {
881
+ request['callbackValue'] = trailingAmount;
882
+ }
883
+ else if (isTrailingPercentOrder) {
884
+ const convertedTrailingPercent = Precise["default"].stringDiv(trailingPercent, '100');
885
+ request['callbackRate'] = convertedTrailingPercent;
886
+ }
887
+ }
888
+ else if (stopPrice !== undefined) {
866
889
  if (algoType !== 'TRAILING_STOP') {
867
890
  request['triggerPrice'] = this.priceToPrecision(symbol, stopPrice);
868
891
  request['algoType'] = 'STOP';
@@ -901,7 +924,7 @@ class woo extends woo$1 {
901
924
  }
902
925
  request['childOrders'] = [outterOrder];
903
926
  }
904
- params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLoss', 'takeProfit']);
927
+ params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingPercent', 'trailingAmount', 'trailingTriggerPrice']);
905
928
  let response = undefined;
906
929
  if (isStop) {
907
930
  response = await this.v3PrivatePostAlgoOrder(this.extend(request, params));
@@ -947,11 +970,11 @@ class woo extends woo$1 {
947
970
  /**
948
971
  * @method
949
972
  * @name woo#editOrder
973
+ * @description edit a trade order
950
974
  * @see https://docs.woo.org/#edit-order
951
975
  * @see https://docs.woo.org/#edit-order-by-client_order_id
952
976
  * @see https://docs.woo.org/#edit-algo-order
953
977
  * @see https://docs.woo.org/#edit-algo-order-by-client_order_id
954
- * @description edit a trade order
955
978
  * @param {string} id order id
956
979
  * @param {string} symbol unified symbol of the market to create an order in
957
980
  * @param {string} type 'market' or 'limit'
@@ -962,6 +985,9 @@ class woo extends woo$1 {
962
985
  * @param {float} [params.triggerPrice] The price a trigger order is triggered at
963
986
  * @param {float} [params.stopLossPrice] price to trigger stop-loss orders
964
987
  * @param {float} [params.takeProfitPrice] price to trigger take-profit orders
988
+ * @param {string} [params.trailingAmount] the quote amount to trail away from the current market price
989
+ * @param {string} [params.trailingPercent] the percent to trail away from the current market price
990
+ * @param {string} [params.trailingTriggerPrice] the price to trigger a trailing order, default uses the price argument
965
991
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
966
992
  */
967
993
  await this.loadMarkets();
@@ -983,8 +1009,26 @@ class woo extends woo$1 {
983
1009
  if (stopPrice !== undefined) {
984
1010
  request['triggerPrice'] = this.priceToPrecision(symbol, stopPrice);
985
1011
  }
986
- params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id', 'stopPrice', 'triggerPrice', 'takeProfitPrice', 'stopLossPrice']);
987
- const isStop = (stopPrice !== undefined) || (this.safeValue(params, 'childOrders') !== undefined);
1012
+ const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activatedPrice', price);
1013
+ const trailingAmount = this.safeString2(params, 'trailingAmount', 'callbackValue');
1014
+ const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
1015
+ const isTrailingAmountOrder = trailingAmount !== undefined;
1016
+ const isTrailingPercentOrder = trailingPercent !== undefined;
1017
+ const isTrailing = isTrailingAmountOrder || isTrailingPercentOrder;
1018
+ if (isTrailing) {
1019
+ if (trailingTriggerPrice !== undefined) {
1020
+ request['activatedPrice'] = this.priceToPrecision(symbol, trailingTriggerPrice);
1021
+ }
1022
+ if (isTrailingAmountOrder) {
1023
+ request['callbackValue'] = trailingAmount;
1024
+ }
1025
+ else if (isTrailingPercentOrder) {
1026
+ const convertedTrailingPercent = Precise["default"].stringDiv(trailingPercent, '100');
1027
+ request['callbackRate'] = convertedTrailingPercent;
1028
+ }
1029
+ }
1030
+ params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id', 'stopPrice', 'triggerPrice', 'takeProfitPrice', 'stopLossPrice', 'trailingTriggerPrice', 'trailingAmount', 'trailingPercent']);
1031
+ const isStop = isTrailing || (stopPrice !== undefined) || (this.safeValue(params, 'childOrders') !== undefined);
988
1032
  let response = undefined;
989
1033
  if (isByClientOrder) {
990
1034
  request['client_order_id'] = clientOrderIdExchangeSpecific;
@@ -1184,9 +1228,9 @@ class woo extends woo$1 {
1184
1228
  /**
1185
1229
  * @method
1186
1230
  * @name woo#fetchOrders
1231
+ * @description fetches information on multiple orders made by the user
1187
1232
  * @see https://docs.woo.org/#get-orders
1188
1233
  * @see https://docs.woo.org/#get-algo-orders
1189
- * @description fetches information on multiple orders made by the user
1190
1234
  * @param {string} symbol unified market symbol of the market orders were made in
1191
1235
  * @param {int} [since] the earliest time in ms to fetch orders for
1192
1236
  * @param {int} [limit] the maximum number of order structures to retrieve
@@ -1194,19 +1238,21 @@ class woo extends woo$1 {
1194
1238
  * @param {boolean} [params.stop] whether the order is a stop/algo order
1195
1239
  * @param {boolean} [params.isTriggered] whether the order has been triggered (false by default)
1196
1240
  * @param {string} [params.side] 'buy' or 'sell'
1241
+ * @param {boolean} [params.trailing] set to true if you want to fetch trailing orders
1197
1242
  * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1198
1243
  */
1199
1244
  await this.loadMarkets();
1200
1245
  const request = {};
1201
1246
  let market = undefined;
1202
1247
  const stop = this.safeValue(params, 'stop');
1203
- params = this.omit(params, 'stop');
1248
+ const trailing = this.safeValue(params, 'trailing', false);
1249
+ params = this.omit(params, ['stop', 'trailing']);
1204
1250
  if (symbol !== undefined) {
1205
1251
  market = this.market(symbol);
1206
1252
  request['symbol'] = market['id'];
1207
1253
  }
1208
1254
  if (since !== undefined) {
1209
- if (stop) {
1255
+ if (stop || trailing) {
1210
1256
  request['createdTimeStart'] = since;
1211
1257
  }
1212
1258
  else {
@@ -1216,8 +1262,11 @@ class woo extends woo$1 {
1216
1262
  if (stop) {
1217
1263
  request['algoType'] = 'stop';
1218
1264
  }
1265
+ else if (trailing) {
1266
+ request['algoType'] = 'TRAILING_STOP';
1267
+ }
1219
1268
  let response = undefined;
1220
- if (stop) {
1269
+ if (stop || trailing) {
1221
1270
  response = await this.v3PrivateGetAlgoOrders(this.extend(request, params));
1222
1271
  }
1223
1272
  else {
package/js/ccxt.d.ts CHANGED
@@ -4,7 +4,7 @@ import * as functions from './src/base/functions.js';
4
4
  import * as errors from './src/base/errors.js';
5
5
  import type { Market, Trade, Fee, Ticker, OrderBook, Order, Transaction, Tickers, Currency, Balance, DepositAddress, WithdrawalResponse, DepositAddressResponse, OHLCV, Balances, PartialBalances, Dictionary, MinMax, Position, FundingRateHistory, Liquidation, FundingHistory, MarginMode, Greeks } from './src/base/types.js';
6
6
  import { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, NoChange } from './src/base/errors.js';
7
- declare const version = "4.2.4";
7
+ declare const version = "4.2.5";
8
8
  import ace from './src/ace.js';
9
9
  import alpaca from './src/alpaca.js';
10
10
  import ascendex from './src/ascendex.js';
package/js/ccxt.js CHANGED
@@ -38,7 +38,7 @@ import * as errors from './src/base/errors.js';
38
38
  import { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, NoChange } from './src/base/errors.js';
39
39
  //-----------------------------------------------------------------------------
40
40
  // this is updated by vss.js when building
41
- const version = '4.2.5';
41
+ const version = '4.2.6';
42
42
  Exchange.ccxtVersion = version;
43
43
  //-----------------------------------------------------------------------------
44
44
  import ace from './src/ace.js';
@@ -546,7 +546,7 @@ export default class Exchange {
546
546
  onConnected(client: any, message?: any): void;
547
547
  onError(client: any, error: any): void;
548
548
  onClose(client: any, error: any): void;
549
- close(): Promise<any[]>;
549
+ close(): Promise<void>;
550
550
  loadOrderBook(client: any, messageHash: any, symbol: any, limit?: any, params?: {}): Promise<void>;
551
551
  convertToBigInt(value: string): bigint;
552
552
  stringToCharsArray(value: any): any;
@@ -11,7 +11,7 @@ const { isNode, deepExtend, extend, clone, flatten, unique, indexBy, sortBy, sor
11
11
  import { keys as keysFunc, values as valuesFunc, vwap as vwapFunc } from './functions.js';
12
12
  // import exceptions from "./errors.js"
13
13
  import { // eslint-disable-line object-curly-newline
14
- ExchangeError, BadSymbol, NullResponse, InvalidAddress, InvalidOrder, NotSupported, BadResponse, AuthenticationError, DDoSProtection, RequestTimeout, NetworkError, ProxyError, ExchangeNotAvailable, ArgumentsRequired, RateLimitExceeded, BadRequest } from "./errors.js";
14
+ ExchangeError, BadSymbol, NullResponse, InvalidAddress, InvalidOrder, NotSupported, BadResponse, AuthenticationError, DDoSProtection, RequestTimeout, NetworkError, ProxyError, ExchangeNotAvailable, ArgumentsRequired, RateLimitExceeded, BadRequest, ExchangeClosedByUser } from "./errors.js";
15
15
  import { Precise } from './Precise.js';
16
16
  //-----------------------------------------------------------------------------
17
17
  import WsClient from './ws/WsClient.js';
@@ -1227,10 +1227,15 @@ export default class Exchange {
1227
1227
  const closedClients = [];
1228
1228
  for (let i = 0; i < clients.length; i++) {
1229
1229
  const client = clients[i];
1230
- delete this.clients[client.url];
1230
+ client.error = new ExchangeClosedByUser(this.id + ' closedByUser');
1231
1231
  closedClients.push(client.close());
1232
1232
  }
1233
- return Promise.all(closedClients);
1233
+ await Promise.all(closedClients);
1234
+ for (let i = 0; i < clients.length; i++) {
1235
+ const client = clients[i];
1236
+ delete this.clients[client.url];
1237
+ }
1238
+ return;
1234
1239
  }
1235
1240
  async loadOrderBook(client, messageHash, symbol, limit = undefined, params = {}) {
1236
1241
  if (!(symbol in this.orderbooks)) {
@@ -45,6 +45,7 @@ declare const errorHierarchy: {
45
45
  RequestTimeout: {};
46
46
  };
47
47
  };
48
+ ExchangeClosedByUser: {};
48
49
  };
49
50
  };
50
51
  export default errorHierarchy;
@@ -51,6 +51,7 @@ const errorHierarchy = {
51
51
  'RequestTimeout': {},
52
52
  },
53
53
  },
54
+ 'ExchangeClosedByUser': {},
54
55
  },
55
56
  };
56
57
  export default errorHierarchy;
@@ -4,6 +4,9 @@ declare class BaseError extends Error {
4
4
  declare class ExchangeError extends Error {
5
5
  constructor(message: any);
6
6
  }
7
+ declare class ExchangeClosedByUser extends Error {
8
+ constructor(message: any);
9
+ }
7
10
  declare class AuthenticationError extends ExchangeError {
8
11
  constructor(message: any);
9
12
  }
@@ -105,6 +108,7 @@ declare class RequestTimeout extends NetworkError {
105
108
  }
106
109
  declare const errors: {
107
110
  BaseError: typeof BaseError;
111
+ ExchangeClosedByUser: typeof ExchangeClosedByUser;
108
112
  ExchangeError: typeof ExchangeError;
109
113
  PermissionDenied: typeof PermissionDenied;
110
114
  AccountNotEnabled: typeof AccountNotEnabled;
@@ -140,5 +144,5 @@ declare const errors: {
140
144
  OperationFailed: typeof OperationFailed;
141
145
  ProxyError: typeof ProxyError;
142
146
  };
143
- export { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
147
+ export { BaseError, ExchangeClosedByUser, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
144
148
  export default errors;
@@ -48,6 +48,12 @@ class ExchangeError extends Error {
48
48
  this.name = 'ExchangeError';
49
49
  }
50
50
  }
51
+ class ExchangeClosedByUser extends Error {
52
+ constructor(message) {
53
+ super(message);
54
+ this.name = 'ExchangeClosedByUser';
55
+ }
56
+ }
51
57
  class AuthenticationError extends ExchangeError {
52
58
  constructor(message) {
53
59
  super(message);
@@ -254,6 +260,6 @@ class RequestTimeout extends NetworkError {
254
260
  // // Derived class hierarchy
255
261
  // errorHierarchy
256
262
  // )
257
- const errors = { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
258
- export { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
263
+ const errors = { BaseError, ExchangeClosedByUser, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
264
+ export { BaseError, ExchangeClosedByUser, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
259
265
  export default errors;