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.
- package/CHANGELOG.md +44 -16
- package/README.md +3 -3
- package/build.sh +1 -1
- package/dist/ccxt.browser.js +515 -270
- package/dist/ccxt.browser.min.js +2 -2
- package/dist/cjs/ccxt.js +1 -1
- package/dist/cjs/src/base/Exchange.js +6 -10
- package/dist/cjs/src/bybit.js +1 -0
- package/dist/cjs/src/coinbase.js +3 -1
- package/dist/cjs/src/deribit.js +114 -101
- package/dist/cjs/src/gemini.js +2 -1
- package/dist/cjs/src/kraken.js +67 -16
- package/dist/cjs/src/okx.js +30 -30
- package/dist/cjs/src/pro/bitmex.js +39 -18
- package/dist/cjs/src/pro/kucoin.js +91 -0
- package/dist/cjs/src/pro/kucoinfutures.js +151 -82
- package/js/ccxt.d.ts +1 -1
- package/js/ccxt.js +1 -1
- package/js/src/abstract/bybit.d.ts +1 -0
- package/js/src/base/Exchange.js +6 -10
- package/js/src/bybit.js +1 -0
- package/js/src/coinbase.js +3 -1
- package/js/src/deribit.js +114 -101
- package/js/src/gemini.js +2 -1
- package/js/src/kraken.d.ts +2 -1
- package/js/src/kraken.js +67 -16
- package/js/src/okx.js +30 -30
- package/js/src/pro/bitmex.d.ts +1 -0
- package/js/src/pro/bitmex.js +39 -18
- package/js/src/pro/kucoin.d.ts +4 -0
- package/js/src/pro/kucoin.js +91 -0
- package/js/src/pro/kucoinfutures.d.ts +9 -5
- package/js/src/pro/kucoinfutures.js +151 -82
- package/package.json +1 -1
package/js/src/pro/bitmex.js
CHANGED
|
@@ -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.
|
|
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
|
package/js/src/pro/kucoin.d.ts
CHANGED
|
@@ -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[]>;
|
package/js/src/pro/kucoin.js
CHANGED
|
@@ -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,
|
|
10
|
+
subscribeMultiple(url: any, messageHashes: any, topic: any, subscriptionHashes: any, subscriptionArgs: any, params?: {}): Promise<any>;
|
|
11
11
|
watchTicker(symbol: string, params?: {}): Promise<Ticker>;
|
|
12
|
-
|
|
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,
|
|
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
|
-
|
|
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://
|
|
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
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
//
|
|
198
|
+
// ticker (v1)
|
|
195
199
|
//
|
|
196
200
|
// {
|
|
197
|
-
//
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
//
|
|
204
|
-
//
|
|
205
|
-
//
|
|
206
|
-
//
|
|
207
|
-
//
|
|
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
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
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
|
-
'
|
|
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