ccxt 4.3.19 → 4.3.21

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 (56) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/ccxt.js +1 -1
  3. package/dist/cjs/src/base/Exchange.js +3 -0
  4. package/dist/cjs/src/base/functions/platform.js +3 -1
  5. package/dist/cjs/src/base/functions.js +1 -0
  6. package/dist/cjs/src/binance.js +10 -1
  7. package/dist/cjs/src/bitget.js +3 -0
  8. package/dist/cjs/src/bitmex.js +1 -0
  9. package/dist/cjs/src/bybit.js +38 -9
  10. package/dist/cjs/src/coinex.js +180 -201
  11. package/dist/cjs/src/hyperliquid.js +24 -2
  12. package/dist/cjs/src/okx.js +3 -0
  13. package/dist/cjs/src/phemex.js +17 -6
  14. package/dist/cjs/src/pro/htx.js +12 -7
  15. package/dist/cjs/src/pro/kucoinfutures.js +92 -0
  16. package/dist/cjs/src/pro/woo.js +52 -24
  17. package/js/ccxt.d.ts +1 -1
  18. package/js/ccxt.js +1 -1
  19. package/js/src/abstract/binance.d.ts +1 -0
  20. package/js/src/abstract/binancecoinm.d.ts +1 -0
  21. package/js/src/abstract/binanceus.d.ts +1 -0
  22. package/js/src/abstract/binanceusdm.d.ts +1 -0
  23. package/js/src/abstract/bitget.d.ts +3 -0
  24. package/js/src/abstract/okx.d.ts +3 -0
  25. package/js/src/ascendex.d.ts +1 -1
  26. package/js/src/base/Exchange.d.ts +1 -1
  27. package/js/src/base/Exchange.js +3 -0
  28. package/js/src/base/functions/platform.d.ts +2 -1
  29. package/js/src/base/functions/platform.js +3 -2
  30. package/js/src/binance.d.ts +1 -1
  31. package/js/src/binance.js +10 -1
  32. package/js/src/bingx.d.ts +1 -1
  33. package/js/src/bitget.d.ts +1 -1
  34. package/js/src/bitget.js +3 -0
  35. package/js/src/bitmex.js +1 -0
  36. package/js/src/bybit.d.ts +1 -0
  37. package/js/src/bybit.js +38 -9
  38. package/js/src/coinex.d.ts +2 -2
  39. package/js/src/coinex.js +180 -201
  40. package/js/src/delta.d.ts +1 -1
  41. package/js/src/digifinex.d.ts +1 -1
  42. package/js/src/exmo.d.ts +1 -1
  43. package/js/src/gate.d.ts +1 -1
  44. package/js/src/hitbtc.d.ts +1 -1
  45. package/js/src/hyperliquid.d.ts +1 -1
  46. package/js/src/hyperliquid.js +24 -2
  47. package/js/src/okx.d.ts +1 -1
  48. package/js/src/okx.js +3 -0
  49. package/js/src/phemex.d.ts +1 -1
  50. package/js/src/phemex.js +17 -6
  51. package/js/src/pro/htx.js +12 -7
  52. package/js/src/pro/kucoinfutures.d.ts +3 -1
  53. package/js/src/pro/kucoinfutures.js +93 -1
  54. package/js/src/pro/woo.d.ts +2 -1
  55. package/js/src/pro/woo.js +52 -24
  56. package/package.json +1 -1
package/js/src/gate.d.ts CHANGED
@@ -250,7 +250,7 @@ export default class gate extends Exchange {
250
250
  headers: any;
251
251
  };
252
252
  modifyMarginHelper(symbol: string, amount: any, params?: {}): Promise<MarginModification>;
253
- parseMarginModification(data: any, market?: Market): MarginModification;
253
+ parseMarginModification(data: Dict, market?: Market): MarginModification;
254
254
  reduceMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
255
255
  addMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
256
256
  fetchOpenInterestHistory(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OpenInterest[]>;
@@ -113,7 +113,7 @@ export default class hitbtc extends Exchange {
113
113
  previousFundingDatetime: any;
114
114
  };
115
115
  modifyMarginHelper(symbol: string, amount: any, type: any, params?: {}): Promise<MarginModification>;
116
- parseMarginModification(data: any, market?: Market): MarginModification;
116
+ parseMarginModification(data: Dict, market?: Market): MarginModification;
117
117
  reduceMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
118
118
  addMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
119
119
  fetchLeverage(symbol: string, params?: {}): Promise<Leverage>;
@@ -75,7 +75,7 @@ export default class hyperliquid extends Exchange {
75
75
  addMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
76
76
  reduceMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
77
77
  modifyMarginHelper(symbol: string, amount: any, type: any, params?: {}): Promise<MarginModification>;
78
- parseMarginModification(data: any, market?: Market): MarginModification;
78
+ parseMarginModification(data: Dict, market?: Market): MarginModification;
79
79
  transfer(code: string, amount: number, fromAccount: string, toAccount: string, params?: {}): Promise<TransferEntry>;
80
80
  withdraw(code: string, amount: any, address: any, tag?: any, params?: {}): Promise<any>;
81
81
  formatVaultAddress(address?: Str): string;
@@ -1631,14 +1631,17 @@ export default class hyperliquid extends Exchange {
1631
1631
  * @param {int} [limit] the maximum number of open orders structures to retrieve
1632
1632
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1633
1633
  * @param {string} [params.user] user address, will default to this.walletAddress if not provided
1634
+ * @param {string} [params.method] 'openOrders' or 'frontendOpenOrders' default is 'frontendOpenOrders'
1634
1635
  * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1635
1636
  */
1636
1637
  let userAddress = undefined;
1637
1638
  [userAddress, params] = this.handlePublicAddress('fetchOpenOrders', params);
1639
+ let method = undefined;
1640
+ [method, params] = this.handleOptionAndParams(params, 'fetchOpenOrders', 'method', 'frontendOpenOrders');
1638
1641
  await this.loadMarkets();
1639
1642
  const market = this.safeMarket(symbol);
1640
1643
  const request = {
1641
- 'type': 'openOrders',
1644
+ 'type': method,
1642
1645
  'user': userAddress,
1643
1646
  };
1644
1647
  const response = await this.publicPostInfo(this.extend(request, params));
@@ -1816,6 +1819,25 @@ export default class hyperliquid extends Exchange {
1816
1819
  // "oid":6195281425
1817
1820
  // }
1818
1821
  // }
1822
+ // frontendOrder
1823
+ // {
1824
+ // "children": [],
1825
+ // "cloid": null,
1826
+ // "coin": "BLUR",
1827
+ // "isPositionTpsl": false,
1828
+ // "isTrigger": true,
1829
+ // "limitPx": "0.5",
1830
+ // "oid": 8670487141,
1831
+ // "orderType": "Stop Limit",
1832
+ // "origSz": "20.0",
1833
+ // "reduceOnly": false,
1834
+ // "side": "B",
1835
+ // "sz": "20.0",
1836
+ // "tif": null,
1837
+ // "timestamp": 1715523663687,
1838
+ // "triggerCondition": "Price above 0.6",
1839
+ // "triggerPx": "0.6"
1840
+ // }
1819
1841
  //
1820
1842
  let entry = this.safeDictN(order, ['order', 'resting', 'filled']);
1821
1843
  if (entry === undefined) {
@@ -1853,7 +1875,7 @@ export default class hyperliquid extends Exchange {
1853
1875
  'lastTradeTimestamp': undefined,
1854
1876
  'lastUpdateTimestamp': undefined,
1855
1877
  'symbol': symbol,
1856
- 'type': this.safeStringLower(entry, 'orderType'),
1878
+ 'type': this.parseOrderType(this.safeStringLower(entry, 'orderType')),
1857
1879
  'timeInForce': this.safeStringUpper(entry, 'tif'),
1858
1880
  'postOnly': undefined,
1859
1881
  'reduceOnly': this.safeBool(entry, 'reduceOnly'),
package/js/src/okx.d.ts CHANGED
@@ -172,7 +172,7 @@ export default class okx extends Exchange {
172
172
  fetchBorrowRateHistories(codes?: any, since?: Int, limit?: Int, params?: {}): Promise<{}>;
173
173
  fetchBorrowRateHistory(code: string, since?: Int, limit?: Int, params?: {}): Promise<any>;
174
174
  modifyMarginHelper(symbol: string, amount: any, type: any, params?: {}): Promise<MarginModification>;
175
- parseMarginModification(data: any, market?: Market): MarginModification;
175
+ parseMarginModification(data: Dict, market?: Market): MarginModification;
176
176
  reduceMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
177
177
  addMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
178
178
  fetchMarketLeverageTiers(symbol: string, params?: {}): Promise<any[]>;
package/js/src/okx.js CHANGED
@@ -248,6 +248,9 @@ export default class okx extends Exchange {
248
248
  'sprd/books': 1 / 2,
249
249
  'sprd/ticker': 1,
250
250
  'sprd/public-trades': 1 / 5,
251
+ 'market/sprd-ticker': 2,
252
+ 'market/sprd-candles': 2,
253
+ 'market/sprd-history-candles': 2,
251
254
  'tradingBot/grid/ai-param': 1,
252
255
  'tradingBot/grid/min-investment': 1,
253
256
  'tradingBot/public/rsi-back-testing': 1,
@@ -101,7 +101,7 @@ export default class phemex extends Exchange {
101
101
  };
102
102
  setMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
103
103
  parseMarginStatus(status: any): string;
104
- parseMarginModification(data: any, market?: Market): MarginModification;
104
+ parseMarginModification(data: Dict, market?: Market): MarginModification;
105
105
  setMarginMode(marginMode: string, symbol?: Str, params?: {}): Promise<any>;
106
106
  setPositionMode(hedged: boolean, symbol?: Str, params?: {}): Promise<any>;
107
107
  fetchLeverageTiers(symbols?: Strings, params?: {}): Promise<{}>;
package/js/src/phemex.js CHANGED
@@ -2435,12 +2435,14 @@ export default class phemex extends Exchange {
2435
2435
  * @name phemex#createOrder
2436
2436
  * @description create a trade order
2437
2437
  * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#place-order
2438
+ * @see https://phemex-docs.github.io/#place-order-http-put-prefered-3
2438
2439
  * @param {string} symbol unified symbol of the market to create an order in
2439
2440
  * @param {string} type 'market' or 'limit'
2440
2441
  * @param {string} side 'buy' or 'sell'
2441
2442
  * @param {float} amount how much of currency you want to trade in units of base currency
2442
2443
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2443
2444
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2445
+ * @param {float} [params.trigger] trigger price for conditional orders
2444
2446
  * @param {object} [params.takeProfit] *swap only* *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered (perpetual swap markets only)
2445
2447
  * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
2446
2448
  * @param {object} [params.stopLoss] *swap only* *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered (perpetual swap markets only)
@@ -2451,7 +2453,7 @@ export default class phemex extends Exchange {
2451
2453
  const market = this.market(symbol);
2452
2454
  const requestSide = this.capitalize(side);
2453
2455
  type = this.capitalize(type);
2454
- const reduceOnly = this.safeValue(params, 'reduceOnly');
2456
+ const reduceOnly = this.safeBool(params, 'reduceOnly');
2455
2457
  const request = {
2456
2458
  // common
2457
2459
  'symbol': market['id'],
@@ -2495,13 +2497,13 @@ export default class phemex extends Exchange {
2495
2497
  request['clOrdID'] = clientOrderId;
2496
2498
  params = this.omit(params, ['clOrdID', 'clientOrderId']);
2497
2499
  }
2498
- const stopPrice = this.safeStringN(params, ['stopPx', 'stopPrice', 'triggerPrice']);
2499
- if (stopPrice !== undefined) {
2500
+ const triggerPrice = this.safeStringN(params, ['stopPx', 'stopPrice', 'triggerPrice']);
2501
+ if (triggerPrice !== undefined) {
2500
2502
  if (market['settle'] === 'USDT') {
2501
- request['stopPxRp'] = this.priceToPrecision(symbol, stopPrice);
2503
+ request['stopPxRp'] = this.priceToPrecision(symbol, triggerPrice);
2502
2504
  }
2503
2505
  else {
2504
- request['stopPxEp'] = this.toEp(stopPrice, market);
2506
+ request['stopPxEp'] = this.toEp(triggerPrice, market);
2505
2507
  }
2506
2508
  }
2507
2509
  params = this.omit(params, ['stopPx', 'stopPrice', 'stopLoss', 'takeProfit', 'triggerPrice']);
@@ -2512,6 +2514,15 @@ export default class phemex extends Exchange {
2512
2514
  qtyType = 'ByQuote';
2513
2515
  }
2514
2516
  }
2517
+ if (triggerPrice !== undefined) {
2518
+ if (type === 'Limit') {
2519
+ request['ordType'] = 'StopLimit';
2520
+ }
2521
+ else if (type === 'Market') {
2522
+ request['ordType'] = 'Stop';
2523
+ }
2524
+ request['trigger'] = 'ByLastPrice';
2525
+ }
2515
2526
  request['qtyType'] = qtyType;
2516
2527
  if (qtyType === 'ByQuote') {
2517
2528
  let cost = this.safeNumber(params, 'cost');
@@ -2552,7 +2563,7 @@ export default class phemex extends Exchange {
2552
2563
  else {
2553
2564
  request['orderQty'] = this.parseToInt(amount);
2554
2565
  }
2555
- if (stopPrice !== undefined) {
2566
+ if (triggerPrice !== undefined) {
2556
2567
  const triggerType = this.safeString(params, 'triggerType', 'ByMarkPrice');
2557
2568
  request['triggerType'] = triggerType;
2558
2569
  }
package/js/src/pro/htx.js CHANGED
@@ -1900,7 +1900,7 @@ export default class htx extends htxRest {
1900
1900
  // "data": { "user-id": "35930539" }
1901
1901
  // }
1902
1902
  //
1903
- const promise = client.futures['authenticated'];
1903
+ const promise = client.futures['auth'];
1904
1904
  promise.resolve(message);
1905
1905
  }
1906
1906
  handleErrorMessage(client, message) {
@@ -1928,6 +1928,12 @@ export default class htx extends htxRest {
1928
1928
  // 'err-msg': "Non - single account user is not available, please check through the cross and isolated account asset interface",
1929
1929
  // "ts": 1698419490189
1930
1930
  // }
1931
+ // {
1932
+ // "action":"req",
1933
+ // "code":2002,
1934
+ // "ch":"auth",
1935
+ // "message":"auth.fail"
1936
+ // }
1931
1937
  //
1932
1938
  const status = this.safeString(message, 'status');
1933
1939
  if (status === 'error') {
@@ -1938,6 +1944,7 @@ export default class htx extends htxRest {
1938
1944
  const errorCode = this.safeString(message, 'err-code');
1939
1945
  try {
1940
1946
  this.throwExactlyMatchedException(this.exceptions['ws']['exact'], errorCode, this.json(message));
1947
+ throw new ExchangeError(this.json(message));
1941
1948
  }
1942
1949
  catch (e) {
1943
1950
  const messageHash = this.safeString(subscription, 'messageHash');
@@ -1950,11 +1957,12 @@ export default class htx extends htxRest {
1950
1957
  }
1951
1958
  return false;
1952
1959
  }
1953
- const code = this.safeInteger2(message, 'code', 'err-code');
1954
- if (code !== undefined && ((code !== 200) && (code !== 0))) {
1960
+ const code = this.safeString2(message, 'code', 'err-code');
1961
+ if (code !== undefined && ((code !== '200') && (code !== '0'))) {
1955
1962
  const feedback = this.id + ' ' + this.json(message);
1956
1963
  try {
1957
1964
  this.throwExactlyMatchedException(this.exceptions['ws']['exact'], code, feedback);
1965
+ throw new ExchangeError(feedback);
1958
1966
  }
1959
1967
  catch (e) {
1960
1968
  if (e instanceof AuthenticationError) {
@@ -2308,9 +2316,6 @@ export default class htx extends htxRest {
2308
2316
  'url': url,
2309
2317
  'hostname': hostname,
2310
2318
  };
2311
- if (type === 'spot') {
2312
- this.options['ws']['gunzip'] = false;
2313
- }
2314
2319
  await this.authenticate(authParams);
2315
2320
  return await this.watch(url, messageHash, this.extend(request, params), channel, extendedSubsription);
2316
2321
  }
@@ -2322,7 +2327,7 @@ export default class htx extends htxRest {
2322
2327
  throw new ArgumentsRequired(this.id + ' authenticate requires a url, hostname and type argument');
2323
2328
  }
2324
2329
  this.checkRequiredCredentials();
2325
- const messageHash = 'authenticated';
2330
+ const messageHash = 'auth';
2326
2331
  const relativePath = url.replace('wss://' + hostname, '');
2327
2332
  const client = this.client(url);
2328
2333
  const future = client.future(messageHash);
@@ -1,5 +1,5 @@
1
1
  import kucoinfuturesRest from '../kucoinfutures.js';
2
- import type { Int, Str, OrderBook, Order, Trade, Ticker, Balances, Position, Strings, Tickers } from '../base/types.js';
2
+ import type { Int, Str, OrderBook, Order, Trade, Ticker, Balances, Position, Strings, Tickers, OHLCV } from '../base/types.js';
3
3
  import Client from '../base/ws/Client.js';
4
4
  export default class kucoinfutures extends kucoinfuturesRest {
5
5
  describe(): any;
@@ -23,6 +23,8 @@ export default class kucoinfutures extends kucoinfuturesRest {
23
23
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
24
24
  watchTradesForSymbols(symbols: string[], since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
25
25
  handleTrade(client: Client, message: any): any;
26
+ watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
27
+ handleOHLCV(client: Client, message: any): void;
26
28
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
27
29
  watchOrderBookForSymbols(symbols: string[], limit?: Int, params?: {}): Promise<OrderBook>;
28
30
  handleDelta(orderbook: any, delta: any): void;
@@ -7,7 +7,7 @@
7
7
  // ---------------------------------------------------------------------------
8
8
  import kucoinfuturesRest from '../kucoinfutures.js';
9
9
  import { ExchangeError, ArgumentsRequired } from '../base/errors.js';
10
- import { ArrayCache, ArrayCacheBySymbolById } from '../base/ws/Cache.js';
10
+ import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
11
11
  // ---------------------------------------------------------------------------
12
12
  export default class kucoinfutures extends kucoinfuturesRest {
13
13
  describe() {
@@ -18,6 +18,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
18
18
  'watchTickers': true,
19
19
  'watchBidsAsks': true,
20
20
  'watchTrades': true,
21
+ 'watchOHLCV': true,
21
22
  'watchOrderBook': true,
22
23
  'watchOrders': true,
23
24
  'watchBalance': true,
@@ -28,6 +29,21 @@ export default class kucoinfutures extends kucoinfuturesRest {
28
29
  'watchOrderBookForSymbols': true,
29
30
  },
30
31
  'options': {
32
+ 'timeframes': {
33
+ '1m': '1min',
34
+ '3m': '1min',
35
+ '5m': '5min',
36
+ '15m': '15min',
37
+ '30m': '30min',
38
+ '1h': '1hour',
39
+ '2h': '2hour',
40
+ '4h': '4hour',
41
+ '8h': '8hour',
42
+ '12h': '12hour',
43
+ '1d': '1day',
44
+ '1w': '1week',
45
+ '1M': '1month',
46
+ },
31
47
  'accountsByType': {
32
48
  'swap': 'future',
33
49
  'cross': 'margin',
@@ -570,6 +586,81 @@ export default class kucoinfutures extends kucoinfuturesRest {
570
586
  client.resolve(trades, messageHash);
571
587
  return message;
572
588
  }
589
+ async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
590
+ /**
591
+ * @method
592
+ * @name kucoinfutures#watchOHLCV
593
+ * @see https://www.kucoin.com/docs/websocket/futures-trading/public-channels/klines
594
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
595
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
596
+ * @param {string} timeframe the length of time each candle represents
597
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
598
+ * @param {int} [limit] the maximum amount of candles to fetch
599
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
600
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
601
+ */
602
+ await this.loadMarkets();
603
+ symbol = this.symbol(symbol);
604
+ const url = await this.negotiate(false);
605
+ const marketId = this.marketId(symbol);
606
+ const timeframes = this.safeDict(this.options, 'timeframes');
607
+ const timeframeId = this.safeString(timeframes, timeframe, timeframe);
608
+ const topic = '/contractMarket/limitCandle:' + marketId + '_' + timeframeId;
609
+ const messageHash = 'ohlcv::' + symbol + '_' + timeframe;
610
+ const ohlcv = await this.subscribe(url, messageHash, topic, undefined, params);
611
+ if (this.newUpdates) {
612
+ limit = ohlcv.getLimit(symbol, limit);
613
+ }
614
+ return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
615
+ }
616
+ handleOHLCV(client, message) {
617
+ //
618
+ // {
619
+ // "topic":"/contractMarket/limitCandle:LTCUSDTM_1min",
620
+ // "type":"message",
621
+ // "data":{
622
+ // "symbol":"LTCUSDTM",
623
+ // "candles":[
624
+ // "1715470980",
625
+ // "81.38",
626
+ // "81.38",
627
+ // "81.38",
628
+ // "81.38",
629
+ // "61.0",
630
+ // "61"
631
+ // ],
632
+ // "time":1715470994801
633
+ // },
634
+ // "subject":"candle.stick"
635
+ // }
636
+ //
637
+ const topic = this.safeString(message, 'topic');
638
+ const parts = topic.split('_');
639
+ const timeframeId = this.safeString(parts, 1);
640
+ const data = this.safeDict(message, 'data');
641
+ const timeframes = this.safeDict(this.options, 'timeframes');
642
+ const timeframe = this.findTimeframe(timeframeId, timeframes);
643
+ const marketId = this.safeString(data, 'symbol');
644
+ const symbol = this.safeSymbol(marketId);
645
+ const messageHash = 'ohlcv::' + symbol + '_' + timeframe;
646
+ const ohlcv = this.safeList(data, 'candles');
647
+ const parsed = [
648
+ this.safeInteger(ohlcv, 0),
649
+ this.safeNumber(ohlcv, 1),
650
+ this.safeNumber(ohlcv, 2),
651
+ this.safeNumber(ohlcv, 3),
652
+ this.safeNumber(ohlcv, 4),
653
+ this.safeNumber(ohlcv, 6), // Note value 5 is incorrect and will be fixed in subsequent versions of kucoin
654
+ ];
655
+ this.ohlcvs[symbol] = this.safeDict(this.ohlcvs, symbol, {});
656
+ if (!(timeframe in this.ohlcvs[symbol])) {
657
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
658
+ this.ohlcvs[symbol][timeframe] = new ArrayCacheByTimestamp(limit);
659
+ }
660
+ const stored = this.ohlcvs[symbol][timeframe];
661
+ stored.append(parsed);
662
+ client.resolve(stored, messageHash);
663
+ }
573
664
  async watchOrderBook(symbol, limit = undefined, params = {}) {
574
665
  /**
575
666
  * @method
@@ -986,6 +1077,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
986
1077
  const methods = {
987
1078
  'level2': this.handleOrderBook,
988
1079
  'ticker': this.handleTicker,
1080
+ 'candle.stick': this.handleOHLCV,
989
1081
  'tickerV2': this.handleBidAsk,
990
1082
  'availableBalance.change': this.handleBalance,
991
1083
  'match': this.handleTrade,
@@ -20,11 +20,12 @@ export default class woo extends wooRest {
20
20
  checkRequiredUid(error?: boolean): boolean;
21
21
  authenticate(params?: {}): Promise<any>;
22
22
  watchPrivate(messageHash: any, message: any, params?: {}): Promise<any>;
23
+ watchPrivateMultiple(messageHashes: any, message: any, params?: {}): Promise<any>;
23
24
  watchOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
24
25
  watchMyTrades(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
25
26
  parseWsOrder(order: any, market?: any): Order;
26
27
  handleOrderUpdate(client: Client, message: any): void;
27
- handleOrder(client: Client, message: any): void;
28
+ handleOrder(client: Client, message: any, topic: any): void;
28
29
  handleMyTrade(client: Client, message: any): void;
29
30
  watchPositions(symbols?: Strings, since?: Int, limit?: Int, params?: {}): Promise<Position[]>;
30
31
  setPositionsCache(client: Client, type: any, symbols?: Strings): void;
package/js/src/pro/woo.js CHANGED
@@ -550,6 +550,16 @@ export default class woo extends wooRest {
550
550
  const request = this.extend(subscribe, message);
551
551
  return await this.watch(url, messageHash, request, messageHash, subscribe);
552
552
  }
553
+ async watchPrivateMultiple(messageHashes, message, params = {}) {
554
+ await this.authenticate(params);
555
+ const url = this.urls['api']['ws']['private'] + '/' + this.uid;
556
+ const requestId = this.requestId(url);
557
+ const subscribe = {
558
+ 'id': requestId,
559
+ };
560
+ const request = this.extend(subscribe, message);
561
+ return await this.watchMultiple(url, messageHashes, request, messageHashes, subscribe);
562
+ }
553
563
  async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
554
564
  /**
555
565
  * @method
@@ -561,10 +571,13 @@ export default class woo extends wooRest {
561
571
  * @param {int} [since] the earliest time in ms to fetch orders for
562
572
  * @param {int} [limit] the maximum number of order structures to retrieve
563
573
  * @param {object} [params] extra parameters specific to the exchange API endpoint
574
+ * @param {bool} [params.trigger] true if trigger order
564
575
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
565
576
  */
566
577
  await this.loadMarkets();
567
- const topic = 'executionreport';
578
+ const trigger = this.safeBool2(params, 'stop', 'trigger', false);
579
+ const topic = (trigger) ? 'algoexecutionreportv2' : 'executionreport';
580
+ params = this.omit(params, ['stop', 'trigger']);
568
581
  let messageHash = topic;
569
582
  if (symbol !== undefined) {
570
583
  const market = this.market(symbol);
@@ -587,15 +600,19 @@ export default class woo extends wooRest {
587
600
  * @method
588
601
  * @name woo#watchOrders
589
602
  * @see https://docs.woo.org/#executionreport
603
+ * @see https://docs.woo.org/#algoexecutionreportv2
590
604
  * @description watches information on multiple trades made by the user
591
605
  * @param {string} symbol unified market symbol of the market orders were made in
592
606
  * @param {int} [since] the earliest time in ms to fetch orders for
593
607
  * @param {int} [limit] the maximum number of order structures to retrieve
594
608
  * @param {object} [params] extra parameters specific to the exchange API endpoint
609
+ * @param {bool} [params.trigger] true if trigger order
595
610
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
596
611
  */
597
612
  await this.loadMarkets();
598
- const topic = 'executionreport';
613
+ const trigger = this.safeBool2(params, 'stop', 'trigger', false);
614
+ const topic = (trigger) ? 'algoexecutionreportv2' : 'executionreport';
615
+ params = this.omit(params, ['stop', 'trigger']);
599
616
  let messageHash = 'myTrades';
600
617
  if (symbol !== undefined) {
601
618
  const market = this.market(symbol);
@@ -721,15 +738,29 @@ export default class woo extends wooRest {
721
738
  // }
722
739
  // }
723
740
  //
724
- const order = this.safeDict(message, 'data');
725
- const tradeId = this.safeString(order, 'tradeId');
726
- if ((tradeId !== undefined) && (tradeId !== '0')) {
727
- this.handleMyTrade(client, order);
741
+ const topic = this.safeString(message, 'topic');
742
+ const data = this.safeValue(message, 'data');
743
+ if (Array.isArray(data)) {
744
+ // algoexecutionreportv2
745
+ for (let i = 0; i < data.length; i++) {
746
+ const order = data[i];
747
+ const tradeId = this.omitZero(this.safeString(data, 'tradeId'));
748
+ if (tradeId !== undefined) {
749
+ this.handleMyTrade(client, order);
750
+ }
751
+ this.handleOrder(client, order, topic);
752
+ }
753
+ }
754
+ else {
755
+ // executionreport
756
+ const tradeId = this.omitZero(this.safeString(data, 'tradeId'));
757
+ if (tradeId !== undefined) {
758
+ this.handleMyTrade(client, data);
759
+ }
760
+ this.handleOrder(client, data, topic);
728
761
  }
729
- this.handleOrder(client, order);
730
762
  }
731
- handleOrder(client, message) {
732
- const topic = 'executionreport';
763
+ handleOrder(client, message, topic) {
733
764
  const parsed = this.parseWsOrder(message);
734
765
  const symbol = this.safeString(parsed, 'symbol');
735
766
  const orderId = this.safeString(parsed, 'id');
@@ -814,12 +845,17 @@ export default class woo extends wooRest {
814
845
  * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
815
846
  */
816
847
  await this.loadMarkets();
817
- let messageHash = '';
848
+ const messageHashes = [];
818
849
  symbols = this.marketSymbols(symbols);
819
850
  if (!this.isEmpty(symbols)) {
820
- messageHash = '::' + symbols.join(',');
851
+ for (let i = 0; i < symbols.length; i++) {
852
+ const symbol = symbols[i];
853
+ messageHashes.push('positions::' + symbol);
854
+ }
855
+ }
856
+ else {
857
+ messageHashes.push('positions');
821
858
  }
822
- messageHash = 'positions' + messageHash;
823
859
  const url = this.urls['api']['ws']['private'] + '/' + this.uid;
824
860
  const client = this.client(url);
825
861
  this.setPositionsCache(client, symbols);
@@ -833,7 +869,7 @@ export default class woo extends wooRest {
833
869
  'event': 'subscribe',
834
870
  'topic': 'position',
835
871
  };
836
- const newPositions = await this.watchPrivate(messageHash, request, params);
872
+ const newPositions = await this.watchPrivateMultiple(messageHashes, request, params);
837
873
  if (this.newUpdates) {
838
874
  return newPositions;
839
875
  }
@@ -909,17 +945,8 @@ export default class woo extends wooRest {
909
945
  const position = this.parsePosition(rawPosition, market);
910
946
  newPositions.push(position);
911
947
  cache.append(position);
912
- }
913
- const messageHashes = this.findMessageHashes(client, 'positions::');
914
- for (let i = 0; i < messageHashes.length; i++) {
915
- const messageHash = messageHashes[i];
916
- const parts = messageHash.split('::');
917
- const symbolsString = parts[1];
918
- const symbols = symbolsString.split(',');
919
- const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
920
- if (!this.isEmpty(positions)) {
921
- client.resolve(positions, messageHash);
922
- }
948
+ const messageHash = 'positions::' + market['symbol'];
949
+ client.resolve(position, messageHash);
923
950
  }
924
951
  client.resolve(newPositions, 'positions');
925
952
  }
@@ -1040,6 +1067,7 @@ export default class woo extends wooRest {
1040
1067
  'kline': this.handleOHLCV,
1041
1068
  'auth': this.handleAuth,
1042
1069
  'executionreport': this.handleOrderUpdate,
1070
+ 'algoexecutionreportv2': this.handleOrderUpdate,
1043
1071
  'trade': this.handleTrade,
1044
1072
  'balance': this.handleBalance,
1045
1073
  'position': this.handlePositions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccxt",
3
- "version": "4.3.19",
3
+ "version": "4.3.21",
4
4
  "description": "A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges",
5
5
  "unpkg": "dist/ccxt.browser.js",
6
6
  "type": "module",