ccxt 4.2.92 → 4.2.94

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 (52) hide show
  1. package/README.md +3 -3
  2. package/build.sh +1 -1
  3. package/dist/ccxt.browser.js +807 -175
  4. package/dist/ccxt.browser.min.js +3 -3
  5. package/dist/cjs/ccxt.js +1 -1
  6. package/dist/cjs/src/base/Exchange.js +50 -9
  7. package/dist/cjs/src/base/functions/encode.js +4 -4
  8. package/dist/cjs/src/binance.js +63 -2
  9. package/dist/cjs/src/bitget.js +139 -0
  10. package/dist/cjs/src/coinex.js +0 -30
  11. package/dist/cjs/src/digifinex.js +1 -22
  12. package/dist/cjs/src/okx.js +153 -0
  13. package/dist/cjs/src/pro/kraken.js +107 -17
  14. package/dist/cjs/src/pro/krakenfutures.js +117 -40
  15. package/dist/cjs/src/pro/kucoin.js +30 -19
  16. package/dist/cjs/src/probit.js +3 -4
  17. package/dist/cjs/src/woo.js +139 -0
  18. package/examples/js/cli.js +4 -1
  19. package/examples/ts/cli.ts +4 -1
  20. package/js/ccxt.d.ts +3 -3
  21. package/js/ccxt.js +1 -1
  22. package/js/src/abstract/binance.d.ts +1 -0
  23. package/js/src/abstract/binancecoinm.d.ts +1 -0
  24. package/js/src/abstract/binanceus.d.ts +1 -0
  25. package/js/src/abstract/binanceusdm.d.ts +1 -0
  26. package/js/src/base/Exchange.d.ts +16 -10
  27. package/js/src/base/Exchange.js +50 -9
  28. package/js/src/base/functions/encode.d.ts +1 -1
  29. package/js/src/base/functions/encode.js +4 -4
  30. package/js/src/base/functions/rsa.d.ts +1 -1
  31. package/js/src/base/types.d.ts +12 -0
  32. package/js/src/binance.d.ts +1 -0
  33. package/js/src/binance.js +63 -2
  34. package/js/src/bitget.d.ts +4 -1
  35. package/js/src/bitget.js +139 -0
  36. package/js/src/coinex.d.ts +0 -1
  37. package/js/src/coinex.js +0 -30
  38. package/js/src/digifinex.d.ts +0 -1
  39. package/js/src/digifinex.js +1 -49
  40. package/js/src/okx.d.ts +4 -1
  41. package/js/src/okx.js +153 -0
  42. package/js/src/pro/kraken.d.ts +6 -1
  43. package/js/src/pro/kraken.js +107 -17
  44. package/js/src/pro/krakenfutures.d.ts +8 -2
  45. package/js/src/pro/krakenfutures.js +117 -40
  46. package/js/src/pro/kucoin.js +30 -19
  47. package/js/src/probit.d.ts +1 -1
  48. package/js/src/probit.js +3 -4
  49. package/js/src/woo.d.ts +4 -1
  50. package/js/src/woo.js +139 -0
  51. package/package.json +1 -1
  52. package/skip-tests.json +4 -0
@@ -19,10 +19,12 @@ export default class kraken extends krakenRest {
19
19
  'watchMyTrades': true,
20
20
  'watchOHLCV': true,
21
21
  'watchOrderBook': true,
22
+ 'watchOrderBookForSymbols': true,
22
23
  'watchOrders': true,
23
24
  'watchTicker': true,
24
- 'watchTickers': false,
25
+ 'watchTickers': true,
25
26
  'watchTrades': true,
27
+ 'watchTradesForSymbols': true,
26
28
  'createOrderWs': true,
27
29
  'editOrderWs': true,
28
30
  'cancelOrderWs': true,
@@ -313,10 +315,9 @@ export default class kraken extends krakenRest {
313
315
  // ]
314
316
  //
315
317
  const wsName = message[3];
316
- const name = 'ticker';
317
- const messageHash = name + ':' + wsName;
318
318
  const market = this.safeValue(this.options['marketsByWsName'], wsName);
319
319
  const symbol = market['symbol'];
320
+ const messageHash = this.getMessageHash('ticker', undefined, symbol);
320
321
  const ticker = message[1];
321
322
  const vwap = this.safeString(ticker['p'], 0);
322
323
  let quoteVolume = undefined;
@@ -347,9 +348,6 @@ export default class kraken extends krakenRest {
347
348
  'quoteVolume': quoteVolume,
348
349
  'info': ticker,
349
350
  });
350
- // todo add support for multiple tickers (may be tricky)
351
- // kraken confirms multi-pair subscriptions separately one by one
352
- // trigger correct watchTickers calls upon receiving any of symbols
353
351
  this.tickers[symbol] = result;
354
352
  client.resolve(result, messageHash);
355
353
  }
@@ -367,9 +365,9 @@ export default class kraken extends krakenRest {
367
365
  //
368
366
  const wsName = this.safeString(message, 3);
369
367
  const name = this.safeString(message, 2);
370
- const messageHash = name + ':' + wsName;
371
368
  const market = this.safeValue(this.options['marketsByWsName'], wsName);
372
369
  const symbol = market['symbol'];
370
+ const messageHash = this.getMessageHash(name, undefined, symbol);
373
371
  let stored = this.safeValue(this.trades, symbol);
374
372
  if (stored === undefined) {
375
373
  const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
@@ -470,25 +468,61 @@ export default class kraken extends krakenRest {
470
468
  * @param {object} [params] extra parameters specific to the exchange API endpoint
471
469
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
472
470
  */
473
- return await this.watchPublic('ticker', symbol, params);
471
+ await this.loadMarkets();
472
+ symbol = this.symbol(symbol);
473
+ const tickers = await this.watchTickers([symbol], params);
474
+ return tickers[symbol];
475
+ }
476
+ async watchTickers(symbols = undefined, params = {}) {
477
+ /**
478
+ * @method
479
+ * @name kraken#watchTickers
480
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
481
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
482
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
483
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
484
+ */
485
+ await this.loadMarkets();
486
+ symbols = this.marketSymbols(symbols, undefined, false);
487
+ const ticker = await this.watchMultiHelper('ticker', 'ticker', symbols, undefined, params);
488
+ if (this.newUpdates) {
489
+ const result = {};
490
+ result[ticker['symbol']] = ticker;
491
+ return result;
492
+ }
493
+ return this.filterByArray(this.tickers, 'symbol', symbols);
474
494
  }
475
495
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
476
496
  /**
477
497
  * @method
478
498
  * @name kraken#watchTrades
479
499
  * @description get the list of most recent trades for a particular symbol
500
+ * @see https://docs.kraken.com/websockets/#message-trade
480
501
  * @param {string} symbol unified symbol of the market to fetch trades for
481
502
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
482
503
  * @param {int} [limit] the maximum amount of trades to fetch
483
504
  * @param {object} [params] extra parameters specific to the exchange API endpoint
484
505
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
485
506
  */
486
- await this.loadMarkets();
487
- symbol = this.symbol(symbol);
488
- const name = 'trade';
489
- const trades = await this.watchPublic(name, symbol, params);
507
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
508
+ }
509
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
510
+ /**
511
+ * @method
512
+ * @name kraken#watchTradesForSymbols
513
+ * @see https://docs.kraken.com/websockets/#message-trade
514
+ * @description get the list of most recent trades for a list of symbols
515
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
516
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
517
+ * @param {int} [limit] the maximum amount of trades to fetch
518
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
519
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
520
+ */
521
+ const trades = await this.watchMultiHelper('trade', 'trade', symbols, undefined, params);
490
522
  if (this.newUpdates) {
491
- limit = trades.getLimit(symbol, limit);
523
+ const first = this.safeList(trades, 0);
524
+ const tradeSymbol = this.safeString(first, 'symbol');
525
+ limit = trades.getLimit(tradeSymbol, limit);
492
526
  }
493
527
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
494
528
  }
@@ -497,15 +531,28 @@ export default class kraken extends krakenRest {
497
531
  * @method
498
532
  * @name kraken#watchOrderBook
499
533
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
534
+ * @see https://docs.kraken.com/websockets/#message-book
500
535
  * @param {string} symbol unified symbol of the market to fetch the order book for
501
536
  * @param {int} [limit] the maximum amount of order book entries to return
502
537
  * @param {object} [params] extra parameters specific to the exchange API endpoint
503
538
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
504
539
  */
505
- const name = 'book';
540
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
541
+ }
542
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
543
+ /**
544
+ * @method
545
+ * @name kraken#watchOrderBookForSymbols
546
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
547
+ * @see https://docs.kraken.com/websockets/#message-book
548
+ * @param {string[]} symbols unified array of symbols
549
+ * @param {int} [limit] the maximum amount of order book entries to return
550
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
551
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
552
+ */
506
553
  const request = {};
507
554
  if (limit !== undefined) {
508
- if ((limit === 10) || (limit === 25) || (limit === 100) || (limit === 500) || (limit === 1000)) {
555
+ if (this.inArray(limit, [10, 25, 100, 500, 1000])) {
509
556
  request['subscription'] = {
510
557
  'depth': limit, // default 10, valid options 10, 25, 100, 500, 1000
511
558
  };
@@ -514,7 +561,7 @@ export default class kraken extends krakenRest {
514
561
  throw new NotSupported(this.id + ' watchOrderBook accepts limit values of 10, 25, 100, 500 and 1000 only');
515
562
  }
516
563
  }
517
- const orderbook = await this.watchPublic(name, symbol, this.extend(request, params));
564
+ const orderbook = await this.watchMultiHelper('orderbook', 'book', symbols, { 'limit': limit }, this.extend(request, params));
518
565
  return orderbook.limit();
519
566
  }
520
567
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
@@ -643,7 +690,7 @@ export default class kraken extends krakenRest {
643
690
  const market = this.safeValue(this.options['marketsByWsName'], wsName);
644
691
  const symbol = market['symbol'];
645
692
  let timestamp = undefined;
646
- const messageHash = 'book:' + wsName;
693
+ const messageHash = this.getMessageHash('orderbook', undefined, symbol);
647
694
  // if this is a snapshot
648
695
  if ('as' in message[1]) {
649
696
  // todo get depth from marketsByWsName
@@ -724,6 +771,7 @@ export default class kraken extends krakenRest {
724
771
  if (localChecksum !== c) {
725
772
  const error = new InvalidNonce(this.id + ' invalid checksum');
726
773
  client.reject(error, messageHash);
774
+ return;
727
775
  }
728
776
  }
729
777
  orderbook['symbol'] = symbol;
@@ -1251,6 +1299,48 @@ export default class kraken extends krakenRest {
1251
1299
  'trades': trades,
1252
1300
  });
1253
1301
  }
1302
+ async watchMultiHelper(unifiedName, channelName, symbols = undefined, subscriptionArgs = undefined, params = {}) {
1303
+ await this.loadMarkets();
1304
+ // symbols are required
1305
+ symbols = this.marketSymbols(symbols, undefined, false, true, false);
1306
+ const messageHashes = [];
1307
+ for (let i = 0; i < symbols.length; i++) {
1308
+ messageHashes.push(this.getMessageHash(unifiedName, undefined, this.symbol(symbols[i])));
1309
+ }
1310
+ // for WS subscriptions, we can't use .marketIds (symbols), instead a custom is field needed
1311
+ const markets = this.marketsForSymbols(symbols);
1312
+ const wsMarketIds = [];
1313
+ for (let i = 0; i < markets.length; i++) {
1314
+ const wsMarketId = this.safeString(markets[i]['info'], 'wsname');
1315
+ wsMarketIds.push(wsMarketId);
1316
+ }
1317
+ const request = {
1318
+ 'event': 'subscribe',
1319
+ 'reqid': this.requestId(),
1320
+ 'pair': wsMarketIds,
1321
+ 'subscription': {
1322
+ 'name': channelName,
1323
+ },
1324
+ };
1325
+ const url = this.urls['api']['ws']['public'];
1326
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscriptionArgs);
1327
+ }
1328
+ getMessageHash(unifiedElementName, subChannelName = undefined, symbol = undefined) {
1329
+ // unifiedElementName can be : orderbook, trade, ticker, bidask ...
1330
+ // subChannelName only applies to channel that needs specific variation (i.e. depth_50, depth_100..) to be selected
1331
+ const withSymbol = symbol !== undefined;
1332
+ let messageHash = unifiedElementName;
1333
+ if (!withSymbol) {
1334
+ messageHash += 's';
1335
+ }
1336
+ else {
1337
+ messageHash += '@' + symbol;
1338
+ }
1339
+ if (subChannelName !== undefined) {
1340
+ messageHash += '#' + subChannelName;
1341
+ }
1342
+ return messageHash;
1343
+ }
1254
1344
  handleSubscriptionStatus(client, message) {
1255
1345
  //
1256
1346
  // public
@@ -4,11 +4,14 @@ import Client from '../base/ws/Client.js';
4
4
  export default class krakenfutures extends krakenfuturesRest {
5
5
  describe(): any;
6
6
  authenticate(params?: {}): Promise<any>;
7
+ watchOrderBookForSymbols(symbols: string[], limit?: Int, params?: {}): Promise<OrderBook>;
7
8
  subscribePublic(name: string, symbols: string[], params?: {}): Promise<any>;
8
9
  subscribePrivate(name: string, messageHash: string, params?: {}): Promise<any>;
9
10
  watchTicker(symbol: string, params?: {}): Promise<Ticker>;
10
11
  watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
12
+ watchBidsAsks(symbols?: Strings, params?: {}): Promise<Tickers>;
11
13
  watchTrades(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
14
+ watchTradesForSymbols(symbols: string[], since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
12
15
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
13
16
  watchPositions(symbols?: Strings, since?: Int, limit?: Int, params?: {}): Promise<Position[]>;
14
17
  handlePositions(client: any, message: any): void;
@@ -16,19 +19,22 @@ export default class krakenfutures extends krakenfuturesRest {
16
19
  watchOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
17
20
  watchMyTrades(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
18
21
  watchBalance(params?: {}): Promise<Balances>;
19
- handleTrade(client: Client, message: any): any;
22
+ handleTrade(client: Client, message: any): void;
20
23
  parseWsTrade(trade: any, market?: any): Trade;
21
24
  parseWsOrderTrade(trade: any, market?: any): Trade;
22
25
  handleOrder(client: Client, message: any): any;
23
26
  handleOrderSnapshot(client: Client, message: any): void;
24
27
  parseWsOrder(order: any, market?: any): Order;
25
- handleTicker(client: Client, message: any): any;
28
+ handleTicker(client: Client, message: any): void;
29
+ handleBidAsk(client: Client, message: any): void;
26
30
  parseWsTicker(ticker: any, market?: any): Ticker;
27
31
  handleOrderBookSnapshot(client: Client, message: any): void;
28
32
  handleOrderBook(client: Client, message: any): void;
29
33
  handleBalance(client: Client, message: any): void;
30
34
  handleMyTrades(client: Client, message: any): void;
31
35
  parseWsMyTrade(trade: any, market?: any): Trade;
36
+ watchMultiHelper(unifiedName: string, channelName: string, symbols?: Strings, subscriptionArgs?: any, params?: {}): Promise<any>;
37
+ getMessageHash(unifiedElementName: string, subChannelName?: Str, symbol?: Str): string;
32
38
  handleErrorMessage(client: Client, message: any): void;
33
39
  handleMessage(client: any, message: any): void;
34
40
  handleAuthenticate(client: Client, message: any): any;
@@ -28,9 +28,12 @@ export default class krakenfutures extends krakenfuturesRest {
28
28
  'fetchTradesWs': false,
29
29
  'watchOHLCV': false,
30
30
  'watchOrderBook': true,
31
+ 'watchOrderBookForSymbols': true,
31
32
  'watchTicker': true,
32
33
  'watchTickers': true,
34
+ 'watchBidsAsks': true,
33
35
  'watchTrades': true,
36
+ 'watchTradesForSymbols': true,
34
37
  'watchBalance': true,
35
38
  // 'watchStatus': true, // https://docs.futures.kraken.com/#websocket-api-public-feeds-heartbeat
36
39
  'watchOrders': true,
@@ -51,12 +54,6 @@ export default class krakenfutures extends krakenfuturesRest {
51
54
  'OHLCVLimit': 1000,
52
55
  'connectionLimit': 100,
53
56
  'requestLimit': 100,
54
- 'watchTicker': {
55
- 'method': 'ticker', // or ticker_lite
56
- },
57
- 'watchTickers': {
58
- 'method': 'ticker', // or ticker_lite
59
- },
60
57
  'fetchBalance': {
61
58
  'type': undefined,
62
59
  },
@@ -94,6 +91,20 @@ export default class krakenfutures extends krakenfuturesRest {
94
91
  }
95
92
  return future;
96
93
  }
94
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
95
+ /**
96
+ * @method
97
+ * @name krakenfutures#watchOrderBookForSymbols
98
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
99
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-challenge
100
+ * @param {string[]} symbols unified array of symbols
101
+ * @param {int} [limit] the maximum amount of order book entries to return
102
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
103
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
104
+ */
105
+ const orderbook = await this.watchMultiHelper('orderbook', 'book', symbols, { 'limit': limit }, params);
106
+ return orderbook.limit();
107
+ }
97
108
  async subscribePublic(name, symbols, params = {}) {
98
109
  /**
99
110
  * @ignore
@@ -161,34 +172,49 @@ export default class krakenfutures extends krakenfuturesRest {
161
172
  * @param {object} [params] extra parameters specific to the exchange API endpoint
162
173
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
163
174
  */
164
- const options = this.safeValue(this.options, 'watchTicker');
165
- const method = this.safeString(options, 'method', 'ticker'); // or ticker_lite
166
- const name = this.safeString(params, 'method', method);
167
- params = this.omit(params, ['method']);
168
- return await this.subscribePublic(name, [symbol], params);
175
+ await this.loadMarkets();
176
+ symbol = this.symbol(symbol);
177
+ const tickers = await this.watchTickers([symbol], params);
178
+ return tickers[symbol];
169
179
  }
170
180
  async watchTickers(symbols = undefined, params = {}) {
171
181
  /**
172
182
  * @method
173
- * @name krakenfutures#watchTicker
183
+ * @name krakenfutures#watchTickers
174
184
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
175
- * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-ticker-lite
185
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-ticker
176
186
  * @param {string} symbol unified symbol of the market to fetch the ticker for
177
187
  * @param {object} [params] extra parameters specific to the exchange API endpoint
178
188
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
179
189
  */
180
- const method = this.safeString(this.options, 'watchTickerMethod', 'ticker'); // or ticker_lite
181
- const name = this.safeString2(params, 'method', 'watchTickerMethod', method);
182
- params = this.omit(params, ['watchTickerMethod', 'method']);
190
+ await this.loadMarkets();
183
191
  symbols = this.marketSymbols(symbols, undefined, false);
184
- const ticker = await this.subscribePublic(name, symbols, params);
192
+ const ticker = await this.watchMultiHelper('ticker', 'ticker', symbols, undefined, params);
185
193
  if (this.newUpdates) {
186
- const tickers = {};
187
- tickers[ticker['symbol']] = ticker;
188
- return tickers;
194
+ const result = {};
195
+ result[ticker['symbol']] = ticker;
196
+ return result;
189
197
  }
190
198
  return this.filterByArray(this.tickers, 'symbol', symbols);
191
199
  }
200
+ async watchBidsAsks(symbols = undefined, params = {}) {
201
+ /**
202
+ * @method
203
+ * @name krakenfutures#watchBidsAsks
204
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-ticker-lite
205
+ * @description watches best bid & ask for symbols
206
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
207
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
208
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
209
+ */
210
+ const ticker = await this.watchMultiHelper('bidask', 'ticker_lite', symbols, undefined, params);
211
+ if (this.newUpdates) {
212
+ const result = {};
213
+ result[ticker['symbol']] = ticker;
214
+ return result;
215
+ }
216
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
217
+ }
192
218
  async watchTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
193
219
  /**
194
220
  * @method
@@ -201,11 +227,25 @@ export default class krakenfutures extends krakenfuturesRest {
201
227
  * @param {object} [params] extra parameters specific to the exchange API endpoint
202
228
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
203
229
  */
204
- await this.loadMarkets();
205
- const name = 'trade';
206
- const trades = await this.subscribePublic(name, [symbol], params);
230
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
231
+ }
232
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
233
+ /**
234
+ * @method
235
+ * @name krakenfutures#watchTradesForSymbols
236
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-trade
237
+ * @description get the list of most recent trades for a list of symbols
238
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
239
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
240
+ * @param {int} [limit] the maximum amount of trades to fetch
241
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
242
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
243
+ */
244
+ const trades = await this.watchMultiHelper('trade', 'trade', symbols, undefined, params);
207
245
  if (this.newUpdates) {
208
- limit = trades.getLimit(symbol, limit);
246
+ const first = this.safeList(trades, 0);
247
+ const tradeSymbol = this.safeString(first, 'symbol');
248
+ limit = trades.getLimit(tradeSymbol, limit);
209
249
  }
210
250
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
211
251
  }
@@ -220,8 +260,7 @@ export default class krakenfutures extends krakenfuturesRest {
220
260
  * @param {object} [params] extra parameters specific to the exchange API endpoint
221
261
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
222
262
  */
223
- const orderbook = await this.subscribePublic('book', [symbol], params);
224
- return orderbook.limit();
263
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
225
264
  }
226
265
  async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
227
266
  /**
@@ -469,7 +508,7 @@ export default class krakenfutures extends krakenfuturesRest {
469
508
  if (marketId !== undefined) {
470
509
  const market = this.market(marketId);
471
510
  const symbol = market['symbol'];
472
- const messageHash = 'trade:' + symbol;
511
+ const messageHash = this.getMessageHash('trade', undefined, symbol);
473
512
  if (this.safeList(this.trades, symbol) === undefined) {
474
513
  const tradesLimit = this.safeInteger(this.options, 'tradesLimit', 1000);
475
514
  this.trades[symbol] = new ArrayCache(tradesLimit);
@@ -491,7 +530,6 @@ export default class krakenfutures extends krakenfuturesRest {
491
530
  }
492
531
  client.resolve(tradesArray, messageHash);
493
532
  }
494
- return message;
495
533
  }
496
534
  parseWsTrade(trade, market = undefined) {
497
535
  //
@@ -917,7 +955,16 @@ export default class krakenfutures extends krakenfuturesRest {
917
955
  // "volumeQuote": 19628180
918
956
  // }
919
957
  //
920
- // ticker_lite
958
+ const marketId = this.safeString(message, 'product_id');
959
+ if (marketId !== undefined) {
960
+ const ticker = this.parseWsTicker(message);
961
+ const symbol = ticker['symbol'];
962
+ this.tickers[symbol] = ticker;
963
+ const messageHash = this.getMessageHash('ticker', undefined, symbol);
964
+ client.resolve(ticker, messageHash);
965
+ }
966
+ }
967
+ handleBidAsk(client, message) {
921
968
  //
922
969
  // {
923
970
  // "feed": "ticker_lite",
@@ -935,16 +982,13 @@ export default class krakenfutures extends krakenfuturesRest {
935
982
  // }
936
983
  //
937
984
  const marketId = this.safeString(message, 'product_id');
938
- const feed = this.safeString(message, 'feed');
939
985
  if (marketId !== undefined) {
940
986
  const ticker = this.parseWsTicker(message);
941
987
  const symbol = ticker['symbol'];
942
- this.tickers[symbol] = ticker;
943
- const messageHash = feed + ':' + symbol;
988
+ this.bidsasks[symbol] = ticker;
989
+ const messageHash = this.getMessageHash('bidask', undefined, symbol);
944
990
  client.resolve(ticker, messageHash);
945
991
  }
946
- client.resolve(this.tickers, feed);
947
- return message;
948
992
  }
949
993
  parseWsTicker(ticker, market = undefined) {
950
994
  //
@@ -1056,14 +1100,14 @@ export default class krakenfutures extends krakenfuturesRest {
1056
1100
  const marketId = this.safeString(message, 'product_id');
1057
1101
  const market = this.safeMarket(marketId);
1058
1102
  const symbol = market['symbol'];
1059
- const messageHash = 'book:' + symbol;
1060
- const subscription = this.safeValue(client.subscriptions, messageHash, {});
1103
+ const messageHash = this.getMessageHash('orderbook', undefined, symbol);
1104
+ const subscription = this.safeDict(client.subscriptions, messageHash, {});
1061
1105
  const limit = this.safeInteger(subscription, 'limit');
1062
1106
  const timestamp = this.safeInteger(message, 'timestamp');
1063
1107
  this.orderbooks[symbol] = this.orderBook({}, limit);
1064
1108
  const orderbook = this.orderbooks[symbol];
1065
- const bids = this.safeValue(message, 'bids');
1066
- const asks = this.safeValue(message, 'asks');
1109
+ const bids = this.safeList(message, 'bids');
1110
+ const asks = this.safeList(message, 'asks');
1067
1111
  for (let i = 0; i < bids.length; i++) {
1068
1112
  const bid = bids[i];
1069
1113
  const price = this.safeNumber(bid, 'price');
@@ -1098,7 +1142,7 @@ export default class krakenfutures extends krakenfuturesRest {
1098
1142
  const marketId = this.safeString(message, 'product_id');
1099
1143
  const market = this.safeMarket(marketId);
1100
1144
  const symbol = market['symbol'];
1101
- const messageHash = 'book:' + symbol;
1145
+ const messageHash = this.getMessageHash('orderbook', undefined, symbol);
1102
1146
  const orderbook = this.orderbooks[symbol];
1103
1147
  const side = this.safeString(message, 'side');
1104
1148
  const price = this.safeNumber(message, 'price');
@@ -1425,6 +1469,39 @@ export default class krakenfutures extends krakenfuturesRest {
1425
1469
  },
1426
1470
  });
1427
1471
  }
1472
+ async watchMultiHelper(unifiedName, channelName, symbols = undefined, subscriptionArgs = undefined, params = {}) {
1473
+ await this.loadMarkets();
1474
+ // symbols are required
1475
+ symbols = this.marketSymbols(symbols, undefined, false, true, false);
1476
+ const messageHashes = [];
1477
+ for (let i = 0; i < symbols.length; i++) {
1478
+ messageHashes.push(this.getMessageHash(unifiedName, undefined, this.symbol(symbols[i])));
1479
+ }
1480
+ const marketIds = this.marketIds(symbols);
1481
+ const request = {
1482
+ 'event': 'subscribe',
1483
+ 'feed': channelName,
1484
+ 'product_ids': marketIds,
1485
+ };
1486
+ const url = this.urls['api']['ws'];
1487
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscriptionArgs);
1488
+ }
1489
+ getMessageHash(unifiedElementName, subChannelName = undefined, symbol = undefined) {
1490
+ // unifiedElementName can be : orderbook, trade, ticker, bidask ...
1491
+ // subChannelName only applies to channel that needs specific variation (i.e. depth_50, depth_100..) to be selected
1492
+ const withSymbol = symbol !== undefined;
1493
+ let messageHash = unifiedElementName;
1494
+ if (!withSymbol) {
1495
+ messageHash += 's';
1496
+ }
1497
+ else {
1498
+ messageHash += ':' + symbol;
1499
+ }
1500
+ if (subChannelName !== undefined) {
1501
+ messageHash += '#' + subChannelName;
1502
+ }
1503
+ return messageHash;
1504
+ }
1428
1505
  handleErrorMessage(client, message) {
1429
1506
  //
1430
1507
  // {
@@ -1455,10 +1532,10 @@ export default class krakenfutures extends krakenfuturesRest {
1455
1532
  const feed = this.safeString(message, 'feed');
1456
1533
  const methods = {
1457
1534
  'ticker': this.handleTicker,
1535
+ 'ticker_lite': this.handleBidAsk,
1458
1536
  'trade': this.handleTrade,
1459
1537
  'trade_snapshot': this.handleTrade,
1460
1538
  // 'heartbeat': this.handleStatus,
1461
- 'ticker_lite': this.handleTicker,
1462
1539
  'book': this.handleOrderBook,
1463
1540
  'book_snapshot': this.handleOrderBookSnapshot,
1464
1541
  'open_orders_verbose': this.handleOrder,
@@ -176,22 +176,46 @@ export default class kucoin extends kucoinRest {
176
176
  /**
177
177
  * @method
178
178
  * @name kucoin#watchTickers
179
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/ticker
179
180
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
180
181
  * @param {string[]} symbols unified symbol of the market to fetch the ticker for
181
182
  * @param {object} [params] extra parameters specific to the exchange API endpoint
183
+ * @param {string} [params.method] either '/market/snapshot' or '/market/ticker' default is '/market/ticker'
182
184
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
183
185
  */
184
186
  await this.loadMarkets();
185
187
  symbols = this.marketSymbols(symbols);
186
- let messageHash = 'tickers';
188
+ const messageHash = 'tickers';
189
+ let method = undefined;
190
+ [method, params] = this.handleOptionAndParams(params, 'watchTickers', 'method', '/market/ticker');
191
+ const messageHashes = [];
192
+ const topics = [];
187
193
  if (symbols !== undefined) {
188
- messageHash = 'tickers::' + symbols.join(',');
194
+ for (let i = 0; i < symbols.length; i++) {
195
+ const symbol = symbols[i];
196
+ messageHashes.push('ticker:' + symbol);
197
+ const market = this.market(symbol);
198
+ topics.push(method + ':' + market['id']);
199
+ }
189
200
  }
190
201
  const url = await this.negotiate(false);
191
- const topic = '/market/ticker:all';
192
- const tickers = await this.subscribe(url, messageHash, topic, params);
193
- if (this.newUpdates) {
194
- return tickers;
202
+ let tickers = undefined;
203
+ if (symbols === undefined) {
204
+ const allTopic = method + ':all';
205
+ tickers = await this.subscribe(url, messageHash, allTopic, params);
206
+ if (this.newUpdates) {
207
+ return tickers;
208
+ }
209
+ }
210
+ else {
211
+ const marketIds = this.marketIds(symbols);
212
+ const symbolsTopic = method + ':' + marketIds.join(',');
213
+ tickers = await this.subscribeMultiple(url, messageHashes, symbolsTopic, topics, params);
214
+ if (this.newUpdates) {
215
+ const newDict = {};
216
+ newDict[tickers['symbol']] = tickers;
217
+ return newDict;
218
+ }
195
219
  }
196
220
  return this.filterByArray(this.tickers, 'symbol', symbols);
197
221
  }
@@ -275,19 +299,6 @@ export default class kucoin extends kucoinRest {
275
299
  const allTickers = {};
276
300
  allTickers[symbol] = ticker;
277
301
  client.resolve(allTickers, 'tickers');
278
- const messageHashes = this.findMessageHashes(client, 'tickers::');
279
- for (let i = 0; i < messageHashes.length; i++) {
280
- const currentMessageHash = messageHashes[i];
281
- const parts = currentMessageHash.split('::');
282
- const symbolsString = parts[1];
283
- const symbols = symbolsString.split(',');
284
- const tickers = this.filterByArray(this.tickers, 'symbol', symbols);
285
- const tickersSymbols = Object.keys(tickers);
286
- const numTickers = tickersSymbols.length;
287
- if (numTickers > 0) {
288
- client.resolve(tickers, currentMessageHash);
289
- }
290
- }
291
302
  }
292
303
  async watchBidsAsks(symbols = undefined, params = {}) {
293
304
  /**
@@ -48,7 +48,7 @@ export default class probit extends Exchange {
48
48
  withdraw(code: string, amount: number, address: any, tag?: any, params?: {}): Promise<Transaction>;
49
49
  fetchDeposits(code?: Str, since?: Int, limit?: Int, params?: {}): Promise<Transaction[]>;
50
50
  fetchWithdrawals(code?: Str, since?: Int, limit?: Int, params?: {}): Promise<Transaction[]>;
51
- fetchTransactions(code?: Str, since?: Int, limit?: Int, params?: {}): Promise<Transaction[]>;
51
+ fetchDepositsWithdrawals(code?: Str, since?: Int, limit?: Int, params?: {}): Promise<Transaction[]>;
52
52
  parseTransaction(transaction: any, currency?: Currency): Transaction;
53
53
  parseTransactionStatus(status: any): string;
54
54
  fetchDepositWithdrawFees(codes?: Strings, params?: {}): Promise<any>;
package/js/src/probit.js CHANGED
@@ -1490,12 +1490,11 @@ export default class probit extends Exchange {
1490
1490
  const result = await this.fetchTransactions(code, since, limit, this.extend(request, params));
1491
1491
  return result;
1492
1492
  }
1493
- async fetchTransactions(code = undefined, since = undefined, limit = undefined, params = {}) {
1493
+ async fetchDepositsWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
1494
1494
  /**
1495
1495
  * @method
1496
- * @name probit#fetchTransactions
1497
- * @deprecated
1498
- * @description use fetchDepositsWithdrawals instead
1496
+ * @name probit#fetchDepositsWithdrawals
1497
+ * @description fetch history of deposits and withdrawals
1499
1498
  * @see https://docs-en.probit.com/reference/transferpayment
1500
1499
  * @param {string} code unified currency code
1501
1500
  * @param {int} [since] the earliest time in ms to fetch transactions for