ccxt 4.1.22 → 4.1.24

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.
@@ -1,776 +0,0 @@
1
- // ----------------------------------------------------------------------------
2
-
3
- // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
- // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
- // EDIT THE CORRESPONDENT .ts FILE INSTEAD
6
-
7
- // ---------------------------------------------------------------------------
8
- import btcexRest from '../btcex.js';
9
- import { NotSupported, ExchangeError, ArgumentsRequired } from '../base/errors.js';
10
- import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
11
- // ---------------------------------------------------------------------------
12
- export default class btcex extends btcexRest {
13
- describe() {
14
- return this.deepExtend(super.describe(), {
15
- 'has': {
16
- 'ws': true,
17
- 'watchBalance': true,
18
- 'watchTicker': true,
19
- 'watchTickers': false,
20
- 'watchTrades': true,
21
- 'watchMyTrades': true,
22
- 'watchOrders': true,
23
- 'watchOrderBook': true,
24
- 'watchOHLCV': true,
25
- },
26
- 'urls': {
27
- 'api': {
28
- 'ws': 'wss://api.btcex.com/ws/api/v1',
29
- },
30
- },
31
- 'options': {
32
- 'watchOrderBook': {
33
- 'snapshotDelay': 0,
34
- 'maxRetries': 3,
35
- },
36
- },
37
- 'streaming': {
38
- 'ping': this.ping,
39
- 'keepAlive': 5000,
40
- },
41
- 'exceptions': {},
42
- 'timeframes': {
43
- '1m': '1',
44
- '3m': '3',
45
- '5m': '4',
46
- '10m': '10',
47
- '15m': '15',
48
- '30m': '30',
49
- '1h': '60',
50
- '2h': '120',
51
- '3h': '180',
52
- '4h': '240',
53
- '6h': '360',
54
- '12h': '720',
55
- '1d': '1D',
56
- },
57
- });
58
- }
59
- requestId() {
60
- const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
61
- this.options['requestId'] = requestId;
62
- return requestId.toString();
63
- }
64
- async watchBalance(params = {}) {
65
- /**
66
- * @method
67
- * @name btcex#watchBalance
68
- * @description query for balance and get the amount of funds available for trading or funds locked in orders
69
- * @see https://docs.btcex.com/#user-asset-asset_type
70
- * @param {object} params extra parameters specific to the btcex api endpoint
71
- * @param {string} params.type asset type WALLET, BTC,ETH,MARGIN,SPOT,PERPETUAL
72
- * @returns {object} a [balance structure]{@link https://docs.ccxt.com/en/latest/manual.html?#balance-structure}
73
- */
74
- const token = await this.authenticate(params);
75
- let type = undefined;
76
- [type, params] = this.handleMarketTypeAndParams('watchBalance', undefined, params);
77
- const types = this.safeValue(this.options, 'accountsByType', {});
78
- const assetType = this.safeString(types, type, type);
79
- params = this.omit(params, 'type');
80
- const messageHash = 'balancess';
81
- const url = this.urls['api']['ws'];
82
- const subscribe = {
83
- 'jsonrpc': '2.0',
84
- 'id': this.requestId(),
85
- 'method': '/private/subscribe',
86
- 'params': {
87
- 'access_token': token,
88
- 'channels': [
89
- 'user.asset.' + assetType,
90
- ],
91
- },
92
- };
93
- const request = this.deepExtend(subscribe, params);
94
- return await this.watch(url, messageHash, request, messageHash, request);
95
- }
96
- handleBalance(client, message) {
97
- //
98
- // {
99
- // "jsonrpc": "2.0",
100
- // "method": "subscription",
101
- // "params": {
102
- // "channel": "user.asset.WALLET",
103
- // "data": {
104
- // "WALLET": {
105
- // "total": "5578184962",
106
- // "coupon": "0",
107
- // "details": [
108
- // {
109
- // "available": "4999",
110
- // "freeze": "0",
111
- // "coin_type": "BTC",
112
- // "current_mark_price": "38000"
113
- // },
114
- // ...
115
- // ]
116
- // }
117
- // }
118
- // }
119
- // }
120
- //
121
- const params = this.safeValue(message, 'params', {});
122
- const data = this.safeValue(params, 'data', {});
123
- const messageHash = 'balancess';
124
- this.balance = this.parseBalance(data);
125
- client.resolve(this.balance, messageHash);
126
- }
127
- async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
128
- /**
129
- * @method
130
- * @name btcex#watchOHLCV
131
- * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market.
132
- * @see https://docs.btcex.com/#chart-trades-instrument_name-resolution
133
- * @param {string} symbol unified symbol of the market to fetch OHLCV data for
134
- * @param {string} timeframe the length of time each candle represents.
135
- * @param {int|undefined} since timestamp in ms of the earliest candle to fetch
136
- * @param {int|undefined} limit the maximum amount of candles to fetch
137
- * @param {object} params extra parameters specific to the bitfinex2 api endpoint
138
- * @returns {[[int]]} A list of candles ordered as timestamp, open, high, low, close, volume
139
- */
140
- await this.loadMarkets();
141
- const market = this.market(symbol);
142
- symbol = market['symbol'];
143
- let instrumentName = market['id'];
144
- if (market['spot']) {
145
- instrumentName = market['baseId'] + '-' + market['quoteId'];
146
- }
147
- const interval = this.safeString(this.timeframes, timeframe, timeframe);
148
- const messageHash = 'ohlcv:' + symbol + ':' + interval;
149
- let request = {
150
- 'jsonrpc': '2.0',
151
- 'id': this.requestId(),
152
- 'method': '/public/subscribe',
153
- 'params': {
154
- 'channels': [
155
- 'chart.trades.' + instrumentName + '.' + interval,
156
- ],
157
- },
158
- };
159
- request = this.deepExtend(request, params);
160
- const url = this.urls['api']['ws'];
161
- const ohlcv = await this.watch(url, messageHash, request, messageHash, request);
162
- if (this.newUpdates) {
163
- limit = ohlcv.getLimit(symbol, limit);
164
- }
165
- return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
166
- }
167
- handleOHLCV(client, message) {
168
- //
169
- // {
170
- // "params": {
171
- // "data": {
172
- // "tick": "1660095420",
173
- // "open": "22890.30000000",
174
- // "high": "22890.50000000",
175
- // "low": "22886.50000000",
176
- // "close": "22886.50000000",
177
- // "volume": "314.46800000",
178
- // "cost": "7197974.01690000"
179
- // },
180
- // "channel": "chart.trades.BTC-USDT-PERPETUAL.1"
181
- // },
182
- // "method": "subscription",
183
- // "jsonrpc": "2.0"
184
- // }
185
- //
186
- const params = this.safeValue(message, 'params');
187
- const channel = this.safeString(params, 'channel');
188
- const symbolInterval = channel.slice(13);
189
- const dotIndex = symbolInterval.indexOf('.');
190
- const marketId = symbolInterval.slice(0, dotIndex);
191
- const timeframeId = symbolInterval.slice(dotIndex + 1);
192
- const timeframe = this.findTimeframe(timeframeId);
193
- const symbol = this.safeSymbol(marketId, undefined, '-');
194
- const messageHash = 'ohlcv:' + symbol + ':' + timeframeId;
195
- const data = this.safeValue(params, 'data', {});
196
- const ohlcv = this.parseOHLCV(data);
197
- this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
198
- let stored = this.safeValue(this.ohlcvs[symbol], timeframe);
199
- if (stored === undefined) {
200
- const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
201
- stored = new ArrayCacheByTimestamp(limit);
202
- this.ohlcvs[symbol][timeframe] = stored;
203
- }
204
- stored.append(ohlcv);
205
- client.resolve(stored, messageHash);
206
- }
207
- async watchTicker(symbol, params = {}) {
208
- /**
209
- * @method
210
- * @name btcex#watchTicker
211
- * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
212
- * @see https://docs.btcex.com/#ticker-instrument_name-interval
213
- * @param {string} symbol unified symbol of the market to fetch the ticker for
214
- * @param {object} params extra parameters specific to the btcex api endpoint
215
- * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
216
- */
217
- await this.loadMarkets();
218
- const market = this.market(symbol);
219
- symbol = market['symbol'];
220
- let instrumentName = market['id'];
221
- if (market['spot']) {
222
- instrumentName = market['baseId'] + '-' + market['quoteId'];
223
- }
224
- const url = this.urls['api']['ws'];
225
- const messageHash = 'ticker:' + symbol;
226
- let request = {
227
- 'jsonrpc': '2.0',
228
- 'id': this.requestId(),
229
- 'method': '/public/subscribe',
230
- 'params': {
231
- 'channels': [
232
- 'ticker.' + instrumentName + '.raw',
233
- ],
234
- },
235
- };
236
- request = this.deepExtend(request, params);
237
- return await this.watch(url, messageHash, request, messageHash);
238
- }
239
- handleTicker(client, message) {
240
- //
241
- // {
242
- // "params": {
243
- // "data": {
244
- // "timestamp": "1660094543813",
245
- // "stats": {
246
- // "volume": "630219.70300000000008822",
247
- // "price_change": "-0.0378",
248
- // "low": "22659.50000000",
249
- // "turnover": "14648416962.26930706016719341",
250
- // "high": "23919.00000000"
251
- // },
252
- // "state": "open",
253
- // "last_price": "22890.00000000",
254
- // "instrument_name": "BTC-USDT-PERPETUAL",
255
- // "best_bid_price": "22888.60000000",
256
- // "best_bid_amount": "33.38500000",
257
- // "best_ask_price": "22889.40000000",
258
- // "best_ask_amount": "5.45200000",
259
- // "mark_price": "22890.5",
260
- // "underlying_price": "22891",
261
- // "open_interest": "33886.083"
262
- // },
263
- // "channel": "ticker.BTC-USDT-PERPETUAL.raw"
264
- // },
265
- // "method": "subscription",
266
- // "jsonrpc": "2.0"
267
- // }
268
- //
269
- const params = this.safeValue(message, 'params');
270
- const data = this.safeValue(params, 'data');
271
- const ticker = this.parseTicker(data);
272
- const symbol = this.safeString(ticker, 'symbol');
273
- const messageHash = 'ticker:' + symbol;
274
- this.tickers[symbol] = ticker;
275
- client.resolve(ticker, messageHash);
276
- }
277
- async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
278
- /**
279
- * @method
280
- * @name btcex#watchTrades
281
- * @description get the list of most recent trades for a particular symbol
282
- * @see https://docs.btcex.com/#trades-instrument_name-interval
283
- * @param {string} symbol unified symbol of the market to fetch trades for
284
- * @param {int|undefined} since timestamp in ms of the earliest trade to fetch
285
- * @param {int|undefined} limit the maximum amount of trades to fetch
286
- * @param {object} params extra parameters specific to the btcex api endpoint
287
- * @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
288
- */
289
- await this.loadMarkets();
290
- const market = this.market(symbol);
291
- symbol = market['symbol'];
292
- const url = this.urls['api']['ws'];
293
- const messageHash = 'trades:' + symbol;
294
- let request = {
295
- 'jsonrpc': '2.0',
296
- 'id': this.requestId(),
297
- 'method': '/public/subscribe',
298
- 'params': {
299
- 'channels': [
300
- 'trades.' + market['id'] + '.raw',
301
- ],
302
- },
303
- };
304
- request = this.deepExtend(request, params);
305
- const trades = await this.watch(url, messageHash, request, messageHash, request);
306
- if (this.newUpdates) {
307
- limit = trades.getLimit(symbol, limit);
308
- }
309
- return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
310
- }
311
- handleTrades(client, message) {
312
- //
313
- // {
314
- // "jsonrpc": "2.0",
315
- // "method": "subscription",
316
- // "params": {
317
- // "channel": "trades.BTC-USDT-PERPETUAL.raw",
318
- // "data": [{
319
- // "timestamp": "1660093462553",
320
- // "price": "22815.9",
321
- // "amount": "4.479",
322
- // "iv": "0",
323
- // "direction": "sell",
324
- // "instrument_name": "BTC-USDT-PERPETUAL",
325
- // "trade_id": "227976617",
326
- // "mark_price": "22812.7"
327
- // }]
328
- // }
329
- // }
330
- //
331
- const params = this.safeValue(message, 'params', {});
332
- const fullChannel = this.safeString(params, 'channel');
333
- const parts = fullChannel.split('.');
334
- const marketId = parts[1];
335
- const symbol = this.safeSymbol(marketId);
336
- const messageHash = 'trades:' + symbol;
337
- let stored = this.safeValue(this.trades, symbol);
338
- if (stored === undefined) {
339
- const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
340
- stored = new ArrayCache(limit);
341
- this.trades[symbol] = stored;
342
- }
343
- const rawTrades = this.safeValue(params, 'data', []);
344
- for (let i = 0; i < rawTrades.length; i++) {
345
- const rawTrade = rawTrades[i];
346
- const trade = this.parseTrade(rawTrade, undefined);
347
- stored.append(trade);
348
- }
349
- this.trades[symbol] = stored;
350
- client.resolve(stored, messageHash);
351
- }
352
- async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
353
- /**
354
- * @method
355
- * @name bibox#fetchMyTrades
356
- * @description watch all trades made by the user
357
- * @see https://docs.btcex.com/#user-trades-instrument_name-interval
358
- * @param {string} symbol unified market symbol
359
- * @param {int|undefined} since the earliest time in ms to fetch trades for
360
- * @param {int|undefined} limit the maximum number of trades structures to retrieve
361
- * @param {object} params extra parameters specific to the bibox api endpoint
362
- * @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
363
- */
364
- if (symbol === undefined) {
365
- throw new ArgumentsRequired(this.id + ' watchMyTrades() requires a symbol argument');
366
- }
367
- await this.loadMarkets();
368
- const token = await this.authenticate();
369
- const market = this.market(symbol);
370
- symbol = market['symbol'];
371
- const url = this.urls['api']['ws'];
372
- const messageHash = 'myTrades:' + symbol;
373
- const request = {
374
- 'jsonrpc': '2.0',
375
- 'id': this.requestId(),
376
- 'method': '/private/subscribe',
377
- 'params': {
378
- 'access_token': token,
379
- 'channels': [
380
- 'user.trades.' + market['id'] + '.raw',
381
- ],
382
- },
383
- };
384
- const trades = await this.watch(url, messageHash, request, messageHash);
385
- if (this.newUpdates) {
386
- limit = trades.getLimit(symbol, limit);
387
- }
388
- return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
389
- }
390
- handleMyTrades(client, message) {
391
- //
392
- // {
393
- // "jsonrpc": "2.0",
394
- // "method": "subscription",
395
- // "params": {
396
- // "channel": "user.trades.BTC-14AUG20.raw",
397
- // "data": [{
398
- // "direction": "sell",
399
- // "amount": "1",
400
- // "price": "33000",
401
- // "iv": "0",
402
- // "fee": "0",
403
- // "timestamp": 1626148488157,
404
- // "trade_id": "1",
405
- // "order_id": "160717710099746816",
406
- // "instrument_name": "BTC-24SEP21",
407
- // "order_type": "limit",
408
- // "fee_coin_type": "USDT",
409
- // "index_price": "33157.63"
410
- // }]
411
- // }
412
- // }
413
- //
414
- const params = this.safeValue(message, 'params', {});
415
- const channel = this.safeString(params, 'channel', '');
416
- const endIndex = channel.indexOf('.raw');
417
- const marketId = channel.slice(12, endIndex);
418
- const symbol = this.safeSymbol(marketId, undefined, '-');
419
- const rawTrades = this.safeValue(params, 'data', []);
420
- let stored = this.myTrades;
421
- if (stored === undefined) {
422
- const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
423
- stored = new ArrayCacheBySymbolById(limit);
424
- }
425
- for (let i = 0; i < rawTrades.length; i++) {
426
- const rawTrade = rawTrades[i];
427
- const trade = this.parseTrade(rawTrade);
428
- stored.append(trade);
429
- }
430
- this.myTrades = stored;
431
- const messageHash = 'myTrades:' + symbol;
432
- client.resolve(stored, messageHash);
433
- }
434
- async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
435
- /**
436
- * @method
437
- * @name btcex#fetchOrders
438
- * @description watches information on multiple orders made by the user
439
- * @see https://docs.btcex.com/#user-changes-kind-currency-interval
440
- * @param {string} symbol unified market symbol of the market orders were made in
441
- * @param {int|undefined} since the earliest time in ms to fetch orders for
442
- * @param {int|undefined} limit the maximum number of orde structures to retrieve
443
- * @param {object} params extra parameters specific to the btcex api endpoint
444
- * @returns {[object]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
445
- */
446
- if (symbol === undefined) {
447
- throw new ArgumentsRequired(this.id + 'watchesOrders() requires a symbol');
448
- }
449
- await this.loadMarkets();
450
- const token = await this.authenticate();
451
- const market = this.market(symbol);
452
- symbol = market['symbol'];
453
- const url = this.urls['api']['ws'];
454
- const message = {
455
- 'jsonrpc': '2.0',
456
- 'id': this.requestId(),
457
- 'method': '/private/subscribe',
458
- 'params': {
459
- 'access_token': token,
460
- 'channels': [
461
- 'user.orders.' + market['id'] + '.raw',
462
- ],
463
- },
464
- };
465
- const messageHash = 'orders:' + symbol;
466
- const request = this.deepExtend(message, params);
467
- const orders = await this.watch(url, messageHash, request, messageHash);
468
- if (this.newUpdates) {
469
- limit = orders.getLimit(symbol, limit);
470
- }
471
- return this.filterBySymbolSinceLimit(orders, symbol, since, limit);
472
- }
473
- handleOrder(client, message) {
474
- //
475
- // {
476
- // "jsonrpc": "2.0",
477
- // "method": "subscription",
478
- // "params": {
479
- // "channel": "user.orders.BTC-14AUG20.raw",
480
- // "data": {
481
- // "amount": "1",
482
- // "price": "11895.00",
483
- // "direction": "buy",
484
- // "version": 0,
485
- // "order_state": "filled",
486
- // "instrument_name": "BTC-14AUG20",
487
- // "time_in_force": "good_til_cancelled",
488
- // "last_update_timestamp": 1597130534567,
489
- // "filled_amount": "1",
490
- // "average_price": "11770.00",
491
- // "order_id": "39007591615041536",
492
- // "creation_timestamp": 1597130534567,
493
- // "order_type": "limit"
494
- // }
495
- // }
496
- //
497
- const params = this.safeValue(message, 'params', {});
498
- const rawOrder = this.safeValue(params, 'data', {});
499
- let cachedOrders = this.orders;
500
- if (cachedOrders === undefined) {
501
- const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
502
- cachedOrders = new ArrayCacheBySymbolById(limit);
503
- }
504
- const order = this.parseOrder(rawOrder);
505
- const symbol = this.safeString(order, 'symbol');
506
- const messageHash = 'orders:' + symbol;
507
- cachedOrders.append(order);
508
- this.orders = cachedOrders;
509
- client.resolve(this.orders, messageHash);
510
- }
511
- async watchOrderBook(symbol, limit = undefined, params = {}) {
512
- /**
513
- * @method
514
- * @name btcex#watchOrderBook
515
- * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
516
- * @see https://docs.btcex.com/#book-instrument_name-interval
517
- * @param {string} symbol unified symbol of the market to fetch the order book for
518
- * @param {int|undefined} limit the maximum amount of order book entries to return
519
- * @param {objectConstructor} params extra parameters specific to the btcex api endpoint
520
- * @param {string|undefined} params.type accepts l2 or l3 for level 2 or level 3 order book
521
- * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
522
- */
523
- await this.loadMarkets();
524
- const market = this.market(symbol);
525
- symbol = market['symbol'];
526
- let instrumentName = market['id'];
527
- if (market['spot']) {
528
- instrumentName = market['baseId'] + '-' + market['quoteId'];
529
- }
530
- const url = this.urls['api']['ws'];
531
- params = this.omit(params, 'type');
532
- const messageHash = 'orderbook:' + symbol;
533
- const subscribe = {
534
- 'jsonrpc': '2.0',
535
- 'id': this.requestId(),
536
- 'method': '/public/subscribe',
537
- 'params': {
538
- 'channels': [
539
- 'book.' + instrumentName + '.raw',
540
- ],
541
- },
542
- };
543
- const request = this.deepExtend(subscribe, params);
544
- const orderbook = await this.watch(url, messageHash, request, messageHash);
545
- return orderbook.limit();
546
- }
547
- handleOrderBook(client, message) {
548
- //
549
- // {
550
- // "params": {
551
- // "data": {
552
- // "timestamp": 1626056933600,
553
- // "change_id": 1566764,
554
- // "asks": [
555
- // [
556
- // "new",
557
- // "34227.122",
558
- // "0.00554"
559
- // ],
560
- // ...
561
- // ],
562
- // "bids": [
563
- // [
564
- // "delete",
565
- // "34105.540",
566
- // "0"
567
- // ],
568
- // ...
569
- // ],
570
- // "instrument_name": "BTC-USDT"
571
- // },
572
- // "channel": "book.BTC-USDT.raw"
573
- // },
574
- // "method": "subscription",
575
- // "jsonrpc": "2.0"
576
- // }
577
- // `
578
- const params = this.safeValue(message, 'params');
579
- const data = this.safeValue(params, 'data');
580
- const marketId = this.safeString(data, 'instrument_name');
581
- const symbol = this.safeSymbol(marketId, undefined, '-');
582
- const storedOrderBook = this.safeValue(this.orderbooks, symbol);
583
- const nonce = this.safeInteger(storedOrderBook, 'nonce');
584
- const deltaNonce = this.safeInteger(data, 'change_id');
585
- const messageHash = 'orderbook:' + symbol;
586
- if (nonce === undefined) {
587
- const cacheLength = storedOrderBook.cache.length;
588
- const snapshotDelay = this.handleOption('watchOrderBook', 'snapshotDelay', 0);
589
- if (cacheLength === snapshotDelay) {
590
- const limit = 0;
591
- this.spawn(this.loadOrderBook, client, messageHash, symbol, limit);
592
- }
593
- storedOrderBook.cache.push(data);
594
- return;
595
- }
596
- else if (deltaNonce <= nonce) {
597
- return;
598
- }
599
- this.handleDelta(storedOrderBook, data);
600
- client.resolve(storedOrderBook, messageHash);
601
- }
602
- getCacheIndex(orderBook, cache) {
603
- const firstElement = cache[0];
604
- let lastChangeId = this.safeInteger(firstElement, 'change_id');
605
- const nonce = this.safeInteger(orderBook, 'nonce');
606
- if (nonce < lastChangeId - 1) {
607
- return -1;
608
- }
609
- for (let i = 0; i < cache.length; i++) {
610
- const delta = cache[i];
611
- lastChangeId = this.safeInteger(delta, 'change_id');
612
- if (nonce === lastChangeId - 1) {
613
- // nonce is inside the cache
614
- // [ d, d, n, d ]
615
- return i;
616
- }
617
- }
618
- return cache.length;
619
- }
620
- handleDelta(orderbook, delta) {
621
- const timestamp = this.safeInteger(delta, 'timestamp');
622
- orderbook['timestamp'] = timestamp;
623
- orderbook['datetime'] = this.iso8601(timestamp);
624
- orderbook['nonce'] = this.safeInteger(delta, 'change_id');
625
- const bids = this.safeValue(delta, 'bids', []);
626
- const asks = this.safeValue(delta, 'asks', []);
627
- const storedBids = orderbook['bids'];
628
- const storedAsks = orderbook['asks'];
629
- this.handleBidAsks(storedBids, bids);
630
- this.handleBidAsks(storedAsks, asks);
631
- }
632
- handleBidAsks(bookSide, bidAsks) {
633
- for (let i = 0; i < bidAsks.length; i++) {
634
- const bidAsk = this.parseBidAsk(bidAsks[i], 1, 2);
635
- bookSide.storeArray(bidAsk);
636
- }
637
- }
638
- handleUser(client, message) {
639
- const params = this.safeValue(message, 'params');
640
- const fullChannel = this.safeString(params, 'channel');
641
- const sliceUser = fullChannel.slice(5);
642
- const endIndex = sliceUser.indexOf('.');
643
- const userChannel = sliceUser.slice(0, endIndex);
644
- const handlers = {
645
- 'asset': this.handleBalance,
646
- 'orders': this.handleOrder,
647
- 'trades': this.handleMyTrades,
648
- };
649
- const handler = this.safeValue(handlers, userChannel);
650
- if (handler !== undefined) {
651
- return handler.call(this, client, message);
652
- }
653
- throw new NotSupported(this.id + ' received an unsupported message: ' + this.json(message));
654
- }
655
- handleErrorMessage(client, message) {
656
- //
657
- // {
658
- // id: '1',
659
- // jsonrpc: '2.0',
660
- // usIn: 1660140064049,
661
- // usOut: 1660140064051,
662
- // usDiff: 2,
663
- // error: { code: 10000, message: 'Authentication Failure' }
664
- // }
665
- //
666
- const error = this.safeValue(message, 'error', {});
667
- throw new ExchangeError(this.id + ' error: ' + this.json(error));
668
- }
669
- handleAuthenticate(client, message) {
670
- //
671
- // {
672
- // id: '1',
673
- // jsonrpc: '2.0',
674
- // usIn: 1660140846671,
675
- // usOut: 1660140846688,
676
- // usDiff: 17,
677
- // result: {
678
- // access_token: 'xxxxxx43jIXYrF3VSm90ar+f5n447M3ll82AiFO58L85pxb/DbVf6Bn4ZyBX1i1tM/KYFBJ234ZkrUkwImUIEu8vY1PBh5JqaaaaaeGnao=',
679
- // token_type: 'bearer',
680
- // refresh_token: '/I56sUOB/zwpwo8X8Q0Z234bW8Lz1YNlXOXSP6C+ZJDWR+49CjVPr0Z3PVXoL3BOB234WxXtTid+YmNjQ8OqGn1MM9pQL5TKZ97s49SvaRc=',
681
- // expires_in: 604014,
682
- // scope: 'account:read_write block_trade:read_write trade:read_write wallet:read_write',
683
- // m: '00000000006e446c6b44694759735570786e5668387335431274546e633867474d647772717a463924a6d3746756951334b637459653970576d63693143e6e335972584e48594c74674c4d416872564a4d56424c347438737938736f4645747263315374454e73324e546d346e5651792b69696279336647347737413d3d'
684
- // }
685
- // }
686
- //
687
- const result = this.safeValue(message, 'result', {});
688
- const expiresIn = this.safeInteger(result, 'expires_in', 0);
689
- this.options['expiresAt'] = this.sum(this.seconds(), expiresIn) * 1000;
690
- const accessToken = this.safeString(result, 'access_token');
691
- client.resolve(accessToken, 'authenticated');
692
- }
693
- handleSubscription(client, message) {
694
- const channels = this.safeValue(message, 'result', []);
695
- for (let i = 0; i < channels.length; i++) {
696
- const fullChannel = channels[i];
697
- const parts = fullChannel.split('.');
698
- const channel = this.safeString(parts, 0);
699
- const marketId = this.safeString(parts, 1);
700
- if (channel === 'book') {
701
- const symbol = this.safeSymbol(marketId, undefined, '-');
702
- this.orderbooks[symbol] = this.orderBook({});
703
- // get full depth book
704
- }
705
- }
706
- }
707
- handlePong(client, message) {
708
- client.lastPong = this.milliseconds();
709
- }
710
- handleMessage(client, message) {
711
- if (message === 'PONG') {
712
- this.handlePong(client, message);
713
- return;
714
- }
715
- const error = this.safeValue(message, 'error');
716
- if (error !== undefined) {
717
- return this.handleErrorMessage(client, message);
718
- }
719
- const result = this.safeValue(message, 'result', {});
720
- const accessToken = this.safeString(result, 'access_token');
721
- if (accessToken !== undefined) {
722
- return this.handleAuthenticate(client, message);
723
- }
724
- const method = this.safeString(message, 'method');
725
- if (method === 'subscription') {
726
- const params = this.safeValue(message, 'params');
727
- const fullChannel = this.safeString(params, 'channel');
728
- const parts = fullChannel.split('.');
729
- const channel = this.safeString(parts, 0);
730
- const handlers = {
731
- 'ticker': this.handleTicker,
732
- 'trades': this.handleTrades,
733
- 'chart': this.handleOHLCV,
734
- 'balances': this.handleBalance,
735
- 'trading': this.handleOrder,
736
- 'user': this.handleUser,
737
- 'book': this.handleOrderBook,
738
- };
739
- const handler = this.safeValue(handlers, channel);
740
- if (handler !== undefined) {
741
- return handler.call(this, client, message);
742
- }
743
- }
744
- else if ('result' in message) {
745
- this.handleSubscription(client, message);
746
- }
747
- return message;
748
- }
749
- authenticate(params = {}) {
750
- const url = this.urls['api']['ws'];
751
- const client = this.client(url);
752
- const messageHash = 'authenticated';
753
- const expiresAt = this.safeNumber(this.options, 'expiresAt');
754
- const time = this.milliseconds();
755
- let future = this.safeValue(client.subscriptions, messageHash);
756
- if ((future === undefined) || (expiresAt <= time)) {
757
- const request = {
758
- 'jsonrpc': '2.0',
759
- 'id': this.requestId(),
760
- 'method': '/public/auth',
761
- 'params': {
762
- 'grant_type': 'client_credentials',
763
- 'client_id': this.apiKey,
764
- 'client_secret': this.secret,
765
- },
766
- };
767
- const message = this.extend(request, params);
768
- future = this.watch(url, messageHash, message);
769
- client.subscriptions[messageHash] = future;
770
- }
771
- return future;
772
- }
773
- ping(client) {
774
- return 'PING';
775
- }
776
- }