ccxt 4.5.29 → 4.5.31

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 (85) 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/base/Exchange.js +16 -1
  5. package/dist/cjs/src/base/ws/WsClient.js +1 -0
  6. package/dist/cjs/src/bingx.js +1 -1
  7. package/dist/cjs/src/bullish.js +1 -1
  8. package/dist/cjs/src/bybit.js +2 -0
  9. package/dist/cjs/src/bydfi.js +2907 -0
  10. package/dist/cjs/src/coinbase.js +34 -1
  11. package/dist/cjs/src/dydx.js +3 -3
  12. package/dist/cjs/src/gate.js +55 -8
  13. package/dist/cjs/src/hyperliquid.js +19 -4
  14. package/dist/cjs/src/kucoin.js +175 -68
  15. package/dist/cjs/src/pro/apex.js +7 -5
  16. package/dist/cjs/src/pro/ascendex.js +1 -1
  17. package/dist/cjs/src/pro/binance.js +10 -6
  18. package/dist/cjs/src/pro/bingx.js +6 -4
  19. package/dist/cjs/src/pro/bitmart.js +5 -3
  20. package/dist/cjs/src/pro/bybit.js +6 -4
  21. package/dist/cjs/src/pro/bydfi.js +1077 -0
  22. package/dist/cjs/src/pro/cryptocom.js +6 -4
  23. package/dist/cjs/src/pro/gate.js +5 -3
  24. package/dist/cjs/src/pro/hashkey.js +5 -3
  25. package/dist/cjs/src/pro/htx.js +1 -1
  26. package/dist/cjs/src/pro/hyperliquid.js +1 -1
  27. package/dist/cjs/src/pro/kucoinfutures.js +5 -3
  28. package/dist/cjs/src/pro/modetrade.js +5 -3
  29. package/dist/cjs/src/pro/p2b.js +1 -1
  30. package/dist/cjs/src/pro/toobit.js +12 -8
  31. package/dist/cjs/src/pro/woo.js +5 -3
  32. package/dist/cjs/src/pro/woofipro.js +5 -3
  33. package/dist/cjs/src/pro/xt.js +5 -3
  34. package/dist/cjs/src/toobit.js +2 -1
  35. package/js/ccxt.d.ts +8 -5
  36. package/js/ccxt.js +6 -4
  37. package/js/src/abstract/bydfi.d.ts +52 -0
  38. package/js/src/abstract/kucoin.d.ts +2 -0
  39. package/js/src/abstract/kucoinfutures.d.ts +2 -0
  40. package/js/src/base/Exchange.d.ts +3 -0
  41. package/js/src/base/Exchange.js +16 -1
  42. package/js/src/base/ws/WsClient.js +1 -0
  43. package/js/src/binance.d.ts +1 -1
  44. package/js/src/bingx.js +1 -1
  45. package/js/src/bullish.js +1 -1
  46. package/js/src/bybit.js +2 -0
  47. package/js/src/bydfi.d.ts +472 -0
  48. package/js/src/bydfi.js +2905 -0
  49. package/js/src/coinbase.d.ts +11 -0
  50. package/js/src/coinbase.js +34 -1
  51. package/js/src/dydx.js +3 -3
  52. package/js/src/exmo.d.ts +1 -1
  53. package/js/src/gate.js +55 -8
  54. package/js/src/hyperliquid.d.ts +1 -0
  55. package/js/src/hyperliquid.js +19 -4
  56. package/js/src/kucoin.d.ts +19 -3
  57. package/js/src/kucoin.js +175 -68
  58. package/js/src/pro/apex.js +7 -5
  59. package/js/src/pro/ascendex.js +1 -1
  60. package/js/src/pro/binance.js +10 -6
  61. package/js/src/pro/bingx.js +6 -4
  62. package/js/src/pro/bitmart.js +5 -3
  63. package/js/src/pro/bybit.js +6 -4
  64. package/js/src/pro/bydfi.d.ts +206 -0
  65. package/js/src/pro/bydfi.js +1076 -0
  66. package/js/src/pro/cryptocom.js +6 -4
  67. package/js/src/pro/gate.js +5 -3
  68. package/js/src/pro/hashkey.js +5 -3
  69. package/js/src/pro/htx.js +1 -1
  70. package/js/src/pro/hyperliquid.js +1 -1
  71. package/js/src/pro/kucoinfutures.js +5 -3
  72. package/js/src/pro/modetrade.js +5 -3
  73. package/js/src/pro/p2b.js +1 -1
  74. package/js/src/pro/toobit.js +12 -8
  75. package/js/src/pro/woo.js +5 -3
  76. package/js/src/pro/woofipro.js +5 -3
  77. package/js/src/pro/xt.js +5 -3
  78. package/js/src/toobit.js +2 -1
  79. package/package.json +1 -1
  80. package/dist/cjs/src/oceanex.js +0 -1125
  81. package/js/src/abstract/oceanex.d.ts +0 -30
  82. package/js/src/oceanex.d.ts +0 -231
  83. package/js/src/oceanex.js +0 -1124
  84. /package/dist/cjs/src/abstract/{oceanex.js → bydfi.js} +0 -0
  85. /package/js/src/abstract/{oceanex.js → bydfi.js} +0 -0
@@ -0,0 +1,1076 @@
1
+ // ----------------------------------------------------------------------------
2
+
3
+ // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+ // EDIT THE CORRESPONDENT .ts FILE INSTEAD
6
+
7
+ // ---------------------------------------------------------------------------
8
+ import bydfiRest from '../bydfi.js';
9
+ import { Precise } from '../base/Precise.js';
10
+ import { ArgumentsRequired, ExchangeError } from '../base/errors.js';
11
+ import { ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
12
+ import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
13
+ // ---------------------------------------------------------------------------
14
+ export default class bydfi extends bydfiRest {
15
+ describe() {
16
+ return this.deepExtend(super.describe(), {
17
+ 'has': {
18
+ 'ws': true,
19
+ 'watchBalance': true,
20
+ 'watchBidsAsks': false,
21
+ 'watchMyTrades': false,
22
+ 'watchOHLCV': true,
23
+ 'watchOHLCVForSymbols': true,
24
+ 'watchOrderBook': true,
25
+ 'watchOrderBookForSymbols': true,
26
+ 'watchOrders': true,
27
+ 'watchOrdersForSymbols': true,
28
+ 'watchPositions': true,
29
+ 'watchTicker': true,
30
+ 'watchTickers': true,
31
+ 'watchTrades': false,
32
+ 'watchTradesForSymbols': false,
33
+ 'unwatchBidsAsks': false,
34
+ 'unwatchOHLCV': true,
35
+ 'unwatchOHLCVForSymbols': true,
36
+ 'unwatchOrderBook': true,
37
+ 'unwatchOrderBookForSymbols': true,
38
+ 'unwatchTicker': true,
39
+ 'unwatchTickers': true,
40
+ 'unWatchTrades': false,
41
+ 'unWatchTradesForSymbols': false,
42
+ 'unWatchOrders': false,
43
+ 'unWatchOrdersForSymbols': false,
44
+ 'unWatchPositions': false,
45
+ },
46
+ 'urls': {
47
+ 'api': {
48
+ 'ws': 'wss://stream.bydfi.com/v1/public/swap',
49
+ },
50
+ },
51
+ 'options': {
52
+ 'watchOrderBookForSymbols': {
53
+ 'depth': '100',
54
+ 'frequency': '1000ms', // 100ms, 1000ms
55
+ },
56
+ 'watchBalance': {
57
+ 'fetchBalanceSnapshot': false,
58
+ 'awaitBalanceSnapshot': true, // whether to wait for the balance snapshot before providing updates
59
+ },
60
+ 'timeframes': {
61
+ '1m': '1m',
62
+ '3m': '3m',
63
+ '5m': '5m',
64
+ '15m': '15m',
65
+ '30m': '30m',
66
+ '1h': '1h',
67
+ '2h': '2h',
68
+ '4h': '4h',
69
+ '6h': '6h',
70
+ '8h': '8h',
71
+ '12h': '12h',
72
+ '1d': '1d',
73
+ '1w': '1w',
74
+ '1M': '1M',
75
+ },
76
+ },
77
+ 'streaming': {
78
+ 'ping': this.ping,
79
+ 'keepAlive': 119000, // 2 minutes
80
+ },
81
+ });
82
+ }
83
+ ping(client) {
84
+ return {
85
+ 'id': this.requestId(),
86
+ 'method': 'ping',
87
+ };
88
+ }
89
+ requestId() {
90
+ this.lockId();
91
+ const reqid = this.sum(this.safeInteger(this.options, 'reqid', 0), 1);
92
+ this.options['reqid'] = reqid;
93
+ this.unlockId();
94
+ return reqid;
95
+ }
96
+ async watchPublic(messageHashes, channels, params = {}, subscription = {}) {
97
+ const url = this.urls['api']['ws'];
98
+ const id = this.requestId();
99
+ const subscriptionParams = {
100
+ 'id': id,
101
+ };
102
+ const unsubscribe = this.safeBool(params, 'unsubscribe', false);
103
+ let method = 'SUBSCRIBE';
104
+ if (unsubscribe) {
105
+ method = 'UNSUBSCRIBE';
106
+ params = this.omit(params, 'unsubscribe');
107
+ subscriptionParams['unsubscribe'] = true;
108
+ subscriptionParams['messageHashes'] = messageHashes;
109
+ }
110
+ const message = {
111
+ 'id': id,
112
+ 'method': method,
113
+ 'params': channels,
114
+ };
115
+ return await this.watchMultiple(url, messageHashes, this.deepExtend(message, params), messageHashes, this.extend(subscriptionParams, subscription));
116
+ }
117
+ async watchPrivate(messageHashes, params = {}) {
118
+ this.checkRequiredCredentials();
119
+ const url = this.urls['api']['ws'];
120
+ const subHash = 'private';
121
+ const client = this.client(url);
122
+ const privateSubscription = this.safeValue(client.subscriptions, subHash);
123
+ const subscription = {};
124
+ if (privateSubscription === undefined) {
125
+ const id = this.requestId();
126
+ const timestamp = this.milliseconds().toString();
127
+ const payload = this.apiKey + timestamp;
128
+ const signature = this.hmac(this.encode(payload), this.encode(this.secret), sha256, 'hex');
129
+ const request = {
130
+ 'id': id,
131
+ 'method': 'LOGIN',
132
+ 'params': {
133
+ 'apiKey': this.apiKey,
134
+ 'timestamp': timestamp,
135
+ 'sign': signature,
136
+ },
137
+ };
138
+ params = this.deepExtend(request, params);
139
+ subscription['id'] = id;
140
+ }
141
+ return await this.watchMultiple(url, messageHashes, params, ['private'], subscription);
142
+ }
143
+ /**
144
+ * @method
145
+ * @name bydfi#watchTicker
146
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
147
+ * @see https://developers.bydfi.com/en/swap/websocket-market#ticker-by-symbol
148
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
149
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
150
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
151
+ */
152
+ async watchTicker(symbol, params = {}) {
153
+ await this.loadMarkets();
154
+ const market = this.market(symbol);
155
+ const marketId = market['id'];
156
+ const messageHash = 'ticker::' + symbol;
157
+ const channel = marketId + '@ticker';
158
+ return await this.watchPublic([messageHash], [channel], params);
159
+ }
160
+ /**
161
+ * @method
162
+ * @name bydfi#unWatchTicker
163
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
164
+ * @see https://developers.bydfi.com/en/swap/websocket-market#ticker-by-symbol
165
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
166
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
167
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
168
+ */
169
+ async unWatchTicker(symbol, params = {}) {
170
+ return await this.unWatchTickers([symbol], params);
171
+ }
172
+ /**
173
+ * @method
174
+ * @name bydfi#watchTickers
175
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
176
+ * @see https://developers.bydfi.com/en/swap/websocket-market#ticker-by-symbol
177
+ * @see https://developers.bydfi.com/en/swap/websocket-market#market-wide-ticker
178
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
179
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
180
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
181
+ */
182
+ async watchTickers(symbols = undefined, params = {}) {
183
+ await this.loadMarkets();
184
+ symbols = this.marketSymbols(symbols, undefined, true);
185
+ const messageHashes = [];
186
+ const messageHash = 'ticker::';
187
+ const channels = [];
188
+ const channel = '@ticker';
189
+ if (symbols === undefined) {
190
+ messageHashes.push(messageHash + 'all');
191
+ channels.push('!ticker@arr');
192
+ }
193
+ else {
194
+ for (let i = 0; i < symbols.length; i++) {
195
+ const symbol = symbols[i];
196
+ const marketId = this.marketId(symbol);
197
+ messageHashes.push(messageHash + symbol);
198
+ channels.push(marketId + channel);
199
+ }
200
+ }
201
+ await this.watchPublic(messageHashes, channels, params);
202
+ return this.filterByArray(this.tickers, 'symbol', symbols);
203
+ }
204
+ /**
205
+ * @method
206
+ * @name bydfi#unWatchTickers
207
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
208
+ * @see https://developers.bydfi.com/en/swap/websocket-market#ticker-by-symbol
209
+ * @see https://developers.bydfi.com/en/swap/websocket-market#market-wide-ticker
210
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
211
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
212
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
213
+ */
214
+ async unWatchTickers(symbols = undefined, params = {}) {
215
+ symbols = this.marketSymbols(symbols, undefined, true);
216
+ const messageHashes = [];
217
+ const messageHash = 'unsubscribe::ticker::';
218
+ const channels = [];
219
+ const channel = '@ticker';
220
+ const subscription = {
221
+ 'topic': 'ticker',
222
+ };
223
+ if (symbols === undefined) {
224
+ // all tickers and tickers for specific symbols are different channels
225
+ // we need to unsubscribe from all ticker channels
226
+ const subHashes = this.getMessageHashesForTickersUnsubscription();
227
+ subscription['subHashIsPrefix'] = true;
228
+ for (let i = 0; i < subHashes.length; i++) {
229
+ const subHash = this.safeString(subHashes, i);
230
+ if (subHash !== undefined) {
231
+ const parts = subHash.split('::');
232
+ const symbol = this.safeString(parts, 1);
233
+ if (symbol === 'all') {
234
+ continue;
235
+ }
236
+ const marketId = this.marketId(symbol);
237
+ channels.push(marketId + channel);
238
+ }
239
+ }
240
+ messageHashes.push(messageHash);
241
+ channels.push('!ticker@arr');
242
+ }
243
+ else {
244
+ for (let i = 0; i < symbols.length; i++) {
245
+ const symbol = symbols[i];
246
+ const marketId = this.marketId(symbol);
247
+ messageHashes.push(messageHash + symbol);
248
+ channels.push(marketId + channel);
249
+ }
250
+ subscription['symbols'] = symbols;
251
+ }
252
+ params = this.extend(params, { 'unsubscribe': true });
253
+ return await this.watchPublic(messageHashes, channels, params, subscription);
254
+ }
255
+ getMessageHashesForTickersUnsubscription() {
256
+ const url = this.urls['api']['ws']['public'];
257
+ const client = this.client(url);
258
+ const subscriptions = client.subscriptions;
259
+ const messageHashes = [];
260
+ const keys = Object.keys(subscriptions);
261
+ for (let i = 0; i < keys.length; i++) {
262
+ const key = keys[i];
263
+ if (key.indexOf('ticker::') === 0) {
264
+ messageHashes.push(key);
265
+ }
266
+ }
267
+ return messageHashes;
268
+ }
269
+ handleTicker(client, message) {
270
+ //
271
+ // {
272
+ // "s": "KAS-USDT",
273
+ // "c": 0.04543,
274
+ // "e": "24hrTicker",
275
+ // "E": 1766528295905,
276
+ // "v": 98278925,
277
+ // "h": 0.04685,
278
+ // "l": 0.04404,
279
+ // "o": 0.04657
280
+ // }
281
+ //
282
+ const ticker = this.parseTicker(message);
283
+ const symbol = ticker['symbol'];
284
+ const messageHash = 'ticker::' + symbol;
285
+ this.tickers[symbol] = ticker;
286
+ client.resolve(this.tickers[symbol], messageHash);
287
+ client.resolve(this.tickers, 'ticker::all');
288
+ }
289
+ /**
290
+ * @method
291
+ * @name bydfi#watchOHLCV
292
+ * @description watches historical candlestick data containing the open, high, low, close price, and the volume of a market
293
+ * @see https://developers.bydfi.com/en/swap/websocket-market#candlestick-data
294
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
295
+ * @param {string} timeframe the length of time each candle represents
296
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
297
+ * @param {int} [limit] the maximum amount of candles to fetch
298
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
299
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
300
+ */
301
+ async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
302
+ const result = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
303
+ return result[symbol][timeframe];
304
+ }
305
+ /**
306
+ * @method
307
+ * @name bydfi#unWatchOHLCV
308
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
309
+ * @see https://developers.bydfi.com/en/swap/websocket-market#candlestick-data
310
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
311
+ * @param {string} timeframe the length of time each candle represents
312
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
313
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
314
+ */
315
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
316
+ return await this.unWatchOHLCVForSymbols([[symbol, timeframe]], params);
317
+ }
318
+ /**
319
+ * @method
320
+ * @name bydfi#watchOHLCVForSymbols
321
+ * @description watches historical candlestick data containing the open, high, low, close price, and the volume of a market
322
+ * @see https://developers.bydfi.com/en/swap/websocket-market#candlestick-data
323
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
324
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
325
+ * @param {int} [limit] the maximum amount of candles to fetch
326
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
327
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
328
+ */
329
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
330
+ const symbolsLength = symbolsAndTimeframes.length;
331
+ if (symbolsLength === 0 || !Array.isArray(symbolsAndTimeframes[0])) {
332
+ throw new ArgumentsRequired(this.id + " watchOHLCVForSymbols() requires a an array of symbols and timeframes, like ['ETH/USDC', '1m']");
333
+ }
334
+ await this.loadMarkets();
335
+ const channels = [];
336
+ const messageHashes = [];
337
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
338
+ const symbolAndTimeframe = symbolsAndTimeframes[i];
339
+ const marketId = this.safeString(symbolAndTimeframe, 0);
340
+ const market = this.market(marketId);
341
+ const tf = this.safeString(symbolAndTimeframe, 1);
342
+ const timeframes = this.safeDict(this.options, 'timeframes', {});
343
+ const interval = this.safeString(timeframes, tf, tf);
344
+ channels.push(market['id'] + '@kline_' + interval);
345
+ messageHashes.push('ohlcv::' + market['symbol'] + '::' + interval);
346
+ }
347
+ const [symbol, timeframe, candles] = await this.watchPublic(messageHashes, channels, params);
348
+ if (this.newUpdates) {
349
+ limit = candles.getLimit(symbol, limit);
350
+ }
351
+ const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
352
+ return this.createOHLCVObject(symbol, timeframe, filtered);
353
+ }
354
+ /**
355
+ * @method
356
+ * @name bydfi#unWatchOHLCVForSymbols
357
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
358
+ * @see https://developers.bydfi.com/en/swap/websocket-market#candlestick-data
359
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
360
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
361
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
362
+ */
363
+ async unWatchOHLCVForSymbols(symbolsAndTimeframes, params = {}) {
364
+ const symbolsLength = symbolsAndTimeframes.length;
365
+ if (symbolsLength === 0 || !Array.isArray(symbolsAndTimeframes[0])) {
366
+ throw new ArgumentsRequired(this.id + " unWatchOHLCVForSymbols() requires a an array of symbols and timeframes, like ['ETH/USDC', '1m']");
367
+ }
368
+ await this.loadMarkets();
369
+ const channels = [];
370
+ const messageHashes = [];
371
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
372
+ const symbolAndTimeframe = symbolsAndTimeframes[i];
373
+ const marketId = this.safeString(symbolAndTimeframe, 0);
374
+ const market = this.market(marketId);
375
+ const tf = this.safeString(symbolAndTimeframe, 1);
376
+ const interval = this.safeString(this.timeframes, tf, tf);
377
+ channels.push(market['id'] + '@kline_' + interval);
378
+ messageHashes.push('unsubscribe::ohlcv::' + market['symbol'] + '::' + interval);
379
+ }
380
+ params = this.extend(params, { 'unsubscribe': true });
381
+ const subscription = {
382
+ 'topic': 'ohlcv',
383
+ 'symbolsAndTimeframes': symbolsAndTimeframes,
384
+ };
385
+ return await this.watchPublic(messageHashes, channels, params, subscription);
386
+ }
387
+ handleOHLCV(client, message) {
388
+ //
389
+ // {
390
+ // "s": "ETH-USDC",
391
+ // "c": 2956.13,
392
+ // "t": 1766506860000,
393
+ // "T": 1766506920000,
394
+ // "e": "kline",
395
+ // "v": 3955,
396
+ // "h": 2956.41,
397
+ // "i": "1m",
398
+ // "l": 2956.05,
399
+ // "o": 2956.05
400
+ // }
401
+ //
402
+ const marketId = this.safeString(message, 's');
403
+ const market = this.safeMarket(marketId);
404
+ const symbol = market['symbol'];
405
+ const interval = this.safeString(message, 'i');
406
+ const timeframes = this.safeDict(this.options, 'timeframes', {});
407
+ const timeframe = this.findTimeframe(interval, timeframes);
408
+ if (!(symbol in this.ohlcvs)) {
409
+ this.ohlcvs[symbol] = {};
410
+ }
411
+ if (!(timeframe in this.ohlcvs[symbol])) {
412
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
413
+ const stored = new ArrayCacheByTimestamp(limit);
414
+ this.ohlcvs[symbol][timeframe] = stored;
415
+ }
416
+ const ohlcv = this.ohlcvs[symbol][timeframe];
417
+ const parsed = this.parseWsOHLCV(message);
418
+ ohlcv.append(parsed);
419
+ const messageHash = 'ohlcv::' + symbol + '::' + timeframe;
420
+ client.resolve([symbol, timeframe, ohlcv], messageHash);
421
+ }
422
+ /**
423
+ * @method
424
+ * @name bydfi#watchOrderBook
425
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
426
+ * @see https://developers.bydfi.com/en/swap/websocket-market#limited-depth-information
427
+ * @param {string} symbol unified symbol of the market to fetch the order book for
428
+ * @param {int} [limit] the maximum amount of order book entries to return (default and maxi is 100)
429
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
430
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
431
+ */
432
+ async watchOrderBook(symbol, limit = undefined, params = {}) {
433
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
434
+ }
435
+ /**
436
+ * @method
437
+ * @name bydfi#unWatchOrderBook
438
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
439
+ * @see https://developers.bydfi.com/en/swap/websocket-market#limited-depth-information
440
+ * @param {string} symbol unified array of symbols
441
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
442
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
443
+ */
444
+ async unWatchOrderBook(symbol, params = {}) {
445
+ return await this.unWatchOrderBookForSymbols([symbol], params);
446
+ }
447
+ /**
448
+ * @method
449
+ * @name bydfi#watchOrderBookForSymbols
450
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
451
+ * @see https://developers.bydfi.com/en/swap/websocket-market#limited-depth-information
452
+ * @param {string[]} symbols unified array of symbols
453
+ * @param {int} [limit] the maximum amount of order book entries to return (default and max is 100)
454
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
455
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
456
+ */
457
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
458
+ await this.loadMarkets();
459
+ symbols = this.marketSymbols(symbols, undefined, false);
460
+ let depth = '100';
461
+ [depth, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'depth', depth);
462
+ let frequency = '100ms';
463
+ [frequency, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'frequency', frequency);
464
+ let channelSuffix = '';
465
+ if (frequency === '100ms') {
466
+ channelSuffix = '@100ms';
467
+ }
468
+ const channels = [];
469
+ const messageHashes = [];
470
+ for (let i = 0; i < symbols.length; i++) {
471
+ const symbol = symbols[i];
472
+ const market = this.market(symbol);
473
+ channels.push(market['id'] + '@depth' + depth + channelSuffix);
474
+ messageHashes.push('orderbook::' + symbol);
475
+ }
476
+ const orderbook = await this.watchPublic(messageHashes, channels, params);
477
+ return orderbook.limit();
478
+ }
479
+ /**
480
+ * @method
481
+ * @name bydfi#unWatchOrderBookForSymbols
482
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
483
+ * @see https://developers.bydfi.com/en/swap/websocket-market#limited-depth-information
484
+ * @param {string[]} symbols unified array of symbols
485
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
486
+ * @param {string} [params.method] either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' default is '/market/level2'
487
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
488
+ */
489
+ async unWatchOrderBookForSymbols(symbols, params = {}) {
490
+ await this.loadMarkets();
491
+ symbols = this.marketSymbols(symbols, undefined, false);
492
+ let depth = '100';
493
+ [depth, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'depth', depth);
494
+ let frequency = '100ms';
495
+ [frequency, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'frequency', frequency);
496
+ let channelSuffix = '';
497
+ if (frequency === '100ms') {
498
+ channelSuffix = '@100ms';
499
+ }
500
+ const channels = [];
501
+ const messageHashes = [];
502
+ for (let i = 0; i < symbols.length; i++) {
503
+ const symbol = symbols[i];
504
+ const market = this.market(symbol);
505
+ channels.push(market['id'] + '@depth' + depth + channelSuffix);
506
+ messageHashes.push('unsubscribe::orderbook::' + symbol);
507
+ }
508
+ const subscription = {
509
+ 'topic': 'orderbook',
510
+ 'symbols': symbols,
511
+ };
512
+ params = this.extend(params, { 'unsubscribe': true });
513
+ return await this.watchPublic(messageHashes, channels, params, subscription);
514
+ }
515
+ handleOrderBook(client, message) {
516
+ //
517
+ // {
518
+ // "a": [ [ 150000, 15 ], ... ],
519
+ // "b": [ [ 90450.7, 3615 ], ... ],
520
+ // "s": "BTC-USDT",
521
+ // "e": "depthUpdate",
522
+ // "E": 1766577624512
523
+ // }
524
+ //
525
+ const marketId = this.safeString(message, 's');
526
+ const symbol = this.safeSymbol(marketId);
527
+ const timestamp = this.safeInteger(message, 'E');
528
+ if (!(symbol in this.orderbooks)) {
529
+ this.orderbooks[symbol] = this.orderBook();
530
+ }
531
+ const orderbook = this.orderbooks[symbol];
532
+ const parsed = this.parseOrderBook(message, symbol, timestamp, 'b', 'a');
533
+ orderbook.reset(parsed);
534
+ const messageHash = 'orderbook::' + symbol;
535
+ this.orderbooks[symbol] = orderbook;
536
+ client.resolve(orderbook, messageHash);
537
+ }
538
+ /**
539
+ * @method
540
+ * @name bydfi#watchOrders
541
+ * @description watches information on multiple orders made by the user
542
+ * @see https://developers.bydfi.com/en/swap/websocket-account#order-trade-update-push
543
+ * @param {string} symbol unified market symbol of the market orders were made in
544
+ * @param {int} [since] the earliest time in ms to fetch orders for
545
+ * @param {int} [limit] the maximum number of order structures to retrieve
546
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
547
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
548
+ */
549
+ async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
550
+ let symbols = undefined;
551
+ if (symbol !== undefined) {
552
+ symbols = [symbol];
553
+ }
554
+ return await this.watchOrdersForSymbols(symbols, since, limit, params);
555
+ }
556
+ /**
557
+ * @method
558
+ * @name bydfi#watchOrdersForSymbols
559
+ * @description watches information on multiple orders made by the user
560
+ * @see https://developers.bydfi.com/en/swap/websocket-account#order-trade-update-push
561
+ * @param {string[]} symbols unified symbol of the market to fetch orders for
562
+ * @param {int} [since] the earliest time in ms to fetch orders for
563
+ * @param {int} [limit] the maximum number of trade structures to retrieve
564
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
565
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
566
+ */
567
+ async watchOrdersForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
568
+ await this.loadMarkets();
569
+ symbols = this.marketSymbols(symbols, undefined, true);
570
+ const messageHashes = [];
571
+ if (symbols === undefined) {
572
+ messageHashes.push('orders');
573
+ }
574
+ else {
575
+ for (let i = 0; i < symbols.length; i++) {
576
+ const symbol = symbols[i];
577
+ messageHashes.push('orders::' + symbol);
578
+ }
579
+ }
580
+ const orders = await this.watchPrivate(messageHashes, params);
581
+ if (this.newUpdates) {
582
+ const first = this.safeValue(orders, 0);
583
+ const tradeSymbol = this.safeString(first, 'symbol');
584
+ limit = orders.getLimit(tradeSymbol, limit);
585
+ }
586
+ return this.filterBySinceLimit(orders, since, limit, 'timestamp', true);
587
+ }
588
+ handleOrder(client, message) {
589
+ //
590
+ // {
591
+ // "T": 1766588450558,
592
+ // "E": 1766588450685,
593
+ // "e": "ORDER_TRADE_UPDATE",
594
+ // "o": {
595
+ // "S": "BUY",
596
+ // "ap": "0",
597
+ // "cpt": false,
598
+ // "ct": "future",
599
+ // "ev": "0",
600
+ // "fee": "0",
601
+ // "lv": 2,
602
+ // "mt": "isolated",
603
+ // "o": "7409609004526010368",
604
+ // "p": "1000",
605
+ // "ps": "BOTH",
606
+ // "pt": "ONE_WAY",
607
+ // "ro": false,
608
+ // "s": "ETH-USDC",
609
+ // "st": "NEW",
610
+ // "t": "LIMIT",
611
+ // "tp": "0",
612
+ // "u": "0.001",
613
+ // "v": "2"
614
+ // }
615
+ // }
616
+ //
617
+ const rawOrder = this.safeDict(message, 'o', {});
618
+ const marketId = this.safeString(rawOrder, 's');
619
+ const market = this.safeMarket(marketId);
620
+ const symbol = market['symbol'];
621
+ let match = false;
622
+ const messageHash = 'orders';
623
+ const symbolMessageHash = messageHash + '::' + symbol;
624
+ const messageHashes = this.findMessageHashes(client, messageHash);
625
+ for (let i = 0; i < messageHashes.length; i++) {
626
+ const hash = messageHashes[i];
627
+ if (hash === symbolMessageHash || hash === messageHash) {
628
+ match = true;
629
+ break;
630
+ }
631
+ }
632
+ if (match) {
633
+ if (this.orders === undefined) {
634
+ const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
635
+ this.orders = new ArrayCacheBySymbolById(limit);
636
+ }
637
+ const orders = this.orders;
638
+ const order = this.parseWsOrder(rawOrder, market);
639
+ const lastUpdateTimestamp = this.safeInteger(message, 'T');
640
+ order['lastUpdateTimestamp'] = lastUpdateTimestamp;
641
+ orders.append(order);
642
+ client.resolve(orders, messageHash);
643
+ client.resolve(orders, symbolMessageHash);
644
+ }
645
+ }
646
+ parseWsOrder(order, market = undefined) {
647
+ //
648
+ // {
649
+ // "S": "BUY",
650
+ // "ap": "0",
651
+ // "cpt": false,
652
+ // "ct": "future",
653
+ // "ev": "0",
654
+ // "fee": "0",
655
+ // "lv": 2,
656
+ // "mt": "isolated",
657
+ // "o": "7409609004526010368",
658
+ // "p": "1000",
659
+ // "ps": "BOTH",
660
+ // "pt": "ONE_WAY",
661
+ // "ro": false,
662
+ // "s": "ETH-USDC",
663
+ // "st": "NEW",
664
+ // "t": "LIMIT",
665
+ // "tp": "0",
666
+ // "u": "0.001",
667
+ // "v": "2"
668
+ // }
669
+ //
670
+ const marketId = this.safeString(order, 's');
671
+ market = this.safeMarket(marketId, market);
672
+ const rawStatus = this.safeString(order, 'st');
673
+ const rawType = this.safeString(order, 't');
674
+ let fee = undefined;
675
+ const feeCost = this.safeString(order, 'fee');
676
+ if (feeCost !== undefined) {
677
+ fee = {
678
+ 'cost': Precise.stringAbs(feeCost),
679
+ 'currency': market['quote'],
680
+ };
681
+ }
682
+ return this.safeOrder({
683
+ 'info': order,
684
+ 'id': this.safeString(order, 'o'),
685
+ 'clientOrderId': this.safeString(order, 'cid'),
686
+ 'timestamp': undefined,
687
+ 'datetime': undefined,
688
+ 'lastTradeTimestamp': undefined,
689
+ 'lastUpdateTimestamp': undefined,
690
+ 'status': this.parseOrderStatus(rawStatus),
691
+ 'symbol': market['symbol'],
692
+ 'type': this.parseOrderType(rawType),
693
+ 'timeInForce': undefined,
694
+ 'postOnly': undefined,
695
+ 'reduceOnly': this.safeBool(order, 'ro'),
696
+ 'side': this.safeStringLower(order, 'S'),
697
+ 'price': this.safeString(order, 'p'),
698
+ 'triggerPrice': undefined,
699
+ 'stopLossPrice': undefined,
700
+ 'takeProfitPrice': undefined,
701
+ 'amount': this.safeString(order, 'v'),
702
+ 'filled': this.safeString(order, 'ev'),
703
+ 'remaining': this.safeString(order, 'qty'),
704
+ 'cost': undefined,
705
+ 'trades': undefined,
706
+ 'fee': fee,
707
+ 'average': this.omitZero(this.safeString(order, 'ap')),
708
+ }, market);
709
+ }
710
+ /**
711
+ * @method
712
+ * @name bydfi#watchPositions
713
+ * @description watch all open positions
714
+ * @see https://developers.bydfi.com/en/swap/websocket-account#balance-and-position-update-push
715
+ * @param {string[]} [symbols] list of unified market symbols
716
+ * @param {int} [since] the earliest time in ms to fetch positions for
717
+ * @param {int} [limit] the maximum number of positions to retrieve
718
+ * @param {object} params extra parameters specific to the exchange API endpoint
719
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
720
+ */
721
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
722
+ await this.loadMarkets();
723
+ symbols = this.marketSymbols(symbols, undefined, true);
724
+ const messageHashes = [];
725
+ const messageHash = 'positions';
726
+ if (symbols === undefined) {
727
+ messageHashes.push(messageHash);
728
+ }
729
+ else {
730
+ for (let i = 0; i < symbols.length; i++) {
731
+ const symbol = symbols[i];
732
+ messageHashes.push(messageHash + '::' + symbol);
733
+ }
734
+ }
735
+ const positions = await this.watchPrivate(messageHashes, params);
736
+ if (this.newUpdates) {
737
+ return positions;
738
+ }
739
+ return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
740
+ }
741
+ handlePositions(client, message) {
742
+ //
743
+ // {
744
+ // "a": {
745
+ // "B": [
746
+ // {
747
+ // "a": "USDC",
748
+ // "ba": "0",
749
+ // "im": "1.46282986",
750
+ // "om": "0",
751
+ // "tfm": "1.46282986",
752
+ // "wb": "109.86879703"
753
+ // }
754
+ // ],
755
+ // "m": "ORDER",
756
+ // "p": [
757
+ // {
758
+ // "S": "1",
759
+ // "ap": "2925.81666667",
760
+ // "c": "USDC",
761
+ // "ct": "FUTURE",
762
+ // "l": 2,
763
+ // "lq": "1471.1840621072728637",
764
+ // "lv": "0",
765
+ // "ma": "0",
766
+ // "mt": "ISOLATED",
767
+ // "pm": "1.4628298566666665",
768
+ // "pt": "ONEWAY",
769
+ // "rp": "-0.00036721",
770
+ // "s": "ETH-USDC",
771
+ // "t": "0",
772
+ // "uq": "0.001",
773
+ // "v": "1"
774
+ // }
775
+ // ]
776
+ // },
777
+ // "T": 1766592694451,
778
+ // "E": 1766592694554,
779
+ // "e": "ACCOUNT_UPDATE"
780
+ // }
781
+ //
782
+ const data = this.safeDict(message, 'a', {});
783
+ const positionsData = this.safeList(data, 'p', []);
784
+ const rawPosition = this.safeDict(positionsData, 0, {});
785
+ const marketId = this.safeString(rawPosition, 's');
786
+ const market = this.safeMarket(marketId);
787
+ const symbol = market['symbol'];
788
+ const messageHash = 'positions';
789
+ const symbolMessageHash = messageHash + '::' + symbol;
790
+ const messageHashes = this.findMessageHashes(client, messageHash);
791
+ let match = false;
792
+ for (let i = 0; i < messageHashes.length; i++) {
793
+ const hash = messageHashes[i];
794
+ if (hash === symbolMessageHash || hash === messageHash) {
795
+ match = true;
796
+ break;
797
+ }
798
+ }
799
+ if (match) {
800
+ if (this.positions === undefined) {
801
+ this.positions = new ArrayCacheBySymbolBySide();
802
+ }
803
+ const cache = this.positions;
804
+ const parsedPosition = this.parseWsPosition(rawPosition, market);
805
+ const timestamp = this.safeInteger(message, 'T');
806
+ parsedPosition['timestamp'] = timestamp;
807
+ parsedPosition['datetime'] = this.iso8601(timestamp);
808
+ cache.append(parsedPosition);
809
+ const symbolSpecificMessageHash = messageHash + ':' + parsedPosition['symbol'];
810
+ client.resolve([parsedPosition], messageHash);
811
+ client.resolve([parsedPosition], symbolSpecificMessageHash);
812
+ }
813
+ }
814
+ parseWsPosition(position, market = undefined) {
815
+ //
816
+ // {
817
+ // "S": "1",
818
+ // "ap": "2925.81666667",
819
+ // "c": "USDC",
820
+ // "ct": "FUTURE",
821
+ // "l": 2,
822
+ // "lq": "1471.1840621072728637",
823
+ // "lv": "0",
824
+ // "ma": "0",
825
+ // "mt": "ISOLATED",
826
+ // "pm": "1.4628298566666665",
827
+ // "pt": "ONEWAY",
828
+ // "rp": "-0.00036721",
829
+ // "s": "ETH-USDC",
830
+ // "t": "0",
831
+ // "uq": "0.001",
832
+ // "v": "1"
833
+ // }
834
+ //
835
+ const marketId = this.safeString(position, 's');
836
+ market = this.safeMarket(marketId, market);
837
+ const rawPositionSide = this.safeString(position, 'S');
838
+ const positionMode = this.safeString(position, 'pt');
839
+ return this.safePosition({
840
+ 'info': position,
841
+ 'id': this.safeString(position, 'id'),
842
+ 'symbol': market['symbol'],
843
+ 'entryPrice': this.parseNumber(this.safeString(position, 'ap')),
844
+ 'markPrice': undefined,
845
+ 'lastPrice': undefined,
846
+ 'notional': undefined,
847
+ 'collateral': undefined,
848
+ 'unrealizedPnl': undefined,
849
+ 'realizedPnl': this.parseNumber(this.safeString(position, 'rp')),
850
+ 'side': this.parseWsPositionSide(rawPositionSide),
851
+ 'contracts': this.parseNumber(this.safeString(position, 'v')),
852
+ 'contractSize': this.parseNumber(this.safeString(position, 'uq')),
853
+ 'timestamp': undefined,
854
+ 'datetime': undefined,
855
+ 'lastUpdateTimestamp': undefined,
856
+ 'hedged': (positionMode !== 'ONEWAY'),
857
+ 'maintenanceMargin': undefined,
858
+ 'maintenanceMarginPercentage': undefined,
859
+ 'initialMargin': this.parseNumber(this.safeString(position, 'pm')),
860
+ 'initialMarginPercentage': undefined,
861
+ 'leverage': this.safeInteger(position, 'l'),
862
+ 'liquidationPrice': this.parseNumber(this.safeString(position, 'lq')),
863
+ 'marginRatio': undefined,
864
+ 'marginMode': this.safeStringLower(position, 'mt'),
865
+ 'percentage': undefined,
866
+ });
867
+ }
868
+ parseWsPositionSide(rawPositionSide) {
869
+ const sides = {
870
+ '1': 'long',
871
+ '2': 'short',
872
+ };
873
+ return this.safeString(sides, rawPositionSide, rawPositionSide);
874
+ }
875
+ /**
876
+ * @method
877
+ * @name bydfi#watchBalance
878
+ * @description watch balance and get the amount of funds available for trading or funds locked in orders
879
+ * @see https://developers.bydfi.com/en/swap/websocket-account#balance-and-position-update-push
880
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
881
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
882
+ */
883
+ async watchBalance(params = {}) {
884
+ await this.loadMarkets();
885
+ const url = this.urls['api']['ws'];
886
+ const client = this.client(url);
887
+ this.fetchBalanceSnapshot(client);
888
+ const options = this.safeDict(this.options, 'watchBalance');
889
+ const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
890
+ const awaitBalanceSnapshot = this.safeBool(options, 'awaitBalanceSnapshot', true);
891
+ if (fetchBalanceSnapshot && awaitBalanceSnapshot) {
892
+ await client.future('fetchBalanceSnapshot');
893
+ }
894
+ const messageHash = 'balance';
895
+ return await this.watchPrivate([messageHash], params);
896
+ }
897
+ fetchBalanceSnapshot(client) {
898
+ const options = this.safeValue(this.options, 'watchBalance');
899
+ const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
900
+ if (fetchBalanceSnapshot) {
901
+ const messageHash = 'fetchBalanceSnapshot';
902
+ if (!(messageHash in client.futures)) {
903
+ client.future(messageHash);
904
+ this.spawn(this.loadBalanceSnapshot, client, messageHash);
905
+ }
906
+ }
907
+ }
908
+ async loadBalanceSnapshot(client, messageHash) {
909
+ const params = {
910
+ 'type': 'swap',
911
+ };
912
+ const response = await this.fetchBalance(params);
913
+ this.balance = this.extend(response, this.balance);
914
+ // don't remove the future from the .futures cache
915
+ const future = client.futures[messageHash];
916
+ future.resolve();
917
+ client.resolve(this.balance, 'balance');
918
+ }
919
+ handleBalance(client, message) {
920
+ //
921
+ // {
922
+ // "a": {
923
+ // "B": [
924
+ // {
925
+ // "a": "USDC",
926
+ // "ba": "0",
927
+ // "im": "1.46282986",
928
+ // "om": "0",
929
+ // "tfm": "1.46282986",
930
+ // "wb": "109.86879703"
931
+ // }
932
+ // ],
933
+ // "m": "ORDER",
934
+ // "p": [
935
+ // {
936
+ // "S": "1",
937
+ // "ap": "2925.81666667",
938
+ // "c": "USDC",
939
+ // "ct": "FUTURE",
940
+ // "l": 2,
941
+ // "lq": "1471.1840621072728637",
942
+ // "lv": "0",
943
+ // "ma": "0",
944
+ // "mt": "ISOLATED",
945
+ // "pm": "1.4628298566666665",
946
+ // "pt": "ONEWAY",
947
+ // "rp": "-0.00036721",
948
+ // "s": "ETH-USDC",
949
+ // "t": "0",
950
+ // "uq": "0.001",
951
+ // "v": "1"
952
+ // }
953
+ // ]
954
+ // },
955
+ // "T": 1766592694451,
956
+ // "E": 1766592694554,
957
+ // "e": "ACCOUNT_UPDATE"
958
+ // }
959
+ //
960
+ const messageHash = 'balance';
961
+ if (messageHash in client.futures) {
962
+ const data = this.safeDict(message, 'a', {});
963
+ const balances = this.safeList(data, 'B', []);
964
+ const timestamp = this.safeInteger(message, 'T');
965
+ const result = {
966
+ 'info': message,
967
+ 'timestamp': timestamp,
968
+ 'datetime': this.iso8601(timestamp),
969
+ };
970
+ for (let i = 0; i < balances.length; i++) {
971
+ const balance = balances[i];
972
+ const currencyId = this.safeString(balance, 'a');
973
+ const code = this.safeCurrencyCode(currencyId);
974
+ const account = this.account();
975
+ account['total'] = this.safeString(balance, 'wb');
976
+ account['used'] = this.safeString(balance, 'tfm');
977
+ result[code] = account;
978
+ }
979
+ const parsedBalance = this.safeBalance(result);
980
+ this.balance = this.extend(this.balance, parsedBalance);
981
+ client.resolve(this.balance, messageHash);
982
+ }
983
+ }
984
+ handleSubscriptionStatus(client, message) {
985
+ //
986
+ // {
987
+ // "result": true,
988
+ // "id": 1
989
+ // }
990
+ //
991
+ const id = this.safeString(message, 'id');
992
+ const subscriptionsById = this.indexBy(client.subscriptions, 'id');
993
+ const subscription = this.safeDict(subscriptionsById, id, {});
994
+ const isUnSubMessage = this.safeBool(subscription, 'unsubscribe', false);
995
+ if (isUnSubMessage) {
996
+ this.handleUnSubscription(client, subscription);
997
+ }
998
+ return message;
999
+ }
1000
+ handleUnSubscription(client, subscription) {
1001
+ const messageHashes = this.safeList(subscription, 'messageHashes', []);
1002
+ const subHashIsPrefix = this.safeBool(subscription, 'subHashIsPrefix', false);
1003
+ for (let i = 0; i < messageHashes.length; i++) {
1004
+ const unsubHash = messageHashes[i];
1005
+ const subHash = unsubHash.replace('unsubscribe::', '');
1006
+ this.cleanUnsubscription(client, subHash, unsubHash, subHashIsPrefix);
1007
+ }
1008
+ this.cleanCache(subscription);
1009
+ }
1010
+ handlePong(client, message) {
1011
+ //
1012
+ // {
1013
+ // "id": 1,
1014
+ // "result": "pong"
1015
+ // }
1016
+ //
1017
+ client.lastPong = this.milliseconds();
1018
+ return message;
1019
+ }
1020
+ handleErrorMessage(client, message) {
1021
+ //
1022
+ // {
1023
+ // "msg": "Service error",
1024
+ // "code": "-1"
1025
+ // }
1026
+ //
1027
+ const code = this.safeString(message, 'code');
1028
+ const msg = this.safeString(message, 'msg');
1029
+ const feedback = this.id + ' ' + this.json(message);
1030
+ this.throwExactlyMatchedException(this.exceptions['exact'], msg, feedback);
1031
+ this.throwBroadlyMatchedException(this.exceptions['broad'], msg, feedback);
1032
+ this.throwExactlyMatchedException(this.exceptions['exact'], code, feedback);
1033
+ throw new ExchangeError(feedback);
1034
+ }
1035
+ handleMessage(client, message) {
1036
+ const code = this.safeString(message, 'code');
1037
+ if (code !== undefined && (code !== '0')) {
1038
+ this.handleErrorMessage(client, message);
1039
+ }
1040
+ const result = this.safeString(message, 'result');
1041
+ if (result === 'pong') {
1042
+ this.handlePong(client, message);
1043
+ }
1044
+ else if (result !== undefined) {
1045
+ this.handleSubscriptionStatus(client, message);
1046
+ }
1047
+ else {
1048
+ const event = this.safeString(message, 'e');
1049
+ if (event === '24hrTicker') {
1050
+ this.handleTicker(client, message);
1051
+ }
1052
+ else if (event === 'kline') {
1053
+ this.handleOHLCV(client, message);
1054
+ }
1055
+ else if (event === 'depthUpdate') {
1056
+ this.handleOrderBook(client, message);
1057
+ }
1058
+ else if (event === 'ORDER_TRADE_UPDATE') {
1059
+ this.handleOrder(client, message);
1060
+ }
1061
+ else if (event === 'ACCOUNT_UPDATE') {
1062
+ const account = this.safeDict(message, 'a', {});
1063
+ const balances = this.safeList(account, 'B', []);
1064
+ const balancesLength = balances.length;
1065
+ if (balancesLength > 0) {
1066
+ this.handleBalance(client, message);
1067
+ }
1068
+ const positions = this.safeList(account, 'p', []);
1069
+ const positionsLength = positions.length;
1070
+ if (positionsLength > 0) {
1071
+ this.handlePositions(client, message);
1072
+ }
1073
+ }
1074
+ }
1075
+ }
1076
+ }