ccxt 4.4.35 → 4.4.36

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 (43) hide show
  1. package/README.md +6 -5
  2. package/dist/ccxt.browser.min.js +2 -2
  3. package/dist/cjs/ccxt.js +6 -1
  4. package/dist/cjs/src/abstract/defx.js +9 -0
  5. package/dist/cjs/src/bitfinex2.js +20 -12
  6. package/dist/cjs/src/bitmex.js +103 -1
  7. package/dist/cjs/src/bitopro.js +22 -4
  8. package/dist/cjs/src/bitso.js +2 -1
  9. package/dist/cjs/src/bybit.js +20 -0
  10. package/dist/cjs/src/defx.js +2048 -0
  11. package/dist/cjs/src/deribit.js +34 -14
  12. package/dist/cjs/src/gate.js +15 -1
  13. package/dist/cjs/src/hashkey.js +1 -1
  14. package/dist/cjs/src/htx.js +14 -2
  15. package/dist/cjs/src/kraken.js +39 -48
  16. package/dist/cjs/src/pro/defx.js +864 -0
  17. package/js/ccxt.d.ts +8 -2
  18. package/js/ccxt.js +6 -2
  19. package/js/src/abstract/bitopro.d.ts +1 -0
  20. package/js/src/abstract/bybit.d.ts +15 -0
  21. package/js/src/abstract/defx.d.ts +72 -0
  22. package/js/src/abstract/defx.js +11 -0
  23. package/js/src/abstract/deribit.d.ts +1 -0
  24. package/js/src/abstract/gate.d.ts +14 -0
  25. package/js/src/abstract/gateio.d.ts +14 -0
  26. package/js/src/bitfinex2.js +21 -13
  27. package/js/src/bitmex.js +103 -1
  28. package/js/src/bitopro.d.ts +11 -0
  29. package/js/src/bitopro.js +22 -4
  30. package/js/src/bitso.js +2 -1
  31. package/js/src/bybit.js +20 -0
  32. package/js/src/defx.d.ts +349 -0
  33. package/js/src/defx.js +2049 -0
  34. package/js/src/deribit.d.ts +2 -0
  35. package/js/src/deribit.js +34 -14
  36. package/js/src/gate.js +15 -1
  37. package/js/src/hashkey.js +1 -1
  38. package/js/src/htx.d.ts +3 -0
  39. package/js/src/htx.js +14 -2
  40. package/js/src/kraken.js +39 -48
  41. package/js/src/pro/defx.d.ts +236 -0
  42. package/js/src/pro/defx.js +865 -0
  43. package/package.json +1 -1
@@ -0,0 +1,864 @@
1
+ 'use strict';
2
+
3
+ var defx$1 = require('../defx.js');
4
+ var errors = require('../base/errors.js');
5
+ var Cache = require('../base/ws/Cache.js');
6
+
7
+ // ---------------------------------------------------------------------------
8
+ // ---------------------------------------------------------------------------
9
+ class defx extends defx$1 {
10
+ describe() {
11
+ return this.deepExtend(super.describe(), {
12
+ 'has': {
13
+ 'ws': true,
14
+ 'watchBalance': true,
15
+ 'watchTicker': true,
16
+ 'watchTickers': true,
17
+ 'watchBidsAsks': true,
18
+ 'watchTrades': true,
19
+ 'watchTradesForSymbols': true,
20
+ 'watchMyTrades': false,
21
+ 'watchOrders': true,
22
+ 'watchOrderBook': true,
23
+ 'watchOrderBookForSymbols': true,
24
+ 'watchOHLCV': true,
25
+ 'watchOHLCVForSymbols': true,
26
+ },
27
+ 'urls': {
28
+ 'test': {
29
+ 'ws': {
30
+ 'public': 'wss://stream.testnet.defx.com/pricefeed',
31
+ 'private': 'wss://ws.testnet.defx.com/user',
32
+ },
33
+ },
34
+ 'api': {
35
+ 'ws': {
36
+ 'public': 'wss://marketfeed.api.defx.com/pricefeed',
37
+ 'private': 'wss://userfeed.api.defx.com/user',
38
+ },
39
+ },
40
+ },
41
+ 'options': {
42
+ 'listenKeyRefreshRate': 3540000,
43
+ 'ws': {
44
+ 'timeframes': {
45
+ '1m': '1m',
46
+ '3m': '3m',
47
+ '5m': '5m',
48
+ '15m': '15m',
49
+ '30m': '30m',
50
+ '1h': '1h',
51
+ '2h': '2h',
52
+ '4h': '4h',
53
+ '12h': '12h',
54
+ '1d': '1d',
55
+ '1w': '1w',
56
+ '1M': '1M',
57
+ },
58
+ },
59
+ },
60
+ 'streaming': {},
61
+ 'exceptions': {},
62
+ });
63
+ }
64
+ async watchPublic(topics, messageHashes, params = {}) {
65
+ await this.loadMarkets();
66
+ const url = this.urls['api']['ws']['public'];
67
+ const request = {
68
+ 'method': 'SUBSCRIBE',
69
+ 'topics': topics,
70
+ };
71
+ const message = this.extend(request, params);
72
+ return await this.watchMultiple(url, messageHashes, message, messageHashes);
73
+ }
74
+ async unWatchPublic(topics, messageHashes, params = {}) {
75
+ await this.loadMarkets();
76
+ const url = this.urls['api']['ws']['public'];
77
+ const request = {
78
+ 'method': 'UNSUBSCRIBE',
79
+ 'topics': topics,
80
+ };
81
+ const message = this.extend(request, params);
82
+ return await this.watchMultiple(url, messageHashes, message, messageHashes);
83
+ }
84
+ /**
85
+ * @method
86
+ * @name defx#watchOHLCV
87
+ * @description watches historical candlestick data containing the open, high, low, close price, and the volume of a market
88
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
89
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
90
+ * @param {string} timeframe the length of time each candle represents
91
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
92
+ * @param {int} [limit] the maximum amount of candles to fetch
93
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
94
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
95
+ */
96
+ async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
97
+ const result = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
98
+ return result[symbol][timeframe];
99
+ }
100
+ /**
101
+ * @method
102
+ * @name defx#unWatchOHLCV
103
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
104
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
105
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
106
+ * @param {string} timeframe the length of time each candle represents
107
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
108
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
109
+ */
110
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
111
+ return await this.unWatchOHLCVForSymbols([[symbol, timeframe]], params);
112
+ }
113
+ /**
114
+ * @method
115
+ * @name defx#watchOHLCVForSymbols
116
+ * @description watches historical candlestick data containing the open, high, low, close price, and the volume of a market
117
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
118
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
119
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
120
+ * @param {int} [limit] the maximum amount of candles to fetch
121
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
122
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
123
+ */
124
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
125
+ const symbolsLength = symbolsAndTimeframes.length;
126
+ if (symbolsLength === 0 || !Array.isArray(symbolsAndTimeframes[0])) {
127
+ throw new errors.ArgumentsRequired(this.id + " watchOHLCVForSymbols() requires a an array of symbols and timeframes, like [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]");
128
+ }
129
+ await this.loadMarkets();
130
+ const topics = [];
131
+ const messageHashes = [];
132
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
133
+ const symbolAndTimeframe = symbolsAndTimeframes[i];
134
+ const marketId = this.safeString(symbolAndTimeframe, 0);
135
+ const market = this.market(marketId);
136
+ const tf = this.safeString(symbolAndTimeframe, 1);
137
+ const interval = this.safeString(this.timeframes, tf, tf);
138
+ topics.push('symbol:' + market['id'] + ':ohlc:' + interval);
139
+ messageHashes.push('candles:' + interval + ':' + market['symbol']);
140
+ }
141
+ const [symbol, timeframe, candles] = await this.watchPublic(topics, messageHashes, params);
142
+ if (this.newUpdates) {
143
+ limit = candles.getLimit(symbol, limit);
144
+ }
145
+ const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
146
+ return this.createOHLCVObject(symbol, timeframe, filtered);
147
+ }
148
+ /**
149
+ * @method
150
+ * @name defx#unWatchOHLCVForSymbols
151
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
152
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
153
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
154
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
155
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
156
+ */
157
+ async unWatchOHLCVForSymbols(symbolsAndTimeframes, params = {}) {
158
+ const symbolsLength = symbolsAndTimeframes.length;
159
+ if (symbolsLength === 0 || !Array.isArray(symbolsAndTimeframes[0])) {
160
+ throw new errors.ArgumentsRequired(this.id + " unWatchOHLCVForSymbols() requires a an array of symbols and timeframes, like [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]");
161
+ }
162
+ await this.loadMarkets();
163
+ const topics = [];
164
+ const messageHashes = [];
165
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
166
+ const symbolAndTimeframe = symbolsAndTimeframes[i];
167
+ const marketId = this.safeString(symbolAndTimeframe, 0);
168
+ const market = this.market(marketId);
169
+ const tf = this.safeString(symbolAndTimeframe, 1);
170
+ const interval = this.safeString(this.timeframes, tf, tf);
171
+ topics.push('symbol:' + market['id'] + ':ohlc:' + interval);
172
+ messageHashes.push('candles:' + interval + ':' + market['symbol']);
173
+ }
174
+ return await this.unWatchPublic(topics, messageHashes, params);
175
+ }
176
+ handleOHLCV(client, message) {
177
+ //
178
+ // {
179
+ // "topic": "symbol:BTC_USDC:ohlc:3m",
180
+ // "event": "ohlc",
181
+ // "timestamp": 1730794277104,
182
+ // "data": {
183
+ // "symbol": "BTC_USDC",
184
+ // "window": "3m",
185
+ // "open": "57486.90000000",
186
+ // "high": "57486.90000000",
187
+ // "low": "57486.90000000",
188
+ // "close": "57486.90000000",
189
+ // "volume": "0.000",
190
+ // "quoteAssetVolume": "0.00000000",
191
+ // "takerBuyAssetVolume": "0.000",
192
+ // "takerBuyQuoteAssetVolume": "0.00000000",
193
+ // "numberOfTrades": 0,
194
+ // "start": 1730794140000,
195
+ // "end": 1730794320000,
196
+ // "isClosed": false
197
+ // }
198
+ // }
199
+ //
200
+ const data = this.safeDict(message, 'data', {});
201
+ const marketId = this.safeString(data, 'symbol');
202
+ const market = this.market(marketId);
203
+ const symbol = market['symbol'];
204
+ const timeframe = this.safeString(data, 'window');
205
+ if (!(symbol in this.ohlcvs)) {
206
+ this.ohlcvs[symbol] = {};
207
+ }
208
+ if (!(timeframe in this.ohlcvs[symbol])) {
209
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
210
+ const stored = new Cache.ArrayCacheByTimestamp(limit);
211
+ this.ohlcvs[symbol][timeframe] = stored;
212
+ }
213
+ const ohlcv = this.ohlcvs[symbol][timeframe];
214
+ const parsed = this.parseOHLCV(data);
215
+ ohlcv.append(parsed);
216
+ const messageHash = 'candles:' + timeframe + ':' + symbol;
217
+ client.resolve([symbol, timeframe, ohlcv], messageHash);
218
+ }
219
+ /**
220
+ * @method
221
+ * @name defx#watchTicker
222
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
223
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
224
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
225
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
226
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
227
+ */
228
+ async watchTicker(symbol, params = {}) {
229
+ await this.loadMarkets();
230
+ const market = this.market(symbol);
231
+ symbol = market['symbol'];
232
+ const topic = 'symbol:' + market['id'] + ':24hrTicker';
233
+ const messageHash = 'ticker:' + symbol;
234
+ return await this.watchPublic([topic], [messageHash], params);
235
+ }
236
+ /**
237
+ * @method
238
+ * @name defx#unWatchTicker
239
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
240
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
241
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
242
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
243
+ * @param {string} [params.channel] the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
244
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
245
+ */
246
+ async unWatchTicker(symbol, params = {}) {
247
+ return await this.unWatchTickers([symbol], params);
248
+ }
249
+ /**
250
+ * @method
251
+ * @name defx#watchTickers
252
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
253
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
254
+ * @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
255
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
256
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
257
+ */
258
+ async watchTickers(symbols = undefined, params = {}) {
259
+ await this.loadMarkets();
260
+ symbols = this.marketSymbols(symbols, undefined, false);
261
+ const topics = [];
262
+ const messageHashes = [];
263
+ for (let i = 0; i < symbols.length; i++) {
264
+ const symbol = symbols[i];
265
+ const marketId = this.marketId(symbol);
266
+ topics.push('symbol:' + marketId + ':24hrTicker');
267
+ messageHashes.push('ticker:' + symbol);
268
+ }
269
+ await this.watchPublic(topics, messageHashes, params);
270
+ return this.filterByArray(this.tickers, 'symbol', symbols);
271
+ }
272
+ /**
273
+ * @method
274
+ * @name defx#unWatchTickers
275
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
276
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
277
+ * @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
278
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
279
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
280
+ */
281
+ async unWatchTickers(symbols = undefined, params = {}) {
282
+ await this.loadMarkets();
283
+ symbols = this.marketSymbols(symbols, undefined, false);
284
+ const topics = [];
285
+ const messageHashes = [];
286
+ for (let i = 0; i < symbols.length; i++) {
287
+ const symbol = symbols[i];
288
+ const marketId = this.marketId(symbol);
289
+ topics.push('symbol:' + marketId + ':24hrTicker');
290
+ messageHashes.push('ticker:' + symbol);
291
+ }
292
+ return await this.unWatchPublic(topics, messageHashes, params);
293
+ }
294
+ handleTicker(client, message) {
295
+ //
296
+ // {
297
+ // "topic": "symbol:BTC_USDC:24hrTicker",
298
+ // "event": "24hrTicker",
299
+ // "timestamp": 1730862543095,
300
+ // "data": {
301
+ // "symbol": "BTC_USDC",
302
+ // "priceChange": "17114.70000000",
303
+ // "priceChangePercent": "29.77",
304
+ // "weightedAvgPrice": "6853147668",
305
+ // "lastPrice": "74378.90000000",
306
+ // "lastQty": "0.107",
307
+ // "bestBidPrice": "61987.60000000",
308
+ // "bestBidQty": "0.005",
309
+ // "bestAskPrice": "84221.60000000",
310
+ // "bestAskQty": "0.015",
311
+ // "openPrice": "57486.90000000",
312
+ // "highPrice": "88942.60000000",
313
+ // "lowPrice": "47364.20000000",
314
+ // "volume": "28.980",
315
+ // "quoteVolume": "1986042.19424035",
316
+ // "openTime": 1730776080000,
317
+ // "closeTime": 1730862540000,
318
+ // "openInterestBase": "67.130",
319
+ // "openInterestQuote": "5008005.40800000"
320
+ // }
321
+ // }
322
+ //
323
+ this.handleBidAsk(client, message);
324
+ const data = this.safeDict(message, 'data', {});
325
+ const parsedTicker = this.parseTicker(data);
326
+ const symbol = parsedTicker['symbol'];
327
+ const timestamp = this.safeInteger(message, 'timestamp');
328
+ parsedTicker['timestamp'] = timestamp;
329
+ parsedTicker['datetime'] = this.iso8601(timestamp);
330
+ this.tickers[symbol] = parsedTicker;
331
+ const messageHash = 'ticker:' + symbol;
332
+ client.resolve(parsedTicker, messageHash);
333
+ }
334
+ /**
335
+ * @method
336
+ * @name defx#watchBidsAsks
337
+ * @description watches best bid & ask for symbols
338
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
339
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
340
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
341
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
342
+ */
343
+ async watchBidsAsks(symbols = undefined, params = {}) {
344
+ await this.loadMarkets();
345
+ symbols = this.marketSymbols(symbols, undefined, false);
346
+ const topics = [];
347
+ const messageHashes = [];
348
+ for (let i = 0; i < symbols.length; i++) {
349
+ const symbol = symbols[i];
350
+ const marketId = this.marketId(symbol);
351
+ topics.push('symbol:' + marketId + ':24hrTicker');
352
+ messageHashes.push('bidask:' + symbol);
353
+ }
354
+ await this.watchPublic(topics, messageHashes, params);
355
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
356
+ }
357
+ handleBidAsk(client, message) {
358
+ const data = this.safeDict(message, 'data', {});
359
+ const parsedTicker = this.parseWsBidAsk(data);
360
+ const symbol = parsedTicker['symbol'];
361
+ const timestamp = this.safeInteger(message, 'timestamp');
362
+ parsedTicker['timestamp'] = timestamp;
363
+ parsedTicker['datetime'] = this.iso8601(timestamp);
364
+ this.bidsasks[symbol] = parsedTicker;
365
+ const messageHash = 'bidask:' + symbol;
366
+ client.resolve(parsedTicker, messageHash);
367
+ }
368
+ parseWsBidAsk(ticker, market = undefined) {
369
+ const marketId = this.safeString(ticker, 'symbol');
370
+ market = this.safeMarket(marketId, market);
371
+ const symbol = this.safeString(market, 'symbol');
372
+ return this.safeTicker({
373
+ 'symbol': symbol,
374
+ 'timestamp': undefined,
375
+ 'datetime': undefined,
376
+ 'ask': this.safeString(ticker, 'bestAskPrice'),
377
+ 'askVolume': this.safeString(ticker, 'bestAskQty'),
378
+ 'bid': this.safeString(ticker, 'bestBidPrice'),
379
+ 'bidVolume': this.safeString(ticker, 'bestBidQty'),
380
+ 'info': ticker,
381
+ }, market);
382
+ }
383
+ /**
384
+ * @method
385
+ * @name defx#watchTrades
386
+ * @description watches information on multiple trades made in a market
387
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
388
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
389
+ * @param {int} [since] the earliest time in ms to fetch trades for
390
+ * @param {int} [limit] the maximum number of trade structures to retrieve
391
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
392
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
393
+ */
394
+ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
395
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
396
+ }
397
+ /**
398
+ * @method
399
+ * @name defx#unWatchTradesForSymbols
400
+ * @description unWatches from the stream channel
401
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
402
+ * @param {string} symbol unified symbol of the market to fetch trades for
403
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
404
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
405
+ */
406
+ async unWatchTrades(symbol, params = {}) {
407
+ return await this.unWatchTradesForSymbols([symbol], params);
408
+ }
409
+ /**
410
+ * @method
411
+ * @name defx#watchTradesForSymbols
412
+ * @description watches information on multiple trades made in a market
413
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
414
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
415
+ * @param {int} [since] the earliest time in ms to fetch trades for
416
+ * @param {int} [limit] the maximum number of trade structures to retrieve
417
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
418
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
419
+ */
420
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
421
+ await this.loadMarkets();
422
+ symbols = this.marketSymbols(symbols);
423
+ const symbolsLength = symbols.length;
424
+ if (symbolsLength === 0) {
425
+ throw new errors.ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
426
+ }
427
+ const topics = [];
428
+ const messageHashes = [];
429
+ for (let i = 0; i < symbols.length; i++) {
430
+ const symbol = symbols[i];
431
+ const marketId = this.marketId(symbol);
432
+ topics.push('symbol:' + marketId + ':trades');
433
+ messageHashes.push('trade:' + symbol);
434
+ }
435
+ const trades = await this.watchPublic(topics, messageHashes, params);
436
+ if (this.newUpdates) {
437
+ const first = this.safeValue(trades, 0);
438
+ const tradeSymbol = this.safeString(first, 'symbol');
439
+ limit = trades.getLimit(tradeSymbol, limit);
440
+ }
441
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
442
+ }
443
+ /**
444
+ * @method
445
+ * @name defx#unWatchTradesForSymbols
446
+ * @description unWatches from the stream channel
447
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
448
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
449
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
450
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
451
+ */
452
+ async unWatchTradesForSymbols(symbols, params = {}) {
453
+ await this.loadMarkets();
454
+ symbols = this.marketSymbols(symbols);
455
+ const symbolsLength = symbols.length;
456
+ if (symbolsLength === 0) {
457
+ throw new errors.ArgumentsRequired(this.id + ' unWatchTradesForSymbols() requires a non-empty array of symbols');
458
+ }
459
+ const topics = [];
460
+ const messageHashes = [];
461
+ for (let i = 0; i < symbols.length; i++) {
462
+ const symbol = symbols[i];
463
+ const marketId = this.marketId(symbol);
464
+ topics.push('symbol:' + marketId + ':trades');
465
+ messageHashes.push('trade:' + symbol);
466
+ }
467
+ return await this.unWatchPublic(topics, messageHashes, params);
468
+ }
469
+ handleTrades(client, message) {
470
+ //
471
+ // {
472
+ // "topic": "symbol:SOL_USDC:trades",
473
+ // "event": "trades",
474
+ // "timestamp": 1730967426331,
475
+ // "data": {
476
+ // "buyerMaker": true,
477
+ // "price": "188.38700000",
478
+ // "qty": "1.00",
479
+ // "symbol": "SOL_USDC",
480
+ // "timestamp": 1730967426328
481
+ // }
482
+ // }
483
+ //
484
+ const data = this.safeDict(message, 'data', {});
485
+ const parsedTrade = this.parseTrade(data);
486
+ const symbol = parsedTrade['symbol'];
487
+ if (!(symbol in this.trades)) {
488
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
489
+ const stored = new Cache.ArrayCache(limit);
490
+ this.trades[symbol] = stored;
491
+ }
492
+ const trades = this.trades[symbol];
493
+ trades.append(parsedTrade);
494
+ const messageHash = 'trade:' + symbol;
495
+ client.resolve(trades, messageHash);
496
+ }
497
+ /**
498
+ * @method
499
+ * @name defx#watchOrderBook
500
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
501
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
502
+ * @param {string} symbol unified symbol of the market to fetch the order book for
503
+ * @param {int} [limit] the maximum amount of order book entries to return
504
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
505
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
506
+ */
507
+ async watchOrderBook(symbol, limit = undefined, params = {}) {
508
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
509
+ }
510
+ /**
511
+ * @method
512
+ * @name defx#unWatchOrderBook
513
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
514
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
515
+ * @param {string} symbol unified array of symbols
516
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
517
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
518
+ */
519
+ async unWatchOrderBook(symbol, params = {}) {
520
+ return await this.unWatchOrderBookForSymbols([symbol], params);
521
+ }
522
+ /**
523
+ * @method
524
+ * @name defx#watchOrderBookForSymbols
525
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
526
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
527
+ * @param {string[]} symbols unified array of symbols
528
+ * @param {int} [limit] the maximum amount of order book entries to return
529
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
530
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
531
+ */
532
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
533
+ await this.loadMarkets();
534
+ const symbolsLength = symbols.length;
535
+ if (symbolsLength === 0) {
536
+ throw new errors.ArgumentsRequired(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
537
+ }
538
+ symbols = this.marketSymbols(symbols);
539
+ const topics = [];
540
+ const messageHashes = [];
541
+ for (let i = 0; i < symbols.length; i++) {
542
+ const symbol = symbols[i];
543
+ const marketId = this.marketId(symbol);
544
+ topics.push('symbol:' + marketId + ':depth:20:0.001');
545
+ messageHashes.push('orderbook:' + symbol);
546
+ }
547
+ const orderbook = await this.watchPublic(topics, messageHashes, params);
548
+ return orderbook.limit();
549
+ }
550
+ /**
551
+ * @method
552
+ * @name defx#unWatchOrderBookForSymbols
553
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
554
+ * @see https://www.postman.com/defxcode/defx-public-apis/collection/667939a1b5d8069c13d614e9
555
+ * @param {string[]} symbols unified array of symbols
556
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
557
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
558
+ */
559
+ async unWatchOrderBookForSymbols(symbols, params = {}) {
560
+ await this.loadMarkets();
561
+ const symbolsLength = symbols.length;
562
+ if (symbolsLength === 0) {
563
+ throw new errors.ArgumentsRequired(this.id + ' unWatchOrderBookForSymbols() requires a non-empty array of symbols');
564
+ }
565
+ symbols = this.marketSymbols(symbols);
566
+ const topics = [];
567
+ const messageHashes = [];
568
+ for (let i = 0; i < symbols.length; i++) {
569
+ const symbol = symbols[i];
570
+ const marketId = this.marketId(symbol);
571
+ topics.push('symbol:' + marketId + ':depth:20:0.001');
572
+ messageHashes.push('orderbook:' + symbol);
573
+ }
574
+ return await this.unWatchPublic(topics, messageHashes, params);
575
+ }
576
+ handleOrderBook(client, message) {
577
+ //
578
+ // {
579
+ // "topic": "symbol:SOL_USDC:depth:20:0.01",
580
+ // "event": "depth",
581
+ // "timestamp": 1731030695319,
582
+ // "data": {
583
+ // "symbol": "SOL_USDC",
584
+ // "timestamp": 1731030695319,
585
+ // "lastTradeTimestamp": 1731030275258,
586
+ // "level": "20",
587
+ // "slab": "0.01",
588
+ // "bids": [
589
+ // {
590
+ // "price": "198.27000000",
591
+ // "qty": "1.52"
592
+ // }
593
+ // ],
594
+ // "asks": [
595
+ // {
596
+ // "price": "198.44000000",
597
+ // "qty": "6.61"
598
+ // }
599
+ // ]
600
+ // }
601
+ // }
602
+ //
603
+ const data = this.safeDict(message, 'data', {});
604
+ const marketId = this.safeString(data, 'symbol');
605
+ const market = this.market(marketId);
606
+ const symbol = market['symbol'];
607
+ const timestamp = this.safeInteger(data, 'timestamp');
608
+ const snapshot = this.parseOrderBook(data, symbol, timestamp, 'bids', 'asks', 'price', 'qty');
609
+ if (!(symbol in this.orderbooks)) {
610
+ const ob = this.orderBook(snapshot);
611
+ this.orderbooks[symbol] = ob;
612
+ }
613
+ const orderbook = this.orderbooks[symbol];
614
+ orderbook.reset(snapshot);
615
+ const messageHash = 'orderbook:' + symbol;
616
+ client.resolve(orderbook, messageHash);
617
+ }
618
+ async keepAliveListenKey(params = {}) {
619
+ const listenKey = this.safeString(this.options, 'listenKey');
620
+ if (listenKey === undefined) {
621
+ // A network error happened: we can't renew a listen key that does not exist.
622
+ return;
623
+ }
624
+ try {
625
+ await this.v1PrivatePutApiUsersSocketListenKeysListenKey({ 'listenKey': listenKey }); // extend the expiry
626
+ }
627
+ catch (error) {
628
+ const url = this.urls['api']['ws']['private'] + '?listenKey=' + listenKey;
629
+ const client = this.client(url);
630
+ const messageHashes = Object.keys(client.futures);
631
+ for (let j = 0; j < messageHashes.length; j++) {
632
+ const messageHash = messageHashes[j];
633
+ client.reject(error, messageHash);
634
+ }
635
+ this.options['listenKey'] = undefined;
636
+ this.options['lastAuthenticatedTime'] = 0;
637
+ return;
638
+ }
639
+ // whether or not to schedule another listenKey keepAlive request
640
+ const listenKeyRefreshRate = this.safeInteger(this.options, 'listenKeyRefreshRate', 3540000);
641
+ this.delay(listenKeyRefreshRate, this.keepAliveListenKey, params);
642
+ }
643
+ async authenticate(params = {}) {
644
+ const time = this.milliseconds();
645
+ const lastAuthenticatedTime = this.safeInteger(this.options, 'lastAuthenticatedTime', 0);
646
+ const listenKeyRefreshRate = this.safeInteger(this.options, 'listenKeyRefreshRate', 3540000); // 1 hour
647
+ if (time - lastAuthenticatedTime > listenKeyRefreshRate) {
648
+ const response = await this.v1PrivatePostApiUsersSocketListenKeys();
649
+ this.options['listenKey'] = this.safeString(response, 'listenKey');
650
+ this.options['lastAuthenticatedTime'] = time;
651
+ this.delay(listenKeyRefreshRate, this.keepAliveListenKey, params);
652
+ }
653
+ }
654
+ /**
655
+ * @method
656
+ * @name defx#watchBalance
657
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
658
+ * @see https://www.postman.com/defxcode/defx-public-apis/ws-raw-request/667939b2f00f79161bb47809
659
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
660
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
661
+ */
662
+ async watchBalance(params = {}) {
663
+ await this.loadMarkets();
664
+ await this.authenticate();
665
+ const baseUrl = this.urls['api']['ws']['private'];
666
+ const messageHash = 'WALLET_BALANCE_UPDATE';
667
+ const url = baseUrl + '?listenKey=' + this.options['listenKey'];
668
+ return await this.watch(url, messageHash, undefined, messageHash);
669
+ }
670
+ handleBalance(client, message) {
671
+ //
672
+ // {
673
+ // "event": "WALLET_BALANCE_UPDATE",
674
+ // "timestamp": 1711015961397,
675
+ // "data": {
676
+ // "asset": "USDC", "balance": "27.64712963"
677
+ // }
678
+ // }
679
+ //
680
+ const messageHash = this.safeString(message, 'event');
681
+ const data = this.safeDict(message, 'data', []);
682
+ const timestamp = this.safeInteger(message, 'timestamp');
683
+ if (this.balance === undefined) {
684
+ this.balance = {};
685
+ }
686
+ this.balance['info'] = data;
687
+ this.balance['timestamp'] = timestamp;
688
+ this.balance['datetime'] = this.iso8601(timestamp);
689
+ const currencyId = this.safeString(data, 'asset');
690
+ const code = this.safeCurrencyCode(currencyId);
691
+ const account = (code in this.balance) ? this.balance[code] : this.account();
692
+ account['free'] = this.safeString(data, 'balance');
693
+ this.balance[code] = account;
694
+ this.balance = this.safeBalance(this.balance);
695
+ client.resolve(this.balance, messageHash);
696
+ }
697
+ /**
698
+ * @method
699
+ * @name defx#watchOrders
700
+ * @description watches information on multiple orders made by the user
701
+ * @see https://www.postman.com/defxcode/defx-public-apis/ws-raw-request/667939b2f00f79161bb47809
702
+ * @param {string} [symbol] unified market symbol of the market the orders were made in
703
+ * @param {int} [since] the earliest time in ms to fetch orders for
704
+ * @param {int} [limit] the maximum number of order structures to retrieve
705
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
706
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
707
+ */
708
+ async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
709
+ await this.loadMarkets();
710
+ await this.authenticate();
711
+ const baseUrl = this.urls['api']['ws']['private'];
712
+ let messageHash = 'orders';
713
+ if (symbol !== undefined) {
714
+ const market = this.market(symbol);
715
+ messageHash += ':' + market['symbol'];
716
+ }
717
+ const url = baseUrl + '?listenKey=' + this.options['listenKey'];
718
+ const orders = await this.watch(url, messageHash, undefined, messageHash);
719
+ if (this.newUpdates) {
720
+ limit = orders.getLimit(symbol, limit);
721
+ }
722
+ return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
723
+ }
724
+ handleOrder(client, message) {
725
+ //
726
+ // {
727
+ // "event": "ORDER_UPDATE",
728
+ // "timestamp": 1731417961446,
729
+ // "data": {
730
+ // "orderId": "766738557656630928",
731
+ // "symbol": "SOL_USDC",
732
+ // "side": "SELL",
733
+ // "type": "MARKET",
734
+ // "status": "FILLED",
735
+ // "clientOrderId": "0193208d-717b-7811-a80e-c036e220ad9b",
736
+ // "reduceOnly": false,
737
+ // "postOnly": false,
738
+ // "timeInForce": "GTC",
739
+ // "isTriggered": false,
740
+ // "createdAt": "2024-11-12T13:26:00.829Z",
741
+ // "updatedAt": "2024-11-12T13:26:01.436Z",
742
+ // "avgPrice": "209.60000000",
743
+ // "cumulativeQuote": "104.80000000",
744
+ // "totalFee": "0.05764000",
745
+ // "executedQty": "0.50",
746
+ // "origQty": "0.50",
747
+ // "role": "TAKER",
748
+ // "pnl": "0.00000000",
749
+ // "lastFillPnL": "0.00000000",
750
+ // "lastFillPrice": "209.60000000",
751
+ // "lastFillQty": "0.50",
752
+ // "linkedOrderParentType": null,
753
+ // "workingType": null
754
+ // }
755
+ // }
756
+ //
757
+ const channel = 'orders';
758
+ const data = this.safeDict(message, 'data', {});
759
+ if (this.orders === undefined) {
760
+ const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
761
+ this.orders = new Cache.ArrayCacheBySymbolById(limit);
762
+ }
763
+ const orders = this.orders;
764
+ const parsedOrder = this.parseOrder(data);
765
+ orders.append(parsedOrder);
766
+ const messageHash = channel + ':' + parsedOrder['symbol'];
767
+ client.resolve(orders, channel);
768
+ client.resolve(orders, messageHash);
769
+ }
770
+ /**
771
+ * @method
772
+ * @name defx#watchPositions
773
+ * @description watch all open positions
774
+ * @see https://www.postman.com/defxcode/defx-public-apis/ws-raw-request/667939b2f00f79161bb47809
775
+ * @param {string[]|undefined} symbols list of unified market symbols
776
+ * @param {number} [since] since timestamp
777
+ * @param {number} [limit] limit
778
+ * @param {object} params extra parameters specific to the exchange API endpoint
779
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
780
+ */
781
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
782
+ await this.loadMarkets();
783
+ await this.authenticate();
784
+ symbols = this.marketSymbols(symbols);
785
+ const baseUrl = this.urls['api']['ws']['private'];
786
+ const channel = 'positions';
787
+ const url = baseUrl + '?listenKey=' + this.options['listenKey'];
788
+ let newPosition = undefined;
789
+ if (symbols !== undefined) {
790
+ const messageHashes = [];
791
+ for (let i = 0; i < symbols.length; i++) {
792
+ const symbol = symbols[i];
793
+ messageHashes.push(channel + ':' + symbol);
794
+ }
795
+ newPosition = await this.watchMultiple(url, messageHashes, undefined, messageHashes);
796
+ }
797
+ else {
798
+ newPosition = await this.watch(url, channel, undefined, channel);
799
+ }
800
+ if (this.newUpdates) {
801
+ return newPosition;
802
+ }
803
+ return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
804
+ }
805
+ handlePositions(client, message) {
806
+ //
807
+ // {
808
+ // "event": "POSITION_UPDATE",
809
+ // "timestamp": 1731417961456,
810
+ // "data": {
811
+ // "positionId": "0193208d-735d-7fe9-90bd-8bc6d6bc1eda",
812
+ // "createdAt": 1289847904328,
813
+ // "symbol": "SOL_USDC",
814
+ // "positionSide": "SHORT",
815
+ // "entryPrice": "209.60000000",
816
+ // "quantity": "0.50",
817
+ // "status": "ACTIVE",
818
+ // "marginAsset": "USDC",
819
+ // "marginAmount": "15.17475649",
820
+ // "realizedPnL": "0.00000000"
821
+ // }
822
+ // }
823
+ //
824
+ const channel = 'positions';
825
+ const data = this.safeDict(message, 'data', {});
826
+ if (this.positions === undefined) {
827
+ this.positions = new Cache.ArrayCacheBySymbolById();
828
+ }
829
+ const cache = this.positions;
830
+ const parsedPosition = this.parsePosition(data);
831
+ const timestamp = this.safeInteger(message, 'timestamp');
832
+ parsedPosition['timestamp'] = timestamp;
833
+ parsedPosition['datetime'] = this.iso8601(timestamp);
834
+ cache.append(parsedPosition);
835
+ const messageHash = channel + ':' + parsedPosition['symbol'];
836
+ client.resolve([parsedPosition], channel);
837
+ client.resolve([parsedPosition], messageHash);
838
+ }
839
+ handleMessage(client, message) {
840
+ const error = this.safeString(message, 'code');
841
+ if (error !== undefined) {
842
+ const errorMsg = this.safeString(message, 'msg');
843
+ throw new errors.ExchangeError(this.id + ' ' + errorMsg);
844
+ }
845
+ const event = this.safeString(message, 'event');
846
+ if (event !== undefined) {
847
+ const methods = {
848
+ 'ohlc': this.handleOHLCV,
849
+ '24hrTicker': this.handleTicker,
850
+ 'trades': this.handleTrades,
851
+ 'depth': this.handleOrderBook,
852
+ 'WALLET_BALANCE_UPDATE': this.handleBalance,
853
+ 'ORDER_UPDATE': this.handleOrder,
854
+ 'POSITION_UPDATE': this.handlePositions,
855
+ };
856
+ const exacMethod = this.safeValue(methods, event);
857
+ if (exacMethod !== undefined) {
858
+ exacMethod.call(this, client, message);
859
+ }
860
+ }
861
+ }
862
+ }
863
+
864
+ module.exports = defx;