ccxt 4.3.20 → 4.3.22

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 (46) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/ccxt.js +1 -1
  3. package/dist/cjs/src/base/functions/platform.js +3 -1
  4. package/dist/cjs/src/base/functions.js +1 -0
  5. package/dist/cjs/src/binance.js +10 -1
  6. package/dist/cjs/src/bitmex.js +1 -0
  7. package/dist/cjs/src/coinex.js +142 -179
  8. package/dist/cjs/src/hyperliquid.js +24 -2
  9. package/dist/cjs/src/okx.js +3 -0
  10. package/dist/cjs/src/phemex.js +39 -4
  11. package/dist/cjs/src/pro/kucoinfutures.js +92 -0
  12. package/dist/cjs/src/pro/woo.js +52 -24
  13. package/js/ccxt.d.ts +1 -1
  14. package/js/ccxt.js +1 -1
  15. package/js/src/abstract/binance.d.ts +1 -0
  16. package/js/src/abstract/binancecoinm.d.ts +1 -0
  17. package/js/src/abstract/binanceus.d.ts +1 -0
  18. package/js/src/abstract/binanceusdm.d.ts +1 -0
  19. package/js/src/abstract/okx.d.ts +3 -0
  20. package/js/src/ascendex.d.ts +1 -1
  21. package/js/src/base/Exchange.d.ts +1 -1
  22. package/js/src/base/functions/platform.d.ts +2 -1
  23. package/js/src/base/functions/platform.js +3 -2
  24. package/js/src/binance.d.ts +1 -1
  25. package/js/src/binance.js +10 -1
  26. package/js/src/bingx.d.ts +1 -1
  27. package/js/src/bitget.d.ts +1 -1
  28. package/js/src/bitmex.js +1 -0
  29. package/js/src/coinex.d.ts +1 -1
  30. package/js/src/coinex.js +142 -179
  31. package/js/src/delta.d.ts +1 -1
  32. package/js/src/digifinex.d.ts +1 -1
  33. package/js/src/exmo.d.ts +1 -1
  34. package/js/src/gate.d.ts +1 -1
  35. package/js/src/hitbtc.d.ts +1 -1
  36. package/js/src/hyperliquid.d.ts +1 -1
  37. package/js/src/hyperliquid.js +24 -2
  38. package/js/src/okx.d.ts +1 -1
  39. package/js/src/okx.js +3 -0
  40. package/js/src/phemex.d.ts +1 -1
  41. package/js/src/phemex.js +39 -4
  42. package/js/src/pro/kucoinfutures.d.ts +3 -1
  43. package/js/src/pro/kucoinfutures.js +93 -1
  44. package/js/src/pro/woo.d.ts +2 -1
  45. package/js/src/pro/woo.js +52 -24
  46. package/package.json +1 -1
package/js/src/phemex.js CHANGED
@@ -1707,6 +1707,26 @@ export default class phemex extends Exchange {
1707
1707
  // "execId": "8718cae",
1708
1708
  // "execStatus": 6
1709
1709
  // }
1710
+ // spot with fees paid using PT token
1711
+ // "createdAt": "1714990724076",
1712
+ // "symbol": "BTCUSDT",
1713
+ // "currency": "USDT",
1714
+ // "action": "1",
1715
+ // "tradeType": "1",
1716
+ // "execQtyRq": "0.003",
1717
+ // "execPriceRp": "64935",
1718
+ // "side": "2",
1719
+ // "orderQtyRq": "0.003",
1720
+ // "priceRp": "51600",
1721
+ // "execValueRv": "194.805",
1722
+ // "feeRateRr": "0.000495",
1723
+ // "execFeeRv": "0",
1724
+ // "ordType": "3",
1725
+ // "execId": "XXXXXX",
1726
+ // "execStatus": "7",
1727
+ // "posSide": "1",
1728
+ // "ptFeeRv": "0.110012249248",
1729
+ // "ptPriceRp": "0.876524893"
1710
1730
  //
1711
1731
  let priceString;
1712
1732
  let amountString;
@@ -1763,10 +1783,19 @@ export default class phemex extends Exchange {
1763
1783
  priceString = this.safeString(trade, 'execPriceRp');
1764
1784
  amountString = this.safeString(trade, 'execQtyRq');
1765
1785
  costString = this.safeString(trade, 'execValueRv');
1766
- feeCostString = this.safeString(trade, 'execFeeRv');
1786
+ feeCostString = this.omitZero(this.safeString(trade, 'execFeeRv'));
1767
1787
  feeRateString = this.safeString(trade, 'feeRateRr');
1768
- const currencyId = this.safeString(trade, 'currency');
1769
- feeCurrencyCode = this.safeCurrencyCode(currencyId);
1788
+ if (feeCostString !== undefined) {
1789
+ const currencyId = this.safeString(trade, 'currency');
1790
+ feeCurrencyCode = this.safeCurrencyCode(currencyId);
1791
+ }
1792
+ else {
1793
+ const ptFeeRv = this.omitZero(this.safeString(trade, 'ptFeeRv'));
1794
+ if (ptFeeRv !== undefined) {
1795
+ feeCostString = ptFeeRv;
1796
+ feeCurrencyCode = 'PT';
1797
+ }
1798
+ }
1770
1799
  }
1771
1800
  else {
1772
1801
  side = this.safeStringLower(trade, 'side');
@@ -1779,7 +1808,7 @@ export default class phemex extends Exchange {
1779
1808
  amountString = this.fromEv(this.safeString(trade, 'execBaseQtyEv'), market);
1780
1809
  amountString = this.safeString(trade, 'execQty', amountString);
1781
1810
  costString = this.fromEr(this.safeString2(trade, 'execQuoteQtyEv', 'execValueEv'), market);
1782
- feeCostString = this.fromEr(this.safeString(trade, 'execFeeEv'), market);
1811
+ feeCostString = this.fromEr(this.omitZero(this.safeString(trade, 'execFeeEv')), market);
1783
1812
  if (feeCostString !== undefined) {
1784
1813
  feeRateString = this.fromEr(this.safeString(trade, 'feeRateEr'), market);
1785
1814
  if (market['spot']) {
@@ -1793,6 +1822,12 @@ export default class phemex extends Exchange {
1793
1822
  }
1794
1823
  }
1795
1824
  }
1825
+ else {
1826
+ feeCostString = this.safeString(trade, 'ptFeeRv');
1827
+ if (feeCostString !== undefined) {
1828
+ feeCurrencyCode = 'PT';
1829
+ }
1830
+ }
1796
1831
  }
1797
1832
  fee = {
1798
1833
  'cost': feeCostString,
@@ -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.20",
3
+ "version": "4.3.22",
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",