ccxt 4.4.85 → 4.4.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +6 -7
  2. package/dist/ccxt.browser.min.js +2 -2
  3. package/dist/cjs/ccxt.js +6 -9
  4. package/dist/cjs/src/abstract/bittrade.js +9 -0
  5. package/dist/cjs/src/ascendex.js +189 -155
  6. package/dist/cjs/src/bequant.js +1 -1
  7. package/dist/cjs/src/bitget.js +5 -4
  8. package/dist/cjs/src/bitmart.js +1 -1
  9. package/dist/cjs/src/bittrade.js +2049 -0
  10. package/dist/cjs/src/coinbase.js +2 -6
  11. package/dist/cjs/src/deribit.js +4 -5
  12. package/dist/cjs/src/hollaex.js +107 -49
  13. package/dist/cjs/src/htx.js +20 -44
  14. package/dist/cjs/src/hyperliquid.js +4 -4
  15. package/dist/cjs/src/mexc.js +2 -2
  16. package/dist/cjs/src/ndax.js +25 -24
  17. package/dist/cjs/src/okcoin.js +12 -31
  18. package/dist/cjs/src/okx.js +9 -0
  19. package/dist/cjs/src/onetrading.js +9 -6
  20. package/dist/cjs/src/oxfun.js +42 -114
  21. package/dist/cjs/src/paradex.js +5 -1
  22. package/dist/cjs/src/pro/binance.js +1 -0
  23. package/dist/cjs/src/pro/bittrade.js +605 -0
  24. package/dist/cjs/src/pro/luno.js +6 -5
  25. package/dist/cjs/src/pro/mexc.js +3 -0
  26. package/js/ccxt.d.ts +8 -11
  27. package/js/ccxt.js +6 -8
  28. package/js/src/abstract/myokx.d.ts +2 -0
  29. package/js/src/abstract/okx.d.ts +2 -0
  30. package/js/src/ascendex.d.ts +2 -0
  31. package/js/src/ascendex.js +189 -155
  32. package/js/src/bequant.js +1 -1
  33. package/js/src/bitget.js +5 -4
  34. package/js/src/bitmart.js +1 -1
  35. package/js/src/{huobijp.d.ts → bittrade.d.ts} +29 -29
  36. package/js/src/{huobijp.js → bittrade.js} +35 -35
  37. package/js/src/coinbase.js +2 -6
  38. package/js/src/deribit.js +4 -5
  39. package/js/src/hollaex.js +107 -49
  40. package/js/src/htx.js +20 -44
  41. package/js/src/hyperliquid.js +4 -4
  42. package/js/src/mexc.js +2 -2
  43. package/js/src/ndax.js +25 -24
  44. package/js/src/okcoin.js +12 -31
  45. package/js/src/okx.js +9 -0
  46. package/js/src/onetrading.js +9 -6
  47. package/js/src/oxfun.js +42 -114
  48. package/js/src/paradex.js +5 -1
  49. package/js/src/pro/binance.js +1 -0
  50. package/js/src/pro/{huobijp.d.ts → bittrade.d.ts} +6 -6
  51. package/js/src/pro/{huobijp.js → bittrade.js} +7 -7
  52. package/js/src/pro/luno.js +6 -5
  53. package/js/src/pro/mexc.js +3 -0
  54. package/package.json +1 -1
  55. package/js/src/abstract/kuna.d.ts +0 -185
  56. package/js/src/abstract/kuna.js +0 -11
  57. package/js/src/kuna.d.ts +0 -335
  58. package/js/src/kuna.js +0 -2006
  59. /package/js/src/abstract/{huobijp.d.ts → bittrade.d.ts} +0 -0
  60. /package/js/src/abstract/{huobijp.js → bittrade.js} +0 -0
@@ -0,0 +1,605 @@
1
+ 'use strict';
2
+
3
+ var bittrade$1 = require('../bittrade.js');
4
+ var errors = require('../base/errors.js');
5
+ var Cache = require('../base/ws/Cache.js');
6
+
7
+ // ----------------------------------------------------------------------------
8
+ // ----------------------------------------------------------------------------
9
+ class bittrade extends bittrade$1 {
10
+ describe() {
11
+ return this.deepExtend(super.describe(), {
12
+ 'has': {
13
+ 'ws': true,
14
+ 'watchOrderBook': true,
15
+ 'watchTickers': false,
16
+ 'watchTicker': true,
17
+ 'watchTrades': true,
18
+ 'watchTradesForSymbols': false,
19
+ 'watchBalance': false,
20
+ 'watchOHLCV': true,
21
+ },
22
+ 'urls': {
23
+ 'api': {
24
+ 'ws': {
25
+ 'api': {
26
+ 'public': 'wss://{hostname}/ws',
27
+ 'private': 'wss://{hostname}/ws/v2',
28
+ },
29
+ },
30
+ },
31
+ },
32
+ 'options': {
33
+ 'tradesLimit': 1000,
34
+ 'OHLCVLimit': 1000,
35
+ 'api': 'api',
36
+ 'ws': {
37
+ 'gunzip': true,
38
+ },
39
+ },
40
+ });
41
+ }
42
+ requestId() {
43
+ const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
44
+ this.options['requestId'] = requestId;
45
+ return requestId.toString();
46
+ }
47
+ /**
48
+ * @method
49
+ * @name bittrade#watchTicker
50
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
51
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
52
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
53
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
54
+ */
55
+ async watchTicker(symbol, params = {}) {
56
+ await this.loadMarkets();
57
+ const market = this.market(symbol);
58
+ symbol = market['symbol'];
59
+ // only supports a limit of 150 at this time
60
+ const messageHash = 'market.' + market['id'] + '.detail';
61
+ const api = this.safeString(this.options, 'api', 'api');
62
+ const hostname = { 'hostname': this.hostname };
63
+ const url = this.implodeParams(this.urls['api']['ws'][api]['public'], hostname);
64
+ const requestId = this.requestId();
65
+ const request = {
66
+ 'sub': messageHash,
67
+ 'id': requestId,
68
+ };
69
+ const subscription = {
70
+ 'id': requestId,
71
+ 'messageHash': messageHash,
72
+ 'symbol': symbol,
73
+ 'params': params,
74
+ };
75
+ return await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
76
+ }
77
+ handleTicker(client, message) {
78
+ //
79
+ // {
80
+ // "ch": "market.btcusdt.detail",
81
+ // "ts": 1583494163784,
82
+ // "tick": {
83
+ // "id": 209988464418,
84
+ // "low": 8988,
85
+ // "high": 9155.41,
86
+ // "open": 9078.91,
87
+ // "close": 9136.46,
88
+ // "vol": 237813910.5928412,
89
+ // "amount": 26184.202558551195,
90
+ // "version": 209988464418,
91
+ // "count": 265673
92
+ // }
93
+ // }
94
+ //
95
+ const tick = this.safeValue(message, 'tick', {});
96
+ const ch = this.safeString(message, 'ch');
97
+ const parts = ch.split('.');
98
+ const marketId = this.safeString(parts, 1);
99
+ const market = this.safeMarket(marketId);
100
+ const ticker = this.parseTicker(tick, market);
101
+ const timestamp = this.safeValue(message, 'ts');
102
+ ticker['timestamp'] = timestamp;
103
+ ticker['datetime'] = this.iso8601(timestamp);
104
+ const symbol = ticker['symbol'];
105
+ this.tickers[symbol] = ticker;
106
+ client.resolve(ticker, ch);
107
+ return message;
108
+ }
109
+ /**
110
+ * @method
111
+ * @name bittrade#watchTrades
112
+ * @description get the list of most recent trades for a particular symbol
113
+ * @param {string} symbol unified symbol of the market to fetch trades for
114
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
115
+ * @param {int} [limit] the maximum amount of trades to fetch
116
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
117
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
118
+ */
119
+ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
120
+ await this.loadMarkets();
121
+ const market = this.market(symbol);
122
+ symbol = market['symbol'];
123
+ // only supports a limit of 150 at this time
124
+ const messageHash = 'market.' + market['id'] + '.trade.detail';
125
+ const api = this.safeString(this.options, 'api', 'api');
126
+ const hostname = { 'hostname': this.hostname };
127
+ const url = this.implodeParams(this.urls['api']['ws'][api]['public'], hostname);
128
+ const requestId = this.requestId();
129
+ const request = {
130
+ 'sub': messageHash,
131
+ 'id': requestId,
132
+ };
133
+ const subscription = {
134
+ 'id': requestId,
135
+ 'messageHash': messageHash,
136
+ 'symbol': symbol,
137
+ 'params': params,
138
+ };
139
+ const trades = await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
140
+ if (this.newUpdates) {
141
+ limit = trades.getLimit(symbol, limit);
142
+ }
143
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
144
+ }
145
+ handleTrades(client, message) {
146
+ //
147
+ // {
148
+ // "ch": "market.btcusdt.trade.detail",
149
+ // "ts": 1583495834011,
150
+ // "tick": {
151
+ // "id": 105004645372,
152
+ // "ts": 1583495833751,
153
+ // "data": [
154
+ // {
155
+ // "id": 1.050046453727319e+22,
156
+ // "ts": 1583495833751,
157
+ // "tradeId": 102090727790,
158
+ // "amount": 0.003893,
159
+ // "price": 9150.01,
160
+ // "direction": "sell"
161
+ // }
162
+ // ]
163
+ // }
164
+ // }
165
+ //
166
+ const tick = this.safeValue(message, 'tick', {});
167
+ const data = this.safeValue(tick, 'data', {});
168
+ const ch = this.safeString(message, 'ch');
169
+ const parts = ch.split('.');
170
+ const marketId = this.safeString(parts, 1);
171
+ const market = this.safeMarket(marketId);
172
+ const symbol = market['symbol'];
173
+ let tradesCache = this.safeValue(this.trades, symbol);
174
+ if (tradesCache === undefined) {
175
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
176
+ tradesCache = new Cache.ArrayCache(limit);
177
+ this.trades[symbol] = tradesCache;
178
+ }
179
+ for (let i = 0; i < data.length; i++) {
180
+ const trade = this.parseTrade(data[i], market);
181
+ tradesCache.append(trade);
182
+ }
183
+ client.resolve(tradesCache, ch);
184
+ return message;
185
+ }
186
+ /**
187
+ * @method
188
+ * @name bittrade#watchOHLCV
189
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
190
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
191
+ * @param {string} timeframe the length of time each candle represents
192
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
193
+ * @param {int} [limit] the maximum amount of candles to fetch
194
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
195
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
196
+ */
197
+ async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
198
+ await this.loadMarkets();
199
+ const market = this.market(symbol);
200
+ symbol = market['symbol'];
201
+ const interval = this.safeString(this.timeframes, timeframe, timeframe);
202
+ const messageHash = 'market.' + market['id'] + '.kline.' + interval;
203
+ const api = this.safeString(this.options, 'api', 'api');
204
+ const hostname = { 'hostname': this.hostname };
205
+ const url = this.implodeParams(this.urls['api']['ws'][api]['public'], hostname);
206
+ const requestId = this.requestId();
207
+ const request = {
208
+ 'sub': messageHash,
209
+ 'id': requestId,
210
+ };
211
+ const subscription = {
212
+ 'id': requestId,
213
+ 'messageHash': messageHash,
214
+ 'symbol': symbol,
215
+ 'timeframe': timeframe,
216
+ 'params': params,
217
+ };
218
+ const ohlcv = await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
219
+ if (this.newUpdates) {
220
+ limit = ohlcv.getLimit(symbol, limit);
221
+ }
222
+ return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
223
+ }
224
+ handleOHLCV(client, message) {
225
+ //
226
+ // {
227
+ // "ch": "market.btcusdt.kline.1min",
228
+ // "ts": 1583501786794,
229
+ // "tick": {
230
+ // "id": 1583501760,
231
+ // "open": 9094.5,
232
+ // "close": 9094.51,
233
+ // "low": 9094.5,
234
+ // "high": 9094.51,
235
+ // "amount": 0.44639786263800907,
236
+ // "vol": 4059.76919054,
237
+ // "count": 16
238
+ // }
239
+ // }
240
+ //
241
+ const ch = this.safeString(message, 'ch');
242
+ const parts = ch.split('.');
243
+ const marketId = this.safeString(parts, 1);
244
+ const market = this.safeMarket(marketId);
245
+ const symbol = market['symbol'];
246
+ const interval = this.safeString(parts, 3);
247
+ const timeframe = this.findTimeframe(interval);
248
+ this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
249
+ let stored = this.safeValue(this.ohlcvs[symbol], timeframe);
250
+ if (stored === undefined) {
251
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
252
+ stored = new Cache.ArrayCacheByTimestamp(limit);
253
+ this.ohlcvs[symbol][timeframe] = stored;
254
+ }
255
+ const tick = this.safeValue(message, 'tick');
256
+ const parsed = this.parseOHLCV(tick, market);
257
+ stored.append(parsed);
258
+ client.resolve(stored, ch);
259
+ }
260
+ /**
261
+ * @method
262
+ * @name bittrade#watchOrderBook
263
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
264
+ * @param {string} symbol unified symbol of the market to fetch the order book for
265
+ * @param {int} [limit] the maximum amount of order book entries to return
266
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
267
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
268
+ */
269
+ async watchOrderBook(symbol, limit = undefined, params = {}) {
270
+ if ((limit !== undefined) && (limit !== 150)) {
271
+ throw new errors.ExchangeError(this.id + ' watchOrderBook accepts limit = 150 only');
272
+ }
273
+ await this.loadMarkets();
274
+ const market = this.market(symbol);
275
+ symbol = market['symbol'];
276
+ // only supports a limit of 150 at this time
277
+ limit = (limit === undefined) ? 150 : limit;
278
+ const messageHash = 'market.' + market['id'] + '.mbp.' + limit.toString();
279
+ const api = this.safeString(this.options, 'api', 'api');
280
+ const hostname = { 'hostname': this.hostname };
281
+ const url = this.implodeParams(this.urls['api']['ws'][api]['public'], hostname);
282
+ const requestId = this.requestId();
283
+ const request = {
284
+ 'sub': messageHash,
285
+ 'id': requestId,
286
+ };
287
+ const subscription = {
288
+ 'id': requestId,
289
+ 'messageHash': messageHash,
290
+ 'symbol': symbol,
291
+ 'limit': limit,
292
+ 'params': params,
293
+ 'method': this.handleOrderBookSubscription,
294
+ };
295
+ const orderbook = await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
296
+ return orderbook.limit();
297
+ }
298
+ handleOrderBookSnapshot(client, message, subscription) {
299
+ //
300
+ // {
301
+ // "id": 1583473663565,
302
+ // "rep": "market.btcusdt.mbp.150",
303
+ // "status": "ok",
304
+ // "data": {
305
+ // "seqNum": 104999417756,
306
+ // "bids": [
307
+ // [9058.27, 0],
308
+ // [9058.43, 0],
309
+ // [9058.99, 0],
310
+ // ],
311
+ // "asks": [
312
+ // [9084.27, 0.2],
313
+ // [9085.69, 0],
314
+ // [9085.81, 0],
315
+ // ]
316
+ // }
317
+ // }
318
+ //
319
+ const symbol = this.safeString(subscription, 'symbol');
320
+ const messageHash = this.safeString(subscription, 'messageHash');
321
+ const orderbook = this.orderbooks[symbol];
322
+ const data = this.safeValue(message, 'data');
323
+ const snapshot = this.parseOrderBook(data, symbol);
324
+ snapshot['nonce'] = this.safeInteger(data, 'seqNum');
325
+ orderbook.reset(snapshot);
326
+ // unroll the accumulated deltas
327
+ const messages = orderbook.cache;
328
+ for (let i = 0; i < messages.length; i++) {
329
+ this.handleOrderBookMessage(client, messages[i], orderbook);
330
+ }
331
+ this.orderbooks[symbol] = orderbook;
332
+ client.resolve(orderbook, messageHash);
333
+ }
334
+ async watchOrderBookSnapshot(client, message, subscription) {
335
+ const messageHash = this.safeString(subscription, 'messageHash');
336
+ try {
337
+ const symbol = this.safeString(subscription, 'symbol');
338
+ const limit = this.safeInteger(subscription, 'limit');
339
+ const params = this.safeValue(subscription, 'params');
340
+ const api = this.safeString(this.options, 'api', 'api');
341
+ const hostname = { 'hostname': this.hostname };
342
+ const url = this.implodeParams(this.urls['api']['ws'][api]['public'], hostname);
343
+ const requestId = this.requestId();
344
+ const request = {
345
+ 'req': messageHash,
346
+ 'id': requestId,
347
+ };
348
+ // this is a temporary subscription by a specific requestId
349
+ // it has a very short lifetime until the snapshot is received over ws
350
+ const snapshotSubscription = {
351
+ 'id': requestId,
352
+ 'messageHash': messageHash,
353
+ 'symbol': symbol,
354
+ 'limit': limit,
355
+ 'params': params,
356
+ 'method': this.handleOrderBookSnapshot,
357
+ };
358
+ const orderbook = await this.watch(url, requestId, request, requestId, snapshotSubscription);
359
+ return orderbook.limit();
360
+ }
361
+ catch (e) {
362
+ delete client.subscriptions[messageHash];
363
+ client.reject(e, messageHash);
364
+ }
365
+ return undefined;
366
+ }
367
+ handleDelta(bookside, delta) {
368
+ const price = this.safeFloat(delta, 0);
369
+ const amount = this.safeFloat(delta, 1);
370
+ bookside.store(price, amount);
371
+ }
372
+ handleDeltas(bookside, deltas) {
373
+ for (let i = 0; i < deltas.length; i++) {
374
+ this.handleDelta(bookside, deltas[i]);
375
+ }
376
+ }
377
+ handleOrderBookMessage(client, message, orderbook) {
378
+ //
379
+ // {
380
+ // "ch": "market.btcusdt.mbp.150",
381
+ // "ts": 1583472025885,
382
+ // "tick": {
383
+ // "seqNum": 104998984994,
384
+ // "prevSeqNum": 104998984977,
385
+ // "bids": [
386
+ // [9058.27, 0],
387
+ // [9058.43, 0],
388
+ // [9058.99, 0],
389
+ // ],
390
+ // "asks": [
391
+ // [9084.27, 0.2],
392
+ // [9085.69, 0],
393
+ // [9085.81, 0],
394
+ // ]
395
+ // }
396
+ // }
397
+ //
398
+ const tick = this.safeValue(message, 'tick', {});
399
+ const seqNum = this.safeInteger(tick, 'seqNum');
400
+ const prevSeqNum = this.safeInteger(tick, 'prevSeqNum');
401
+ if ((prevSeqNum <= orderbook['nonce']) && (seqNum > orderbook['nonce'])) {
402
+ const asks = this.safeValue(tick, 'asks', []);
403
+ const bids = this.safeValue(tick, 'bids', []);
404
+ this.handleDeltas(orderbook['asks'], asks);
405
+ this.handleDeltas(orderbook['bids'], bids);
406
+ orderbook['nonce'] = seqNum;
407
+ const timestamp = this.safeInteger(message, 'ts');
408
+ orderbook['timestamp'] = timestamp;
409
+ orderbook['datetime'] = this.iso8601(timestamp);
410
+ }
411
+ return orderbook;
412
+ }
413
+ handleOrderBook(client, message) {
414
+ //
415
+ // deltas
416
+ //
417
+ // {
418
+ // "ch": "market.btcusdt.mbp.150",
419
+ // "ts": 1583472025885,
420
+ // "tick": {
421
+ // "seqNum": 104998984994,
422
+ // "prevSeqNum": 104998984977,
423
+ // "bids": [
424
+ // [9058.27, 0],
425
+ // [9058.43, 0],
426
+ // [9058.99, 0],
427
+ // ],
428
+ // "asks": [
429
+ // [9084.27, 0.2],
430
+ // [9085.69, 0],
431
+ // [9085.81, 0],
432
+ // ]
433
+ // }
434
+ // }
435
+ //
436
+ const messageHash = this.safeString(message, 'ch');
437
+ const ch = this.safeValue(message, 'ch');
438
+ const parts = ch.split('.');
439
+ const marketId = this.safeString(parts, 1);
440
+ const symbol = this.safeSymbol(marketId);
441
+ const orderbook = this.orderbooks[symbol];
442
+ if (orderbook['nonce'] === undefined) {
443
+ orderbook.cache.push(message);
444
+ }
445
+ else {
446
+ this.handleOrderBookMessage(client, message, orderbook);
447
+ client.resolve(orderbook, messageHash);
448
+ }
449
+ }
450
+ handleOrderBookSubscription(client, message, subscription) {
451
+ const symbol = this.safeString(subscription, 'symbol');
452
+ const limit = this.safeInteger(subscription, 'limit');
453
+ if (symbol in this.orderbooks) {
454
+ delete this.orderbooks[symbol];
455
+ }
456
+ this.orderbooks[symbol] = this.orderBook({}, limit);
457
+ // watch the snapshot in a separate async call
458
+ this.spawn(this.watchOrderBookSnapshot, client, message, subscription);
459
+ }
460
+ handleSubscriptionStatus(client, message) {
461
+ //
462
+ // {
463
+ // "id": 1583414227,
464
+ // "status": "ok",
465
+ // "subbed": "market.btcusdt.mbp.150",
466
+ // "ts": 1583414229143
467
+ // }
468
+ //
469
+ const id = this.safeString(message, 'id');
470
+ const subscriptionsById = this.indexBy(client.subscriptions, 'id');
471
+ const subscription = this.safeValue(subscriptionsById, id);
472
+ if (subscription !== undefined) {
473
+ const method = this.safeValue(subscription, 'method');
474
+ if (method !== undefined) {
475
+ return method.call(this, client, message, subscription);
476
+ }
477
+ // clean up
478
+ if (id in client.subscriptions) {
479
+ delete client.subscriptions[id];
480
+ }
481
+ }
482
+ return message;
483
+ }
484
+ handleSystemStatus(client, message) {
485
+ //
486
+ // todo: answer the question whether handleSystemStatus should be renamed
487
+ // and unified as handleStatus for any usage pattern that
488
+ // involves system status and maintenance updates
489
+ //
490
+ // {
491
+ // "id": "1578090234088", // connectId
492
+ // "type": "welcome",
493
+ // }
494
+ //
495
+ return message;
496
+ }
497
+ handleSubject(client, message) {
498
+ //
499
+ // {
500
+ // "ch": "market.btcusdt.mbp.150",
501
+ // "ts": 1583472025885,
502
+ // "tick": {
503
+ // "seqNum": 104998984994,
504
+ // "prevSeqNum": 104998984977,
505
+ // "bids": [
506
+ // [9058.27, 0],
507
+ // [9058.43, 0],
508
+ // [9058.99, 0],
509
+ // ],
510
+ // "asks": [
511
+ // [9084.27, 0.2],
512
+ // [9085.69, 0],
513
+ // [9085.81, 0],
514
+ // ]
515
+ // }
516
+ // }
517
+ //
518
+ const ch = this.safeValue(message, 'ch');
519
+ const parts = ch.split('.');
520
+ const type = this.safeString(parts, 0);
521
+ if (type === 'market') {
522
+ const methodName = this.safeString(parts, 2);
523
+ const methods = {
524
+ 'mbp': this.handleOrderBook,
525
+ 'detail': this.handleTicker,
526
+ 'trade': this.handleTrades,
527
+ 'kline': this.handleOHLCV,
528
+ // ...
529
+ };
530
+ const method = this.safeValue(methods, methodName);
531
+ if (method !== undefined) {
532
+ method.call(this, client, message);
533
+ }
534
+ }
535
+ }
536
+ async pong(client, message) {
537
+ //
538
+ // { ping: 1583491673714 }
539
+ //
540
+ await client.send({ 'pong': this.safeInteger(message, 'ping') });
541
+ }
542
+ handlePing(client, message) {
543
+ this.spawn(this.pong, client, message);
544
+ }
545
+ handleErrorMessage(client, message) {
546
+ //
547
+ // {
548
+ // "ts": 1586323747018,
549
+ // "status": "error",
550
+ // 'err-code': "bad-request",
551
+ // 'err-msg': "invalid mbp.150.symbol linkusdt",
552
+ // "id": "2"
553
+ // }
554
+ //
555
+ const status = this.safeString(message, 'status');
556
+ if (status === 'error') {
557
+ const id = this.safeString(message, 'id');
558
+ const subscriptionsById = this.indexBy(client.subscriptions, 'id');
559
+ const subscription = this.safeValue(subscriptionsById, id);
560
+ if (subscription !== undefined) {
561
+ const errorCode = this.safeString(message, 'err-code');
562
+ try {
563
+ this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, this.json(message));
564
+ }
565
+ catch (e) {
566
+ const messageHash = this.safeString(subscription, 'messageHash');
567
+ client.reject(e, messageHash);
568
+ client.reject(e, id);
569
+ if (id in client.subscriptions) {
570
+ delete client.subscriptions[id];
571
+ }
572
+ }
573
+ }
574
+ return false;
575
+ }
576
+ return message;
577
+ }
578
+ handleMessage(client, message) {
579
+ if (this.handleErrorMessage(client, message)) {
580
+ //
581
+ // {"id":1583414227,"status":"ok","subbed":"market.btcusdt.mbp.150","ts":1583414229143}
582
+ //
583
+ // ________________________
584
+ //
585
+ // sometimes bittrade responds with half of a JSON response like
586
+ //
587
+ // " {"ch":"market.ethbtc.m "
588
+ //
589
+ // this is passed to handleMessage as a string since it failed to be decoded as JSON
590
+ //
591
+ if (this.safeString(message, 'id') !== undefined) {
592
+ this.handleSubscriptionStatus(client, message);
593
+ }
594
+ else if (this.safeString(message, 'ch') !== undefined) {
595
+ // route by channel aka topic aka subject
596
+ this.handleSubject(client, message);
597
+ }
598
+ else if (this.safeString(message, 'ping') !== undefined) {
599
+ this.handlePing(client, message);
600
+ }
601
+ }
602
+ }
603
+ }
604
+
605
+ module.exports = bittrade;
@@ -195,17 +195,18 @@ class luno extends luno$1 {
195
195
  if (!(symbol in this.orderbooks)) {
196
196
  this.orderbooks[symbol] = this.indexedOrderBook({});
197
197
  }
198
- const orderbook = this.orderbooks[symbol];
199
198
  const asks = this.safeValue(message, 'asks');
200
199
  if (asks !== undefined) {
201
200
  const snapshot = this.customParseOrderBook(message, symbol, timestamp, 'bids', 'asks', 'price', 'volume', 'id');
202
- orderbook.reset(snapshot);
201
+ this.orderbooks[symbol] = this.indexedOrderBook(snapshot);
203
202
  }
204
203
  else {
205
- this.handleDelta(orderbook, message);
206
- orderbook['timestamp'] = timestamp;
207
- orderbook['datetime'] = this.iso8601(timestamp);
204
+ const ob = this.orderbooks[symbol];
205
+ this.handleDelta(ob, message);
206
+ ob['timestamp'] = timestamp;
207
+ ob['datetime'] = this.iso8601(timestamp);
208
208
  }
209
+ const orderbook = this.orderbooks[symbol];
209
210
  const nonce = this.safeInteger(message, 'sequence');
210
211
  orderbook['nonce'] = nonce;
211
212
  client.resolve(orderbook, messageHash);
@@ -794,6 +794,9 @@ class mexc extends mexc$1 {
794
794
  const messageHash = 'orderbook:' + symbol;
795
795
  const subscription = this.safeValue(client.subscriptions, messageHash);
796
796
  const limit = this.safeInteger(subscription, 'limit');
797
+ if (!(symbol in this.orderbooks)) {
798
+ this.orderbooks[symbol] = this.orderBook();
799
+ }
797
800
  const storedOrderBook = this.orderbooks[symbol];
798
801
  const nonce = this.safeInteger(storedOrderBook, 'nonce');
799
802
  if (nonce === undefined) {