ccxt 4.5.30 → 4.5.32

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 (73) hide show
  1. package/README.md +4 -4
  2. package/dist/ccxt.browser.min.js +18 -18
  3. package/dist/cjs/ccxt.js +6 -4
  4. package/dist/cjs/src/aster.js +3802 -0
  5. package/dist/cjs/src/backpack.js +1 -1
  6. package/dist/cjs/src/base/Exchange.js +35 -2
  7. package/dist/cjs/src/base/ws/WsClient.js +1 -0
  8. package/dist/cjs/src/bigone.js +1 -1
  9. package/dist/cjs/src/binance.js +1 -0
  10. package/dist/cjs/src/bingx.js +73 -0
  11. package/dist/cjs/src/cryptomus.js +1 -1
  12. package/dist/cjs/src/gate.js +52 -6
  13. package/dist/cjs/src/hyperliquid.js +9 -1
  14. package/dist/cjs/src/kucoin.js +63 -64
  15. package/dist/cjs/src/okx.js +14 -5
  16. package/dist/cjs/src/pro/apex.js +2 -2
  17. package/dist/cjs/src/pro/ascendex.js +1 -1
  18. package/dist/cjs/src/pro/aster.js +1046 -0
  19. package/dist/cjs/src/pro/bingx.js +1 -1
  20. package/dist/cjs/src/pro/bybit.js +1 -1
  21. package/dist/cjs/src/pro/cryptocom.js +1 -1
  22. package/dist/cjs/src/pro/dydx.js +1 -1
  23. package/dist/cjs/src/pro/htx.js +1 -1
  24. package/dist/cjs/src/pro/hyperliquid.js +1 -1
  25. package/dist/cjs/src/pro/p2b.js +1 -1
  26. package/dist/cjs/src/pro/toobit.js +1 -1
  27. package/js/ccxt.d.ts +8 -5
  28. package/js/ccxt.js +6 -4
  29. package/js/src/abstract/aster.d.ts +88 -0
  30. package/js/src/abstract/binance.d.ts +1 -0
  31. package/js/src/abstract/binancecoinm.d.ts +1 -0
  32. package/js/src/abstract/binanceus.d.ts +1 -0
  33. package/js/src/abstract/binanceusdm.d.ts +1 -0
  34. package/js/src/abstract/kucoin.d.ts +2 -0
  35. package/js/src/abstract/kucoinfutures.d.ts +2 -0
  36. package/js/src/aster.d.ts +563 -0
  37. package/js/src/aster.js +3801 -0
  38. package/js/src/backpack.js +1 -1
  39. package/js/src/base/Exchange.d.ts +4 -0
  40. package/js/src/base/Exchange.js +35 -1
  41. package/js/src/base/ws/WsClient.js +1 -0
  42. package/js/src/bigone.js +1 -1
  43. package/js/src/binance.d.ts +1 -1
  44. package/js/src/binance.js +1 -0
  45. package/js/src/bingx.d.ts +12 -1
  46. package/js/src/bingx.js +73 -0
  47. package/js/src/cryptomus.js +1 -1
  48. package/js/src/exmo.d.ts +1 -1
  49. package/js/src/gate.js +52 -6
  50. package/js/src/hyperliquid.d.ts +1 -0
  51. package/js/src/hyperliquid.js +9 -1
  52. package/js/src/kucoin.d.ts +5 -3
  53. package/js/src/kucoin.js +63 -64
  54. package/js/src/okx.js +14 -5
  55. package/js/src/pro/apex.js +2 -2
  56. package/js/src/pro/ascendex.js +1 -1
  57. package/js/src/pro/aster.d.ts +273 -0
  58. package/js/src/pro/aster.js +1045 -0
  59. package/js/src/pro/bingx.js +1 -1
  60. package/js/src/pro/bybit.js +1 -1
  61. package/js/src/pro/cryptocom.js +1 -1
  62. package/js/src/pro/dydx.js +1 -1
  63. package/js/src/pro/htx.js +1 -1
  64. package/js/src/pro/hyperliquid.js +1 -1
  65. package/js/src/pro/p2b.js +1 -1
  66. package/js/src/pro/toobit.js +1 -1
  67. package/package.json +1 -1
  68. package/dist/cjs/src/oceanex.js +0 -1125
  69. package/js/src/abstract/oceanex.d.ts +0 -30
  70. package/js/src/oceanex.d.ts +0 -231
  71. package/js/src/oceanex.js +0 -1124
  72. /package/dist/cjs/src/abstract/{oceanex.js → aster.js} +0 -0
  73. /package/js/src/abstract/{oceanex.js → aster.js} +0 -0
@@ -0,0 +1,1046 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var aster$1 = require('../aster.js');
6
+ var errors = require('../base/errors.js');
7
+ var Cache = require('../base/ws/Cache.js');
8
+
9
+ // ----------------------------------------------------------------------------
10
+ // ---------------------------------------------------------------------------
11
+ class aster extends aster$1["default"] {
12
+ describe() {
13
+ return this.deepExtend(super.describe(), {
14
+ 'has': {
15
+ 'ws': true,
16
+ 'watchBalance': false,
17
+ 'watchBidsAsks': true,
18
+ 'watchTicker': true,
19
+ 'watchTickers': true,
20
+ 'watchMarkPrice': true,
21
+ 'watchMarkPrices': true,
22
+ 'watchTrades': true,
23
+ 'watchTradesForSymbols': true,
24
+ 'watchOrderBook': true,
25
+ 'watchOrderBookForSymbols': true,
26
+ 'watchOHLCV': true,
27
+ 'watchOHLCVForSymbols': true,
28
+ 'unWatchTicker': true,
29
+ 'unWatchTickers': true,
30
+ 'unWatchMarkPrice': true,
31
+ 'unWatchMarkPrices': true,
32
+ 'unWatchBidsAsks': true,
33
+ 'unWatchTrades': true,
34
+ 'unWatchTradesForSymbols': true,
35
+ 'unWatchOrderBook': true,
36
+ 'unWatchOrderBookForSymbols': true,
37
+ 'unWatchOHLCV': true,
38
+ 'unWatchOHLCVForSymbols': true,
39
+ },
40
+ 'urls': {
41
+ 'api': {
42
+ 'ws': {
43
+ 'spot': 'wss://sstream.asterdex.com/stream',
44
+ 'swap': 'wss://fstream.asterdex.com/stream',
45
+ },
46
+ },
47
+ },
48
+ 'options': {},
49
+ 'streaming': {},
50
+ 'exceptions': {},
51
+ });
52
+ }
53
+ getAccountTypeFromSubscriptions(subscriptions) {
54
+ let accountType = '';
55
+ for (let i = 0; i < subscriptions.length; i++) {
56
+ const subscription = subscriptions[i];
57
+ if ((subscription === 'spot') || (subscription === 'swap')) {
58
+ accountType = subscription;
59
+ break;
60
+ }
61
+ }
62
+ return accountType;
63
+ }
64
+ /**
65
+ * @method
66
+ * @name aster#watchTicker
67
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
68
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#full-ticker-per-symbol
69
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-ticker-streams
70
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
71
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
72
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
73
+ */
74
+ async watchTicker(symbol, params = {}) {
75
+ params['callerMethodName'] = 'watchTicker';
76
+ await this.loadMarkets();
77
+ symbol = this.safeSymbol(symbol);
78
+ const tickers = await this.watchTickers([symbol], params);
79
+ return tickers[symbol];
80
+ }
81
+ /**
82
+ * @method
83
+ * @name aster#unWatchTicker
84
+ * @description unWatches a price ticker
85
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#full-ticker-per-symbol
86
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-ticker-streams
87
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
88
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
89
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
90
+ */
91
+ async unWatchTicker(symbol, params = {}) {
92
+ params['callerMethodName'] = 'unWatchTicker';
93
+ return await this.unWatchTickers([symbol], params);
94
+ }
95
+ /**
96
+ * @method
97
+ * @name aster#watchTickers
98
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
99
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#full-ticker-per-symbol
100
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-ticker-streams
101
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
102
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
103
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
104
+ */
105
+ async watchTickers(symbols = undefined, params = {}) {
106
+ await this.loadMarkets();
107
+ symbols = this.marketSymbols(symbols, undefined, true, true, true);
108
+ const firstMarket = this.getMarketFromSymbols(symbols);
109
+ const type = this.safeString(firstMarket, 'type', 'swap');
110
+ const symbolsLength = symbols.length;
111
+ let methodName = undefined;
112
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', 'watchTickers');
113
+ params = this.omit(params, 'callerMethodName');
114
+ if (symbolsLength === 0) {
115
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
116
+ }
117
+ const url = this.urls['api']['ws'][type];
118
+ const subscriptionArgs = [];
119
+ const messageHashes = [];
120
+ const request = {
121
+ 'method': 'SUBSCRIBE',
122
+ 'params': subscriptionArgs,
123
+ };
124
+ for (let i = 0; i < symbols.length; i++) {
125
+ const symbol = symbols[i];
126
+ const market = this.market(symbol);
127
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@ticker');
128
+ messageHashes.push('ticker:' + market['symbol']);
129
+ }
130
+ const newTicker = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
131
+ if (this.newUpdates) {
132
+ const result = {};
133
+ result[newTicker['symbol']] = newTicker;
134
+ return result;
135
+ }
136
+ return this.filterByArray(this.tickers, 'symbol', symbols);
137
+ }
138
+ /**
139
+ * @method
140
+ * @name aster#unWatchTickers
141
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
142
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#full-ticker-per-symbol
143
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-ticker-streams
144
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
145
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
146
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
147
+ */
148
+ async unWatchTickers(symbols = undefined, params = {}) {
149
+ await this.loadMarkets();
150
+ symbols = this.marketSymbols(symbols, undefined, true, true, true);
151
+ const firstMarket = this.getMarketFromSymbols(symbols);
152
+ const type = this.safeString(firstMarket, 'type', 'swap');
153
+ const symbolsLength = symbols.length;
154
+ let methodName = undefined;
155
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', 'unWatchTickers');
156
+ params = this.omit(params, 'callerMethodName');
157
+ if (symbolsLength === 0) {
158
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
159
+ }
160
+ const url = this.urls['api']['ws'][type];
161
+ const subscriptionArgs = [];
162
+ const messageHashes = [];
163
+ const request = {
164
+ 'method': 'UNSUBSCRIBE',
165
+ 'params': subscriptionArgs,
166
+ };
167
+ for (let i = 0; i < symbols.length; i++) {
168
+ const symbol = symbols[i];
169
+ const market = this.market(symbol);
170
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@ticker');
171
+ messageHashes.push('unsubscribe:ticker:' + market['symbol']);
172
+ }
173
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
174
+ }
175
+ /**
176
+ * @method
177
+ * @name aster#watchMarkPrice
178
+ * @description watches a mark price for a specific market
179
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#mark-price-stream
180
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
181
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
182
+ * @param {boolean} [params.use1sFreq] *default is true* if set to true, the mark price will be updated every second, otherwise every 3 seconds
183
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
184
+ */
185
+ async watchMarkPrice(symbol, params = {}) {
186
+ params['callerMethodName'] = 'watchMarkPrice';
187
+ await this.loadMarkets();
188
+ symbol = this.safeSymbol(symbol);
189
+ const tickers = await this.watchMarkPrices([symbol], params);
190
+ return tickers[symbol];
191
+ }
192
+ /**
193
+ * @method
194
+ * @name aster#unWatchMarkPrice
195
+ * @description unWatches a mark price for a specific market
196
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#mark-price-stream
197
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
198
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
199
+ * @param {boolean} [params.use1sFreq] *default is true* if set to true, the mark price will be updated every second, otherwise every 3 seconds
200
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
201
+ */
202
+ async unWatchMarkPrice(symbol, params = {}) {
203
+ params['callerMethodName'] = 'unWatchMarkPrice';
204
+ return await this.unWatchMarkPrices([symbol], params);
205
+ }
206
+ /**
207
+ * @method
208
+ * @name aster#watchMarkPrices
209
+ * @description watches the mark price for all markets
210
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#mark-price-stream
211
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
212
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
213
+ * @param {boolean} [params.use1sFreq] *default is true* if set to true, the mark price will be updated every second, otherwise every 3 seconds
214
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
215
+ */
216
+ async watchMarkPrices(symbols = undefined, params = {}) {
217
+ await this.loadMarkets();
218
+ symbols = this.marketSymbols(symbols, undefined, true, true, true);
219
+ const firstMarket = this.getMarketFromSymbols(symbols);
220
+ const type = this.safeString(firstMarket, 'type', 'swap');
221
+ const symbolsLength = symbols.length;
222
+ let methodName = undefined;
223
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', 'watchMarkPrices');
224
+ params = this.omit(params, 'callerMethodName');
225
+ if (symbolsLength === 0) {
226
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
227
+ }
228
+ const url = this.urls['api']['ws'][type];
229
+ const subscriptionArgs = [];
230
+ const messageHashes = [];
231
+ const request = {
232
+ 'method': 'SUBSCRIBE',
233
+ 'params': subscriptionArgs,
234
+ };
235
+ const use1sFreq = this.safeBool(params, 'use1sFreq', true);
236
+ for (let i = 0; i < symbols.length; i++) {
237
+ const symbol = symbols[i];
238
+ const market = this.market(symbol);
239
+ const suffix = (use1sFreq) ? '@1s' : '';
240
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@markPrice' + suffix);
241
+ messageHashes.push('ticker:' + market['symbol']);
242
+ }
243
+ const newTicker = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
244
+ if (this.newUpdates) {
245
+ const result = {};
246
+ result[newTicker['symbol']] = newTicker;
247
+ return result;
248
+ }
249
+ return this.filterByArray(this.tickers, 'symbol', symbols);
250
+ }
251
+ /**
252
+ * @method
253
+ * @name aster#unWatchMarkPrices
254
+ * @description watches the mark price for all markets
255
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#mark-price-stream
256
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
257
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
258
+ * @param {boolean} [params.use1sFreq] *default is true* if set to true, the mark price will be updated every second, otherwise every 3 seconds
259
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
260
+ */
261
+ async unWatchMarkPrices(symbols = undefined, params = {}) {
262
+ await this.loadMarkets();
263
+ symbols = this.marketSymbols(symbols, undefined, true, true, true);
264
+ const firstMarket = this.getMarketFromSymbols(symbols);
265
+ const type = this.safeString(firstMarket, 'type', 'swap');
266
+ const symbolsLength = symbols.length;
267
+ let methodName = undefined;
268
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', 'unWatchMarkPrices');
269
+ params = this.omit(params, 'callerMethodName');
270
+ if (symbolsLength === 0) {
271
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
272
+ }
273
+ const url = this.urls['api']['ws'][type];
274
+ const subscriptionArgs = [];
275
+ const messageHashes = [];
276
+ const request = {
277
+ 'method': 'UNSUBSCRIBE',
278
+ 'params': subscriptionArgs,
279
+ };
280
+ const use1sFreq = this.safeBool(params, 'use1sFreq', true);
281
+ for (let i = 0; i < symbols.length; i++) {
282
+ const symbol = symbols[i];
283
+ const market = this.market(symbol);
284
+ const suffix = (use1sFreq) ? '@1s' : '';
285
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@markPrice' + suffix);
286
+ messageHashes.push('unsubscribe:ticker:' + market['symbol']);
287
+ }
288
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
289
+ }
290
+ handleTicker(client, message) {
291
+ //
292
+ // {
293
+ // "stream": "trumpusdt@ticker",
294
+ // "data": {
295
+ // "e": "24hrTicker",
296
+ // "E": 1754451187277,
297
+ // "s": "CAKEUSDT",
298
+ // "p": "-0.08800",
299
+ // "P": "-3.361",
300
+ // "w": "2.58095",
301
+ // "c": "2.53000",
302
+ // "Q": "5",
303
+ // "o": "2.61800",
304
+ // "h": "2.64700",
305
+ // "l": "2.52400",
306
+ // "v": "15775",
307
+ // "q": "40714.46000",
308
+ // "O": 1754364780000,
309
+ // "C": 1754451187274,
310
+ // "F": 6571389,
311
+ // "L": 6574507,
312
+ // "n": 3119
313
+ // }
314
+ // }
315
+ // {
316
+ // "stream": "btcusdt@markPrice",
317
+ // "data": {
318
+ // "e": "markPriceUpdate",
319
+ // "E": 1754660466000,
320
+ // "s": "BTCUSDT",
321
+ // "p": "116809.60000000",
322
+ // "P": "116595.54012838",
323
+ // "i": "116836.93534884",
324
+ // "r": "0.00010000",
325
+ // "T": 1754668800000
326
+ // }
327
+ // }
328
+ //
329
+ const subscriptions = client.subscriptions;
330
+ const subscriptionsKeys = Object.keys(subscriptions);
331
+ const marketType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
332
+ const ticker = this.safeDict(message, 'data');
333
+ const parsed = this.parseWsTicker(ticker, marketType);
334
+ const symbol = parsed['symbol'];
335
+ const messageHash = 'ticker:' + symbol;
336
+ this.tickers[symbol] = parsed;
337
+ client.resolve(this.tickers[symbol], messageHash);
338
+ }
339
+ parseWsTicker(message, marketType) {
340
+ const event = this.safeString(message, 'e');
341
+ const part = event.split('@');
342
+ const channel = this.safeString(part, 1);
343
+ const marketId = this.safeString(message, 's');
344
+ const timestamp = this.safeInteger(message, 'E');
345
+ const market = this.safeMarket(marketId, undefined, undefined, marketType);
346
+ const last = this.safeString(message, 'c');
347
+ if (channel === 'markPriceUpdate') {
348
+ return this.safeTicker({
349
+ 'symbol': market['symbol'],
350
+ 'timestamp': timestamp,
351
+ 'datetime': this.iso8601(timestamp),
352
+ 'info': message,
353
+ 'markPrice': this.safeString(message, 'p'),
354
+ 'indexPrice': this.safeString(message, 'i'),
355
+ });
356
+ }
357
+ return this.safeTicker({
358
+ 'symbol': market['symbol'],
359
+ 'timestamp': timestamp,
360
+ 'datetime': this.iso8601(timestamp),
361
+ 'high': this.safeString(message, 'h'),
362
+ 'low': this.safeString(message, 'l'),
363
+ 'bid': undefined,
364
+ 'bidVolume': undefined,
365
+ 'ask': undefined,
366
+ 'askVolume': undefined,
367
+ 'vwap': this.safeString(message, 'w'),
368
+ 'open': this.safeString(message, 'o'),
369
+ 'close': last,
370
+ 'last': last,
371
+ 'previousClose': undefined,
372
+ 'change': this.safeString(message, 'p'),
373
+ 'percentage': this.safeString(message, 'P'),
374
+ 'average': undefined,
375
+ 'baseVolume': this.safeString(message, 'v'),
376
+ 'quoteVolume': this.safeString(message, 'q'),
377
+ 'info': message,
378
+ }, market);
379
+ }
380
+ /**
381
+ * @method
382
+ * @name aster#watchBidsAsks
383
+ * @description watches best bid & ask for symbols
384
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#best-order-book-information-by-symbol
385
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-book-ticker-streams
386
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
387
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
388
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
389
+ */
390
+ async watchBidsAsks(symbols = undefined, params = {}) {
391
+ await this.loadMarkets();
392
+ symbols = this.marketSymbols(symbols, undefined, true, true, true);
393
+ const firstMarket = this.getMarketFromSymbols(symbols);
394
+ const type = this.safeString(firstMarket, 'type', 'swap');
395
+ const symbolsLength = symbols.length;
396
+ if (symbolsLength === 0) {
397
+ throw new errors.ArgumentsRequired(this.id + ' watchBidsAsks() requires a non-empty array of symbols');
398
+ }
399
+ const url = this.urls['api']['ws'][type];
400
+ const subscriptionArgs = [];
401
+ const messageHashes = [];
402
+ const request = {
403
+ 'method': 'SUBSCRIBE',
404
+ 'params': subscriptionArgs,
405
+ };
406
+ for (let i = 0; i < symbols.length; i++) {
407
+ const symbol = symbols[i];
408
+ const market = this.market(symbol);
409
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@bookTicker');
410
+ messageHashes.push('bidask:' + market['symbol']);
411
+ }
412
+ const newTicker = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
413
+ if (this.newUpdates) {
414
+ const result = {};
415
+ result[newTicker['symbol']] = newTicker;
416
+ return result;
417
+ }
418
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
419
+ }
420
+ /**
421
+ * @method
422
+ * @name aster#unWatchBidsAsks
423
+ * @description unWatches best bid & ask for symbols
424
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#best-order-book-information-by-symbol
425
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-book-ticker-streams
426
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
427
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
428
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
429
+ */
430
+ async unWatchBidsAsks(symbols = undefined, params = {}) {
431
+ await this.loadMarkets();
432
+ symbols = this.marketSymbols(symbols, undefined, true, true, true);
433
+ const firstMarket = this.getMarketFromSymbols(symbols);
434
+ const type = this.safeString(firstMarket, 'type', 'swap');
435
+ const symbolsLength = symbols.length;
436
+ if (symbolsLength === 0) {
437
+ throw new errors.ArgumentsRequired(this.id + ' unWatchBidsAsks() requires a non-empty array of symbols');
438
+ }
439
+ const url = this.urls['api']['ws'][type];
440
+ const subscriptionArgs = [];
441
+ const messageHashes = [];
442
+ const request = {
443
+ 'method': 'UNSUBSCRIBE',
444
+ 'params': subscriptionArgs,
445
+ };
446
+ for (let i = 0; i < symbols.length; i++) {
447
+ const symbol = symbols[i];
448
+ const market = this.market(symbol);
449
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@bookTicker');
450
+ messageHashes.push('unsubscribe:bidask:' + market['symbol']);
451
+ }
452
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
453
+ }
454
+ handleBidAsk(client, message) {
455
+ //
456
+ // {
457
+ // "stream": "btcusdt@bookTicker",
458
+ // "data": {
459
+ // "e": "bookTicker",
460
+ // "u": 157240846459,
461
+ // "s": "BTCUSDT",
462
+ // "b": "122046.7",
463
+ // "B": "1.084",
464
+ // "a": "122046.8",
465
+ // "A": "0.001",
466
+ // "T": 1754896692922,
467
+ // "E": 1754896692926
468
+ // }
469
+ // }
470
+ //
471
+ const subscriptions = client.subscriptions;
472
+ const subscriptionsKeys = Object.keys(subscriptions);
473
+ const marketType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
474
+ const data = this.safeDict(message, 'data', {});
475
+ const marketId = this.safeString(data, 's');
476
+ const market = this.safeMarket(marketId, undefined, undefined, marketType);
477
+ const ticker = this.parseWsBidAsk(data, market);
478
+ const symbol = ticker['symbol'];
479
+ this.bidsasks[symbol] = ticker;
480
+ const messageHash = 'bidask:' + symbol;
481
+ client.resolve(ticker, messageHash);
482
+ }
483
+ parseWsBidAsk(message, market = undefined) {
484
+ const timestamp = this.safeInteger(message, 'T');
485
+ return this.safeTicker({
486
+ 'symbol': market['symbol'],
487
+ 'timestamp': timestamp,
488
+ 'datetime': this.iso8601(timestamp),
489
+ 'ask': this.safeString(message, 'a'),
490
+ 'askVolume': this.safeString(message, 'A'),
491
+ 'bid': this.safeString(message, 'b'),
492
+ 'bidVolume': this.safeString(message, 'B'),
493
+ 'info': message,
494
+ }, market);
495
+ }
496
+ /**
497
+ * @method
498
+ * @name aster#watchTrades
499
+ * @description watches information on multiple trades made in a market
500
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#collection-transaction-flow
501
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#aggregate-trade-streams
502
+ * @param {string} symbol unified market symbol of the market trades were made in
503
+ * @param {int} [since] the earliest time in ms to fetch trades for
504
+ * @param {int} [limit] the maximum number of trade structures to retrieve
505
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
506
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
507
+ */
508
+ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
509
+ params['callerMethodName'] = 'watchTrades';
510
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
511
+ }
512
+ /**
513
+ * @method
514
+ * @name aster#unWatchTrades
515
+ * @description unsubscribe from the trades channel
516
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#collection-transaction-flow
517
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#aggregate-trade-streams
518
+ * @param {string} symbol unified market symbol of the market trades were made in
519
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
520
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
521
+ */
522
+ async unWatchTrades(symbol, params = {}) {
523
+ params['callerMethodName'] = 'unWatchTrades';
524
+ return await this.unWatchTradesForSymbols([symbol], params);
525
+ }
526
+ /**
527
+ * @method
528
+ * @name aster#watchTradesForSymbols
529
+ * @description get the list of most recent trades for a list of symbols
530
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#collection-transaction-flow
531
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#aggregate-trade-streams
532
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
533
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
534
+ * @param {int} [limit] the maximum amount of trades to fetch
535
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
536
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
537
+ */
538
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
539
+ await this.loadMarkets();
540
+ symbols = this.marketSymbols(symbols, undefined, true, true, true);
541
+ const firstMarket = this.getMarketFromSymbols(symbols);
542
+ const type = this.safeString(firstMarket, 'type', 'swap');
543
+ const symbolsLength = symbols.length;
544
+ let methodName = undefined;
545
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', 'watchTradesForSymbols');
546
+ params = this.omit(params, 'callerMethodName');
547
+ if (symbolsLength === 0) {
548
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
549
+ }
550
+ const url = this.urls['api']['ws'][type];
551
+ const subscriptionArgs = [];
552
+ const messageHashes = [];
553
+ const request = {
554
+ 'method': 'SUBSCRIBE',
555
+ 'params': subscriptionArgs,
556
+ };
557
+ for (let i = 0; i < symbols.length; i++) {
558
+ const symbol = symbols[i];
559
+ const market = this.market(symbol);
560
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@aggTrade');
561
+ messageHashes.push('trade:' + market['symbol']);
562
+ }
563
+ const trades = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
564
+ if (this.newUpdates) {
565
+ const first = this.safeValue(trades, 0);
566
+ const tradeSymbol = this.safeString(first, 'symbol');
567
+ limit = trades.getLimit(tradeSymbol, limit);
568
+ }
569
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
570
+ }
571
+ /**
572
+ * @method
573
+ * @name aster#unWatchTradesForSymbols
574
+ * @description unsubscribe from the trades channel
575
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#collection-transaction-flow
576
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#aggregate-trade-streams
577
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
578
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
579
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
580
+ */
581
+ async unWatchTradesForSymbols(symbols, params = {}) {
582
+ await this.loadMarkets();
583
+ symbols = this.marketSymbols(symbols, undefined, true, true, true);
584
+ const firstMarket = this.getMarketFromSymbols(symbols);
585
+ const type = this.safeString(firstMarket, 'type', 'swap');
586
+ const symbolsLength = symbols.length;
587
+ let methodName = undefined;
588
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', 'unWatchTradesForSymbols');
589
+ params = this.omit(params, 'callerMethodName');
590
+ if (symbolsLength === 0) {
591
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
592
+ }
593
+ const url = this.urls['api']['ws'][type];
594
+ const subscriptionArgs = [];
595
+ const messageHashes = [];
596
+ const request = {
597
+ 'method': 'UNSUBSCRIBE',
598
+ 'params': subscriptionArgs,
599
+ };
600
+ for (let i = 0; i < symbols.length; i++) {
601
+ const symbol = symbols[i];
602
+ const market = this.market(symbol);
603
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@aggTrade');
604
+ messageHashes.push('unsubscribe:trade:' + market['symbol']);
605
+ }
606
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
607
+ }
608
+ handleTrade(client, message) {
609
+ //
610
+ // {
611
+ // "stream": "btcusdt@aggTrade",
612
+ // "data": {
613
+ // "e": "aggTrade",
614
+ // "E": 1754551358681,
615
+ // "a": 20505890,
616
+ // "s": "BTCUSDT",
617
+ // "p": "114783.7",
618
+ // "q": "0.020",
619
+ // "f": 26024678,
620
+ // "l": 26024682,
621
+ // "T": 1754551358528,
622
+ // "m": false
623
+ // }
624
+ // }
625
+ //
626
+ const subscriptions = client.subscriptions;
627
+ const subscriptionsKeys = Object.keys(subscriptions);
628
+ const marketType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
629
+ const trade = this.safeDict(message, 'data');
630
+ const marketId = this.safeString(trade, 's');
631
+ const market = this.safeMarket(marketId, undefined, undefined, marketType);
632
+ const parsed = this.parseWsTrade(trade, market);
633
+ const symbol = parsed['symbol'];
634
+ let stored = this.safeValue(this.trades, symbol);
635
+ if (stored === undefined) {
636
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
637
+ stored = new Cache.ArrayCache(limit);
638
+ this.trades[symbol] = stored;
639
+ }
640
+ stored.append(parsed);
641
+ const messageHash = 'trade' + ':' + symbol;
642
+ client.resolve(stored, messageHash);
643
+ }
644
+ parseWsTrade(trade, market = undefined) {
645
+ const timestamp = this.safeInteger(trade, 'T');
646
+ const symbol = market['symbol'];
647
+ const amountString = this.safeString(trade, 'q');
648
+ const priceString = this.safeString(trade, 'p');
649
+ const isMaker = this.safeBool(trade, 'm');
650
+ let takerOrMaker = undefined;
651
+ if (isMaker !== undefined) {
652
+ takerOrMaker = isMaker ? 'maker' : 'taker';
653
+ }
654
+ return this.safeTrade({
655
+ 'id': this.safeString(trade, 'a'),
656
+ 'info': trade,
657
+ 'timestamp': timestamp,
658
+ 'datetime': this.iso8601(timestamp),
659
+ 'symbol': symbol,
660
+ 'order': undefined,
661
+ 'type': undefined,
662
+ 'side': undefined,
663
+ 'takerOrMaker': takerOrMaker,
664
+ 'price': priceString,
665
+ 'amount': amountString,
666
+ 'cost': undefined,
667
+ 'fee': undefined,
668
+ }, market);
669
+ }
670
+ /**
671
+ * @method
672
+ * @name aster#watchOrderBook
673
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
674
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#limited-depth-information
675
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#partial-book-depth-streams
676
+ * @param {string} symbol unified symbol of the market to fetch the order book for
677
+ * @param {int} [limit] the maximum amount of order book entries to return.
678
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
679
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
680
+ */
681
+ async watchOrderBook(symbol, limit = undefined, params = {}) {
682
+ params['callerMethodName'] = 'watchOrderBook';
683
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
684
+ }
685
+ /**
686
+ * @method
687
+ * @name aster#unWatchOrderBook
688
+ * @description unsubscribe from the orderbook channel
689
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#limited-depth-information
690
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#partial-book-depth-streams
691
+ * @param {string} symbol symbol of the market to unwatch the trades for
692
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
693
+ * @param {int} [params.limit] orderbook limit, default is undefined
694
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
695
+ */
696
+ async unWatchOrderBook(symbol, params = {}) {
697
+ params['callerMethodName'] = 'unWatchOrderBook';
698
+ return await this.unWatchOrderBookForSymbols([symbol], params);
699
+ }
700
+ /**
701
+ * @method
702
+ * @name aster#watchOrderBookForSymbols
703
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
704
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#limited-depth-information
705
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#partial-book-depth-streams
706
+ * @param {string[]} symbols unified array of symbols
707
+ * @param {int} [limit] the maximum amount of order book entries to return.
708
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
709
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
710
+ */
711
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
712
+ await this.loadMarkets();
713
+ symbols = this.marketSymbols(symbols, undefined, true, true, true);
714
+ const firstMarket = this.getMarketFromSymbols(symbols);
715
+ const type = this.safeString(firstMarket, 'type', 'swap');
716
+ const symbolsLength = symbols.length;
717
+ let methodName = undefined;
718
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', 'watchOrderBookForSymbols');
719
+ params = this.omit(params, 'callerMethodName');
720
+ if (symbolsLength === 0) {
721
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
722
+ }
723
+ const url = this.urls['api']['ws'][type];
724
+ const subscriptionArgs = [];
725
+ const messageHashes = [];
726
+ const request = {
727
+ 'method': 'SUBSCRIBE',
728
+ 'params': subscriptionArgs,
729
+ };
730
+ if (limit === undefined || (limit !== 5 && limit !== 10 && limit !== 20)) {
731
+ limit = 20;
732
+ }
733
+ for (let i = 0; i < symbols.length; i++) {
734
+ const symbol = symbols[i];
735
+ const market = this.market(symbol);
736
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@depth' + limit);
737
+ messageHashes.push('orderbook:' + market['symbol']);
738
+ }
739
+ const orderbook = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
740
+ return orderbook.limit();
741
+ }
742
+ /**
743
+ * @method
744
+ * @name aster#unWatchOrderBookForSymbols
745
+ * @description unsubscribe from the orderbook channel
746
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#limited-depth-information
747
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#partial-book-depth-streams
748
+ * @param {string[]} symbols unified symbol of the market to unwatch the trades for
749
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
750
+ * @param {int} [params.limit] orderbook limit, default is undefined
751
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
752
+ */
753
+ async unWatchOrderBookForSymbols(symbols, params = {}) {
754
+ await this.loadMarkets();
755
+ symbols = this.marketSymbols(symbols, undefined, true, true, true);
756
+ const firstMarket = this.getMarketFromSymbols(symbols);
757
+ const type = this.safeString(firstMarket, 'type', 'swap');
758
+ const symbolsLength = symbols.length;
759
+ let methodName = undefined;
760
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', 'unWatchOrderBookForSymbols');
761
+ params = this.omit(params, 'callerMethodName');
762
+ if (symbolsLength === 0) {
763
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
764
+ }
765
+ const url = this.urls['api']['ws'][type];
766
+ const subscriptionArgs = [];
767
+ const messageHashes = [];
768
+ const request = {
769
+ 'method': 'UNSUBSCRIBE',
770
+ 'params': subscriptionArgs,
771
+ };
772
+ let limit = this.safeNumber(params, 'limit');
773
+ params = this.omit(params, 'limit');
774
+ if (limit === undefined || (limit !== 5 && limit !== 10 && limit !== 20)) {
775
+ limit = 20;
776
+ }
777
+ for (let i = 0; i < symbols.length; i++) {
778
+ const symbol = symbols[i];
779
+ const market = this.market(symbol);
780
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@depth' + limit);
781
+ messageHashes.push('unsubscribe:orderbook:' + market['symbol']);
782
+ }
783
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
784
+ }
785
+ handleOrderBook(client, message) {
786
+ //
787
+ // {
788
+ // "stream": "btcusdt@depth20",
789
+ // "data": {
790
+ // "e": "depthUpdate",
791
+ // "E": 1754556878284,
792
+ // "T": 1754556878031,
793
+ // "s": "BTCUSDT",
794
+ // "U": 156391349814,
795
+ // "u": 156391349814,
796
+ // "pu": 156391348236,
797
+ // "b": [
798
+ // [
799
+ // "114988.3",
800
+ // "0.147"
801
+ // ]
802
+ // ],
803
+ // "a": [
804
+ // [
805
+ // "114988.4",
806
+ // "1.060"
807
+ // ]
808
+ // ]
809
+ // }
810
+ // }
811
+ //
812
+ const subscriptions = client.subscriptions;
813
+ const subscriptionsKeys = Object.keys(subscriptions);
814
+ const marketType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
815
+ const data = this.safeDict(message, 'data');
816
+ const marketId = this.safeString(data, 's');
817
+ const timestamp = this.safeInteger(data, 'T');
818
+ const market = this.safeMarket(marketId, undefined, undefined, marketType);
819
+ const symbol = market['symbol'];
820
+ if (!(symbol in this.orderbooks)) {
821
+ this.orderbooks[symbol] = this.orderBook();
822
+ }
823
+ const orderbook = this.orderbooks[symbol];
824
+ const snapshot = this.parseOrderBook(data, symbol, timestamp, 'b', 'a');
825
+ orderbook.reset(snapshot);
826
+ const messageHash = 'orderbook' + ':' + symbol;
827
+ this.orderbooks[symbol] = orderbook;
828
+ client.resolve(orderbook, messageHash);
829
+ }
830
+ /**
831
+ * @method
832
+ * @name aster#watchOHLCV
833
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
834
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#k-line-streams
835
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#klinecandlestick-streams
836
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
837
+ * @param {string} timeframe the length of time each candle represents
838
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
839
+ * @param {int} [limit] the maximum amount of candles to fetch
840
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
841
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
842
+ */
843
+ async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
844
+ params['callerMethodName'] = 'watchOHLCV';
845
+ await this.loadMarkets();
846
+ symbol = this.safeSymbol(symbol);
847
+ const result = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
848
+ return result[symbol][timeframe];
849
+ }
850
+ /**
851
+ * @method
852
+ * @name aster#unWatchOHLCV
853
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
854
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#k-line-streams
855
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#klinecandlestick-streams
856
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
857
+ * @param {string} timeframe the length of time each candle represents
858
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
859
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
860
+ */
861
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
862
+ params['callerMethodName'] = 'unWatchOHLCV';
863
+ return await this.unWatchOHLCVForSymbols([[symbol, timeframe]], params);
864
+ }
865
+ /**
866
+ * @method
867
+ * @name aster#watchOHLCVForSymbols
868
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
869
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#k-line-streams
870
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#klinecandlestick-streams
871
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
872
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
873
+ * @param {int} [limit] the maximum amount of candles to fetch
874
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
875
+ * @returns {object} A list of candles ordered as timestamp, open, high, low, close, volume
876
+ */
877
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
878
+ await this.loadMarkets();
879
+ const symbolsLength = symbolsAndTimeframes.length;
880
+ let methodName = undefined;
881
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', 'watchOHLCVForSymbols');
882
+ params = this.omit(params, 'callerMethodName');
883
+ if (symbolsLength === 0) {
884
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
885
+ }
886
+ const symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
887
+ const marketSymbols = this.marketSymbols(symbols, undefined, false, true, true);
888
+ const firstMarket = this.market(marketSymbols[0]);
889
+ const type = this.safeString(firstMarket, 'type', 'swap');
890
+ const url = this.urls['api']['ws'][type];
891
+ const subscriptionArgs = [];
892
+ const messageHashes = [];
893
+ const request = {
894
+ 'method': 'SUBSCRIBE',
895
+ 'params': subscriptionArgs,
896
+ };
897
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
898
+ const data = symbolsAndTimeframes[i];
899
+ let symbolString = this.safeString(data, 0);
900
+ const market = this.market(symbolString);
901
+ symbolString = market['symbol'];
902
+ const unfiedTimeframe = this.safeString(data, 1);
903
+ const timeframeId = this.safeString(this.timeframes, unfiedTimeframe, unfiedTimeframe);
904
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@kline_' + timeframeId);
905
+ messageHashes.push('ohlcv:' + market['symbol'] + ':' + unfiedTimeframe);
906
+ }
907
+ const [symbol, timeframe, stored] = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
908
+ if (this.newUpdates) {
909
+ limit = stored.getLimit(symbol, limit);
910
+ }
911
+ const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
912
+ return this.createOHLCVObject(symbol, timeframe, filtered);
913
+ }
914
+ /**
915
+ * @method
916
+ * @name aster#unWatchOHLCVForSymbols
917
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
918
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#k-line-streams
919
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#klinecandlestick-streams
920
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
921
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
922
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
923
+ */
924
+ async unWatchOHLCVForSymbols(symbolsAndTimeframes, params = {}) {
925
+ await this.loadMarkets();
926
+ const symbolsLength = symbolsAndTimeframes.length;
927
+ let methodName = undefined;
928
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', 'unWatchOHLCVForSymbols');
929
+ params = this.omit(params, 'callerMethodName');
930
+ if (symbolsLength === 0) {
931
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
932
+ }
933
+ const symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
934
+ const marketSymbols = this.marketSymbols(symbols, undefined, false, true, true);
935
+ const firstMarket = this.market(marketSymbols[0]);
936
+ const type = this.safeString(firstMarket, 'type', 'swap');
937
+ const url = this.urls['api']['ws'][type];
938
+ const subscriptionArgs = [];
939
+ const messageHashes = [];
940
+ const request = {
941
+ 'method': 'UNSUBSCRIBE',
942
+ 'params': subscriptionArgs,
943
+ };
944
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
945
+ const data = symbolsAndTimeframes[i];
946
+ let symbolString = this.safeString(data, 0);
947
+ const market = this.market(symbolString);
948
+ symbolString = market['symbol'];
949
+ const unfiedTimeframe = this.safeString(data, 1);
950
+ const timeframeId = this.safeString(this.timeframes, unfiedTimeframe, unfiedTimeframe);
951
+ subscriptionArgs.push(this.safeStringLower(market, 'id') + '@kline_' + timeframeId);
952
+ messageHashes.push('unsubscribe:ohlcv:' + market['symbol'] + ':' + unfiedTimeframe);
953
+ }
954
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
955
+ }
956
+ handleOHLCV(client, message) {
957
+ //
958
+ // {
959
+ // "stream": "btcusdt@kline_1m",
960
+ // "data": {
961
+ // "e": "kline",
962
+ // "E": 1754655777119,
963
+ // "s": "BTCUSDT",
964
+ // "k": {
965
+ // "t": 1754655720000,
966
+ // "T": 1754655779999,
967
+ // "s": "BTCUSDT",
968
+ // "i": "1m",
969
+ // "f": 26032629,
970
+ // "L": 26032629,
971
+ // "o": "116546.9",
972
+ // "c": "116546.9",
973
+ // "h": "116546.9",
974
+ // "l": "116546.9",
975
+ // "v": "0.011",
976
+ // "n": 1,
977
+ // "x": false,
978
+ // "q": "1282.0159",
979
+ // "V": "0.000",
980
+ // "Q": "0.0000",
981
+ // "B": "0"
982
+ // }
983
+ // }
984
+ // }
985
+ //
986
+ const subscriptions = client.subscriptions;
987
+ const subscriptionsKeys = Object.keys(subscriptions);
988
+ const marketType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
989
+ const data = this.safeDict(message, 'data');
990
+ const marketId = this.safeString(data, 's');
991
+ const market = this.safeMarket(marketId, undefined, undefined, marketType);
992
+ const symbol = market['symbol'];
993
+ const kline = this.safeDict(data, 'k');
994
+ const timeframeId = this.safeString(kline, 'i');
995
+ const timeframe = this.findTimeframe(timeframeId);
996
+ const ohlcvsByTimeframe = this.safeValue(this.ohlcvs, symbol);
997
+ if (ohlcvsByTimeframe === undefined) {
998
+ this.ohlcvs[symbol] = {};
999
+ }
1000
+ if (this.safeValue(ohlcvsByTimeframe, timeframe) === undefined) {
1001
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
1002
+ this.ohlcvs[symbol][timeframe] = new Cache.ArrayCacheByTimestamp(limit);
1003
+ }
1004
+ const stored = this.ohlcvs[symbol][timeframe];
1005
+ const parsed = this.parseWsOHLCV(kline);
1006
+ stored.append(parsed);
1007
+ const messageHash = 'ohlcv:' + symbol + ':' + timeframe;
1008
+ const resolveData = [symbol, timeframe, stored];
1009
+ client.resolve(resolveData, messageHash);
1010
+ }
1011
+ parseWsOHLCV(ohlcv, market = undefined) {
1012
+ return [
1013
+ this.safeInteger(ohlcv, 't'),
1014
+ this.safeNumber(ohlcv, 'o'),
1015
+ this.safeNumber(ohlcv, 'h'),
1016
+ this.safeNumber(ohlcv, 'l'),
1017
+ this.safeNumber(ohlcv, 'c'),
1018
+ this.safeNumber(ohlcv, 'v'),
1019
+ ];
1020
+ }
1021
+ handleMessage(client, message) {
1022
+ const stream = this.safeString(message, 'stream');
1023
+ if (stream !== undefined) {
1024
+ const part = stream.split('@');
1025
+ let topic = this.safeString(part, 1, '');
1026
+ const part2 = topic.split('_');
1027
+ topic = this.safeString(part2, 0, '');
1028
+ const methods = {
1029
+ 'ticker': this.handleTicker,
1030
+ 'aggTrade': this.handleTrade,
1031
+ 'depth5': this.handleOrderBook,
1032
+ 'depth10': this.handleOrderBook,
1033
+ 'depth20': this.handleOrderBook,
1034
+ 'kline': this.handleOHLCV,
1035
+ 'markPrice': this.handleTicker,
1036
+ 'bookTicker': this.handleBidAsk,
1037
+ };
1038
+ const method = this.safeValue(methods, topic);
1039
+ if (method !== undefined) {
1040
+ method.call(this, client, message);
1041
+ }
1042
+ }
1043
+ }
1044
+ }
1045
+
1046
+ exports["default"] = aster;