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.
package/js/src/pro/zb.js DELETED
@@ -1,605 +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 zbRest from '../zb.js';
9
- import { ExchangeError, AuthenticationError, NotSupported } from '../base/errors.js';
10
- import { ArrayCache, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
11
- // ---------------------------------------------------------------------------
12
- export default class zb extends zbRest {
13
- describe() {
14
- return this.deepExtend(super.describe(), {
15
- 'has': {
16
- 'ws': true,
17
- 'watchOrderBook': true,
18
- 'watchTicker': true,
19
- 'watchTrades': true,
20
- 'watchOHLCV': true,
21
- },
22
- 'urls': {
23
- 'api': {
24
- 'ws': {
25
- 'spot': 'wss://api.{hostname}/websocket',
26
- 'contract': 'wss://fapi.{hostname}/ws/public/v1',
27
- },
28
- },
29
- },
30
- 'options': {
31
- 'tradesLimit': 1000,
32
- 'ordersLimit': 1000,
33
- 'OHLCVLimit': 1000,
34
- },
35
- });
36
- }
37
- async watchPublic(url, messageHash, symbol, method, limit = undefined, params = {}) {
38
- await this.loadMarkets();
39
- const market = this.market(symbol);
40
- const type = market['spot'] ? 'spot' : 'contract';
41
- let request = undefined;
42
- const isLimitSet = limit !== undefined;
43
- if (type === 'spot') {
44
- request = {
45
- 'event': 'addChannel',
46
- 'channel': messageHash,
47
- };
48
- if (isLimitSet) {
49
- request['length'] = limit;
50
- }
51
- }
52
- else {
53
- request = {
54
- 'action': 'subscribe',
55
- 'channel': messageHash,
56
- };
57
- if (isLimitSet) {
58
- request['size'] = limit;
59
- }
60
- }
61
- const message = this.extend(request, params);
62
- const subscription = {
63
- 'symbol': symbol,
64
- 'messageHash': messageHash,
65
- 'method': method,
66
- };
67
- if (isLimitSet) {
68
- subscription['limit'] = limit;
69
- }
70
- return await this.watch(url, messageHash, message, messageHash, subscription);
71
- }
72
- async watchTicker(symbol, params = {}) {
73
- await this.loadMarkets();
74
- const market = this.market(symbol);
75
- let messageHash = undefined;
76
- const type = market['spot'] ? 'spot' : 'contract';
77
- if (type === 'spot') {
78
- messageHash = market['baseId'] + market['quoteId'] + '_' + 'ticker';
79
- }
80
- else {
81
- messageHash = market['id'] + '.' + 'Ticker';
82
- }
83
- const url = this.implodeHostname(this.urls['api']['ws'][type]);
84
- return await this.watchPublic(url, messageHash, symbol, this.handleTicker, undefined, params);
85
- }
86
- parseWsTicker(ticker, market = undefined) {
87
- //
88
- // contract ticker
89
- // {
90
- // data: [
91
- // 38568.36, // open
92
- // 39958.75, // high
93
- // 38100, // low
94
- // 39211.78, // last
95
- // 61695.496, // volume 24h
96
- // 1.67, // change
97
- // 1647369457, // time
98
- // 285916.615048
99
- // ]
100
- // }
101
- //
102
- const timestamp = this.safeInteger(ticker, 6);
103
- const last = this.safeString(ticker, 3);
104
- return this.safeTicker({
105
- 'symbol': this.safeSymbol(undefined, market),
106
- 'timestamp': timestamp,
107
- 'datetime': undefined,
108
- 'high': this.safeString(ticker, 1),
109
- 'low': this.safeString(ticker, 2),
110
- 'bid': undefined,
111
- 'bidVolume': undefined,
112
- 'ask': undefined,
113
- 'askVolume': undefined,
114
- 'vwap': undefined,
115
- 'open': this.safeString(ticker, 0),
116
- 'close': last,
117
- 'last': last,
118
- 'previousClose': undefined,
119
- 'change': undefined,
120
- 'percentage': this.safeString(ticker, 5),
121
- 'average': undefined,
122
- 'baseVolume': this.safeString(ticker, 4),
123
- 'quoteVolume': undefined,
124
- 'info': ticker,
125
- }, market);
126
- }
127
- handleTicker(client, message, subscription) {
128
- //
129
- // spot ticker
130
- //
131
- // {
132
- // date: '1624398991255',
133
- // ticker: {
134
- // high: '33298.38',
135
- // vol: '56375.9469',
136
- // last: '32396.95',
137
- // low: '28808.19',
138
- // buy: '32395.81',
139
- // sell: '32409.3',
140
- // turnover: '1771122527.0000',
141
- // open: '31652.44',
142
- // riseRate: '2.36'
143
- // },
144
- // dataType: 'ticker',
145
- // channel: 'btcusdt_ticker'
146
- // }
147
- //
148
- // contract ticker
149
- // {
150
- // channel: 'BTC_USDT.Ticker',
151
- // data: [
152
- // 38568.36,
153
- // 39958.75,
154
- // 38100,
155
- // 39211.78,
156
- // 61695.496,
157
- // 1.67,
158
- // 1647369457,
159
- // 285916.615048
160
- // ]
161
- // }
162
- //
163
- const symbol = this.safeString(subscription, 'symbol');
164
- const channel = this.safeString(message, 'channel');
165
- const market = this.market(symbol);
166
- let data = this.safeValue(message, 'ticker');
167
- let ticker = undefined;
168
- if (data === undefined) {
169
- data = this.safeValue(message, 'data', []);
170
- ticker = this.parseWsTicker(data, market);
171
- }
172
- else {
173
- data['date'] = this.safeValue(message, 'date');
174
- ticker = this.parseTicker(data, market);
175
- }
176
- ticker['symbol'] = symbol;
177
- this.tickers[symbol] = ticker;
178
- client.resolve(ticker, channel);
179
- return message;
180
- }
181
- async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
182
- await this.loadMarkets();
183
- const market = this.market(symbol);
184
- if (market['spot']) {
185
- throw new NotSupported(this.id + ' watchOHLCV() supports contract markets only');
186
- }
187
- if ((limit === undefined) || (limit > 1440)) {
188
- limit = 100;
189
- }
190
- const interval = this.safeString(this.timeframes, timeframe, timeframe);
191
- const messageHash = market['id'] + '.KLine' + '_' + interval;
192
- const url = this.implodeHostname(this.urls['api']['ws']['contract']);
193
- const ohlcv = await this.watchPublic(url, messageHash, symbol, this.handleOHLCV, limit, params);
194
- if (this.newUpdates) {
195
- limit = ohlcv.getLimit(symbol, limit);
196
- }
197
- return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
198
- }
199
- handleOHLCV(client, message, subscription) {
200
- //
201
- // snapshot update
202
- // {
203
- // channel: 'BTC_USDT.KLine_1m',
204
- // type: 'Whole',
205
- // data: [
206
- // [ 48543.77, 48543.77, 48542.82, 48542.82, 0.43, 1640227260 ],
207
- // [ 48542.81, 48542.81, 48529.89, 48529.89, 1.202, 1640227320 ],
208
- // [ 48529.95, 48529.99, 48529.85, 48529.9, 4.226, 1640227380 ],
209
- // [ 48529.96, 48529.99, 48525.11, 48525.11, 8.858, 1640227440 ],
210
- // [ 48525.05, 48525.05, 48464.17, 48476.63, 32.772, 1640227500 ],
211
- // [ 48475.62, 48485.65, 48475.12, 48479.36, 20.04, 1640227560 ],
212
- // ]
213
- // }
214
- // partial update
215
- // {
216
- // channel: 'BTC_USDT.KLine_1m',
217
- // data: [
218
- // [ 39095.45, 45339.48, 36923.58, 39204.94, 1215304.988, 1645920000 ]
219
- // ]
220
- // }
221
- //
222
- const data = this.safeValue(message, 'data', []);
223
- const channel = this.safeString(message, 'channel', '');
224
- const parts = channel.split('_');
225
- const partsLength = parts.length;
226
- const interval = this.safeString(parts, partsLength - 1);
227
- const timeframe = this.findTimeframe(interval);
228
- const symbol = this.safeString(subscription, 'symbol');
229
- const market = this.market(symbol);
230
- for (let i = 0; i < data.length; i++) {
231
- const candle = data[i];
232
- const parsed = this.parseOHLCV(candle, market);
233
- this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
234
- let stored = this.safeValue(this.ohlcvs[symbol], timeframe);
235
- if (stored === undefined) {
236
- const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
237
- stored = new ArrayCacheByTimestamp(limit);
238
- this.ohlcvs[symbol][timeframe] = stored;
239
- }
240
- stored.append(parsed);
241
- client.resolve(stored, channel);
242
- }
243
- return message;
244
- }
245
- async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
246
- await this.loadMarkets();
247
- const market = this.market(symbol);
248
- let messageHash = undefined;
249
- const type = market['spot'] ? 'spot' : 'contract';
250
- if (type === 'spot') {
251
- messageHash = market['baseId'] + market['quoteId'] + '_' + 'trades';
252
- }
253
- else {
254
- messageHash = market['id'] + '.' + 'Trade';
255
- }
256
- const url = this.implodeHostname(this.urls['api']['ws'][type]);
257
- const trades = await this.watchPublic(url, messageHash, symbol, this.handleTrades, limit, params);
258
- if (this.newUpdates) {
259
- limit = trades.getLimit(symbol, limit);
260
- }
261
- return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
262
- }
263
- handleTrades(client, message, subscription) {
264
- // contract trades
265
- // {
266
- // "channel":"BTC_USDT.Trade",
267
- // "type":"Whole",
268
- // "data":[
269
- // [
270
- // 40768.07,
271
- // 0.01,
272
- // 1,
273
- // 1647442757
274
- // ],
275
- // [
276
- // 40792.22,
277
- // 0.334,
278
- // -1,
279
- // 1647442765
280
- // ],
281
- // [
282
- // 40789.77,
283
- // 0.14,
284
- // 1,
285
- // 1647442766
286
- // ]
287
- // ]
288
- // }
289
- // spot trades
290
- //
291
- // {
292
- // data: [
293
- // { date: 1624537147, amount: '0.0357', price: '34066.11', trade_type: 'bid', type: 'buy', tid: 1718857158 },
294
- // { date: 1624537147, amount: '0.0255', price: '34071.04', trade_type: 'bid', type: 'buy', tid: 1718857159 },
295
- // { date: 1624537147, amount: '0.0153', price: '34071.29', trade_type: 'bid', type: 'buy', tid: 1718857160 }
296
- // ],
297
- // dataType: 'trades',
298
- // channel: 'btcusdt_trades'
299
- // }
300
- //
301
- const channel = this.safeValue(message, 'channel');
302
- const symbol = this.safeString(subscription, 'symbol');
303
- const market = this.market(symbol);
304
- const data = this.safeValue(message, 'data');
305
- const type = this.safeString(message, 'type');
306
- let trades = [];
307
- if (type === 'Whole') {
308
- // contract trades
309
- for (let i = 0; i < data.length; i++) {
310
- const trade = data[i];
311
- const parsed = this.parseWsTrade(trade, market);
312
- trades.push(parsed);
313
- }
314
- }
315
- else {
316
- // spot trades
317
- trades = this.parseTrades(data, market);
318
- }
319
- let array = this.safeValue(this.trades, symbol);
320
- if (array === undefined) {
321
- const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
322
- array = new ArrayCache(limit);
323
- }
324
- for (let i = 0; i < trades.length; i++) {
325
- array.append(trades[i]);
326
- }
327
- this.trades[symbol] = array;
328
- client.resolve(array, channel);
329
- }
330
- async watchOrderBook(symbol, limit = undefined, params = {}) {
331
- if (limit !== undefined) {
332
- if ((limit !== 5) && (limit !== 10)) {
333
- throw new ExchangeError(this.id + ' watchOrderBook limit argument must be undefined, 5, or 10');
334
- }
335
- }
336
- else {
337
- limit = 5; // default
338
- }
339
- await this.loadMarkets();
340
- const market = this.market(symbol);
341
- const type = market['spot'] ? 'spot' : 'contract';
342
- let messageHash = undefined;
343
- let url = this.implodeHostname(this.urls['api']['ws'][type]);
344
- if (type === 'spot') {
345
- url += '/' + market['baseId'];
346
- messageHash = market['baseId'] + market['quoteId'] + '_' + 'quick_depth';
347
- }
348
- else {
349
- messageHash = market['id'] + '.' + 'Depth';
350
- }
351
- const orderbook = await this.watchPublic(url, messageHash, symbol, this.handleOrderBook, limit, params);
352
- return orderbook.limit();
353
- }
354
- parseWsTrade(trade, market = undefined) {
355
- //
356
- // [
357
- // 40768.07, // price
358
- // 0.01, // quantity
359
- // 1, // buy or -1 sell
360
- // 1647442757 // time
361
- // ],
362
- //
363
- const timestamp = this.safeTimestamp(trade, 3);
364
- const price = this.safeString(trade, 0);
365
- const amount = this.safeString(trade, 1);
366
- market = this.safeMarket(undefined, market);
367
- const sideNumber = this.safeInteger(trade, 2);
368
- const side = (sideNumber === 1) ? 'buy' : 'sell';
369
- return this.safeTrade({
370
- 'id': undefined,
371
- 'timestamp': timestamp,
372
- 'datetime': this.iso8601(timestamp),
373
- 'symbol': market['symbol'],
374
- 'order': undefined,
375
- 'type': undefined,
376
- 'side': side,
377
- 'takerOrMaker': undefined,
378
- 'price': price,
379
- 'amount': amount,
380
- 'cost': undefined,
381
- 'fee': undefined,
382
- 'info': trade,
383
- }, market);
384
- }
385
- handleOrderBook(client, message, subscription) {
386
- // spot snapshot
387
- //
388
- // {
389
- // lastTime: 1624524640066,
390
- // dataType: 'quickDepth',
391
- // channel: 'btcusdt_quick_depth',
392
- // currentPrice: 33183.79,
393
- // listDown: [
394
- // [ 33166.87, 0.2331 ],
395
- // [ 33166.86, 0.15 ],
396
- // [ 33166.76, 0.15 ],
397
- // [ 33161.02, 0.212 ],
398
- // [ 33146.35, 0.6066 ]
399
- // ],
400
- // market: 'btcusdt',
401
- // listUp: [
402
- // [ 33186.88, 0.15 ],
403
- // [ 33190.1, 0.15 ],
404
- // [ 33193.03, 0.2518 ],
405
- // [ 33195.05, 0.2031 ],
406
- // [ 33199.99, 0.6066 ]
407
- // ],
408
- // high: 34816.8,
409
- // rate: '6.484',
410
- // low: 32312.41,
411
- // currentIsBuy: true,
412
- // dayNumber: 26988.5536,
413
- // totalBtc: 26988.5536,
414
- // showMarket: 'btcusdt'
415
- // }
416
- //
417
- // contract snapshot
418
- // {
419
- // channel: 'BTC_USDT.Depth',
420
- // type: 'Whole',
421
- // data: {
422
- // asks: [ [Array], [Array], [Array], [Array], [Array] ],
423
- // bids: [ [Array], [Array], [Array], [Array], [Array] ],
424
- // time: '1647359998198'
425
- // }
426
- // }
427
- //
428
- // contract deltas
429
- // {
430
- // channel: 'BTC_USDT.Depth',
431
- // data: {
432
- // bids: [ [Array], [Array], [Array], [Array] ],
433
- // asks: [ [Array], [Array], [Array] ],
434
- // time: '1647360038079'
435
- // }
436
- // }
437
- //
438
- // For contract markets zb will:
439
- // 1: send snapshot
440
- // 2: send deltas
441
- // 3: repeat 1-2
442
- // So we have a guarentee that deltas
443
- // are always updated and arrive after
444
- // the snapshot
445
- //
446
- const type = this.safeString2(message, 'type', 'dataType');
447
- const channel = this.safeString(message, 'channel');
448
- const symbol = this.safeString(subscription, 'symbol');
449
- let orderbook = this.safeValue(this.orderbooks, symbol);
450
- if (type !== undefined) {
451
- // handle orderbook snapshot
452
- const isContractSnapshot = (type === 'Whole');
453
- const data = isContractSnapshot ? this.safeValue(message, 'data') : message;
454
- const timestamp = this.safeInteger2(data, 'lastTime', 'time');
455
- const asksKey = isContractSnapshot ? 'asks' : 'listUp';
456
- const bidsKey = isContractSnapshot ? 'bids' : 'listDown';
457
- const snapshot = this.parseOrderBook(data, symbol, timestamp, bidsKey, asksKey);
458
- if (!(symbol in this.orderbooks)) {
459
- const defaultLimit = this.safeInteger(this.options, 'watchOrderBookLimit', 1000);
460
- const limit = this.safeInteger(subscription, 'limit', defaultLimit);
461
- orderbook = this.orderBook(snapshot, limit);
462
- this.orderbooks[symbol] = orderbook;
463
- }
464
- else {
465
- orderbook = this.orderbooks[symbol];
466
- orderbook.reset(snapshot);
467
- }
468
- orderbook['symbol'] = symbol;
469
- client.resolve(orderbook, channel);
470
- }
471
- else {
472
- this.handleOrderBookMessage(client, message, orderbook);
473
- client.resolve(orderbook, channel);
474
- }
475
- }
476
- handleOrderBookMessage(client, message, orderbook) {
477
- //
478
- // {
479
- // channel: 'BTC_USDT.Depth',
480
- // data: {
481
- // bids: [ [Array], [Array], [Array], [Array] ],
482
- // asks: [ [Array], [Array], [Array] ],
483
- // time: '1647360038079'
484
- // }
485
- // }
486
- //
487
- const data = this.safeValue(message, 'data', {});
488
- const timestamp = this.safeInteger(data, 'time');
489
- const asks = this.safeValue(data, 'asks', []);
490
- const bids = this.safeValue(data, 'bids', []);
491
- this.handleDeltas(orderbook['asks'], asks);
492
- this.handleDeltas(orderbook['bids'], bids);
493
- orderbook['timestamp'] = timestamp;
494
- orderbook['datetime'] = this.iso8601(timestamp);
495
- return orderbook;
496
- }
497
- handleDelta(bookside, delta) {
498
- const price = this.safeFloat(delta, 0);
499
- const amount = this.safeFloat(delta, 1);
500
- bookside.store(price, amount);
501
- }
502
- handleDeltas(bookside, deltas) {
503
- for (let i = 0; i < deltas.length; i++) {
504
- this.handleDelta(bookside, deltas[i]);
505
- }
506
- }
507
- handleMessage(client, message) {
508
- //
509
- //
510
- // {
511
- // no: '0',
512
- // code: 1007,
513
- // success: false,
514
- // channel: 'btc_usdt_ticker',
515
- // message: 'Channel is empty'
516
- // }
517
- //
518
- // {
519
- // date: '1624398991255',
520
- // ticker: {
521
- // high: '33298.38',
522
- // vol: '56375.9469',
523
- // last: '32396.95',
524
- // low: '28808.19',
525
- // buy: '32395.81',
526
- // sell: '32409.3',
527
- // turnover: '1771122527.0000',
528
- // open: '31652.44',
529
- // riseRate: '2.36'
530
- // },
531
- // dataType: 'ticker',
532
- // channel: 'btcusdt_ticker'
533
- // }
534
- //
535
- // {
536
- // data: [
537
- // { date: 1624537147, amount: '0.0357', price: '34066.11', trade_type: 'bid', type: 'buy', tid: 1718857158 },
538
- // { date: 1624537147, amount: '0.0255', price: '34071.04', trade_type: 'bid', type: 'buy', tid: 1718857159 },
539
- // { date: 1624537147, amount: '0.0153', price: '34071.29', trade_type: 'bid', type: 'buy', tid: 1718857160 }
540
- // ],
541
- // dataType: 'trades',
542
- // channel: 'btcusdt_trades'
543
- // }
544
- //
545
- // contract snapshot
546
- //
547
- // {
548
- // channel: 'BTC_USDT.Depth',
549
- // type: 'Whole',
550
- // data: {
551
- // asks: [ [Array], [Array], [Array], [Array], [Array] ],
552
- // bids: [ [Array], [Array], [Array], [Array], [Array] ],
553
- // time: '1647359998198'
554
- // }
555
- // }
556
- //
557
- // contract deltas update
558
- // {
559
- // channel: 'BTC_USDT.Depth',
560
- // data: {
561
- // bids: [ [Array], [Array], [Array], [Array] ],
562
- // asks: [ [Array], [Array], [Array] ],
563
- // time: '1647360038079'
564
- // }
565
- // }
566
- //
567
- const channel = this.safeString(message, 'channel');
568
- const subscription = this.safeValue(client.subscriptions, channel);
569
- if (subscription !== undefined) {
570
- const method = this.safeValue(subscription, 'method');
571
- if (method !== undefined) {
572
- return method.call(this, client, message, subscription);
573
- }
574
- }
575
- return message;
576
- }
577
- handleErrorMessage(client, message) {
578
- //
579
- // { errorCode: 10020, errorMsg: "action param can't be empty" }
580
- // { errorCode: 10015, errorMsg: '无效的签名(1002)' }
581
- //
582
- const errorCode = this.safeString(message, 'errorCode');
583
- try {
584
- if (errorCode !== undefined) {
585
- const feedback = this.id + ' ' + this.json(message);
586
- this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
587
- const messageString = this.safeValue(message, 'message');
588
- if (messageString !== undefined) {
589
- this.throwBroadlyMatchedException(this.exceptions['broad'], messageString, feedback);
590
- }
591
- }
592
- }
593
- catch (e) {
594
- if (e instanceof AuthenticationError) {
595
- client.reject(e, 'authenticated');
596
- const method = 'login';
597
- if (method in client.subscriptions) {
598
- delete client.subscriptions[method];
599
- }
600
- return false;
601
- }
602
- }
603
- return message;
604
- }
605
- }