ccxt 4.2.58 → 4.2.59
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 +83 -0
- package/README.md +3 -3
- package/cleanup.sh +3 -0
- package/dist/ccxt.browser.js +311 -218
- package/dist/ccxt.browser.min.js +3 -3
- package/dist/cjs/ccxt.js +1 -1
- package/dist/cjs/src/base/Exchange.js +2 -0
- package/dist/cjs/src/binance.js +2 -2
- package/dist/cjs/src/bingx.js +3 -3
- package/dist/cjs/src/bitget.js +1 -1
- package/dist/cjs/src/bitmex.js +1 -1
- package/dist/cjs/src/blofin.js +1 -1
- package/dist/cjs/src/coinbase.js +24 -14
- package/dist/cjs/src/lbank.js +1 -1
- package/dist/cjs/src/mexc.js +1 -1
- package/dist/cjs/src/okx.js +1 -1
- package/dist/cjs/src/phemex.js +1 -1
- package/dist/cjs/src/pro/binance.js +1 -1
- package/dist/cjs/src/pro/bitfinex2.js +1 -1
- package/dist/cjs/src/pro/bitget.js +1 -1
- package/dist/cjs/src/pro/bitmart.js +51 -89
- package/dist/cjs/src/pro/bitvavo.js +1 -1
- package/dist/cjs/src/pro/bybit.js +1 -1
- package/dist/cjs/src/pro/coinex.js +1 -1
- package/dist/cjs/src/pro/cryptocom.js +1 -1
- package/dist/cjs/src/pro/deribit.js +201 -84
- package/dist/cjs/src/pro/gate.js +1 -1
- package/dist/cjs/src/pro/independentreserve.js +1 -1
- package/dist/cjs/src/pro/kraken.js +1 -1
- package/dist/cjs/src/pro/kucoinfutures.js +1 -1
- package/dist/cjs/src/pro/mexc.js +5 -3
- package/dist/cjs/src/pro/okx.js +1 -1
- package/dist/cjs/src/pro/woo.js +1 -1
- package/dist/cjs/src/woo.js +2 -2
- package/js/ccxt.d.ts +1 -1
- package/js/ccxt.js +1 -1
- package/js/src/base/Exchange.js +2 -0
- package/js/src/binance.js +2 -2
- package/js/src/bingx.js +3 -3
- package/js/src/bitget.js +1 -1
- package/js/src/bitmex.js +1 -1
- package/js/src/blofin.js +1 -1
- package/js/src/coinbase.js +24 -14
- package/js/src/lbank.js +1 -1
- package/js/src/mexc.js +1 -1
- package/js/src/okx.js +1 -1
- package/js/src/phemex.js +1 -1
- package/js/src/pro/binance.js +1 -1
- package/js/src/pro/bitfinex2.js +1 -1
- package/js/src/pro/bitget.js +1 -1
- package/js/src/pro/bitmart.d.ts +2 -2
- package/js/src/pro/bitmart.js +51 -89
- package/js/src/pro/bitvavo.js +1 -1
- package/js/src/pro/bybit.js +1 -1
- package/js/src/pro/coinex.js +1 -1
- package/js/src/pro/cryptocom.js +1 -1
- package/js/src/pro/deribit.d.ts +5 -0
- package/js/src/pro/deribit.js +202 -85
- package/js/src/pro/gate.js +1 -1
- package/js/src/pro/independentreserve.js +1 -1
- package/js/src/pro/kraken.js +1 -1
- package/js/src/pro/kucoinfutures.js +1 -1
- package/js/src/pro/mexc.js +6 -4
- package/js/src/pro/okx.js +1 -1
- package/js/src/pro/woo.js +1 -1
- package/js/src/woo.js +2 -2
- package/package.json +1 -1
- package/skip-tests.json +2 -2
package/js/src/pro/deribit.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
import deribitRest from '../deribit.js';
|
|
9
|
-
import { NotSupported, ExchangeError } from '../base/errors.js';
|
|
9
|
+
import { NotSupported, ExchangeError, ArgumentsRequired } from '../base/errors.js';
|
|
10
10
|
import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
|
|
11
11
|
import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
@@ -19,10 +19,13 @@ export default class deribit extends deribitRest {
|
|
|
19
19
|
'watchTicker': true,
|
|
20
20
|
'watchTickers': false,
|
|
21
21
|
'watchTrades': true,
|
|
22
|
+
'watchTradesForSymbols': true,
|
|
22
23
|
'watchMyTrades': true,
|
|
23
24
|
'watchOrders': true,
|
|
24
25
|
'watchOrderBook': true,
|
|
26
|
+
'watchOrderBookForSymbols': true,
|
|
25
27
|
'watchOHLCV': true,
|
|
28
|
+
'watchOHLCVForSymbols': true,
|
|
26
29
|
},
|
|
27
30
|
'urls': {
|
|
28
31
|
'test': {
|
|
@@ -33,18 +36,31 @@ export default class deribit extends deribitRest {
|
|
|
33
36
|
},
|
|
34
37
|
},
|
|
35
38
|
'options': {
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
'ws': {
|
|
40
|
+
'timeframes': {
|
|
41
|
+
'1m': '1',
|
|
42
|
+
'3m': '3',
|
|
43
|
+
'5m': '5',
|
|
44
|
+
'15m': '15',
|
|
45
|
+
'30m': '30',
|
|
46
|
+
'1h': '60',
|
|
47
|
+
'2h': '120',
|
|
48
|
+
'4h': '180',
|
|
49
|
+
'6h': '360',
|
|
50
|
+
'12h': '720',
|
|
51
|
+
'1d': '1D',
|
|
52
|
+
},
|
|
53
|
+
// watchTrades replacement
|
|
54
|
+
'watchTradesForSymbols': {
|
|
55
|
+
'interval': '100ms', // 100ms, agg2, raw
|
|
56
|
+
},
|
|
57
|
+
// watchOrderBook replacement
|
|
58
|
+
'watchOrderBookForSymbols': {
|
|
59
|
+
'interval': '100ms',
|
|
60
|
+
'useDepthEndpoint': false,
|
|
61
|
+
'depth': '20',
|
|
62
|
+
'group': 'none', // none, 1, 2, 5, 10, 25, 100, 250
|
|
63
|
+
},
|
|
48
64
|
},
|
|
49
65
|
'currencies': ['BTC', 'ETH', 'SOL', 'USDC'],
|
|
50
66
|
},
|
|
@@ -224,27 +240,31 @@ export default class deribit extends deribitRest {
|
|
|
224
240
|
* @param {str} [params.interval] specify aggregation and frequency of notifications. Possible values: 100ms, raw
|
|
225
241
|
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
|
|
226
242
|
*/
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
243
|
+
params['callerMethodName'] = 'watchTrades';
|
|
244
|
+
return await this.watchTradesForSymbols([symbol], since, limit, params);
|
|
245
|
+
}
|
|
246
|
+
async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
|
|
247
|
+
/**
|
|
248
|
+
* @method
|
|
249
|
+
* @name deribit#watchTradesForSymbols
|
|
250
|
+
* @description get the list of most recent trades for a list of symbols
|
|
251
|
+
* @see https://docs.deribit.com/#trades-instrument_name-interval
|
|
252
|
+
* @param {string[]} symbols unified symbol of the market to fetch trades for
|
|
253
|
+
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
254
|
+
* @param {int} [limit] the maximum amount of trades to fetch
|
|
255
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
256
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
|
|
257
|
+
*/
|
|
258
|
+
let interval = undefined;
|
|
259
|
+
[interval, params] = this.handleOptionAndParams(params, 'watchTradesForSymbols', 'interval', '100ms');
|
|
233
260
|
if (interval === 'raw') {
|
|
234
261
|
await this.authenticate();
|
|
235
262
|
}
|
|
236
|
-
const
|
|
237
|
-
'jsonrpc': '2.0',
|
|
238
|
-
'method': 'public/subscribe',
|
|
239
|
-
'params': {
|
|
240
|
-
'channels': [channel],
|
|
241
|
-
},
|
|
242
|
-
'id': this.requestId(),
|
|
243
|
-
};
|
|
244
|
-
const request = this.deepExtend(message, params);
|
|
245
|
-
const trades = await this.watch(url, channel, request, channel, request);
|
|
263
|
+
const trades = await this.watchMultipleWrapper('trades', interval, symbols, params);
|
|
246
264
|
if (this.newUpdates) {
|
|
247
|
-
|
|
265
|
+
const first = this.safeDict(trades, 0);
|
|
266
|
+
const tradeSymbol = this.safeString(first, 'symbol');
|
|
267
|
+
limit = trades.getLimit(tradeSymbol, limit);
|
|
248
268
|
}
|
|
249
269
|
return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
|
|
250
270
|
}
|
|
@@ -270,26 +290,27 @@ export default class deribit extends deribitRest {
|
|
|
270
290
|
// }
|
|
271
291
|
// }
|
|
272
292
|
//
|
|
273
|
-
const params = this.
|
|
293
|
+
const params = this.safeDict(message, 'params', {});
|
|
274
294
|
const channel = this.safeString(params, 'channel', '');
|
|
275
295
|
const parts = channel.split('.');
|
|
276
296
|
const marketId = this.safeString(parts, 1);
|
|
297
|
+
const interval = this.safeString(parts, 2);
|
|
277
298
|
const symbol = this.safeSymbol(marketId);
|
|
278
299
|
const market = this.safeMarket(marketId);
|
|
279
|
-
const trades = this.
|
|
280
|
-
|
|
281
|
-
if (stored === undefined) {
|
|
300
|
+
const trades = this.safeList(params, 'data', []);
|
|
301
|
+
if (this.safeValue(this.trades, symbol) === undefined) {
|
|
282
302
|
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
283
|
-
|
|
284
|
-
this.trades[symbol] = stored;
|
|
303
|
+
this.trades[symbol] = new ArrayCache(limit);
|
|
285
304
|
}
|
|
305
|
+
const stored = this.trades[symbol];
|
|
286
306
|
for (let i = 0; i < trades.length; i++) {
|
|
287
307
|
const trade = trades[i];
|
|
288
308
|
const parsed = this.parseTrade(trade, market);
|
|
289
309
|
stored.append(parsed);
|
|
290
310
|
}
|
|
291
311
|
this.trades[symbol] = stored;
|
|
292
|
-
|
|
312
|
+
const messageHash = 'trades|' + symbol + '|' + interval;
|
|
313
|
+
client.resolve(this.trades[symbol], messageHash);
|
|
293
314
|
}
|
|
294
315
|
async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
295
316
|
/**
|
|
@@ -380,7 +401,7 @@ export default class deribit extends deribitRest {
|
|
|
380
401
|
/**
|
|
381
402
|
* @method
|
|
382
403
|
* @name deribit#watchOrderBook
|
|
383
|
-
* @see https://docs.deribit.com/#
|
|
404
|
+
* @see https://docs.deribit.com/#book-instrument_name-group-depth-interval
|
|
384
405
|
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
385
406
|
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
386
407
|
* @param {int} [limit] the maximum amount of order book entries to return
|
|
@@ -388,25 +409,39 @@ export default class deribit extends deribitRest {
|
|
|
388
409
|
* @param {string} [params.interval] Frequency of notifications. Events will be aggregated over this interval. Possible values: 100ms, raw
|
|
389
410
|
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
390
411
|
*/
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
412
|
+
params['callerMethodName'] = 'watchOrderBook';
|
|
413
|
+
return await this.watchOrderBookForSymbols([symbol], limit, params);
|
|
414
|
+
}
|
|
415
|
+
async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
|
|
416
|
+
/**
|
|
417
|
+
* @method
|
|
418
|
+
* @name deribit#watchOrderBookForSymbols
|
|
419
|
+
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
420
|
+
* @see https://docs.deribit.com/#book-instrument_name-group-depth-interval
|
|
421
|
+
* @param {string[]} symbols unified array of symbols
|
|
422
|
+
* @param {int} [limit] the maximum amount of order book entries to return
|
|
423
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
424
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
425
|
+
*/
|
|
426
|
+
let interval = undefined;
|
|
427
|
+
[interval, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'interval', '100ms');
|
|
396
428
|
if (interval === 'raw') {
|
|
397
429
|
await this.authenticate();
|
|
398
430
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
431
|
+
let descriptor = '';
|
|
432
|
+
let useDepthEndpoint = undefined; // for more info, see comment in .options
|
|
433
|
+
[useDepthEndpoint, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'useDepthEndpoint', false);
|
|
434
|
+
if (useDepthEndpoint) {
|
|
435
|
+
let depth = undefined;
|
|
436
|
+
[depth, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'depth', '20');
|
|
437
|
+
let group = undefined;
|
|
438
|
+
[group, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'group', 'none');
|
|
439
|
+
descriptor = group + '.' + depth + '.' + interval;
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
descriptor = interval;
|
|
443
|
+
}
|
|
444
|
+
const orderbook = await this.watchMultipleWrapper('book', descriptor, symbols, params);
|
|
410
445
|
return orderbook.limit();
|
|
411
446
|
}
|
|
412
447
|
handleOrderBook(client, message) {
|
|
@@ -458,6 +493,20 @@ export default class deribit extends deribitRest {
|
|
|
458
493
|
const params = this.safeValue(message, 'params', {});
|
|
459
494
|
const data = this.safeValue(params, 'data', {});
|
|
460
495
|
const channel = this.safeString(params, 'channel');
|
|
496
|
+
const parts = channel.split('.');
|
|
497
|
+
let descriptor = '';
|
|
498
|
+
const partsLength = parts.length;
|
|
499
|
+
const isDetailed = partsLength === 5;
|
|
500
|
+
if (isDetailed) {
|
|
501
|
+
const group = this.safeString(parts, 2);
|
|
502
|
+
const depth = this.safeString(parts, 3);
|
|
503
|
+
const interval = this.safeString(parts, 4);
|
|
504
|
+
descriptor = group + '.' + depth + '.' + interval;
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
const interval = this.safeString(parts, 2);
|
|
508
|
+
descriptor = interval;
|
|
509
|
+
}
|
|
461
510
|
const marketId = this.safeString(data, 'instrument_name');
|
|
462
511
|
const symbol = this.safeSymbol(marketId);
|
|
463
512
|
const timestamp = this.safeInteger(data, 'timestamp');
|
|
@@ -474,7 +523,8 @@ export default class deribit extends deribitRest {
|
|
|
474
523
|
storedOrderBook['datetime'] = this.iso8601(timestamp);
|
|
475
524
|
storedOrderBook['symbol'] = symbol;
|
|
476
525
|
this.orderbooks[symbol] = storedOrderBook;
|
|
477
|
-
|
|
526
|
+
const messageHash = 'book|' + symbol + '|' + descriptor;
|
|
527
|
+
client.resolve(storedOrderBook, messageHash);
|
|
478
528
|
}
|
|
479
529
|
cleanOrderBook(data) {
|
|
480
530
|
const bids = this.safeValue(data, 'bids', []);
|
|
@@ -614,28 +664,32 @@ export default class deribit extends deribitRest {
|
|
|
614
664
|
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
615
665
|
*/
|
|
616
666
|
await this.loadMarkets();
|
|
617
|
-
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
667
|
+
symbol = this.symbol(symbol);
|
|
668
|
+
const ohlcvs = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
|
|
669
|
+
return ohlcvs[symbol][timeframe];
|
|
670
|
+
}
|
|
671
|
+
async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
|
|
672
|
+
/**
|
|
673
|
+
* @method
|
|
674
|
+
* @name deribit#watchOHLCVForSymbols
|
|
675
|
+
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
676
|
+
* @see https://docs.deribit.com/#chart-trades-instrument_name-resolution
|
|
677
|
+
* @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
|
|
678
|
+
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
679
|
+
* @param {int} [limit] the maximum amount of candles to fetch
|
|
680
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
681
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
682
|
+
*/
|
|
683
|
+
const symbolsLength = symbolsAndTimeframes.length;
|
|
684
|
+
if (symbolsLength === 0 || !Array.isArray(symbolsAndTimeframes[0])) {
|
|
685
|
+
throw new ArgumentsRequired(this.id + " watchOHLCVForSymbols() requires a an array of symbols and timeframes, like [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]");
|
|
623
686
|
}
|
|
624
|
-
const
|
|
625
|
-
const message = {
|
|
626
|
-
'jsonrpc': '2.0',
|
|
627
|
-
'method': 'public/subscribe',
|
|
628
|
-
'params': {
|
|
629
|
-
'channels': [channel],
|
|
630
|
-
},
|
|
631
|
-
'id': this.requestId(),
|
|
632
|
-
};
|
|
633
|
-
const request = this.deepExtend(message, params);
|
|
634
|
-
const ohlcv = await this.watch(url, channel, request, channel, request);
|
|
687
|
+
const [symbol, timeframe, candles] = await this.watchMultipleWrapper('chart.trades', undefined, symbolsAndTimeframes, params);
|
|
635
688
|
if (this.newUpdates) {
|
|
636
|
-
limit =
|
|
689
|
+
limit = candles.getLimit(symbol, limit);
|
|
637
690
|
}
|
|
638
|
-
|
|
691
|
+
const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
|
|
692
|
+
return this.createOHLCVObject(symbol, timeframe, filtered);
|
|
639
693
|
}
|
|
640
694
|
handleOHLCV(client, message) {
|
|
641
695
|
//
|
|
@@ -656,13 +710,44 @@ export default class deribit extends deribitRest {
|
|
|
656
710
|
// }
|
|
657
711
|
// }
|
|
658
712
|
//
|
|
659
|
-
const params = this.
|
|
713
|
+
const params = this.safeDict(message, 'params', {});
|
|
660
714
|
const channel = this.safeString(params, 'channel', '');
|
|
661
715
|
const parts = channel.split('.');
|
|
662
716
|
const marketId = this.safeString(parts, 2);
|
|
663
|
-
const
|
|
664
|
-
const
|
|
665
|
-
const
|
|
717
|
+
const rawTimeframe = this.safeString(parts, 3);
|
|
718
|
+
const market = this.safeMarket(marketId);
|
|
719
|
+
const symbol = market['symbol'];
|
|
720
|
+
const wsOptions = this.safeDict(this.options, 'ws', {});
|
|
721
|
+
const timeframes = this.safeDict(wsOptions, 'timeframes', {});
|
|
722
|
+
const unifiedTimeframe = this.findTimeframe(rawTimeframe, timeframes);
|
|
723
|
+
this.ohlcvs[symbol] = this.safeDict(this.ohlcvs, symbol, {});
|
|
724
|
+
if (this.safeValue(this.ohlcvs[symbol], unifiedTimeframe) === undefined) {
|
|
725
|
+
const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
|
|
726
|
+
this.ohlcvs[symbol][unifiedTimeframe] = new ArrayCacheByTimestamp(limit);
|
|
727
|
+
}
|
|
728
|
+
const stored = this.ohlcvs[symbol][unifiedTimeframe];
|
|
729
|
+
const ohlcv = this.safeDict(params, 'data', {});
|
|
730
|
+
// data contains a single OHLCV candle
|
|
731
|
+
const parsed = this.parseWsOHLCV(ohlcv, market);
|
|
732
|
+
stored.append(parsed);
|
|
733
|
+
this.ohlcvs[symbol][unifiedTimeframe] = stored;
|
|
734
|
+
const resolveData = [symbol, unifiedTimeframe, stored];
|
|
735
|
+
const messageHash = 'chart.trades|' + symbol + '|' + rawTimeframe;
|
|
736
|
+
client.resolve(resolveData, messageHash);
|
|
737
|
+
}
|
|
738
|
+
parseWsOHLCV(ohlcv, market = undefined) {
|
|
739
|
+
//
|
|
740
|
+
// {
|
|
741
|
+
// "c": "28909.0",
|
|
742
|
+
// "o": "28915.4",
|
|
743
|
+
// "h": "28915.4",
|
|
744
|
+
// "l": "28896.1",
|
|
745
|
+
// "v": "27.6919",
|
|
746
|
+
// "T": 1696687499999,
|
|
747
|
+
// "t": 1696687440000
|
|
748
|
+
// }
|
|
749
|
+
//
|
|
750
|
+
return [
|
|
666
751
|
this.safeInteger(ohlcv, 'tick'),
|
|
667
752
|
this.safeNumber(ohlcv, 'open'),
|
|
668
753
|
this.safeNumber(ohlcv, 'high'),
|
|
@@ -670,14 +755,46 @@ export default class deribit extends deribitRest {
|
|
|
670
755
|
this.safeNumber(ohlcv, 'close'),
|
|
671
756
|
this.safeNumber(ohlcv, 'volume'),
|
|
672
757
|
];
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
758
|
+
}
|
|
759
|
+
async watchMultipleWrapper(channelName, channelDescriptor, symbolsArray = undefined, params = {}) {
|
|
760
|
+
await this.loadMarkets();
|
|
761
|
+
const url = this.urls['api']['ws'];
|
|
762
|
+
const rawSubscriptions = [];
|
|
763
|
+
const messageHashes = [];
|
|
764
|
+
const isOHLCV = (channelName === 'chart.trades');
|
|
765
|
+
const symbols = isOHLCV ? this.getListFromObjectValues(symbolsArray, 0) : symbolsArray;
|
|
766
|
+
this.marketSymbols(symbols, undefined, false);
|
|
767
|
+
for (let i = 0; i < symbolsArray.length; i++) {
|
|
768
|
+
const current = symbolsArray[i];
|
|
769
|
+
let market = undefined;
|
|
770
|
+
if (isOHLCV) {
|
|
771
|
+
market = this.market(current[0]);
|
|
772
|
+
const unifiedTf = current[1];
|
|
773
|
+
const rawTf = this.safeString(this.timeframes, unifiedTf, unifiedTf);
|
|
774
|
+
channelDescriptor = rawTf;
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
market = this.market(current);
|
|
778
|
+
}
|
|
779
|
+
const message = channelName + '.' + market['id'] + '.' + channelDescriptor;
|
|
780
|
+
rawSubscriptions.push(message);
|
|
781
|
+
messageHashes.push(channelName + '|' + market['symbol'] + '|' + channelDescriptor);
|
|
677
782
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
783
|
+
const request = {
|
|
784
|
+
'jsonrpc': '2.0',
|
|
785
|
+
'method': 'public/subscribe',
|
|
786
|
+
'params': {
|
|
787
|
+
'channels': rawSubscriptions,
|
|
788
|
+
},
|
|
789
|
+
'id': this.requestId(),
|
|
790
|
+
};
|
|
791
|
+
const extendedRequest = this.deepExtend(request, params);
|
|
792
|
+
const maxMessageByteLimit = 32768 - 1; // 'Message Too Big: limit 32768B'
|
|
793
|
+
const jsonedText = this.json(extendedRequest);
|
|
794
|
+
if (jsonedText.length >= maxMessageByteLimit) {
|
|
795
|
+
throw new ExchangeError(this.id + ' requested subscription length over limit, try to reduce symbols amount');
|
|
796
|
+
}
|
|
797
|
+
return await this.watchMultiple(url, messageHashes, extendedRequest, rawSubscriptions);
|
|
681
798
|
}
|
|
682
799
|
handleMessage(client, message) {
|
|
683
800
|
//
|
package/js/src/pro/gate.js
CHANGED
|
@@ -825,7 +825,7 @@ export default class gate extends gateRest {
|
|
|
825
825
|
const client = this.client(url);
|
|
826
826
|
this.setPositionsCache(client, type, symbols);
|
|
827
827
|
const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
|
|
828
|
-
const awaitPositionsSnapshot = this.
|
|
828
|
+
const awaitPositionsSnapshot = this.safeBool('watchPositions', 'awaitPositionsSnapshot', true);
|
|
829
829
|
const cache = this.safeValue(this.positions, type);
|
|
830
830
|
if (fetchPositionsSnapshot && awaitPositionsSnapshot && cache === undefined) {
|
|
831
831
|
return await client.future(type + ':fetchPositionsSnapshot');
|
|
@@ -199,7 +199,7 @@ export default class independentreserve extends independentreserveRest {
|
|
|
199
199
|
orderbook['timestamp'] = timestamp;
|
|
200
200
|
orderbook['datetime'] = this.iso8601(timestamp);
|
|
201
201
|
}
|
|
202
|
-
const checksum = this.
|
|
202
|
+
const checksum = this.safeBool(this.options, 'checksum', true);
|
|
203
203
|
if (checksum && receivedSnapshot) {
|
|
204
204
|
const storedAsks = orderbook['asks'];
|
|
205
205
|
const storedBids = orderbook['bids'];
|
package/js/src/pro/kraken.js
CHANGED
|
@@ -700,7 +700,7 @@ export default class kraken extends krakenRest {
|
|
|
700
700
|
}
|
|
701
701
|
// don't remove this line or I will poop on your face
|
|
702
702
|
orderbook.limit();
|
|
703
|
-
const checksum = this.
|
|
703
|
+
const checksum = this.safeBool(this.options, 'checksum', true);
|
|
704
704
|
if (checksum) {
|
|
705
705
|
const priceString = this.safeString(example, 0);
|
|
706
706
|
const amountString = this.safeString(example, 1);
|
|
@@ -241,7 +241,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
|
|
|
241
241
|
const client = this.client(url);
|
|
242
242
|
this.setPositionCache(client, symbol);
|
|
243
243
|
const fetchPositionSnapshot = this.handleOption('watchPosition', 'fetchPositionSnapshot', true);
|
|
244
|
-
const awaitPositionSnapshot = this.
|
|
244
|
+
const awaitPositionSnapshot = this.safeBool('watchPosition', 'awaitPositionSnapshot', true);
|
|
245
245
|
const currentPosition = this.getCurrentPosition(symbol);
|
|
246
246
|
if (fetchPositionSnapshot && awaitPositionSnapshot && currentPosition === undefined) {
|
|
247
247
|
const snapshot = await client.future('fetchPositionSnapshot:' + symbol);
|
package/js/src/pro/mexc.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
import mexcRest from '../mexc.js';
|
|
9
|
-
import {
|
|
9
|
+
import { AuthenticationError } from '../base/errors.js';
|
|
10
10
|
import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
|
|
11
11
|
import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
@@ -503,10 +503,12 @@ export default class mexc extends mexcRest {
|
|
|
503
503
|
}
|
|
504
504
|
}
|
|
505
505
|
handleDelta(orderbook, delta) {
|
|
506
|
-
const
|
|
506
|
+
const existingNonce = this.safeInteger(orderbook, 'nonce');
|
|
507
507
|
const deltaNonce = this.safeInteger2(delta, 'r', 'version');
|
|
508
|
-
if (deltaNonce
|
|
509
|
-
|
|
508
|
+
if (deltaNonce < existingNonce) {
|
|
509
|
+
// even when doing < comparison, this happens: https://app.travis-ci.com/github/ccxt/ccxt/builds/269234741#L1809
|
|
510
|
+
// so, we just skip old updates
|
|
511
|
+
return;
|
|
510
512
|
}
|
|
511
513
|
orderbook['nonce'] = deltaNonce;
|
|
512
514
|
const asks = this.safeValue(delta, 'asks', []);
|
package/js/src/pro/okx.js
CHANGED
|
@@ -562,7 +562,7 @@ export default class okx extends okxRest {
|
|
|
562
562
|
const storedBids = orderbook['bids'];
|
|
563
563
|
this.handleDeltas(storedAsks, asks);
|
|
564
564
|
this.handleDeltas(storedBids, bids);
|
|
565
|
-
const checksum = this.
|
|
565
|
+
const checksum = this.safeBool(this.options, 'checksum', true);
|
|
566
566
|
if (checksum) {
|
|
567
567
|
const asksLength = storedAsks.length;
|
|
568
568
|
const bidsLength = storedBids.length;
|
package/js/src/pro/woo.js
CHANGED
|
@@ -632,7 +632,7 @@ export default class woo extends wooRest {
|
|
|
632
632
|
const client = this.client(url);
|
|
633
633
|
this.setPositionsCache(client, symbols);
|
|
634
634
|
const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
|
|
635
|
-
const awaitPositionsSnapshot = this.
|
|
635
|
+
const awaitPositionsSnapshot = this.safeBool('watchPositions', 'awaitPositionsSnapshot', true);
|
|
636
636
|
if (fetchPositionsSnapshot && awaitPositionsSnapshot && this.positions === undefined) {
|
|
637
637
|
const snapshot = await client.future('fetchPositionsSnapshot');
|
|
638
638
|
return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
|
package/js/src/woo.js
CHANGED
|
@@ -493,7 +493,7 @@ export default class woo extends Exchange {
|
|
|
493
493
|
// ]
|
|
494
494
|
// }
|
|
495
495
|
//
|
|
496
|
-
const resultResponse = this.
|
|
496
|
+
const resultResponse = this.safeList(response, 'rows', []);
|
|
497
497
|
return this.parseTrades(resultResponse, market, since, limit);
|
|
498
498
|
}
|
|
499
499
|
parseTrade(trade, market = undefined) {
|
|
@@ -2337,7 +2337,7 @@ export default class woo extends Exchange {
|
|
|
2337
2337
|
else {
|
|
2338
2338
|
this.checkRequiredCredentials();
|
|
2339
2339
|
if (method === 'POST' && (path === 'algo/order' || path === 'order')) {
|
|
2340
|
-
const isSandboxMode = this.
|
|
2340
|
+
const isSandboxMode = this.safeBool(this.options, 'sandboxMode', false);
|
|
2341
2341
|
if (!isSandboxMode) {
|
|
2342
2342
|
const applicationId = 'bc830de7-50f3-460b-9ee0-f430f83f9dad';
|
|
2343
2343
|
const brokerId = this.safeString(this.options, 'brokerId', applicationId);
|
package/package.json
CHANGED
package/skip-tests.json
CHANGED
|
@@ -297,7 +297,6 @@
|
|
|
297
297
|
}
|
|
298
298
|
},
|
|
299
299
|
"bitmart": {
|
|
300
|
-
"skipWs": true,
|
|
301
300
|
"skipMethods": {
|
|
302
301
|
"loadMarkets": {
|
|
303
302
|
"expiry":"expiry is expected to be > 0",
|
|
@@ -336,7 +335,8 @@
|
|
|
336
335
|
"spread": "same"
|
|
337
336
|
},
|
|
338
337
|
"watchTrades":{
|
|
339
|
-
"side": "not set https://app.travis-ci.com/github/ccxt/ccxt/builds/267900037#L4312"
|
|
338
|
+
"side": "not set https://app.travis-ci.com/github/ccxt/ccxt/builds/267900037#L4312",
|
|
339
|
+
"timestamp": "messed order coming from exchange"
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
},
|