ccxt 4.5.44 → 4.5.45
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/README.md +9 -12
- package/dist/ccxt.browser.min.js +3 -3
- package/dist/cjs/ccxt.js +1 -12
- package/dist/cjs/src/abstract/kucoinfutures.js +1 -1
- package/dist/cjs/src/base/Exchange.js +36 -3
- package/dist/cjs/src/base/functions/encode.js +2 -2
- package/dist/cjs/src/base/functions/generic.js +8 -2
- package/dist/cjs/src/bitrue.js +1 -1
- package/dist/cjs/src/bitteam.js +1 -1
- package/dist/cjs/src/btcbox.js +1 -1
- package/dist/cjs/src/cex.js +1 -0
- package/dist/cjs/src/gate.js +227 -168
- package/dist/cjs/src/grvt.js +3 -2
- package/dist/cjs/src/hyperliquid.js +16 -5
- package/dist/cjs/src/kraken.js +2 -2
- package/dist/cjs/src/krakenfutures.js +1 -5
- package/dist/cjs/src/kucoin.js +4729 -970
- package/dist/cjs/src/kucoinfutures.js +14 -3434
- package/dist/cjs/src/lbank.js +1 -1
- package/dist/cjs/src/poloniex.js +1 -1
- package/dist/cjs/src/pro/gate.js +37 -1
- package/dist/cjs/src/pro/kucoin.js +819 -178
- package/dist/cjs/src/pro/kucoinfutures.js +95 -1261
- package/dist/cjs/src/pro/mexc.js +10 -5
- package/dist/cjs/src/pro/okx.js +84 -39
- package/js/ccxt.d.ts +2 -14
- package/js/ccxt.js +2 -10
- package/js/src/abstract/kucoin.d.ts +46 -3
- package/js/src/abstract/kucoinfutures.d.ts +27 -12
- package/js/src/base/Exchange.d.ts +12 -1
- package/js/src/base/Exchange.js +36 -3
- package/js/src/base/functions/encode.js +2 -2
- package/js/src/base/functions/generic.js +9 -3
- package/js/src/bitrue.js +1 -1
- package/js/src/bitteam.js +1 -1
- package/js/src/btcbox.js +1 -1
- package/js/src/cex.js +2 -1
- package/js/src/gate.d.ts +125 -119
- package/js/src/gate.js +227 -168
- package/js/src/grvt.js +3 -2
- package/js/src/hyperliquid.d.ts +3 -1
- package/js/src/hyperliquid.js +16 -5
- package/js/src/kraken.js +2 -2
- package/js/src/krakenfutures.js +1 -5
- package/js/src/kucoin.d.ts +696 -100
- package/js/src/kucoin.js +4730 -971
- package/js/src/kucoinfutures.d.ts +4 -522
- package/js/src/kucoinfutures.js +14 -3434
- package/js/src/lbank.js +1 -1
- package/js/src/poloniex.js +1 -1
- package/js/src/pro/gate.d.ts +30 -1
- package/js/src/pro/gate.js +37 -1
- package/js/src/pro/kucoin.d.ts +70 -30
- package/js/src/pro/kucoin.js +821 -180
- package/js/src/pro/kucoinfutures.d.ts +17 -195
- package/js/src/pro/kucoinfutures.js +96 -1262
- package/js/src/pro/mexc.js +10 -5
- package/js/src/pro/okx.d.ts +1 -0
- package/js/src/pro/okx.js +84 -39
- package/package.json +1 -1
- package/dist/cjs/src/abstract/alp.js +0 -11
- package/dist/cjs/src/abstract/defx.js +0 -11
- package/dist/cjs/src/abstract/timex.js +0 -11
- package/dist/cjs/src/alp.js +0 -1059
- package/dist/cjs/src/defx.js +0 -2142
- package/dist/cjs/src/pro/defx.js +0 -866
- package/dist/cjs/src/timex.js +0 -1793
- package/js/src/abstract/alp.d.ts +0 -21
- package/js/src/abstract/alp.js +0 -5
- package/js/src/abstract/defx.d.ts +0 -72
- package/js/src/abstract/defx.js +0 -5
- package/js/src/abstract/timex.d.ts +0 -65
- package/js/src/abstract/timex.js +0 -5
- package/js/src/alp.d.ts +0 -209
- package/js/src/alp.js +0 -1052
- package/js/src/defx.d.ts +0 -348
- package/js/src/defx.js +0 -2135
- package/js/src/pro/defx.d.ts +0 -236
- package/js/src/pro/defx.js +0 -859
- package/js/src/timex.d.ts +0 -247
- package/js/src/timex.js +0 -1786
package/js/src/pro/kucoin.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
import kucoinRest from '../kucoin.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { ArgumentsRequired, ExchangeError } from '../base/errors.js';
|
|
4
|
+
import { Precise } from '../base/Precise.js';
|
|
5
|
+
import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
|
|
5
6
|
// ---------------------------------------------------------------------------
|
|
6
7
|
export default class kucoin extends kucoinRest {
|
|
7
8
|
describe() {
|
|
@@ -18,6 +19,8 @@ export default class kucoin extends kucoinRest {
|
|
|
18
19
|
'watchBidsAsks': true,
|
|
19
20
|
'watchOrderBook': true,
|
|
20
21
|
'watchOrders': true,
|
|
22
|
+
'watchPosition': true,
|
|
23
|
+
'watchPositions': false,
|
|
21
24
|
'watchMyTrades': true,
|
|
22
25
|
'watchTickers': true,
|
|
23
26
|
'watchTicker': true,
|
|
@@ -35,15 +38,24 @@ export default class kucoin extends kucoinRest {
|
|
|
35
38
|
'options': {
|
|
36
39
|
'tradesLimit': 1000,
|
|
37
40
|
'watchTicker': {
|
|
38
|
-
'
|
|
41
|
+
'spotMethod': '/market/snapshot', // '/market/ticker'
|
|
39
42
|
},
|
|
40
43
|
'watchOrderBook': {
|
|
41
44
|
'snapshotDelay': 5,
|
|
42
45
|
'snapshotMaxRetries': 3,
|
|
43
|
-
'
|
|
46
|
+
'spotMethod': '/market/level2',
|
|
47
|
+
'contractMethod': '/contractMarket/level2', // '/contractMarket/level2Depth5' or '/contractMarket/level2Depth20'
|
|
44
48
|
},
|
|
45
49
|
'watchMyTrades': {
|
|
46
|
-
'
|
|
50
|
+
'spotMethod': '/spotMarket/tradeOrders', // or '/spot/tradeFills'
|
|
51
|
+
},
|
|
52
|
+
'watchBalance': {
|
|
53
|
+
'fetchBalanceSnapshot': true,
|
|
54
|
+
'awaitBalanceSnapshot': true, // whether to wait for the balance snapshot before providing updates
|
|
55
|
+
},
|
|
56
|
+
'watchPosition': {
|
|
57
|
+
'fetchPositionSnapshot': true,
|
|
58
|
+
'awaitPositionSnapshot': true, // whether to wait for the position snapshot before providing updates
|
|
47
59
|
},
|
|
48
60
|
},
|
|
49
61
|
'streaming': {
|
|
@@ -54,9 +66,12 @@ export default class kucoin extends kucoinRest {
|
|
|
54
66
|
},
|
|
55
67
|
});
|
|
56
68
|
}
|
|
57
|
-
async negotiate(privateChannel, params = {}) {
|
|
58
|
-
|
|
59
|
-
|
|
69
|
+
async negotiate(privateChannel, isFuturesMethod = false, params = {}) {
|
|
70
|
+
let connectId = privateChannel ? 'private' : 'public';
|
|
71
|
+
if (isFuturesMethod) {
|
|
72
|
+
connectId += 'Futures';
|
|
73
|
+
}
|
|
74
|
+
const urls = this.safeDict(this.options, 'urls', {});
|
|
60
75
|
let future = this.safeValue(urls, connectId);
|
|
61
76
|
if (future !== undefined) {
|
|
62
77
|
return await future;
|
|
@@ -64,16 +79,15 @@ export default class kucoin extends kucoinRest {
|
|
|
64
79
|
// we store an awaitable to the url
|
|
65
80
|
// so that multiple calls don't asynchronously
|
|
66
81
|
// fetch different urls and overwrite each other
|
|
67
|
-
urls[connectId] = this.spawn(this.negotiateHelper, privateChannel, params);
|
|
82
|
+
urls[connectId] = this.spawn(this.negotiateHelper, privateChannel, connectId, params);
|
|
68
83
|
this.options['urls'] = urls;
|
|
69
84
|
future = urls[connectId];
|
|
70
85
|
return await future;
|
|
71
86
|
}
|
|
72
|
-
async negotiateHelper(privateChannel, params = {}) {
|
|
87
|
+
async negotiateHelper(privateChannel, connectId, params = {}) {
|
|
73
88
|
let response = undefined;
|
|
74
|
-
const connectId = privateChannel ? 'private' : 'public';
|
|
75
89
|
try {
|
|
76
|
-
if (
|
|
90
|
+
if (connectId === 'private') {
|
|
77
91
|
response = await this.privatePostBulletPrivate(params);
|
|
78
92
|
//
|
|
79
93
|
// {
|
|
@@ -93,12 +107,18 @@ export default class kucoin extends kucoinRest {
|
|
|
93
107
|
// }
|
|
94
108
|
//
|
|
95
109
|
}
|
|
96
|
-
else {
|
|
110
|
+
else if (connectId === 'public') {
|
|
97
111
|
response = await this.publicPostBulletPublic(params);
|
|
98
112
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
113
|
+
else if (connectId === 'privateFutures') {
|
|
114
|
+
response = await this.futuresPrivatePostBulletPrivate(params);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
response = await this.futuresPublicPostBulletPublic(params);
|
|
118
|
+
}
|
|
119
|
+
const data = this.safeDict(response, 'data', {});
|
|
120
|
+
const instanceServers = this.safeList(data, 'instanceServers', []);
|
|
121
|
+
const firstInstanceServer = this.safeDict(instanceServers, 0);
|
|
102
122
|
const pingInterval = this.safeInteger(firstInstanceServer, 'pingInterval');
|
|
103
123
|
const endpoint = this.safeString(firstInstanceServer, 'endpoint');
|
|
104
124
|
const token = this.safeString(data, 'token');
|
|
@@ -186,7 +206,8 @@ export default class kucoin extends kucoinRest {
|
|
|
186
206
|
* @method
|
|
187
207
|
* @name kucoin#watchTicker
|
|
188
208
|
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
189
|
-
* @see https://www.kucoin.com/docs
|
|
209
|
+
* @see https://www.kucoin.com/docs-new/3470063w0
|
|
210
|
+
* @see https://www.kucoin.com/docs-new/3470081w0
|
|
190
211
|
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
191
212
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
192
213
|
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
|
|
@@ -195,17 +216,25 @@ export default class kucoin extends kucoinRest {
|
|
|
195
216
|
await this.loadMarkets();
|
|
196
217
|
const market = this.market(symbol);
|
|
197
218
|
symbol = market['symbol'];
|
|
198
|
-
const
|
|
199
|
-
const
|
|
219
|
+
const isFuturesMethod = market['contract'];
|
|
220
|
+
const url = await this.negotiate(false, isFuturesMethod);
|
|
221
|
+
let method = '/market/snapshot';
|
|
222
|
+
if (isFuturesMethod) {
|
|
223
|
+
method = '/contractMarket/ticker';
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
[method, params] = this.handleOptionAndParams(params, 'watchTicker', 'spotMethod', method);
|
|
227
|
+
}
|
|
200
228
|
const topic = method + ':' + market['id'];
|
|
201
229
|
const messageHash = 'ticker:' + symbol;
|
|
202
|
-
return await this.subscribe(url, messageHash, topic,
|
|
230
|
+
return await this.subscribe(url, messageHash, topic, params);
|
|
203
231
|
}
|
|
204
232
|
/**
|
|
205
233
|
* @method
|
|
206
234
|
* @name kucoin#unWatchTicker
|
|
207
235
|
* @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
208
|
-
* @see https://www.kucoin.com/docs
|
|
236
|
+
* @see https://www.kucoin.com/docs-new/3470063w0
|
|
237
|
+
* @see https://www.kucoin.com/docs-new/3470081w0
|
|
209
238
|
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
210
239
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
211
240
|
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
|
|
@@ -214,16 +243,25 @@ export default class kucoin extends kucoinRest {
|
|
|
214
243
|
await this.loadMarkets();
|
|
215
244
|
const market = this.market(symbol);
|
|
216
245
|
symbol = market['symbol'];
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
246
|
+
const isFuturesMethod = market['contract'];
|
|
247
|
+
const url = await this.negotiate(false, isFuturesMethod);
|
|
248
|
+
let method = '/market/snapshot';
|
|
249
|
+
if (isFuturesMethod) {
|
|
250
|
+
method = '/contractMarket/ticker';
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
[method, params] = this.handleOptionAndParams(params, 'watchTicker', 'spotMethod', method);
|
|
254
|
+
}
|
|
220
255
|
const topic = method + ':' + market['id'];
|
|
221
256
|
const messageHash = 'unsubscribe:ticker:' + symbol;
|
|
222
257
|
const subMessageHash = 'ticker:' + symbol;
|
|
223
258
|
const subscription = {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
259
|
+
// we have to add the topic to the messageHashes and subMessageHashes
|
|
260
|
+
// because handleSubscriptionStatus needs them to remove the subscription from the client
|
|
261
|
+
// without them subscription would never be removed and re-subscribe would fail because of duplicate subscriptionHash
|
|
262
|
+
'messageHashes': [messageHash, topic],
|
|
263
|
+
'subMessageHashes': [subMessageHash, topic],
|
|
264
|
+
'topic': 'ticker',
|
|
227
265
|
'unsubscribe': true,
|
|
228
266
|
'symbols': [symbol],
|
|
229
267
|
};
|
|
@@ -232,19 +270,33 @@ export default class kucoin extends kucoinRest {
|
|
|
232
270
|
/**
|
|
233
271
|
* @method
|
|
234
272
|
* @name kucoin#watchTickers
|
|
235
|
-
* @see https://www.kucoin.com/docs
|
|
273
|
+
* @see https://www.kucoin.com/docs-new/3470063w0
|
|
274
|
+
* @see https://www.kucoin.com/docs-new/3470064w0
|
|
275
|
+
* @see https://www.kucoin.com/docs-new/3470081w0
|
|
236
276
|
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
|
237
277
|
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
|
|
238
278
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
239
|
-
* @param {string} [params.method] either '/market/snapshot' or '/market/ticker' default is '/market/ticker'
|
|
279
|
+
* @param {string} [params.method] *spot markets only* either '/market/snapshot' or '/market/ticker' default is '/market/ticker'
|
|
240
280
|
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
|
|
241
281
|
*/
|
|
242
282
|
async watchTickers(symbols = undefined, params = {}) {
|
|
243
283
|
await this.loadMarkets();
|
|
244
|
-
symbols = this.marketSymbols(symbols);
|
|
284
|
+
symbols = this.marketSymbols(symbols, undefined, true, true);
|
|
285
|
+
const firstMarket = this.getMarketFromSymbols(symbols);
|
|
286
|
+
let marketType = undefined;
|
|
287
|
+
[marketType, params] = this.handleMarketTypeAndParams('watchTickers', firstMarket, params);
|
|
288
|
+
const isFuturesMethod = (marketType !== 'spot') && (marketType !== 'margin');
|
|
289
|
+
if (isFuturesMethod && symbols === undefined) {
|
|
290
|
+
throw new ArgumentsRequired(this.id + ' watchTickers() requires a list of symbols for ' + marketType + ' markets');
|
|
291
|
+
}
|
|
245
292
|
const messageHash = 'tickers';
|
|
246
|
-
let method =
|
|
247
|
-
|
|
293
|
+
let method = '/market/ticker';
|
|
294
|
+
if (isFuturesMethod) {
|
|
295
|
+
method = '/contractMarket/ticker';
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
[method, params] = this.handleOptionAndParams2(params, 'watchTickers', 'method', 'spotMethod', method);
|
|
299
|
+
}
|
|
248
300
|
const messageHashes = [];
|
|
249
301
|
const topics = [];
|
|
250
302
|
if (symbols !== undefined) {
|
|
@@ -255,7 +307,7 @@ export default class kucoin extends kucoinRest {
|
|
|
255
307
|
topics.push(method + ':' + market['id']);
|
|
256
308
|
}
|
|
257
309
|
}
|
|
258
|
-
const url = await this.negotiate(false);
|
|
310
|
+
const url = await this.negotiate(false, isFuturesMethod);
|
|
259
311
|
let tickers = undefined;
|
|
260
312
|
if (symbols === undefined) {
|
|
261
313
|
const allTopic = method + ':all';
|
|
@@ -331,43 +383,106 @@ export default class kucoin extends kucoinRest {
|
|
|
331
383
|
// }
|
|
332
384
|
// }
|
|
333
385
|
//
|
|
386
|
+
// futures
|
|
387
|
+
// {
|
|
388
|
+
// "subject": "ticker",
|
|
389
|
+
// "topic": "/contractMarket/ticker:XBTUSDM",
|
|
390
|
+
// "data": {
|
|
391
|
+
// "symbol": "XBTUSDM", //Market of the symbol
|
|
392
|
+
// "sequence": 45, //Sequence number which is used to judge the continuity of the pushed messages
|
|
393
|
+
// "side": "sell", //Transaction side of the last traded taker order
|
|
394
|
+
// "price": "3600.0", //Filled price
|
|
395
|
+
// "size": 16, //Filled quantity
|
|
396
|
+
// "tradeId": "5c9dcf4170744d6f5a3d32fb", //Order ID
|
|
397
|
+
// "bestBidSize": 795, //Best bid size
|
|
398
|
+
// "bestBidPrice": "3200.0", //Best bid
|
|
399
|
+
// "bestAskPrice": "3600.0", //Best ask size
|
|
400
|
+
// "bestAskSize": 284, //Best ask
|
|
401
|
+
// "ts": 1553846081210004941 //Filled time - nanosecond
|
|
402
|
+
// }
|
|
403
|
+
// }
|
|
404
|
+
//
|
|
334
405
|
const topic = this.safeString(message, 'topic');
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
406
|
+
if (topic.indexOf('contractMarket') < 0) {
|
|
407
|
+
let market = undefined;
|
|
408
|
+
if (topic !== undefined) {
|
|
409
|
+
const parts = topic.split(':');
|
|
410
|
+
const first = this.safeString(parts, 1);
|
|
411
|
+
let marketId = undefined;
|
|
412
|
+
if (first === 'all') {
|
|
413
|
+
marketId = this.safeString(message, 'subject');
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
marketId = first;
|
|
417
|
+
}
|
|
418
|
+
market = this.safeMarket(marketId, market, '-');
|
|
345
419
|
}
|
|
346
|
-
|
|
420
|
+
const data = this.safeDict(message, 'data', {});
|
|
421
|
+
const rawTicker = this.safeDict(data, 'data', data);
|
|
422
|
+
const ticker = this.parseTicker(rawTicker, market);
|
|
423
|
+
const symbol = ticker['symbol'];
|
|
424
|
+
this.tickers[symbol] = ticker;
|
|
425
|
+
const messageHash = 'ticker:' + symbol;
|
|
426
|
+
client.resolve(ticker, messageHash);
|
|
427
|
+
// watchTickers
|
|
428
|
+
const allTickers = {};
|
|
429
|
+
allTickers[symbol] = ticker;
|
|
430
|
+
client.resolve(allTickers, 'tickers');
|
|
347
431
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
432
|
+
else {
|
|
433
|
+
this.handleContractTicker(client, message);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
handleContractTicker(client, message) {
|
|
437
|
+
//
|
|
438
|
+
// ticker (v1)
|
|
439
|
+
//
|
|
440
|
+
// {
|
|
441
|
+
// "subject": "ticker",
|
|
442
|
+
// "topic": "/contractMarket/ticker:XBTUSDM",
|
|
443
|
+
// "data": {
|
|
444
|
+
// "symbol": "XBTUSDM", //Market of the symbol
|
|
445
|
+
// "sequence": 45, //Sequence number which is used to judge the continuity of the pushed messages
|
|
446
|
+
// "side": "sell", //Transaction side of the last traded taker order
|
|
447
|
+
// "price": "3600.0", //Filled price
|
|
448
|
+
// "size": 16, //Filled quantity
|
|
449
|
+
// "tradeId": "5c9dcf4170744d6f5a3d32fb", //Order ID
|
|
450
|
+
// "bestBidSize": 795, //Best bid size
|
|
451
|
+
// "bestBidPrice": "3200.0", //Best bid
|
|
452
|
+
// "bestAskPrice": "3600.0", //Best ask size
|
|
453
|
+
// "bestAskSize": 284, //Best ask
|
|
454
|
+
// "ts": 1553846081210004941 //Filled time - nanosecond
|
|
455
|
+
// }
|
|
456
|
+
// }
|
|
457
|
+
//
|
|
458
|
+
const data = this.safeDict(message, 'data', {});
|
|
459
|
+
const marketId = this.safeString(data, 'symbol');
|
|
460
|
+
const market = this.safeMarket(marketId, undefined, '-');
|
|
461
|
+
const ticker = this.parseTicker(data, market);
|
|
462
|
+
this.tickers[market['symbol']] = ticker;
|
|
463
|
+
const messageHash = 'ticker:' + market['symbol'];
|
|
354
464
|
client.resolve(ticker, messageHash);
|
|
355
|
-
// watchTickers
|
|
356
|
-
const allTickers = {};
|
|
357
|
-
allTickers[symbol] = ticker;
|
|
358
|
-
client.resolve(allTickers, 'tickers');
|
|
359
465
|
}
|
|
360
466
|
/**
|
|
361
467
|
* @method
|
|
362
468
|
* @name kucoin#watchBidsAsks
|
|
363
|
-
* @see https://www.kucoin.com/docs
|
|
469
|
+
* @see https://www.kucoin.com/docs-new/3470067w0
|
|
470
|
+
* @see https://www.kucoin.com/docs-new/3470080w0
|
|
364
471
|
* @description watches best bid & ask for symbols
|
|
365
472
|
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
|
|
366
473
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
367
474
|
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
|
|
368
475
|
*/
|
|
369
476
|
async watchBidsAsks(symbols = undefined, params = {}) {
|
|
370
|
-
|
|
477
|
+
await this.loadMarkets();
|
|
478
|
+
symbols = this.marketSymbols(symbols, undefined, false, true, false);
|
|
479
|
+
const firstMarket = this.getMarketFromSymbols(symbols);
|
|
480
|
+
const isFuturesMethod = firstMarket['contract'];
|
|
481
|
+
let channelName = '/spotMarket/level1:';
|
|
482
|
+
if (isFuturesMethod) {
|
|
483
|
+
channelName = '/contractMarket/tickerV2:';
|
|
484
|
+
}
|
|
485
|
+
const ticker = await this.watchMultiHelper('watchBidsAsks', channelName, symbols, params);
|
|
371
486
|
if (this.newUpdates) {
|
|
372
487
|
const tickers = {};
|
|
373
488
|
tickers[ticker['symbol']] = ticker;
|
|
@@ -416,6 +531,20 @@ export default class kucoin extends kucoinRest {
|
|
|
416
531
|
// subject: 'level1'
|
|
417
532
|
// }
|
|
418
533
|
//
|
|
534
|
+
// futures
|
|
535
|
+
// {
|
|
536
|
+
// "subject": "tickerV2",
|
|
537
|
+
// "topic": "/contractMarket/tickerV2:XBTUSDM",
|
|
538
|
+
// "data": {
|
|
539
|
+
// "symbol": "XBTUSDM", //Market of the symbol
|
|
540
|
+
// "bestBidSize": 795, // Best bid size
|
|
541
|
+
// "bestBidPrice": 3200.0, // Best bid
|
|
542
|
+
// "bestAskPrice": 3600.0, // Best ask
|
|
543
|
+
// "bestAskSize": 284, // Best ask size
|
|
544
|
+
// "ts": 1553846081210004941 // Filled time - nanosecond
|
|
545
|
+
// }
|
|
546
|
+
// }
|
|
547
|
+
//
|
|
419
548
|
const parsedTicker = this.parseWsBidAsk(message);
|
|
420
549
|
const symbol = parsedTicker['symbol'];
|
|
421
550
|
this.bidsasks[symbol] = parsedTicker;
|
|
@@ -424,30 +553,51 @@ export default class kucoin extends kucoinRest {
|
|
|
424
553
|
}
|
|
425
554
|
parseWsBidAsk(ticker, market = undefined) {
|
|
426
555
|
const topic = this.safeString(ticker, 'topic');
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
556
|
+
if (topic.indexOf('contractMarket') < 0) {
|
|
557
|
+
const parts = topic.split(':');
|
|
558
|
+
const marketId = parts[1];
|
|
559
|
+
market = this.safeMarket(marketId, market);
|
|
560
|
+
const symbol = this.safeString(market, 'symbol');
|
|
561
|
+
const data = this.safeDict(ticker, 'data', {});
|
|
562
|
+
const ask = this.safeList(data, 'asks', []);
|
|
563
|
+
const bid = this.safeList(data, 'bids', []);
|
|
564
|
+
const timestamp = this.safeInteger(data, 'timestamp');
|
|
565
|
+
return this.safeTicker({
|
|
566
|
+
'symbol': symbol,
|
|
567
|
+
'timestamp': timestamp,
|
|
568
|
+
'datetime': this.iso8601(timestamp),
|
|
569
|
+
'ask': this.safeNumber(ask, 0),
|
|
570
|
+
'askVolume': this.safeNumber(ask, 1),
|
|
571
|
+
'bid': this.safeNumber(bid, 0),
|
|
572
|
+
'bidVolume': this.safeNumber(bid, 1),
|
|
573
|
+
'info': ticker,
|
|
574
|
+
}, market);
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
// futures
|
|
578
|
+
const data = this.safeDict(ticker, 'data', {});
|
|
579
|
+
const marketId = this.safeString(data, 'symbol');
|
|
580
|
+
market = this.safeMarket(marketId, market);
|
|
581
|
+
const symbol = this.safeString(market, 'symbol');
|
|
582
|
+
const timestamp = this.safeIntegerProduct(data, 'ts', 0.000001);
|
|
583
|
+
return this.safeTicker({
|
|
584
|
+
'symbol': symbol,
|
|
585
|
+
'timestamp': timestamp,
|
|
586
|
+
'datetime': this.iso8601(timestamp),
|
|
587
|
+
'ask': this.safeNumber(data, 'bestAskPrice'),
|
|
588
|
+
'askVolume': this.safeNumber(data, 'bestAskSize'),
|
|
589
|
+
'bid': this.safeNumber(data, 'bestBidPrice'),
|
|
590
|
+
'bidVolume': this.safeNumber(data, 'bestBidSize'),
|
|
591
|
+
'info': ticker,
|
|
592
|
+
}, market);
|
|
593
|
+
}
|
|
445
594
|
}
|
|
446
595
|
/**
|
|
447
596
|
* @method
|
|
448
597
|
* @name kucoin#watchOHLCV
|
|
449
598
|
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
450
|
-
* @see https://www.kucoin.com/docs
|
|
599
|
+
* @see https://www.kucoin.com/docs-new/3470071w0
|
|
600
|
+
* @see https://www.kucoin.com/docs-new/3470086w0
|
|
451
601
|
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
452
602
|
* @param {string} timeframe the length of time each candle represents
|
|
453
603
|
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
@@ -457,11 +607,16 @@ export default class kucoin extends kucoinRest {
|
|
|
457
607
|
*/
|
|
458
608
|
async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
459
609
|
await this.loadMarkets();
|
|
460
|
-
const url = await this.negotiate(false);
|
|
461
610
|
const market = this.market(symbol);
|
|
462
611
|
symbol = market['symbol'];
|
|
612
|
+
const isFuturesMethod = market['contract'];
|
|
613
|
+
const url = await this.negotiate(false, isFuturesMethod);
|
|
463
614
|
const period = this.safeString(this.timeframes, timeframe, timeframe);
|
|
464
|
-
|
|
615
|
+
let channelName = '/market/candles:';
|
|
616
|
+
if (isFuturesMethod) {
|
|
617
|
+
channelName = '/contractMarket/limitCandle:';
|
|
618
|
+
}
|
|
619
|
+
const topic = channelName + market['id'] + '_' + period;
|
|
465
620
|
const messageHash = 'candles:' + symbol + ':' + timeframe;
|
|
466
621
|
const ohlcv = await this.subscribe(url, messageHash, topic, params);
|
|
467
622
|
if (this.newUpdates) {
|
|
@@ -473,7 +628,8 @@ export default class kucoin extends kucoinRest {
|
|
|
473
628
|
* @method
|
|
474
629
|
* @name kucoin#unWatchOHLCV
|
|
475
630
|
* @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
476
|
-
* @see https://www.kucoin.com/docs
|
|
631
|
+
* @see https://www.kucoin.com/docs-new/3470071w0
|
|
632
|
+
* @see https://www.kucoin.com/docs-new/3470086w0
|
|
477
633
|
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
478
634
|
* @param {string} timeframe the length of time each candle represents
|
|
479
635
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
@@ -481,19 +637,29 @@ export default class kucoin extends kucoinRest {
|
|
|
481
637
|
*/
|
|
482
638
|
async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
|
|
483
639
|
await this.loadMarkets();
|
|
484
|
-
const url = await this.negotiate(false);
|
|
485
640
|
const market = this.market(symbol);
|
|
486
641
|
symbol = market['symbol'];
|
|
642
|
+
const isFuturesMethod = market['contract'];
|
|
643
|
+
const url = await this.negotiate(false, isFuturesMethod);
|
|
644
|
+
let channelName = '/market/candles:';
|
|
645
|
+
if (isFuturesMethod) {
|
|
646
|
+
channelName = '/contractMarket/limitCandle:';
|
|
647
|
+
}
|
|
487
648
|
const period = this.safeString(this.timeframes, timeframe, timeframe);
|
|
488
|
-
const topic =
|
|
649
|
+
const topic = channelName + market['id'] + '_' + period;
|
|
489
650
|
const messageHash = 'unsubscribe:candles:' + symbol + ':' + timeframe;
|
|
490
651
|
const subMessageHash = 'candles:' + symbol + ':' + timeframe;
|
|
652
|
+
const symbolAndTimeframe = [symbol, timeframe];
|
|
491
653
|
const subscription = {
|
|
492
|
-
|
|
493
|
-
|
|
654
|
+
// we have to add the topic to the messageHashes and subMessageHashes
|
|
655
|
+
// because handleSubscriptionStatus needs them to remove the subscription from the client
|
|
656
|
+
// without them subscription would never be removed and re-subscribe would fail because of duplicate subscriptionHash
|
|
657
|
+
'messageHashes': [messageHash, topic],
|
|
658
|
+
'subMessageHashes': [subMessageHash, topic],
|
|
494
659
|
'topic': 'ohlcv',
|
|
495
660
|
'unsubscribe': true,
|
|
496
661
|
'symbols': [symbol],
|
|
662
|
+
'symbolsAndTimeframes': [symbolAndTimeframe],
|
|
497
663
|
};
|
|
498
664
|
return await this.unSubscribe(url, messageHash, topic, messageHash, params, subscription);
|
|
499
665
|
}
|
|
@@ -518,9 +684,29 @@ export default class kucoin extends kucoinRest {
|
|
|
518
684
|
// "type": "message"
|
|
519
685
|
// }
|
|
520
686
|
//
|
|
521
|
-
|
|
687
|
+
// futures
|
|
688
|
+
// {
|
|
689
|
+
// "topic":"/contractMarket/limitCandle:LTCUSDTM_1min",
|
|
690
|
+
// "type":"message",
|
|
691
|
+
// "data":{
|
|
692
|
+
// "symbol":"LTCUSDTM",
|
|
693
|
+
// "candles":[
|
|
694
|
+
// "1715470980",
|
|
695
|
+
// "81.38",
|
|
696
|
+
// "81.38",
|
|
697
|
+
// "81.38",
|
|
698
|
+
// "81.38",
|
|
699
|
+
// "61.0", - Note value 5 is incorrect and will be fixed in subsequent versions of kucoin
|
|
700
|
+
// "61"
|
|
701
|
+
// ],
|
|
702
|
+
// "time":1715470994801
|
|
703
|
+
// },
|
|
704
|
+
// "subject":"candle.stick"
|
|
705
|
+
// }
|
|
706
|
+
//
|
|
707
|
+
const data = this.safeDict(message, 'data', {});
|
|
522
708
|
const marketId = this.safeString(data, 'symbol');
|
|
523
|
-
const candles = this.
|
|
709
|
+
const candles = this.safeList(data, 'candles', []);
|
|
524
710
|
const topic = this.safeString(message, 'topic');
|
|
525
711
|
const parts = topic.split('_');
|
|
526
712
|
const interval = this.safeString(parts, 1);
|
|
@@ -536,15 +722,25 @@ export default class kucoin extends kucoinRest {
|
|
|
536
722
|
stored = new ArrayCacheByTimestamp(limit);
|
|
537
723
|
this.ohlcvs[symbol][timeframe] = stored;
|
|
538
724
|
}
|
|
539
|
-
const
|
|
540
|
-
|
|
725
|
+
const isContractMarket = (topic.indexOf('contractMarket') >= 0);
|
|
726
|
+
const baseVolumeIndex = isContractMarket ? 6 : 5; // Note value 5 is incorrect and will be fixed in subsequent versions of kucoin
|
|
727
|
+
const parsed = [
|
|
728
|
+
this.safeTimestamp(candles, 0),
|
|
729
|
+
this.safeNumber(candles, 1),
|
|
730
|
+
this.safeNumber(candles, 3),
|
|
731
|
+
this.safeNumber(candles, 4),
|
|
732
|
+
this.safeNumber(candles, 2),
|
|
733
|
+
this.safeNumber(candles, baseVolumeIndex),
|
|
734
|
+
];
|
|
735
|
+
stored.append(parsed);
|
|
541
736
|
client.resolve(stored, messageHash);
|
|
542
737
|
}
|
|
543
738
|
/**
|
|
544
739
|
* @method
|
|
545
740
|
* @name kucoin#watchTrades
|
|
546
741
|
* @description get the list of most recent trades for a particular symbol
|
|
547
|
-
* @see https://www.kucoin.com/docs
|
|
742
|
+
* @see https://www.kucoin.com/docs-new/3470072w0
|
|
743
|
+
* @see https://www.kucoin.com/docs-new/3470084w0
|
|
548
744
|
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
549
745
|
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
550
746
|
* @param {int} [limit] the maximum amount of trades to fetch
|
|
@@ -558,7 +754,8 @@ export default class kucoin extends kucoinRest {
|
|
|
558
754
|
* @method
|
|
559
755
|
* @name kucoin#watchTradesForSymbols
|
|
560
756
|
* @description get the list of most recent trades for a particular symbol
|
|
561
|
-
* @see https://www.kucoin.com/docs
|
|
757
|
+
* @see https://www.kucoin.com/docs-new/3470072w0
|
|
758
|
+
* @see https://www.kucoin.com/docs-new/3470084w0
|
|
562
759
|
* @param {string[]} symbols
|
|
563
760
|
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
564
761
|
* @param {int} [limit] the maximum amount of trades to fetch
|
|
@@ -571,17 +768,23 @@ export default class kucoin extends kucoinRest {
|
|
|
571
768
|
throw new ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
|
|
572
769
|
}
|
|
573
770
|
await this.loadMarkets();
|
|
574
|
-
symbols = this.marketSymbols(symbols);
|
|
771
|
+
symbols = this.marketSymbols(symbols, undefined, false, true);
|
|
772
|
+
const firstMarket = this.getMarketFromSymbols(symbols);
|
|
773
|
+
const isFuturesMethod = firstMarket['contract'];
|
|
575
774
|
const marketIds = this.marketIds(symbols);
|
|
576
|
-
const url = await this.negotiate(false);
|
|
775
|
+
const url = await this.negotiate(false, isFuturesMethod);
|
|
577
776
|
const messageHashes = [];
|
|
578
777
|
const subscriptionHashes = [];
|
|
579
|
-
|
|
778
|
+
let channelName = '/market/match:';
|
|
779
|
+
if (isFuturesMethod) {
|
|
780
|
+
channelName = '/contractMarket/execution:';
|
|
781
|
+
}
|
|
782
|
+
const topic = channelName + marketIds.join(',');
|
|
580
783
|
for (let i = 0; i < symbols.length; i++) {
|
|
581
784
|
const symbol = symbols[i];
|
|
582
785
|
messageHashes.push('trades:' + symbol);
|
|
583
786
|
const marketId = marketIds[i];
|
|
584
|
-
subscriptionHashes.push(
|
|
787
|
+
subscriptionHashes.push(channelName + marketId);
|
|
585
788
|
}
|
|
586
789
|
const trades = await this.subscribeMultiple(url, messageHashes, topic, subscriptionHashes, params);
|
|
587
790
|
if (this.newUpdates) {
|
|
@@ -595,24 +798,36 @@ export default class kucoin extends kucoinRest {
|
|
|
595
798
|
* @method
|
|
596
799
|
* @name kucoin#unWatchTradesForSymbols
|
|
597
800
|
* @description unWatches trades stream
|
|
598
|
-
* @see https://www.kucoin.com/docs
|
|
801
|
+
* @see https://www.kucoin.com/docs-new/3470072w0
|
|
802
|
+
* @see https://www.kucoin.com/docs-new/3470084w0
|
|
599
803
|
* @param {string} symbols
|
|
600
804
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
601
805
|
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
|
|
602
806
|
*/
|
|
603
807
|
async unWatchTradesForSymbols(symbols, params = {}) {
|
|
604
808
|
await this.loadMarkets();
|
|
605
|
-
symbols = this.marketSymbols(symbols, undefined, false);
|
|
809
|
+
symbols = this.marketSymbols(symbols, undefined, false, true);
|
|
606
810
|
const marketIds = this.marketIds(symbols);
|
|
607
|
-
const
|
|
811
|
+
const firstMarket = this.getMarketFromSymbols(symbols);
|
|
812
|
+
const isFuturesMethod = firstMarket['contract'];
|
|
813
|
+
const url = await this.negotiate(false, isFuturesMethod);
|
|
608
814
|
const messageHashes = [];
|
|
609
815
|
const subscriptionHashes = [];
|
|
610
|
-
|
|
816
|
+
let channelName = '/market/match:';
|
|
817
|
+
if (isFuturesMethod) {
|
|
818
|
+
channelName = '/contractMarket/execution:';
|
|
819
|
+
}
|
|
820
|
+
const topic = channelName + marketIds.join(',');
|
|
611
821
|
for (let i = 0; i < symbols.length; i++) {
|
|
612
822
|
const symbol = symbols[i];
|
|
613
823
|
messageHashes.push('unsubscribe:trades:' + symbol);
|
|
614
824
|
subscriptionHashes.push('trades:' + symbol);
|
|
615
825
|
}
|
|
826
|
+
// we have to add the topic to the messageHashes and subMessageHashes
|
|
827
|
+
// because handleSubscriptionStatus needs them to remove the subscription from the client
|
|
828
|
+
// without them subscription would never be removed and re-subscribe would fail because of duplicate subscriptionHash
|
|
829
|
+
messageHashes.push(topic);
|
|
830
|
+
subscriptionHashes.push(topic);
|
|
616
831
|
const subscription = {
|
|
617
832
|
'messageHashes': messageHashes,
|
|
618
833
|
'subMessageHashes': subscriptionHashes,
|
|
@@ -626,7 +841,8 @@ export default class kucoin extends kucoinRest {
|
|
|
626
841
|
* @method
|
|
627
842
|
* @name kucoin#unWatchTrades
|
|
628
843
|
* @description unWatches trades stream
|
|
629
|
-
* @see https://www.kucoin.com/docs
|
|
844
|
+
* @see https://www.kucoin.com/docs-new/3470072w0
|
|
845
|
+
* @see https://www.kucoin.com/docs-new/3470084w0
|
|
630
846
|
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
631
847
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
632
848
|
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
|
|
@@ -654,18 +870,20 @@ export default class kucoin extends kucoinRest {
|
|
|
654
870
|
// "type": "message"
|
|
655
871
|
// }
|
|
656
872
|
//
|
|
657
|
-
const data = this.
|
|
658
|
-
const
|
|
873
|
+
const data = this.safeDict(message, 'data', {});
|
|
874
|
+
const marketId = this.safeString(data, 'symbol');
|
|
875
|
+
const market = this.safeMarket(marketId);
|
|
876
|
+
const trade = this.parseTrade(data, market);
|
|
659
877
|
const symbol = trade['symbol'];
|
|
660
878
|
const messageHash = 'trades:' + symbol;
|
|
661
|
-
|
|
662
|
-
if (trades === undefined) {
|
|
879
|
+
if (!(symbol in this.trades)) {
|
|
663
880
|
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
664
|
-
|
|
665
|
-
this.trades[symbol] =
|
|
881
|
+
const stored = new ArrayCache(limit);
|
|
882
|
+
this.trades[symbol] = stored;
|
|
666
883
|
}
|
|
667
|
-
trades
|
|
668
|
-
|
|
884
|
+
const cache = this.trades[symbol];
|
|
885
|
+
cache.append(trade);
|
|
886
|
+
client.resolve(cache, messageHash);
|
|
669
887
|
}
|
|
670
888
|
/**
|
|
671
889
|
* @method
|
|
@@ -718,15 +936,16 @@ export default class kucoin extends kucoinRest {
|
|
|
718
936
|
/**
|
|
719
937
|
* @method
|
|
720
938
|
* @name kucoin#watchOrderBookForSymbols
|
|
721
|
-
* @see https://www.kucoin.com/docs/
|
|
722
|
-
* @see https://www.kucoin.com/docs/
|
|
723
|
-
* @see https://www.kucoin.com/docs/
|
|
724
|
-
* @see https://www.kucoin.com/docs
|
|
939
|
+
* @see https://www.kucoin.com/docs-new/3470069w0 // spot level 5
|
|
940
|
+
* @see https://www.kucoin.com/docs-new/3470070w0 // spot level 50
|
|
941
|
+
* @see https://www.kucoin.com/docs-new/3470068w0 // spot incremental
|
|
942
|
+
* @see https://www.kucoin.com/docs-new/3470083w0 // futures level 5
|
|
943
|
+
* @see https://www.kucoin.com/docs-new/3470097w0 // futures level 50
|
|
944
|
+
* @see https://www.kucoin.com/docs-new/3470082w0 // futures incremental
|
|
725
945
|
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
726
946
|
* @param {string[]} symbols unified array of symbols
|
|
727
947
|
* @param {int} [limit] the maximum amount of order book entries to return
|
|
728
948
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
729
|
-
* @param {string} [params.method] either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' default is '/market/level2'
|
|
730
949
|
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
|
|
731
950
|
*/
|
|
732
951
|
async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
|
|
@@ -742,11 +961,19 @@ export default class kucoin extends kucoinRest {
|
|
|
742
961
|
await this.loadMarkets();
|
|
743
962
|
symbols = this.marketSymbols(symbols);
|
|
744
963
|
const marketIds = this.marketIds(symbols);
|
|
745
|
-
const
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
964
|
+
const firstMarket = this.getMarketFromSymbols(symbols);
|
|
965
|
+
const isFuturesMethod = firstMarket['contract'];
|
|
966
|
+
const url = await this.negotiate(false, isFuturesMethod);
|
|
967
|
+
let method = isFuturesMethod ? '/contractMarket/level2' : '/market/level2';
|
|
968
|
+
const optionName = isFuturesMethod ? 'contractMethod' : 'spotMethod';
|
|
969
|
+
[method, params] = this.handleOptionAndParams2(params, 'watchOrderBook', optionName, 'method', method);
|
|
970
|
+
if (method.indexOf('Depth') === -1) {
|
|
971
|
+
if ((limit === 5) || (limit === 50)) {
|
|
972
|
+
if (!isFuturesMethod) {
|
|
973
|
+
method = '/spotMarket/level2';
|
|
974
|
+
}
|
|
975
|
+
method += 'Depth' + limit.toString();
|
|
976
|
+
}
|
|
750
977
|
}
|
|
751
978
|
const topic = method + ':' + marketIds.join(',');
|
|
752
979
|
const messageHashes = [];
|
|
@@ -758,7 +985,7 @@ export default class kucoin extends kucoinRest {
|
|
|
758
985
|
subscriptionHashes.push(method + ':' + marketId);
|
|
759
986
|
}
|
|
760
987
|
let subscription = {};
|
|
761
|
-
if (method === '/market/level2') { // other streams return the entire orderbook, so we don't need to fetch the snapshot through REST
|
|
988
|
+
if ((method === '/market/level2') || (method === '/contractMarket/level2')) { // other streams return the entire orderbook, so we don't need to fetch the snapshot through REST
|
|
762
989
|
subscription = {
|
|
763
990
|
'method': this.handleOrderBookSubscription,
|
|
764
991
|
'symbols': symbols,
|
|
@@ -771,27 +998,37 @@ export default class kucoin extends kucoinRest {
|
|
|
771
998
|
/**
|
|
772
999
|
* @method
|
|
773
1000
|
* @name kucoin#unWatchOrderBookForSymbols
|
|
774
|
-
* @see https://www.kucoin.com/docs/
|
|
775
|
-
* @see https://www.kucoin.com/docs/
|
|
776
|
-
* @see https://www.kucoin.com/docs/
|
|
777
|
-
* @see https://www.kucoin.com/docs
|
|
1001
|
+
* @see https://www.kucoin.com/docs-new/3470069w0 // spot level 5
|
|
1002
|
+
* @see https://www.kucoin.com/docs-new/3470070w0 // spot level 50
|
|
1003
|
+
* @see https://www.kucoin.com/docs-new/3470068w0 // spot incremental
|
|
1004
|
+
* @see https://www.kucoin.com/docs-new/3470083w0 // futures level 5
|
|
1005
|
+
* @see https://www.kucoin.com/docs-new/3470097w0 // futures level 50
|
|
1006
|
+
* @see https://www.kucoin.com/docs-new/3470082w0 // futures incremental
|
|
778
1007
|
* @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
779
1008
|
* @param {string[]} symbols unified array of symbols
|
|
780
1009
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
781
|
-
* @param {string} [params.method] either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' default is '/market/level2'
|
|
1010
|
+
* @param {string} [params.method] either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' or '/contractMarket/level2' or '/contractMarket/level2Depth5' or '/contractMarket/level2Depth50' default is '/market/level2' for spot and '/contractMarket/level2' for futures
|
|
782
1011
|
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
|
|
783
1012
|
*/
|
|
784
1013
|
async unWatchOrderBookForSymbols(symbols, params = {}) {
|
|
785
1014
|
const limit = this.safeInteger(params, 'limit');
|
|
786
1015
|
params = this.omit(params, 'limit');
|
|
787
1016
|
await this.loadMarkets();
|
|
788
|
-
symbols = this.marketSymbols(symbols, undefined, false);
|
|
1017
|
+
symbols = this.marketSymbols(symbols, undefined, false, true);
|
|
789
1018
|
const marketIds = this.marketIds(symbols);
|
|
790
|
-
const
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
1019
|
+
const firstMarket = this.getMarketFromSymbols(symbols);
|
|
1020
|
+
const isFuturesMethod = firstMarket['contract'];
|
|
1021
|
+
const url = await this.negotiate(false, isFuturesMethod);
|
|
1022
|
+
let method = isFuturesMethod ? '/contractMarket/level2' : '/market/level2';
|
|
1023
|
+
const optionName = isFuturesMethod ? 'contractMethod' : 'spotMethod';
|
|
1024
|
+
[method, params] = this.handleOptionAndParams2(params, 'watchOrderBook', optionName, 'method', method);
|
|
1025
|
+
if (method.indexOf('Depth') === -1) {
|
|
1026
|
+
if ((limit === 5) || (limit === 50)) {
|
|
1027
|
+
if (!isFuturesMethod) {
|
|
1028
|
+
method = '/spotMarket/level2';
|
|
1029
|
+
}
|
|
1030
|
+
method += 'Depth' + limit.toString();
|
|
1031
|
+
}
|
|
795
1032
|
}
|
|
796
1033
|
const topic = method + ':' + marketIds.join(',');
|
|
797
1034
|
const messageHashes = [];
|
|
@@ -801,6 +1038,11 @@ export default class kucoin extends kucoinRest {
|
|
|
801
1038
|
messageHashes.push('unsubscribe:orderbook:' + symbol);
|
|
802
1039
|
subscriptionHashes.push('orderbook:' + symbol);
|
|
803
1040
|
}
|
|
1041
|
+
// we have to add the topic to the messageHashes and subMessageHashes
|
|
1042
|
+
// because handleSubscriptionStatus needs them to remove the subscription from the client
|
|
1043
|
+
// without them subscription would never be removed and re-subscribe would fail because of duplicate subscriptionHash
|
|
1044
|
+
messageHashes.push(topic);
|
|
1045
|
+
subscriptionHashes.push(topic);
|
|
804
1046
|
const subscription = {
|
|
805
1047
|
'messageHashes': messageHashes,
|
|
806
1048
|
'symbols': symbols,
|
|
@@ -851,8 +1093,7 @@ export default class kucoin extends kucoinRest {
|
|
|
851
1093
|
// "subject": "level2"
|
|
852
1094
|
// }
|
|
853
1095
|
//
|
|
854
|
-
const data = this.
|
|
855
|
-
const subject = this.safeString(message, 'subject');
|
|
1096
|
+
const data = this.safeDict(message, 'data');
|
|
856
1097
|
const topic = this.safeString(message, 'topic');
|
|
857
1098
|
const topicParts = topic.split(':');
|
|
858
1099
|
const topicSymbol = this.safeString(topicParts, 1);
|
|
@@ -861,7 +1102,7 @@ export default class kucoin extends kucoinRest {
|
|
|
861
1102
|
const symbol = this.safeSymbol(marketId, undefined, '-');
|
|
862
1103
|
const messageHash = 'orderbook:' + symbol;
|
|
863
1104
|
// let orderbook = this.safeDict (this.orderbooks, symbol);
|
|
864
|
-
if (
|
|
1105
|
+
if (topic.indexOf('Depth') >= 0) {
|
|
865
1106
|
if (!(symbol in this.orderbooks)) {
|
|
866
1107
|
this.orderbooks[symbol] = this.orderBook();
|
|
867
1108
|
}
|
|
@@ -907,14 +1148,14 @@ export default class kucoin extends kucoinRest {
|
|
|
907
1148
|
getCacheIndex(orderbook, cache) {
|
|
908
1149
|
const firstDelta = this.safeValue(cache, 0);
|
|
909
1150
|
const nonce = this.safeInteger(orderbook, 'nonce');
|
|
910
|
-
const firstDeltaStart = this.
|
|
1151
|
+
const firstDeltaStart = this.safeInteger2(firstDelta, 'sequenceStart', 'sequence');
|
|
911
1152
|
if (nonce < firstDeltaStart - 1) {
|
|
912
1153
|
return -1;
|
|
913
1154
|
}
|
|
914
1155
|
for (let i = 0; i < cache.length; i++) {
|
|
915
1156
|
const delta = cache[i];
|
|
916
|
-
const deltaStart = this.
|
|
917
|
-
const deltaEnd = this.
|
|
1157
|
+
const deltaStart = this.safeInteger2(delta, 'sequenceStart', 'sequence');
|
|
1158
|
+
const deltaEnd = this.safeInteger2(delta, 'sequenceEnd', 'timestamp'); // todo check
|
|
918
1159
|
if ((nonce >= deltaStart - 1) && (nonce < deltaEnd)) {
|
|
919
1160
|
return i;
|
|
920
1161
|
}
|
|
@@ -923,16 +1164,34 @@ export default class kucoin extends kucoinRest {
|
|
|
923
1164
|
}
|
|
924
1165
|
handleDelta(orderbook, delta) {
|
|
925
1166
|
const timestamp = this.safeInteger2(delta, 'time', 'timestamp');
|
|
926
|
-
orderbook['nonce'] = this.
|
|
1167
|
+
orderbook['nonce'] = this.safeInteger2(delta, 'sequenceEnd', 'sequence', timestamp);
|
|
927
1168
|
orderbook['timestamp'] = timestamp;
|
|
928
1169
|
orderbook['datetime'] = this.iso8601(timestamp);
|
|
929
|
-
const
|
|
930
|
-
const bids = this.safeValue(changes, 'bids', []);
|
|
931
|
-
const asks = this.safeValue(changes, 'asks', []);
|
|
1170
|
+
const change = this.safeString(delta, 'change');
|
|
932
1171
|
const storedBids = orderbook['bids'];
|
|
933
1172
|
const storedAsks = orderbook['asks'];
|
|
934
|
-
|
|
935
|
-
|
|
1173
|
+
if (change !== undefined) {
|
|
1174
|
+
// handling futures orderbook update
|
|
1175
|
+
const splitChange = change.split(',');
|
|
1176
|
+
const price = this.safeNumber(splitChange, 0);
|
|
1177
|
+
const side = this.safeString(splitChange, 1);
|
|
1178
|
+
const quantity = this.safeNumber(splitChange, 2);
|
|
1179
|
+
const type = (side === 'buy') ? 'bids' : 'asks';
|
|
1180
|
+
const value = [price, quantity];
|
|
1181
|
+
if (type === 'bids') {
|
|
1182
|
+
storedBids.storeArray(value);
|
|
1183
|
+
}
|
|
1184
|
+
else {
|
|
1185
|
+
storedAsks.storeArray(value);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
else {
|
|
1189
|
+
const changes = this.safeDict(delta, 'changes', delta);
|
|
1190
|
+
const bids = this.safeList(changes, 'bids', []);
|
|
1191
|
+
const asks = this.safeList(changes, 'asks', []);
|
|
1192
|
+
this.handleBidAsks(storedBids, bids);
|
|
1193
|
+
this.handleBidAsks(storedAsks, asks);
|
|
1194
|
+
}
|
|
936
1195
|
}
|
|
937
1196
|
handleBidAsks(bookSide, bidAsks) {
|
|
938
1197
|
for (let i = 0; i < bidAsks.length; i++) {
|
|
@@ -942,7 +1201,7 @@ export default class kucoin extends kucoinRest {
|
|
|
942
1201
|
}
|
|
943
1202
|
handleOrderBookSubscription(client, message, subscription) {
|
|
944
1203
|
const limit = this.safeInteger(subscription, 'limit');
|
|
945
|
-
const symbols = this.
|
|
1204
|
+
const symbols = this.safeList(subscription, 'symbols');
|
|
946
1205
|
if (symbols === undefined) {
|
|
947
1206
|
const symbol = this.safeString(subscription, 'symbol');
|
|
948
1207
|
this.orderbooks[symbol] = this.orderBook({}, limit);
|
|
@@ -1005,36 +1264,63 @@ export default class kucoin extends kucoinRest {
|
|
|
1005
1264
|
* @method
|
|
1006
1265
|
* @name kucoin#watchOrders
|
|
1007
1266
|
* @description watches information on multiple orders made by the user
|
|
1008
|
-
* @see https://www.kucoin.com/docs/
|
|
1009
|
-
* @see https://www.kucoin.com/docs/
|
|
1267
|
+
* @see https://www.kucoin.com/docs-new/3470074w0 // spot regular orders
|
|
1268
|
+
* @see https://www.kucoin.com/docs-new/3470139w0 // spot trigger orders
|
|
1269
|
+
* @see https://www.kucoin.com/docs-new/3470090w0 // contract regular orders
|
|
1270
|
+
* @see https://www.kucoin.com/docs-new/3470091w0 // contract trigger orders
|
|
1010
1271
|
* @param {string} symbol unified market symbol of the market orders were made in
|
|
1011
1272
|
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
1012
1273
|
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
1013
1274
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1014
1275
|
* @param {boolean} [params.trigger] trigger orders are watched if true
|
|
1276
|
+
* @param {string} [params.type] 'spot' or 'swap' (default is 'spot' if symbol is not provided)
|
|
1015
1277
|
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
|
|
1016
1278
|
*/
|
|
1017
1279
|
async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1018
1280
|
await this.loadMarkets();
|
|
1019
|
-
const trigger = this.
|
|
1281
|
+
const trigger = this.safeBool2(params, 'stop', 'trigger');
|
|
1020
1282
|
params = this.omit(params, ['stop', 'trigger']);
|
|
1021
|
-
|
|
1022
|
-
const topic = trigger ? '/spotMarket/advancedOrders' : '/spotMarket/tradeOrders';
|
|
1023
|
-
const request = {
|
|
1024
|
-
'privateChannel': true,
|
|
1025
|
-
};
|
|
1283
|
+
let market = undefined;
|
|
1026
1284
|
let messageHash = 'orders';
|
|
1027
1285
|
if (symbol !== undefined) {
|
|
1028
|
-
|
|
1286
|
+
market = this.market(symbol);
|
|
1029
1287
|
symbol = market['symbol'];
|
|
1030
1288
|
messageHash = messageHash + ':' + symbol;
|
|
1031
1289
|
}
|
|
1290
|
+
let marketType = undefined;
|
|
1291
|
+
[marketType, params] = this.handleMarketTypeAndParams('watchOrders', market, params);
|
|
1292
|
+
const isFuturesMethod = ((marketType !== 'spot') && (marketType !== 'margin'));
|
|
1293
|
+
const url = await this.negotiate(true, isFuturesMethod);
|
|
1294
|
+
let topic = trigger ? '/spotMarket/advancedOrders' : '/spotMarket/tradeOrders';
|
|
1295
|
+
if (isFuturesMethod) {
|
|
1296
|
+
topic = trigger ? '/contractMarket/advancedOrders' : '/contractMarket/tradeOrders';
|
|
1297
|
+
}
|
|
1298
|
+
if (symbol === undefined) {
|
|
1299
|
+
const suffix = this.getOrdersMessageHashSuffix(topic);
|
|
1300
|
+
messageHash += suffix;
|
|
1301
|
+
}
|
|
1302
|
+
const request = {
|
|
1303
|
+
'privateChannel': true,
|
|
1304
|
+
};
|
|
1032
1305
|
const orders = await this.subscribe(url, messageHash, topic, this.extend(request, params));
|
|
1033
1306
|
if (this.newUpdates) {
|
|
1034
1307
|
limit = orders.getLimit(symbol, limit);
|
|
1035
1308
|
}
|
|
1036
1309
|
return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
|
|
1037
1310
|
}
|
|
1311
|
+
getOrdersMessageHashSuffix(topic) {
|
|
1312
|
+
let suffix = '-spot';
|
|
1313
|
+
if (topic === '/spotMarket/advancedOrders') {
|
|
1314
|
+
suffix += '-trigger';
|
|
1315
|
+
}
|
|
1316
|
+
else if (topic === '/contractMarket/tradeOrders') {
|
|
1317
|
+
suffix = '-contract';
|
|
1318
|
+
}
|
|
1319
|
+
else if (topic === '/contractMarket/advancedOrders') {
|
|
1320
|
+
suffix = '-contract-trigger';
|
|
1321
|
+
}
|
|
1322
|
+
return suffix;
|
|
1323
|
+
}
|
|
1038
1324
|
parseWsOrderStatus(status) {
|
|
1039
1325
|
const statuses = {
|
|
1040
1326
|
'open': 'open',
|
|
@@ -1085,13 +1371,42 @@ export default class kucoin extends kucoinRest {
|
|
|
1085
1371
|
// "type": "triggered"
|
|
1086
1372
|
// }
|
|
1087
1373
|
//
|
|
1374
|
+
// futures
|
|
1375
|
+
// {
|
|
1376
|
+
// "symbol": "ETHUSDTM",
|
|
1377
|
+
// "orderType": "market",
|
|
1378
|
+
// "side": "buy",
|
|
1379
|
+
// "canceledSize": "0",
|
|
1380
|
+
// "orderId": "416204113500479490",
|
|
1381
|
+
// "positionSide": "LONG",
|
|
1382
|
+
// "liquidity": "taker",
|
|
1383
|
+
// "marginMode": "ISOLATED",
|
|
1384
|
+
// "type": "match",
|
|
1385
|
+
// "feeType": "takerFee",
|
|
1386
|
+
// "orderTime": "1772043995356345762",
|
|
1387
|
+
// "size": "1",
|
|
1388
|
+
// "filledSize": "1",
|
|
1389
|
+
// "price": "0",
|
|
1390
|
+
// "matchPrice": "2068.55",
|
|
1391
|
+
// "matchSize": "1",
|
|
1392
|
+
// "remainSize": "0",
|
|
1393
|
+
// "tradeId": "1815302608109",
|
|
1394
|
+
// "clientOid": "9f7a2be0-effe-45bd-bdc8-1614715a583a",
|
|
1395
|
+
// "tradeType": "trade",
|
|
1396
|
+
// "status": "match",
|
|
1397
|
+
// "ts": 1772043995362000000
|
|
1398
|
+
// }
|
|
1399
|
+
//
|
|
1088
1400
|
const rawType = this.safeString(order, 'type');
|
|
1089
1401
|
let status = this.parseWsOrderStatus(rawType);
|
|
1090
|
-
|
|
1402
|
+
let timestamp = this.safeInteger2(order, 'orderTime', 'createdAt');
|
|
1091
1403
|
const marketId = this.safeString(order, 'symbol');
|
|
1092
1404
|
market = this.safeMarket(marketId, market);
|
|
1405
|
+
if (market['contract']) {
|
|
1406
|
+
timestamp = this.safeIntegerProduct(order, 'orderTime', 0.000001);
|
|
1407
|
+
}
|
|
1093
1408
|
const triggerPrice = this.safeString(order, 'stopPrice');
|
|
1094
|
-
const triggerSuccess = this.
|
|
1409
|
+
const triggerSuccess = this.safeBool(order, 'triggerSuccess');
|
|
1095
1410
|
const triggerFail = (triggerSuccess !== true) && (triggerSuccess !== undefined); // TODO: updated to triggerSuccess === False once transpiler transpiles it correctly
|
|
1096
1411
|
if ((status === 'triggered') && triggerFail) {
|
|
1097
1412
|
status = 'canceled';
|
|
@@ -1142,8 +1457,7 @@ export default class kucoin extends kucoinRest {
|
|
|
1142
1457
|
// "type": "open"
|
|
1143
1458
|
// }
|
|
1144
1459
|
//
|
|
1145
|
-
const
|
|
1146
|
-
const data = this.safeValue(message, 'data');
|
|
1460
|
+
const data = this.safeDict(message, 'data');
|
|
1147
1461
|
const tradeId = this.safeString(data, 'tradeId');
|
|
1148
1462
|
if (tradeId !== undefined) {
|
|
1149
1463
|
this.handleMyTrade(client, message);
|
|
@@ -1151,7 +1465,7 @@ export default class kucoin extends kucoinRest {
|
|
|
1151
1465
|
const parsed = this.parseWsOrder(data);
|
|
1152
1466
|
const symbol = this.safeString(parsed, 'symbol');
|
|
1153
1467
|
const orderId = this.safeString(parsed, 'id');
|
|
1154
|
-
const triggerPrice = this.
|
|
1468
|
+
const triggerPrice = this.safeString(parsed, 'triggerPrice');
|
|
1155
1469
|
const isTriggerOrder = (triggerPrice !== undefined);
|
|
1156
1470
|
if (this.orders === undefined) {
|
|
1157
1471
|
const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
|
|
@@ -1168,42 +1482,63 @@ export default class kucoin extends kucoinRest {
|
|
|
1168
1482
|
}
|
|
1169
1483
|
}
|
|
1170
1484
|
cachedOrders.append(parsed);
|
|
1171
|
-
|
|
1485
|
+
const messageHash = 'orders';
|
|
1486
|
+
const topic = this.safeString(message, 'topic');
|
|
1487
|
+
const suffix = this.getOrdersMessageHashSuffix(topic);
|
|
1488
|
+
const typeSpecificMessageHash = messageHash + suffix;
|
|
1489
|
+
client.resolve(cachedOrders, typeSpecificMessageHash);
|
|
1172
1490
|
const symbolSpecificMessageHash = messageHash + ':' + symbol;
|
|
1173
1491
|
client.resolve(cachedOrders, symbolSpecificMessageHash);
|
|
1174
1492
|
}
|
|
1175
1493
|
/**
|
|
1176
1494
|
* @method
|
|
1177
1495
|
* @name kucoin#watchMyTrades
|
|
1178
|
-
* @description watches information on multiple trades made by the user
|
|
1179
|
-
* @see https://www.kucoin.com/docs
|
|
1496
|
+
* @description watches information on multiple trades made by the user on spot
|
|
1497
|
+
* @see https://www.kucoin.com/docs-new/3470074w0
|
|
1498
|
+
* @see https://www.kucoin.com/docs-new/3470090w0
|
|
1180
1499
|
* @param {string} symbol unified market symbol of the market trades were made in
|
|
1181
1500
|
* @param {int} [since] the earliest time in ms to fetch trades for
|
|
1182
1501
|
* @param {int} [limit] the maximum number of trade structures to retrieve
|
|
1183
1502
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1184
|
-
* @param {string} [params.method] '/spotMarket/tradeOrders' or '/spot/tradeFills' default is '/spotMarket/tradeOrders'
|
|
1503
|
+
* @param {string} [params.method] '/spotMarket/tradeOrders' or '/spot/tradeFills' or '/contractMarket/tradeOrders', default is '/spotMarket/tradeOrders'
|
|
1185
1504
|
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=trade-structure}
|
|
1186
1505
|
*/
|
|
1187
1506
|
async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1188
1507
|
await this.loadMarkets();
|
|
1189
|
-
const url = await this.negotiate(true);
|
|
1190
|
-
let topic = undefined;
|
|
1191
|
-
[topic, params] = this.handleOptionAndParams(params, 'watchMyTrades', 'method', '/spotMarket/tradeOrders');
|
|
1192
|
-
const request = {
|
|
1193
|
-
'privateChannel': true,
|
|
1194
|
-
};
|
|
1195
1508
|
let messageHash = 'myTrades';
|
|
1509
|
+
let market = undefined;
|
|
1196
1510
|
if (symbol !== undefined) {
|
|
1197
|
-
|
|
1511
|
+
market = this.market(symbol);
|
|
1198
1512
|
symbol = market['symbol'];
|
|
1199
1513
|
messageHash = messageHash + ':' + market['symbol'];
|
|
1200
1514
|
}
|
|
1515
|
+
let marketType = undefined;
|
|
1516
|
+
[marketType, params] = this.handleMarketTypeAndParams('watchMyTrades', market, params);
|
|
1517
|
+
const isFuturesMethod = ((marketType !== 'spot') && (marketType !== 'margin'));
|
|
1518
|
+
const url = await this.negotiate(true, isFuturesMethod);
|
|
1519
|
+
let topic = isFuturesMethod ? '/contractMarket/tradeOrders' : '/spotMarket/tradeOrders';
|
|
1520
|
+
const optionName = isFuturesMethod ? 'contractMethod' : 'spotMethod';
|
|
1521
|
+
[topic, params] = this.handleOptionAndParams2(params, 'watchMyTrades', optionName, 'method', topic);
|
|
1522
|
+
const request = {
|
|
1523
|
+
'privateChannel': true,
|
|
1524
|
+
};
|
|
1525
|
+
if (symbol === undefined) {
|
|
1526
|
+
const suffix = this.getMyTradesMessageHashSuffix(topic);
|
|
1527
|
+
messageHash += suffix;
|
|
1528
|
+
}
|
|
1201
1529
|
const trades = await this.subscribe(url, messageHash, topic, this.extend(request, params));
|
|
1202
1530
|
if (this.newUpdates) {
|
|
1203
1531
|
limit = trades.getLimit(symbol, limit);
|
|
1204
1532
|
}
|
|
1205
1533
|
return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
|
|
1206
1534
|
}
|
|
1535
|
+
getMyTradesMessageHashSuffix(topic) {
|
|
1536
|
+
let suffix = '-spot';
|
|
1537
|
+
if (topic.indexOf('contractMarket') >= 0) {
|
|
1538
|
+
suffix = '-contract';
|
|
1539
|
+
}
|
|
1540
|
+
return suffix;
|
|
1541
|
+
}
|
|
1207
1542
|
handleMyTrade(client, message) {
|
|
1208
1543
|
//
|
|
1209
1544
|
// {
|
|
@@ -1242,7 +1577,10 @@ export default class kucoin extends kucoinRest {
|
|
|
1242
1577
|
const myTrades = this.myTrades;
|
|
1243
1578
|
myTrades.append(parsed);
|
|
1244
1579
|
const messageHash = 'myTrades';
|
|
1245
|
-
|
|
1580
|
+
const topic = this.safeString(message, 'topic');
|
|
1581
|
+
const suffix = this.getMyTradesMessageHashSuffix(topic);
|
|
1582
|
+
const typeSpecificMessageHash = messageHash + suffix;
|
|
1583
|
+
client.resolve(this.myTrades, typeSpecificMessageHash);
|
|
1246
1584
|
const symbolSpecificMessageHash = messageHash + ':' + parsed['symbol'];
|
|
1247
1585
|
client.resolve(this.myTrades, symbolSpecificMessageHash);
|
|
1248
1586
|
}
|
|
@@ -1329,19 +1667,74 @@ export default class kucoin extends kucoinRest {
|
|
|
1329
1667
|
* @method
|
|
1330
1668
|
* @name kucoin#watchBalance
|
|
1331
1669
|
* @description watch balance and get the amount of funds available for trading or funds locked in orders
|
|
1332
|
-
* @see https://www.kucoin.com/docs/
|
|
1670
|
+
* @see https://www.kucoin.com/docs-new/3470075w0 // spot balance
|
|
1671
|
+
* @see https://www.kucoin.com/docs-new/3470092w0 // contract balance
|
|
1333
1672
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1673
|
+
* @param {string} [params.type] 'spot' or 'swap' (default is 'spot')
|
|
1334
1674
|
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
|
|
1335
1675
|
*/
|
|
1336
1676
|
async watchBalance(params = {}) {
|
|
1337
1677
|
await this.loadMarkets();
|
|
1338
|
-
const
|
|
1339
|
-
const
|
|
1678
|
+
const defaultType = this.safeString(this.options, 'defaultType', 'spot');
|
|
1679
|
+
const type = this.safeString(params, 'type', defaultType);
|
|
1680
|
+
params = this.omit(params, 'type');
|
|
1681
|
+
const accountsByType = this.safeDict(this.options, 'accountsByType', {});
|
|
1682
|
+
const uniformType = this.safeString(accountsByType, type, type);
|
|
1683
|
+
const isFuturesMethod = (uniformType === 'contract');
|
|
1684
|
+
const url = await this.negotiate(true, isFuturesMethod);
|
|
1685
|
+
const client = this.client(url);
|
|
1686
|
+
this.setBalanceCache(client, uniformType);
|
|
1687
|
+
const options = this.safeDict(this.options, 'watchBalance');
|
|
1688
|
+
const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
|
|
1689
|
+
const awaitBalanceSnapshot = this.safeBool(options, 'awaitBalanceSnapshot', true);
|
|
1690
|
+
if (fetchBalanceSnapshot && awaitBalanceSnapshot) {
|
|
1691
|
+
await client.future(uniformType + ':fetchBalanceSnapshot');
|
|
1692
|
+
}
|
|
1693
|
+
const messageHash = uniformType + ':balance';
|
|
1694
|
+
const requestId = this.requestId().toString();
|
|
1695
|
+
const subscriptionHash = isFuturesMethod ? '/contractAccount/wallet' : '/account/balance';
|
|
1340
1696
|
const request = {
|
|
1697
|
+
'id': requestId,
|
|
1698
|
+
'type': 'subscribe',
|
|
1699
|
+
'topic': subscriptionHash,
|
|
1700
|
+
'response': true,
|
|
1341
1701
|
'privateChannel': true,
|
|
1342
1702
|
};
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1703
|
+
const message = this.extend(request, params);
|
|
1704
|
+
if (!(subscriptionHash in client.subscriptions)) {
|
|
1705
|
+
client.subscriptions[requestId] = subscriptionHash;
|
|
1706
|
+
}
|
|
1707
|
+
return await this.watch(url, messageHash, message, type);
|
|
1708
|
+
}
|
|
1709
|
+
setBalanceCache(client, type) {
|
|
1710
|
+
if ((type in client.subscriptions) && (type in this.balance)) {
|
|
1711
|
+
return;
|
|
1712
|
+
}
|
|
1713
|
+
const options = this.safeDict(this.options, 'watchBalance');
|
|
1714
|
+
const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
|
|
1715
|
+
if (fetchBalanceSnapshot) {
|
|
1716
|
+
const messageHash = type + ':fetchBalanceSnapshot';
|
|
1717
|
+
if (!(messageHash in client.futures)) {
|
|
1718
|
+
client.future(messageHash);
|
|
1719
|
+
this.spawn(this.loadBalanceSnapshot, client, messageHash, type);
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
else {
|
|
1723
|
+
this.balance[type] = {};
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
async loadBalanceSnapshot(client, messageHash, type) {
|
|
1727
|
+
const params = {
|
|
1728
|
+
'type': type,
|
|
1729
|
+
};
|
|
1730
|
+
const response = await this.fetchBalance(params);
|
|
1731
|
+
this.balance[type] = this.extend(response, this.safeValue(this.balance, type, {}));
|
|
1732
|
+
// don't remove the future from the .futures cache
|
|
1733
|
+
if (messageHash in client.futures) {
|
|
1734
|
+
const future = client.futures[messageHash];
|
|
1735
|
+
future.resolve();
|
|
1736
|
+
client.resolve(this.balance[type], type + ':balance');
|
|
1737
|
+
}
|
|
1345
1738
|
}
|
|
1346
1739
|
handleBalance(client, message) {
|
|
1347
1740
|
//
|
|
@@ -1367,8 +1760,51 @@ export default class kucoin extends kucoinRest {
|
|
|
1367
1760
|
// "total":"89"
|
|
1368
1761
|
// }
|
|
1369
1762
|
//
|
|
1370
|
-
|
|
1371
|
-
|
|
1763
|
+
// futures
|
|
1764
|
+
// {
|
|
1765
|
+
// "id": "6375553193027a0001f6566f",
|
|
1766
|
+
// "type": "message",
|
|
1767
|
+
// "topic": "/contractAccount/wallet",
|
|
1768
|
+
// "userId": "613a896885d8660006151f01",
|
|
1769
|
+
// "channelType": "private",
|
|
1770
|
+
// "subject": "availableBalance.change",
|
|
1771
|
+
// "data": {
|
|
1772
|
+
// "currency": "USDT",
|
|
1773
|
+
// "holdBalance": "0.0000000000",
|
|
1774
|
+
// "availableBalance": "14.0350281903",
|
|
1775
|
+
// "timestamp": "1668633905657"
|
|
1776
|
+
// }
|
|
1777
|
+
// }
|
|
1778
|
+
//
|
|
1779
|
+
// {
|
|
1780
|
+
// "topic": "/contractAccount/wallet",
|
|
1781
|
+
// "type": "message",
|
|
1782
|
+
// "subject": "walletBalance.change",
|
|
1783
|
+
// "id": "699f586d4416a80001df3804",
|
|
1784
|
+
// "userId": "64f99aced178640001306e6e",
|
|
1785
|
+
// "channelType": "private",
|
|
1786
|
+
// "data": {
|
|
1787
|
+
// "crossPosMargin": "0",
|
|
1788
|
+
// "isolatedOrderMargin": "0",
|
|
1789
|
+
// "holdBalance": "0",
|
|
1790
|
+
// "equity": "49.50050236",
|
|
1791
|
+
// "version": "2874",
|
|
1792
|
+
// "availableBalance": "28.67180236",
|
|
1793
|
+
// "isolatedPosMargin": "20.7308",
|
|
1794
|
+
// "maxWithdrawAmount": "28.67180236",
|
|
1795
|
+
// "walletBalance": "49.40260236",
|
|
1796
|
+
// "isolatedFundingFeeMargin": "0",
|
|
1797
|
+
// "crossUnPnl": "0",
|
|
1798
|
+
// "totalCrossMargin": "28.67180236",
|
|
1799
|
+
// "currency": "USDT",
|
|
1800
|
+
// "isolatedUnPnl": "0.0979",
|
|
1801
|
+
// "availableMargin": "28.67180236",
|
|
1802
|
+
// "crossOrderMargin": "0",
|
|
1803
|
+
// "timestamp": "1772050541214"
|
|
1804
|
+
// }
|
|
1805
|
+
// }
|
|
1806
|
+
//
|
|
1807
|
+
const data = this.safeDict(message, 'data', {});
|
|
1372
1808
|
const currencyId = this.safeString(data, 'currency');
|
|
1373
1809
|
const relationEvent = this.safeString(data, 'relationEvent');
|
|
1374
1810
|
let requestAccountType = undefined;
|
|
@@ -1376,27 +1812,210 @@ export default class kucoin extends kucoinRest {
|
|
|
1376
1812
|
const relationEventParts = relationEvent.split('.');
|
|
1377
1813
|
requestAccountType = this.safeString(relationEventParts, 0);
|
|
1378
1814
|
}
|
|
1379
|
-
const
|
|
1380
|
-
|
|
1815
|
+
const topic = this.safeString(message, 'topic');
|
|
1816
|
+
if (topic === '/contractAccount/wallet') {
|
|
1817
|
+
requestAccountType = 'contract';
|
|
1818
|
+
}
|
|
1819
|
+
const accountsByType = this.safeDict(this.options, 'accountsByType');
|
|
1381
1820
|
const uniformType = this.safeString(accountsByType, requestAccountType, 'trade');
|
|
1382
1821
|
if (!(uniformType in this.balance)) {
|
|
1383
1822
|
this.balance[uniformType] = {};
|
|
1384
1823
|
}
|
|
1385
1824
|
this.balance[uniformType]['info'] = data;
|
|
1386
|
-
const timestamp = this.
|
|
1825
|
+
const timestamp = this.safeInteger2(data, 'time', 'timestamp');
|
|
1387
1826
|
this.balance[uniformType]['timestamp'] = timestamp;
|
|
1388
1827
|
this.balance[uniformType]['datetime'] = this.iso8601(timestamp);
|
|
1389
1828
|
const code = this.safeCurrencyCode(currencyId);
|
|
1390
1829
|
const account = this.account();
|
|
1391
|
-
|
|
1392
|
-
|
|
1830
|
+
let used = this.safeString2(data, 'hold', 'holdBalance');
|
|
1831
|
+
const isolatedPosMargin = this.omitZero(this.safeString(data, 'isolatedPosMargin'));
|
|
1832
|
+
if (isolatedPosMargin !== undefined) {
|
|
1833
|
+
used = Precise.stringAdd(used, isolatedPosMargin);
|
|
1834
|
+
}
|
|
1835
|
+
account['free'] = this.safeString2(data, 'available', 'availableBalance');
|
|
1836
|
+
account['used'] = used;
|
|
1393
1837
|
account['total'] = this.safeString(data, 'total');
|
|
1394
1838
|
this.balance[uniformType][code] = account;
|
|
1395
1839
|
this.balance[uniformType] = this.safeBalance(this.balance[uniformType]);
|
|
1396
|
-
|
|
1397
|
-
|
|
1840
|
+
const messageHash = uniformType + ':balance';
|
|
1841
|
+
client.resolve(this.balance[uniformType], messageHash);
|
|
1842
|
+
}
|
|
1843
|
+
/**
|
|
1844
|
+
* @method
|
|
1845
|
+
* @name kucoin#watchPosition
|
|
1846
|
+
* @description watch open positions for a specific symbol
|
|
1847
|
+
* @see https://www.kucoin.com/docs-new/3470093w0
|
|
1848
|
+
* @param {string|undefined} symbol unified market symbol
|
|
1849
|
+
* @param {object} params extra parameters specific to the exchange API endpoint
|
|
1850
|
+
* @returns {object} a [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
|
|
1851
|
+
*/
|
|
1852
|
+
async watchPosition(symbol = undefined, params = {}) {
|
|
1853
|
+
if (symbol === undefined) {
|
|
1854
|
+
throw new ArgumentsRequired(this.id + ' watchPosition() requires a symbol argument');
|
|
1855
|
+
}
|
|
1856
|
+
await this.loadMarkets();
|
|
1857
|
+
const url = await this.negotiate(true);
|
|
1858
|
+
const market = this.market(symbol);
|
|
1859
|
+
const topic = '/contract/position:' + market['id'];
|
|
1860
|
+
const request = {
|
|
1861
|
+
'privateChannel': true,
|
|
1862
|
+
};
|
|
1863
|
+
const messageHash = 'position:' + market['symbol'];
|
|
1864
|
+
const client = this.client(url);
|
|
1865
|
+
this.setPositionCache(client, symbol);
|
|
1866
|
+
const fetchPositionSnapshot = this.handleOption('watchPosition', 'fetchPositionSnapshot', true);
|
|
1867
|
+
const awaitPositionSnapshot = this.handleOption('watchPosition', 'awaitPositionSnapshot', true);
|
|
1868
|
+
const currentPosition = this.getCurrentPosition(symbol);
|
|
1869
|
+
if (fetchPositionSnapshot && awaitPositionSnapshot && currentPosition === undefined) {
|
|
1870
|
+
const snapshot = await client.future('fetchPositionSnapshot:' + symbol);
|
|
1871
|
+
return snapshot;
|
|
1872
|
+
}
|
|
1873
|
+
return await this.subscribe(url, messageHash, topic, this.extend(request, params));
|
|
1874
|
+
}
|
|
1875
|
+
getCurrentPosition(symbol) {
|
|
1876
|
+
if (this.positions === undefined) {
|
|
1877
|
+
return undefined;
|
|
1878
|
+
}
|
|
1879
|
+
const cache = this.positions.hashmap;
|
|
1880
|
+
const symbolCache = this.safeValue(cache, symbol, {});
|
|
1881
|
+
const values = Object.values(symbolCache);
|
|
1882
|
+
return this.safeValue(values, 0);
|
|
1883
|
+
}
|
|
1884
|
+
setPositionCache(client, symbol) {
|
|
1885
|
+
const fetchPositionSnapshot = this.handleOption('watchPosition', 'fetchPositionSnapshot', false);
|
|
1886
|
+
if (fetchPositionSnapshot) {
|
|
1887
|
+
const messageHash = 'fetchPositionSnapshot:' + symbol;
|
|
1888
|
+
if (!(messageHash in client.futures)) {
|
|
1889
|
+
client.future(messageHash);
|
|
1890
|
+
this.spawn(this.loadPositionSnapshot, client, messageHash, symbol);
|
|
1891
|
+
}
|
|
1398
1892
|
}
|
|
1399
1893
|
}
|
|
1894
|
+
async loadPositionSnapshot(client, messageHash, symbol) {
|
|
1895
|
+
const position = await this.fetchPosition(symbol);
|
|
1896
|
+
this.positions = new ArrayCacheBySymbolById();
|
|
1897
|
+
const cache = this.positions;
|
|
1898
|
+
cache.append(position);
|
|
1899
|
+
// don't remove the future from the .futures cache
|
|
1900
|
+
if (messageHash in client.futures) {
|
|
1901
|
+
const future = client.futures[messageHash];
|
|
1902
|
+
future.resolve(cache);
|
|
1903
|
+
client.resolve(position, 'position:' + symbol);
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
handlePosition(client, message) {
|
|
1907
|
+
//
|
|
1908
|
+
// Position Changes Caused Operations
|
|
1909
|
+
// {
|
|
1910
|
+
// "type": "message",
|
|
1911
|
+
// "userId": "5c32d69203aa676ce4b543c7", // Deprecated, will detele later
|
|
1912
|
+
// "channelType": "private",
|
|
1913
|
+
// "topic": "/contract/position:XBTUSDM",
|
|
1914
|
+
// "subject": "position.change",
|
|
1915
|
+
// "data": {
|
|
1916
|
+
// "realisedGrossPnl": 0E-8, //Accumulated realised profit and loss
|
|
1917
|
+
// "symbol": "XBTUSDM", //Symbol
|
|
1918
|
+
// "crossMode": false, //Cross mode or not
|
|
1919
|
+
// "liquidationPrice": 1000000.0, //Liquidation price
|
|
1920
|
+
// "posLoss": 0E-8, //Manually added margin amount
|
|
1921
|
+
// "avgEntryPrice": 7508.22, //Average entry price
|
|
1922
|
+
// "unrealisedPnl": -0.00014735, //Unrealised profit and loss
|
|
1923
|
+
// "markPrice": 7947.83, //Mark price
|
|
1924
|
+
// "posMargin": 0.00266779, //Position margin
|
|
1925
|
+
// "autoDeposit": false, //Auto deposit margin or not
|
|
1926
|
+
// "riskLimit": 100000, //Risk limit
|
|
1927
|
+
// "unrealisedCost": 0.00266375, //Unrealised value
|
|
1928
|
+
// "posComm": 0.00000392, //Bankruptcy cost
|
|
1929
|
+
// "posMaint": 0.00001724, //Maintenance margin
|
|
1930
|
+
// "posCost": 0.00266375, //Position value
|
|
1931
|
+
// "maintMarginReq": 0.005, //Maintenance margin rate
|
|
1932
|
+
// "bankruptPrice": 1000000.0, //Bankruptcy price
|
|
1933
|
+
// "realisedCost": 0.00000271, //Currently accumulated realised position value
|
|
1934
|
+
// "markValue": 0.00251640, //Mark value
|
|
1935
|
+
// "posInit": 0.00266375, //Position margin
|
|
1936
|
+
// "realisedPnl": -0.00000253, //Realised profit and losts
|
|
1937
|
+
// "maintMargin": 0.00252044, //Position margin
|
|
1938
|
+
// "realLeverage": 1.06, //Leverage of the order
|
|
1939
|
+
// "changeReason": "positionChange", //changeReason:marginChange、positionChange、liquidation、autoAppendMarginStatusChange、adl
|
|
1940
|
+
// "currentCost": 0.00266375, //Current position value
|
|
1941
|
+
// "openingTimestamp": 1558433191000, //Open time
|
|
1942
|
+
// "currentQty": -20, //Current position
|
|
1943
|
+
// "delevPercentage": 0.52, //ADL ranking percentile
|
|
1944
|
+
// "currentComm": 0.00000271, //Current commission
|
|
1945
|
+
// "realisedGrossCost": 0E-8, //Accumulated reliased gross profit value
|
|
1946
|
+
// "isOpen": true, //Opened position or not
|
|
1947
|
+
// "posCross": 1.2E-7, //Manually added margin
|
|
1948
|
+
// "currentTimestamp": 1558506060394, //Current timestamp
|
|
1949
|
+
// "unrealisedRoePcnt": -0.0553, //Rate of return on investment
|
|
1950
|
+
// "unrealisedPnlPcnt": -0.0553, //Position profit and loss ratio
|
|
1951
|
+
// "settleCurrency": "XBT" //Currency used to clear and settle the trades
|
|
1952
|
+
// }
|
|
1953
|
+
// }
|
|
1954
|
+
// Position Changes Caused by Mark Price
|
|
1955
|
+
// {
|
|
1956
|
+
// "userId": "5cd3f1a7b7ebc19ae9558591", // Deprecated, will detele later
|
|
1957
|
+
// "topic": "/contract/position:XBTUSDM",
|
|
1958
|
+
// "subject": "position.change",
|
|
1959
|
+
// "data": {
|
|
1960
|
+
// "markPrice": 7947.83, //Mark price
|
|
1961
|
+
// "markValue": 0.00251640, //Mark value
|
|
1962
|
+
// "maintMargin": 0.00252044, //Position margin
|
|
1963
|
+
// "realLeverage": 10.06, //Leverage of the order
|
|
1964
|
+
// "unrealisedPnl": -0.00014735, //Unrealised profit and lost
|
|
1965
|
+
// "unrealisedRoePcnt": -0.0553, //Rate of return on investment
|
|
1966
|
+
// "unrealisedPnlPcnt": -0.0553, //Position profit and loss ratio
|
|
1967
|
+
// "delevPercentage": 0.52, //ADL ranking percentile
|
|
1968
|
+
// "currentTimestamp": 1558087175068, //Current timestamp
|
|
1969
|
+
// "settleCurrency": "XBT" //Currency used to clear and settle the trades
|
|
1970
|
+
// }
|
|
1971
|
+
// }
|
|
1972
|
+
// Funding Settlement
|
|
1973
|
+
// {
|
|
1974
|
+
// "userId": "xbc453tg732eba53a88ggyt8c", // Deprecated, will detele later
|
|
1975
|
+
// "topic": "/contract/position:XBTUSDM",
|
|
1976
|
+
// "subject": "position.settlement",
|
|
1977
|
+
// "data": {
|
|
1978
|
+
// "fundingTime": 1551770400000, //Funding time
|
|
1979
|
+
// "qty": 100, //Position siz
|
|
1980
|
+
// "markPrice": 3610.85, //Settlement price
|
|
1981
|
+
// "fundingRate": -0.002966, //Funding rate
|
|
1982
|
+
// "fundingFee": -296, //Funding fees
|
|
1983
|
+
// "ts": 1547697294838004923, //Current time (nanosecond)
|
|
1984
|
+
// "settleCurrency": "XBT" //Currency used to clear and settle the trades
|
|
1985
|
+
// }
|
|
1986
|
+
// }
|
|
1987
|
+
// Adjustmet result of risk limit level
|
|
1988
|
+
// {
|
|
1989
|
+
// "userId": "xbc453tg732eba53a88ggyt8c",
|
|
1990
|
+
// "topic": "/contract/position:ADAUSDTM",
|
|
1991
|
+
// "subject": "position.adjustRiskLimit",
|
|
1992
|
+
// "data": {
|
|
1993
|
+
// "success": true, // Successful or not
|
|
1994
|
+
// "riskLimitLevel": 1, // Current risk limit level
|
|
1995
|
+
// "msg": "" // Failure reason
|
|
1996
|
+
// }
|
|
1997
|
+
// }
|
|
1998
|
+
//
|
|
1999
|
+
const topic = this.safeString(message, 'topic', '');
|
|
2000
|
+
const parts = topic.split(':');
|
|
2001
|
+
const marketId = this.safeString(parts, 1);
|
|
2002
|
+
const symbol = this.safeSymbol(marketId, undefined, '');
|
|
2003
|
+
const cache = this.positions;
|
|
2004
|
+
const currentPosition = this.getCurrentPosition(symbol);
|
|
2005
|
+
const messageHash = 'position:' + symbol;
|
|
2006
|
+
const data = this.safeDict(message, 'data', {});
|
|
2007
|
+
const newPosition = this.parsePosition(data);
|
|
2008
|
+
const keys = Object.keys(newPosition);
|
|
2009
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2010
|
+
const key = keys[i];
|
|
2011
|
+
if (newPosition[key] === undefined) {
|
|
2012
|
+
delete newPosition[key];
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
const position = this.extend(currentPosition, newPosition);
|
|
2016
|
+
cache.append(position);
|
|
2017
|
+
client.resolve(position, messageHash);
|
|
2018
|
+
}
|
|
1400
2019
|
handleSubject(client, message) {
|
|
1401
2020
|
//
|
|
1402
2021
|
// {
|
|
@@ -1432,6 +2051,18 @@ export default class kucoin extends kucoinRest {
|
|
|
1432
2051
|
'orderChange': this.handleOrder,
|
|
1433
2052
|
'stopOrder': this.handleOrder,
|
|
1434
2053
|
'/spot/tradeFills': this.handleMyTrade,
|
|
2054
|
+
// futures messages
|
|
2055
|
+
'ticker': this.handleTicker,
|
|
2056
|
+
'tickerV2': this.handleBidAsk,
|
|
2057
|
+
'candle.stick': this.handleOHLCV,
|
|
2058
|
+
'match': this.handleTrade,
|
|
2059
|
+
'orderUpdated': this.handleOrder,
|
|
2060
|
+
'symbolOrderChange': this.handleOrder,
|
|
2061
|
+
'availableBalance.change': this.handleBalance,
|
|
2062
|
+
'walletBalance.change': this.handleBalance,
|
|
2063
|
+
'position.change': this.handlePosition,
|
|
2064
|
+
'position.settlement': this.handlePosition,
|
|
2065
|
+
'position.adjustRiskLimit': this.handlePosition,
|
|
1435
2066
|
};
|
|
1436
2067
|
const method = this.safeValue(methods, subject);
|
|
1437
2068
|
if (method !== undefined) {
|
|
@@ -1487,4 +2118,14 @@ export default class kucoin extends kucoinRest {
|
|
|
1487
2118
|
method.call(this, client, message);
|
|
1488
2119
|
}
|
|
1489
2120
|
}
|
|
2121
|
+
getMessageHash(elementName, symbol = undefined) {
|
|
2122
|
+
// method from kucoinfutures
|
|
2123
|
+
// elementName can be 'ticker', 'bidask', ...
|
|
2124
|
+
if (symbol !== undefined) {
|
|
2125
|
+
return elementName + ':' + symbol;
|
|
2126
|
+
}
|
|
2127
|
+
else {
|
|
2128
|
+
return elementName + 's@all';
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
1490
2131
|
}
|