ccxt 4.2.90 → 4.2.92

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.
@@ -546,8 +546,8 @@ export default class bitmex extends bitmexRest {
546
546
  for (let i = 0; i < marketIds.length; i++) {
547
547
  const marketId = marketIds[i];
548
548
  const market = this.safeMarket(marketId);
549
- const messageHash = table + ':' + marketId;
550
549
  const symbol = market['symbol'];
550
+ const messageHash = table + ':' + symbol;
551
551
  const trades = this.parseTrades(dataByMarketIds[marketId], market);
552
552
  let stored = this.safeValue(this.trades, symbol);
553
553
  if (stored === undefined) {
@@ -572,23 +572,7 @@ export default class bitmex extends bitmexRest {
572
572
  * @param {object} [params] extra parameters specific to the exchange API endpoint
573
573
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
574
574
  */
575
- await this.loadMarkets();
576
- const market = this.market(symbol);
577
- symbol = market['symbol'];
578
- const table = 'trade';
579
- const messageHash = table + ':' + market['id'];
580
- const url = this.urls['api']['ws'];
581
- const request = {
582
- 'op': 'subscribe',
583
- 'args': [
584
- messageHash,
585
- ],
586
- };
587
- const trades = await this.watch(url, messageHash, this.extend(request, params), messageHash);
588
- if (this.newUpdates) {
589
- limit = trades.getLimit(symbol, limit);
590
- }
591
- return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
575
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
592
576
  }
593
577
  async authenticate(params = {}) {
594
578
  const url = this.urls['api']['ws'];
@@ -1221,6 +1205,43 @@ export default class bitmex extends bitmexRest {
1221
1205
  const orderbook = await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), topics);
1222
1206
  return orderbook.limit();
1223
1207
  }
1208
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
1209
+ /**
1210
+ * @method
1211
+ * @name bitmex#watchTradesForSymbols
1212
+ * @description get the list of most recent trades for a list of symbols
1213
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
1214
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
1215
+ * @param {int} [limit] the maximum amount of trades to fetch
1216
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1217
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
1218
+ */
1219
+ await this.loadMarkets();
1220
+ symbols = this.marketSymbols(symbols, undefined, false);
1221
+ const table = 'trade';
1222
+ const topics = [];
1223
+ const messageHashes = [];
1224
+ for (let i = 0; i < symbols.length; i++) {
1225
+ const symbol = symbols[i];
1226
+ const market = this.market(symbol);
1227
+ const topic = table + ':' + market['id'];
1228
+ topics.push(topic);
1229
+ const messageHash = table + ':' + symbol;
1230
+ messageHashes.push(messageHash);
1231
+ }
1232
+ const url = this.urls['api']['ws'];
1233
+ const request = {
1234
+ 'op': 'subscribe',
1235
+ 'args': topics,
1236
+ };
1237
+ const trades = await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), topics);
1238
+ if (this.newUpdates) {
1239
+ const first = this.safeValue(trades, 0);
1240
+ const tradeSymbol = this.safeString(first, 'symbol');
1241
+ limit = trades.getLimit(tradeSymbol, limit);
1242
+ }
1243
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
1244
+ }
1224
1245
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1225
1246
  /**
1226
1247
  * @method
@@ -11,6 +11,10 @@ export default class kucoin extends kucoinRest {
11
11
  watchTicker(symbol: string, params?: {}): Promise<Ticker>;
12
12
  watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
13
13
  handleTicker(client: Client, message: any): void;
14
+ watchBidsAsks(symbols?: Strings, params?: {}): Promise<Tickers>;
15
+ watchMultiHelper(methodName: any, channelName: string, symbols?: Strings, params?: {}): Promise<any>;
16
+ handleBidAsk(client: Client, message: any): void;
17
+ parseWsBidAsk(ticker: any, market?: any): Ticker;
14
18
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
15
19
  handleOHLCV(client: Client, message: any): void;
16
20
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
@@ -21,6 +21,7 @@ export default class kucoin extends kucoinRest {
21
21
  'cancelOrderWs': false,
22
22
  'cancelOrdersWs': false,
23
23
  'cancelAllOrdersWs': false,
24
+ 'watchBidsAsks': true,
24
25
  'watchOrderBook': true,
25
26
  'watchOrders': true,
26
27
  'watchMyTrades': true,
@@ -288,6 +289,92 @@ export default class kucoin extends kucoinRest {
288
289
  }
289
290
  }
290
291
  }
292
+ async watchBidsAsks(symbols = undefined, params = {}) {
293
+ /**
294
+ * @method
295
+ * @name kucoin#watchBidsAsks
296
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level1-bbo-market-data
297
+ * @description watches best bid & ask for symbols
298
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
299
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
300
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
301
+ */
302
+ const ticker = await this.watchMultiHelper('watchBidsAsks', '/spotMarket/level1:', symbols, params);
303
+ if (this.newUpdates) {
304
+ const tickers = {};
305
+ tickers[ticker['symbol']] = ticker;
306
+ return tickers;
307
+ }
308
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
309
+ }
310
+ async watchMultiHelper(methodName, channelName, symbols = undefined, params = {}) {
311
+ await this.loadMarkets();
312
+ symbols = this.marketSymbols(symbols, undefined, false, true, false);
313
+ const length = symbols.length;
314
+ if (length > 100) {
315
+ throw new ArgumentsRequired(this.id + ' ' + methodName + '() accepts a maximum of 100 symbols');
316
+ }
317
+ const messageHashes = [];
318
+ for (let i = 0; i < symbols.length; i++) {
319
+ const symbol = symbols[i];
320
+ const market = this.market(symbol);
321
+ messageHashes.push('bidask@' + market['symbol']);
322
+ }
323
+ const url = await this.negotiate(false);
324
+ const marketIds = this.marketIds(symbols);
325
+ const joined = marketIds.join(',');
326
+ const requestId = this.requestId().toString();
327
+ const request = {
328
+ 'id': requestId,
329
+ 'type': 'subscribe',
330
+ 'topic': channelName + joined,
331
+ 'response': true,
332
+ };
333
+ const message = this.extend(request, params);
334
+ return await this.watchMultiple(url, messageHashes, message, messageHashes);
335
+ }
336
+ handleBidAsk(client, message) {
337
+ //
338
+ // arrives one symbol dict
339
+ //
340
+ // {
341
+ // topic: '/spotMarket/level1:ETH-USDT',
342
+ // type: 'message',
343
+ // data: {
344
+ // asks: [ '3347.42', '2.0778387' ],
345
+ // bids: [ '3347.41', '6.0411697' ],
346
+ // timestamp: 1712231142085
347
+ // },
348
+ // subject: 'level1'
349
+ // }
350
+ //
351
+ const parsedTicker = this.parseWsBidAsk(message);
352
+ const symbol = parsedTicker['symbol'];
353
+ this.bidsasks[symbol] = parsedTicker;
354
+ const messageHash = 'bidask@' + symbol;
355
+ client.resolve(parsedTicker, messageHash);
356
+ }
357
+ parseWsBidAsk(ticker, market = undefined) {
358
+ const topic = this.safeString(ticker, 'topic');
359
+ const parts = topic.split(':');
360
+ const marketId = parts[1];
361
+ market = this.safeMarket(marketId, market);
362
+ const symbol = this.safeString(market, 'symbol');
363
+ const data = this.safeDict(ticker, 'data', {});
364
+ const ask = this.safeList(data, 'asks', []);
365
+ const bid = this.safeList(data, 'bids', []);
366
+ const timestamp = this.safeInteger(data, 'timestamp');
367
+ return this.safeTicker({
368
+ 'symbol': symbol,
369
+ 'timestamp': timestamp,
370
+ 'datetime': this.iso8601(timestamp),
371
+ 'ask': this.safeNumber(ask, 0),
372
+ 'askVolume': this.safeNumber(ask, 1),
373
+ 'bid': this.safeNumber(bid, 0),
374
+ 'bidVolume': this.safeNumber(bid, 1),
375
+ 'info': ticker,
376
+ }, market);
377
+ }
291
378
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
292
379
  /**
293
380
  * @method
@@ -679,6 +766,9 @@ export default class kucoin extends kucoinRest {
679
766
  // }
680
767
  //
681
768
  const id = this.safeString(message, 'id');
769
+ if (!(id in client.subscriptions)) {
770
+ return;
771
+ }
682
772
  const subscriptionHash = this.safeString(client.subscriptions, id);
683
773
  const subscription = this.safeValue(client.subscriptions, subscriptionHash);
684
774
  delete client.subscriptions[id];
@@ -1052,6 +1142,7 @@ export default class kucoin extends kucoinRest {
1052
1142
  }
1053
1143
  const subject = this.safeString(message, 'subject');
1054
1144
  const methods = {
1145
+ 'level1': this.handleBidAsk,
1055
1146
  'level2': this.handleOrderBook,
1056
1147
  'trade.l2update': this.handleOrderBook,
1057
1148
  'trade.ticker': this.handleTicker,
@@ -1,5 +1,5 @@
1
1
  import kucoinfuturesRest from '../kucoinfutures.js';
2
- import type { Int, Str, OrderBook, Order, Trade, Ticker, Balances, Position } from '../base/types.js';
2
+ import type { Int, Str, OrderBook, Order, Trade, Ticker, Balances, Position, Strings, Tickers } 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;
@@ -7,9 +7,14 @@ export default class kucoinfutures extends kucoinfuturesRest {
7
7
  negotiateHelper(privateChannel: any, params?: {}): Promise<string>;
8
8
  requestId(): any;
9
9
  subscribe(url: any, messageHash: any, subscriptionHash: any, subscription: any, params?: {}): Promise<any>;
10
- subscribeMultiple(url: any, messageHashes: any, topic: any, subscriptionHashes: any, subscription: any, params?: {}): Promise<any>;
10
+ subscribeMultiple(url: any, messageHashes: any, topic: any, subscriptionHashes: any, subscriptionArgs: any, params?: {}): Promise<any>;
11
11
  watchTicker(symbol: string, params?: {}): Promise<Ticker>;
12
- handleTicker(client: Client, message: any): any;
12
+ watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
13
+ handleTicker(client: Client, message: any): void;
14
+ watchBidsAsks(symbols?: Strings, params?: {}): Promise<Tickers>;
15
+ watchMultiRequest(methodName: any, channelName: string, symbols?: Strings, params?: {}): Promise<any>;
16
+ handleBidAsk(client: Client, message: any): void;
17
+ parseWsBidAsk(ticker: any, market?: any): Ticker;
13
18
  watchPosition(symbol?: Str, params?: {}): Promise<Position>;
14
19
  getCurrentPosition(symbol: any): any;
15
20
  setPositionCache(client: Client, symbol: string): void;
@@ -24,8 +29,6 @@ export default class kucoinfutures extends kucoinfuturesRest {
24
29
  handleDeltas(bookside: any, deltas: any): void;
25
30
  handleOrderBook(client: Client, message: any): void;
26
31
  getCacheIndex(orderbook: any, cache: any): any;
27
- handleOrderBookSubscription(client: Client, message: any, subscription: any): void;
28
- handleSubscriptionStatus(client: Client, message: any): void;
29
32
  handleSystemStatus(client: Client, message: any): any;
30
33
  watchOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
31
34
  parseWsOrderStatus(status: any): string;
@@ -36,6 +39,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
36
39
  handleBalanceSubscription(client: Client, message: any, subscription: any): void;
37
40
  fetchBalanceSnapshot(client: any, message: any): Promise<void>;
38
41
  handleSubject(client: Client, message: any): void;
42
+ getMessageHash(elementName: string, symbol?: Str): string;
39
43
  ping(client: any): {
40
44
  id: any;
41
45
  type: string;
@@ -15,6 +15,8 @@ export default class kucoinfutures extends kucoinfuturesRest {
15
15
  'has': {
16
16
  'ws': true,
17
17
  'watchTicker': true,
18
+ 'watchTickers': true,
19
+ 'watchBidsAsks': true,
18
20
  'watchTrades': true,
19
21
  'watchOrderBook': true,
20
22
  'watchOrders': true,
@@ -44,9 +46,6 @@ export default class kucoinfutures extends kucoinfuturesRest {
44
46
  'snapshotDelay': 20,
45
47
  'snapshotMaxRetries': 3,
46
48
  },
47
- 'watchTicker': {
48
- 'name': 'contractMarket/tickerV2', // market/ticker
49
- },
50
49
  'watchPosition': {
51
50
  'fetchPositionSnapshot': true,
52
51
  'awaitPositionSnapshot': true, // whether to wait for the position snapshot before providing updates
@@ -149,7 +148,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
149
148
  }
150
149
  return await this.watch(url, messageHash, message, subscriptionHash, subscription);
151
150
  }
152
- async subscribeMultiple(url, messageHashes, topic, subscriptionHashes, subscription, params = {}) {
151
+ async subscribeMultiple(url, messageHashes, topic, subscriptionHashes, subscriptionArgs, params = {}) {
153
152
  const requestId = this.requestId().toString();
154
153
  const request = {
155
154
  'id': requestId,
@@ -157,24 +156,14 @@ export default class kucoinfutures extends kucoinfuturesRest {
157
156
  'topic': topic,
158
157
  'response': true,
159
158
  };
160
- const message = this.extend(request, params);
161
- const subscriptionRequest = {
162
- 'id': requestId,
163
- };
164
- if (subscription === undefined) {
165
- subscription = subscriptionRequest;
166
- }
167
- else {
168
- subscription = this.extend(subscriptionRequest, subscription);
169
- }
170
- return await this.watchMultiple(url, messageHashes, message, subscriptionHashes, subscription);
159
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), subscriptionHashes, subscriptionArgs);
171
160
  }
172
161
  async watchTicker(symbol, params = {}) {
173
162
  /**
174
163
  * @method
175
164
  * @name kucoinfutures#watchTicker
176
165
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
177
- * @see https://docs.kucoin.com/futures/#get-real-time-symbol-ticker-v2
166
+ * @see https://www.kucoin.com/docs/websocket/futures-trading/public-channels/get-ticker
178
167
  * @param {string} symbol unified symbol of the market to fetch the ticker for
179
168
  * @param {object} [params] extra parameters specific to the exchange API endpoint
180
169
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
@@ -182,30 +171,48 @@ export default class kucoinfutures extends kucoinfuturesRest {
182
171
  await this.loadMarkets();
183
172
  const market = this.market(symbol);
184
173
  symbol = market['symbol'];
185
- const url = await this.negotiate(false);
186
- const options = this.safeValue(this.options, 'watchTicker', {});
187
- const channel = this.safeString(options, 'name', 'contractMarket/tickerV2');
188
- const topic = '/' + channel + ':' + market['id'];
189
- const messageHash = 'ticker:' + symbol;
190
- return await this.subscribe(url, messageHash, topic, undefined, params);
174
+ params['callerMethodName'] = 'watchTicker';
175
+ const tickers = await this.watchTickers([symbol], params);
176
+ return tickers[symbol];
177
+ }
178
+ async watchTickers(symbols = undefined, params = {}) {
179
+ /**
180
+ * @method
181
+ * @name kucoinfutures#watchTickers
182
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
183
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
184
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
185
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
186
+ */
187
+ await this.loadMarkets();
188
+ const ticker = await this.watchMultiRequest('watchTickers', '/contractMarket/ticker:', symbols, params);
189
+ if (this.newUpdates) {
190
+ const tickers = {};
191
+ tickers[ticker['symbol']] = ticker;
192
+ return tickers;
193
+ }
194
+ return this.filterByArray(this.tickers, 'symbol', symbols);
191
195
  }
192
196
  handleTicker(client, message) {
193
197
  //
194
- // market/tickerV2
198
+ // ticker (v1)
195
199
  //
196
200
  // {
197
- // "type": "message",
198
- // "topic": "/contractMarket/tickerV2:ADAUSDTM",
199
- // "subject": "tickerV2",
200
- // "data": {
201
- // "symbol": "ADAUSDTM",
202
- // "sequence": 1668007800439,
203
- // "bestBidSize": 178,
204
- // "bestBidPrice": "0.35959",
205
- // "bestAskPrice": "0.35981",
206
- // "ts": "1668141430037124460",
207
- // "bestAskSize": 134
208
- // }
201
+ // "subject": "ticker",
202
+ // "topic": "/contractMarket/ticker:XBTUSDM",
203
+ // "data": {
204
+ // "symbol": "XBTUSDM", //Market of the symbol
205
+ // "sequence": 45, //Sequence number which is used to judge the continuity of the pushed messages
206
+ // "side": "sell", //Transaction side of the last traded taker order
207
+ // "price": "3600.0", //Filled price
208
+ // "size": 16, //Filled quantity
209
+ // "tradeId": "5c9dcf4170744d6f5a3d32fb", //Order ID
210
+ // "bestBidSize": 795, //Best bid size
211
+ // "bestBidPrice": "3200.0", //Best bid
212
+ // "bestAskPrice": "3600.0", //Best ask size
213
+ // "bestAskSize": 284, //Best ask
214
+ // "ts": 1553846081210004941 //Filled time - nanosecond
215
+ // }
209
216
  // }
210
217
  //
211
218
  const data = this.safeValue(message, 'data', {});
@@ -213,9 +220,95 @@ export default class kucoinfutures extends kucoinfuturesRest {
213
220
  const market = this.safeMarket(marketId, undefined, '-');
214
221
  const ticker = this.parseTicker(data, market);
215
222
  this.tickers[market['symbol']] = ticker;
216
- const messageHash = 'ticker:' + market['symbol'];
217
- client.resolve(ticker, messageHash);
218
- return message;
223
+ client.resolve(ticker, this.getMessageHash('ticker', market['symbol']));
224
+ }
225
+ async watchBidsAsks(symbols = undefined, params = {}) {
226
+ /**
227
+ * @method
228
+ * @name kucoinfutures#watchBidsAsks
229
+ * @see https://www.kucoin.com/docs/websocket/futures-trading/public-channels/get-ticker-v2
230
+ * @description watches best bid & ask for symbols
231
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
232
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
233
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
234
+ */
235
+ const ticker = await this.watchMultiRequest('watchBidsAsks', '/contractMarket/tickerV2:', symbols, params);
236
+ if (this.newUpdates) {
237
+ const tickers = {};
238
+ tickers[ticker['symbol']] = ticker;
239
+ return tickers;
240
+ }
241
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
242
+ }
243
+ async watchMultiRequest(methodName, channelName, symbols = undefined, params = {}) {
244
+ await this.loadMarkets();
245
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', methodName);
246
+ const isBidsAsks = (methodName === 'watchBidsAsks');
247
+ symbols = this.marketSymbols(symbols, undefined, false, true, false);
248
+ const length = symbols.length;
249
+ if (length > 100) {
250
+ throw new ArgumentsRequired(this.id + ' ' + methodName + '() accepts a maximum of 100 symbols');
251
+ }
252
+ const messageHashes = [];
253
+ for (let i = 0; i < symbols.length; i++) {
254
+ const symbol = symbols[i];
255
+ const market = this.market(symbol);
256
+ const prefix = isBidsAsks ? 'bidask' : 'ticker';
257
+ messageHashes.push(this.getMessageHash(prefix, market['symbol']));
258
+ }
259
+ const url = await this.negotiate(false);
260
+ const marketIds = this.marketIds(symbols);
261
+ const joined = marketIds.join(',');
262
+ const requestId = this.requestId().toString();
263
+ const request = {
264
+ 'id': requestId,
265
+ 'type': 'subscribe',
266
+ 'topic': channelName + joined,
267
+ 'response': true,
268
+ };
269
+ const subscription = {
270
+ 'id': requestId,
271
+ };
272
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscription);
273
+ }
274
+ handleBidAsk(client, message) {
275
+ //
276
+ // arrives one symbol dict
277
+ //
278
+ // {
279
+ // "subject": "tickerV2",
280
+ // "topic": "/contractMarket/tickerV2:XBTUSDM",
281
+ // "data": {
282
+ // "symbol": "XBTUSDM", //Market of the symbol
283
+ // "bestBidSize": 795, // Best bid size
284
+ // "bestBidPrice": 3200.0, // Best bid
285
+ // "bestAskPrice": 3600.0, // Best ask
286
+ // "bestAskSize": 284, // Best ask size
287
+ // "ts": 1553846081210004941 // Filled time - nanosecond
288
+ // }
289
+ // }
290
+ //
291
+ const parsedTicker = this.parseWsBidAsk(message);
292
+ const symbol = parsedTicker['symbol'];
293
+ this.bidsasks[symbol] = parsedTicker;
294
+ client.resolve(parsedTicker, this.getMessageHash('bidask', symbol));
295
+ }
296
+ parseWsBidAsk(ticker, market = undefined) {
297
+ const data = this.safeDict(ticker, 'data', {});
298
+ const marketId = this.safeString(data, 'symbol');
299
+ market = this.safeMarket(marketId, market);
300
+ const symbol = this.safeString(market, 'symbol');
301
+ const timestamp = this.safeIntegerProduct(data, 'ts', 0.000001);
302
+ return this.safeTicker({
303
+ 'symbol': symbol,
304
+ 'timestamp': timestamp,
305
+ 'datetime': this.iso8601(timestamp),
306
+ 'ask': this.safeNumber(data, 'bestAskPrice'),
307
+ 'askVolume': this.safeNumber(data, 'bestAskSize'),
308
+ 'bid': this.safeNumber(data, 'bestBidPrice'),
309
+ 'bidVolume': this.safeNumber(data, 'bestBidSize'),
310
+ 'info': ticker,
311
+ }, market);
219
312
  }
220
313
  async watchPosition(symbol = undefined, params = {}) {
221
314
  /**
@@ -434,7 +527,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
434
527
  messageHashes.push('trades:' + symbol);
435
528
  subscriptionHashes.push('/contractMarket/execution:' + marketId);
436
529
  }
437
- const trades = await this.subscribeMultiple(url, messageHashes, topic, subscriptionHashes, params);
530
+ const trades = await this.subscribeMultiple(url, messageHashes, topic, subscriptionHashes, undefined, params);
438
531
  if (this.newUpdates) {
439
532
  const first = this.safeValue(trades, 0);
440
533
  const tradeSymbol = this.safeString(first, 'symbol');
@@ -520,9 +613,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
520
613
  const marketIds = this.marketIds(symbols);
521
614
  const url = await this.negotiate(false);
522
615
  const topic = '/contractMarket/level2:' + marketIds.join(',');
523
- const subscription = {
524
- 'method': this.handleOrderBookSubscription,
525
- 'symbols': symbols,
616
+ const subscriptionArgs = {
526
617
  'limit': limit,
527
618
  };
528
619
  const subscriptionHashes = [];
@@ -533,7 +624,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
533
624
  messageHashes.push('orderbook:' + symbol);
534
625
  subscriptionHashes.push('/contractMarket/level2:' + marketId);
535
626
  }
536
- const orderbook = await this.subscribeMultiple(url, messageHashes, topic, subscriptionHashes, subscription, params);
627
+ const orderbook = await this.subscribeMultiple(url, messageHashes, topic, subscriptionHashes, subscriptionArgs, params);
537
628
  return orderbook.limit();
538
629
  }
539
630
  handleDelta(orderbook, delta) {
@@ -584,11 +675,13 @@ export default class kucoinfutures extends kucoinfuturesRest {
584
675
  const marketId = this.safeString(topicParts, 1);
585
676
  const symbol = this.safeSymbol(marketId, undefined, '-');
586
677
  const messageHash = 'orderbook:' + symbol;
587
- const storedOrderBook = this.safeValue(this.orderbooks, symbol);
588
- const nonce = this.safeInteger(storedOrderBook, 'nonce');
589
- if (storedOrderBook === undefined) {
590
- return; // this shouldn't be needed, but for some reason sometimes this runs before handleOrderBookSubscription in c#
678
+ if (!(symbol in this.orderbooks)) {
679
+ const subscriptionArgs = this.safeDict(client.subscriptions, topic, {});
680
+ const limit = this.safeInteger(subscriptionArgs, 'limit');
681
+ this.orderbooks[symbol] = this.orderBook({}, limit);
591
682
  }
683
+ const storedOrderBook = this.orderbooks[symbol];
684
+ const nonce = this.safeInteger(storedOrderBook, 'nonce');
592
685
  const deltaEnd = this.safeInteger(data, 'sequence');
593
686
  if (nonce === undefined) {
594
687
  const cacheLength = storedOrderBook.cache.length;
@@ -634,39 +727,6 @@ export default class kucoinfutures extends kucoinfuturesRest {
634
727
  }
635
728
  return cache.length;
636
729
  }
637
- handleOrderBookSubscription(client, message, subscription) {
638
- const limit = this.safeInteger(subscription, 'limit');
639
- const symbols = this.safeValue(subscription, 'symbols');
640
- if (symbols === undefined) {
641
- const symbol = this.safeString(subscription, 'symbol');
642
- this.orderbooks[symbol] = this.orderBook({}, limit);
643
- }
644
- else {
645
- for (let i = 0; i < symbols.length; i++) {
646
- const symbol = symbols[i];
647
- this.orderbooks[symbol] = this.orderBook({}, limit);
648
- }
649
- }
650
- // moved snapshot initialization to handleOrderBook to fix
651
- // https://github.com/ccxt/ccxt/issues/6820
652
- // the general idea is to fetch the snapshot after the first delta
653
- // but not before, because otherwise we cannot synchronize the feed
654
- }
655
- handleSubscriptionStatus(client, message) {
656
- //
657
- // {
658
- // "id": "1578090438322",
659
- // "type": "ack"
660
- // }
661
- //
662
- const id = this.safeString(message, 'id');
663
- const subscriptionsById = this.indexBy(client.subscriptions, 'id');
664
- const subscription = this.safeValue(subscriptionsById, id, {});
665
- const method = this.safeValue(subscription, 'method');
666
- if (method !== undefined) {
667
- method.call(this, client, message, subscription);
668
- }
669
- }
670
730
  handleSystemStatus(client, message) {
671
731
  //
672
732
  // todo: answer the question whether handleSystemStatus should be renamed
@@ -925,7 +985,8 @@ export default class kucoinfutures extends kucoinfuturesRest {
925
985
  const subject = this.safeString(message, 'subject');
926
986
  const methods = {
927
987
  'level2': this.handleOrderBook,
928
- 'tickerV2': this.handleTicker,
988
+ 'ticker': this.handleTicker,
989
+ 'tickerV2': this.handleBidAsk,
929
990
  'availableBalance.change': this.handleBalance,
930
991
  'match': this.handleTrade,
931
992
  'orderChange': this.handleOrder,
@@ -939,6 +1000,15 @@ export default class kucoinfutures extends kucoinfuturesRest {
939
1000
  method.call(this, client, message);
940
1001
  }
941
1002
  }
1003
+ getMessageHash(elementName, symbol = undefined) {
1004
+ // elementName can be 'ticker', 'bidask', ...
1005
+ if (symbol !== undefined) {
1006
+ return elementName + '@' + symbol;
1007
+ }
1008
+ else {
1009
+ return elementName + 's@all';
1010
+ }
1011
+ }
942
1012
  ping(client) {
943
1013
  // kucoin does not support built-in ws protocol-level ping-pong
944
1014
  // instead it requires a custom json-based text ping-pong
@@ -978,7 +1048,6 @@ export default class kucoinfutures extends kucoinfuturesRest {
978
1048
  const methods = {
979
1049
  // 'heartbeat': this.handleHeartbeat,
980
1050
  'welcome': this.handleSystemStatus,
981
- 'ack': this.handleSubscriptionStatus,
982
1051
  'message': this.handleSubject,
983
1052
  'pong': this.handlePong,
984
1053
  'error': this.handleErrorMessage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccxt",
3
- "version": "4.2.90",
3
+ "version": "4.2.92",
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",