ccxt 4.5.40 → 4.5.42

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 (106) hide show
  1. package/README.md +6 -5
  2. package/dist/ccxt.browser.min.js +18 -18
  3. package/dist/cjs/ccxt.js +6 -1
  4. package/dist/cjs/src/abstract/lighter.js +11 -0
  5. package/dist/cjs/src/ascendex.js +73 -1
  6. package/dist/cjs/src/base/Exchange.js +149 -17
  7. package/dist/cjs/src/base/functions/generic.js +1 -0
  8. package/dist/cjs/src/base/functions/io.js +160 -0
  9. package/dist/cjs/src/base/functions.js +6 -0
  10. package/dist/cjs/src/base/ws/Client.js +1 -0
  11. package/dist/cjs/src/base/ws/WsClient.js +1 -0
  12. package/dist/cjs/src/binance.js +1 -0
  13. package/dist/cjs/src/bingx.js +13 -3
  14. package/dist/cjs/src/bitmex.js +20 -0
  15. package/dist/cjs/src/blofin.js +2 -2
  16. package/dist/cjs/src/bybit.js +1 -1
  17. package/dist/cjs/src/coinspot.js +7 -2
  18. package/dist/cjs/src/delta.js +1 -1
  19. package/dist/cjs/src/gate.js +11 -4
  20. package/dist/cjs/src/gemini.js +76 -1
  21. package/dist/cjs/src/htx.js +2 -2
  22. package/dist/cjs/src/hyperliquid.js +20 -7
  23. package/dist/cjs/src/independentreserve.js +7 -7
  24. package/dist/cjs/src/kraken.js +1 -1
  25. package/dist/cjs/src/krakenfutures.js +96 -5
  26. package/dist/cjs/src/kucoin.js +3 -3
  27. package/dist/cjs/src/kucoinfutures.js +1 -1
  28. package/dist/cjs/src/lighter.js +2931 -0
  29. package/dist/cjs/src/mexc.js +0 -1
  30. package/dist/cjs/src/phemex.js +1 -1
  31. package/dist/cjs/src/pro/binance.js +2 -2
  32. package/dist/cjs/src/pro/bingx.js +215 -2
  33. package/dist/cjs/src/pro/bitget.js +1 -0
  34. package/dist/cjs/src/pro/defx.js +1 -1
  35. package/dist/cjs/src/pro/kucoinfutures.js +1 -1
  36. package/dist/cjs/src/pro/lighter.js +787 -0
  37. package/dist/cjs/src/pro/mexc.js +1 -1
  38. package/dist/cjs/src/pro/paradex.js +1 -1
  39. package/dist/cjs/src/static_dependencies/ethers/abi-coder.js +1 -0
  40. package/dist/cjs/src/static_dependencies/ethers/address/address.js +1 -0
  41. package/dist/cjs/src/static_dependencies/ethers/coders/abstract-coder.js +1 -0
  42. package/dist/cjs/src/static_dependencies/ethers/coders/address.js +1 -0
  43. package/dist/cjs/src/static_dependencies/ethers/coders/array.js +1 -0
  44. package/dist/cjs/src/static_dependencies/ethers/coders/bytes.js +1 -0
  45. package/dist/cjs/src/static_dependencies/ethers/coders/fixed-bytes.js +1 -0
  46. package/dist/cjs/src/static_dependencies/ethers/coders/number.js +1 -0
  47. package/dist/cjs/src/static_dependencies/ethers/fragments.js +1 -0
  48. package/dist/cjs/src/static_dependencies/ethers/index.js +1 -0
  49. package/dist/cjs/src/static_dependencies/ethers/interface.js +1 -0
  50. package/dist/cjs/src/static_dependencies/ethers/typed.js +1 -0
  51. package/dist/cjs/src/static_dependencies/ethers/utils/index.js +1 -0
  52. package/dist/cjs/src/whitebit.js +118 -16
  53. package/dist/cjs/src/woo.js +1 -1
  54. package/js/ccxt.d.ts +8 -2
  55. package/js/ccxt.js +6 -2
  56. package/js/src/abstract/gemini.d.ts +27 -0
  57. package/js/src/abstract/lighter.d.ts +53 -0
  58. package/js/src/abstract/lighter.js +11 -0
  59. package/js/src/ascendex.d.ts +12 -1
  60. package/js/src/ascendex.js +73 -1
  61. package/js/src/base/Exchange.d.ts +18 -6
  62. package/js/src/base/Exchange.js +154 -21
  63. package/js/src/base/functions/generic.js +1 -0
  64. package/js/src/base/functions/io.d.ts +32 -0
  65. package/js/src/base/functions/io.js +137 -0
  66. package/js/src/base/functions.d.ts +1 -0
  67. package/js/src/base/functions.js +1 -0
  68. package/js/src/binance.d.ts +1 -0
  69. package/js/src/binance.js +1 -0
  70. package/js/src/bingx.js +13 -3
  71. package/js/src/bitmex.js +20 -0
  72. package/js/src/blofin.js +2 -2
  73. package/js/src/bybit.js +1 -1
  74. package/js/src/coinspot.js +7 -2
  75. package/js/src/delta.js +1 -1
  76. package/js/src/gate.d.ts +1 -0
  77. package/js/src/gate.js +11 -4
  78. package/js/src/gemini.d.ts +11 -0
  79. package/js/src/gemini.js +76 -1
  80. package/js/src/htx.js +2 -2
  81. package/js/src/hyperliquid.js +20 -7
  82. package/js/src/independentreserve.js +7 -7
  83. package/js/src/kraken.js +1 -1
  84. package/js/src/krakenfutures.d.ts +1 -1
  85. package/js/src/krakenfutures.js +96 -5
  86. package/js/src/kucoin.d.ts +3 -3
  87. package/js/src/kucoin.js +3 -3
  88. package/js/src/kucoinfutures.js +1 -1
  89. package/js/src/lighter.d.ts +424 -0
  90. package/js/src/lighter.js +2930 -0
  91. package/js/src/mexc.js +0 -1
  92. package/js/src/phemex.js +1 -1
  93. package/js/src/pro/binance.js +2 -2
  94. package/js/src/pro/bingx.d.ts +17 -1
  95. package/js/src/pro/bingx.js +216 -3
  96. package/js/src/pro/bitget.js +1 -0
  97. package/js/src/pro/defx.js +1 -1
  98. package/js/src/pro/kucoinfutures.js +1 -1
  99. package/js/src/pro/lighter.d.ts +161 -0
  100. package/js/src/pro/lighter.js +786 -0
  101. package/js/src/pro/mexc.js +1 -1
  102. package/js/src/pro/paradex.js +1 -1
  103. package/js/src/whitebit.d.ts +2 -1
  104. package/js/src/whitebit.js +118 -16
  105. package/js/src/woo.js +1 -1
  106. package/package.json +1 -1
@@ -0,0 +1,787 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var Precise = require('../base/Precise.js');
6
+ var Cache = require('../base/ws/Cache.js');
7
+ var lighter$1 = require('../lighter.js');
8
+
9
+ // ----------------------------------------------------------------------------
10
+ // ---------------------------------------------------------------------------
11
+ class lighter extends lighter$1["default"] {
12
+ describe() {
13
+ return this.deepExtend(super.describe(), {
14
+ 'has': {
15
+ 'ws': true,
16
+ 'watchTicker': true,
17
+ 'watchMarkPrice': true,
18
+ 'watchMarkPrices': true,
19
+ 'watchTickers': true,
20
+ 'watchBidsAsks': false,
21
+ 'watchOrderBook': true,
22
+ 'watchTrades': true,
23
+ 'watchTradesForSymbols': false,
24
+ 'watchOrderBookForSymbols': false,
25
+ 'watchBalance': false,
26
+ 'watchLiquidations': true,
27
+ 'watchLiquidationsForSymbols': false,
28
+ 'watchMyLiquidations': false,
29
+ 'watchMyLiquidationsForSymbols': false,
30
+ 'watchOHLCV': false,
31
+ 'watchOHLCVForSymbols': false,
32
+ 'watchOrders': false,
33
+ 'watchMyTrades': false,
34
+ 'watchPositions': false,
35
+ 'watchFundingRate': false,
36
+ 'watchFundingRates': false,
37
+ 'unWatchOrderBook': true,
38
+ 'unWatchTicker': true,
39
+ 'unWatchTickers': true,
40
+ 'unWatchTrades': true,
41
+ 'unWatchMarkPrice': true,
42
+ 'unWatchMarkPrices': true,
43
+ },
44
+ 'urls': {
45
+ 'api': {
46
+ 'ws': 'wss://mainnet.zklighter.elliot.ai/stream',
47
+ },
48
+ 'test': {
49
+ 'ws': 'wss://testnet.zklighter.elliot.ai/stream',
50
+ },
51
+ },
52
+ 'options': {},
53
+ });
54
+ }
55
+ getMessageHash(unifiedChannel, symbol = undefined, extra = undefined) {
56
+ let hash = unifiedChannel;
57
+ if (symbol !== undefined) {
58
+ hash += '::' + symbol;
59
+ }
60
+ else {
61
+ hash += 's'; // tickers, orderbooks, ohlcvs ...
62
+ }
63
+ if (extra !== undefined) {
64
+ hash += '::' + extra;
65
+ }
66
+ return hash;
67
+ }
68
+ async subscribePublic(messageHash, params = {}) {
69
+ const url = this.urls['api']['ws'];
70
+ const request = {
71
+ 'type': 'subscribe',
72
+ };
73
+ const subscription = {
74
+ 'messageHash': messageHash,
75
+ 'params': params,
76
+ };
77
+ return await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
78
+ }
79
+ async subscribePublicMultiple(messageHashes, params = {}) {
80
+ const url = this.urls['api']['ws'];
81
+ const request = {
82
+ 'type': 'subscribe',
83
+ };
84
+ const subscription = {
85
+ 'messageHashes': messageHashes,
86
+ 'params': params,
87
+ };
88
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscription);
89
+ }
90
+ async unsubscribePublic(messageHash, params = {}) {
91
+ const url = this.urls['api']['ws'];
92
+ const request = {
93
+ 'type': 'unsubscribe',
94
+ };
95
+ const subscription = {
96
+ 'messageHash': messageHash,
97
+ 'params': params,
98
+ };
99
+ return await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
100
+ }
101
+ handleDelta(bookside, delta) {
102
+ const price = this.safeFloat(delta, 'price');
103
+ const amount = this.safeFloat(delta, 'size');
104
+ bookside.store(price, amount);
105
+ }
106
+ handleDeltas(bookside, deltas) {
107
+ for (let i = 0; i < deltas.length; i++) {
108
+ this.handleDelta(bookside, deltas[i]);
109
+ }
110
+ }
111
+ handleOrderBookMessage(client, message, orderbook) {
112
+ const data = this.safeDict(message, 'order_book', {});
113
+ this.handleDeltas(orderbook['asks'], this.safeList(data, 'asks', []));
114
+ this.handleDeltas(orderbook['bids'], this.safeList(data, 'bids', []));
115
+ orderbook['nonce'] = this.safeInteger(data, 'offset');
116
+ const timestamp = this.safeInteger(message, 'timestamp');
117
+ orderbook['timestamp'] = timestamp;
118
+ orderbook['datetime'] = this.iso8601(timestamp);
119
+ return orderbook;
120
+ }
121
+ handleOrderBook(client, message) {
122
+ //
123
+ // {
124
+ // "channel": "order_book:0",
125
+ // "offset": 11413309,
126
+ // "order_book": {
127
+ // "code": 0,
128
+ // "asks": [
129
+ // {
130
+ // "price": "2979.64",
131
+ // "size": "61.9487"
132
+ // }
133
+ // ],
134
+ // "bids": [
135
+ // {
136
+ // "price": "2979.36",
137
+ // "size": "0.0000"
138
+ // }
139
+ // ],
140
+ // "offset": 11413309,
141
+ // "nonce": 3107818665
142
+ // },
143
+ // "timestamp": 1763448665923,
144
+ // "type": "update/order_book"
145
+ // }
146
+ //
147
+ const data = this.safeDict(message, 'order_book', {});
148
+ const channel = this.safeString(message, 'channel', '');
149
+ const parts = channel.split(':');
150
+ const marketId = parts[1];
151
+ const market = this.safeMarket(marketId);
152
+ const symbol = market['symbol'];
153
+ const timestamp = this.safeInteger(message, 'timestamp');
154
+ if (!(symbol in this.orderbooks)) {
155
+ this.orderbooks[symbol] = this.orderBook();
156
+ }
157
+ const orderbook = this.orderbooks[symbol];
158
+ const type = this.safeString(message, 'type', '');
159
+ if (type === 'subscribed/order_book') {
160
+ const parsed = this.parseOrderBook(data, symbol, timestamp, 'bids', 'asks', 'price', 'size');
161
+ parsed['nonce'] = this.safeInteger(data, 'offset');
162
+ orderbook.reset(parsed);
163
+ }
164
+ else if (type === 'update/order_book') {
165
+ this.handleOrderBookMessage(client, message, orderbook);
166
+ }
167
+ const messageHash = this.getMessageHash('orderbook', symbol);
168
+ client.resolve(orderbook, messageHash);
169
+ }
170
+ /**
171
+ * @method
172
+ * @name lighter#watchOrderBook
173
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
174
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#order-book
175
+ * @param {string} symbol unified symbol of the market to fetch the order book for
176
+ * @param {int} [limit] the maximum amount of order book entries to return
177
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
178
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
179
+ */
180
+ async watchOrderBook(symbol, limit = undefined, params = {}) {
181
+ await this.loadMarkets();
182
+ const market = this.market(symbol);
183
+ const request = {
184
+ 'channel': 'order_book/' + market['id'],
185
+ };
186
+ const messageHash = this.getMessageHash('orderbook', symbol);
187
+ const orderbook = await this.subscribePublic(messageHash, this.extend(request, params));
188
+ return orderbook.limit();
189
+ }
190
+ /**
191
+ * @method
192
+ * @name lighter#unWatchOrderBook
193
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
194
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#order-book
195
+ * @param {string} symbol unified symbol of the market
196
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
197
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
198
+ */
199
+ async unWatchOrderBook(symbol, params = {}) {
200
+ await this.loadMarkets();
201
+ const market = this.market(symbol);
202
+ const request = {
203
+ 'channel': 'order_book/' + market['id'],
204
+ };
205
+ const messageHash = this.getMessageHash('unsubscribe', symbol);
206
+ return await this.unsubscribePublic(messageHash, this.extend(request, params));
207
+ }
208
+ handleTicker(client, message) {
209
+ //
210
+ // watchTicker
211
+ // {
212
+ // "channel": "market_stats:0",
213
+ // "market_stats": {
214
+ // "market_id": 0,
215
+ // "index_price": "3015.56",
216
+ // "mark_price": "3013.91",
217
+ // "open_interest": "122736286.659423",
218
+ // "open_interest_limit": "72057594037927936.000000",
219
+ // "funding_clamp_small": "0.0500",
220
+ // "funding_clamp_big": "4.0000",
221
+ // "last_trade_price": "3013.13",
222
+ // "current_funding_rate": "0.0012",
223
+ // "funding_rate": "0.0012",
224
+ // "funding_timestamp": 1763532000004,
225
+ // "daily_base_token_volume": 643235.2763,
226
+ // "daily_quote_token_volume": 1983505435.673896,
227
+ // "daily_price_low": 2977.42,
228
+ // "daily_price_high": 3170.81,
229
+ // "daily_price_change": -0.3061987051035322
230
+ // },
231
+ // "type": "update/market_stats"
232
+ // }
233
+ //
234
+ // watchTickers
235
+ // {
236
+ // "channel": "market_stats:all",
237
+ // "market_stats": {
238
+ // "96": {
239
+ // "market_id": 96,
240
+ // "index_price": "1.15901",
241
+ // "mark_price": "1.15954",
242
+ // "open_interest": "19392952.260530",
243
+ // "open_interest_limit": "50000000000000.000000",
244
+ // "funding_clamp_small": "0.0500",
245
+ // "funding_clamp_big": "4.0000",
246
+ // "last_trade_price": "1.15955",
247
+ // "current_funding_rate": "0.0000",
248
+ // "funding_rate": "0.0000",
249
+ // "funding_timestamp": 1763532000004,
250
+ // "daily_base_token_volume": 117634224.1,
251
+ // "daily_quote_token_volume": 136339744.383989,
252
+ // "daily_price_low": 1.15774,
253
+ // "daily_price_high": 1.16105,
254
+ // "daily_price_change": -0.004311757299805109
255
+ // }
256
+ // },
257
+ // "type": "update/market_stats"
258
+ // }
259
+ //
260
+ const data = this.safeDict(message, 'market_stats', {});
261
+ const channel = this.safeString(message, 'channel');
262
+ if (channel === 'market_stats:all') {
263
+ const marketIds = Object.keys(data);
264
+ for (let i = 0; i < marketIds.length; i++) {
265
+ const marketId = marketIds[i];
266
+ const market = this.safeMarket(marketId);
267
+ const symbol = market['symbol'];
268
+ const ticker = this.parseTicker(data[marketId], market);
269
+ this.tickers[symbol] = ticker;
270
+ client.resolve(ticker, this.getMessageHash('ticker', symbol));
271
+ client.resolve(ticker, this.getMessageHash('ticker'));
272
+ }
273
+ }
274
+ else {
275
+ const marketId = this.safeString(data, 'market_id');
276
+ const market = this.safeMarket(marketId);
277
+ const symbol = market['symbol'];
278
+ const ticker = this.parseTicker(data, market);
279
+ this.tickers[symbol] = ticker;
280
+ client.resolve(ticker, this.getMessageHash('ticker', symbol));
281
+ }
282
+ }
283
+ /**
284
+ * @method
285
+ * @name lighter#watchTicker
286
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
287
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#market-stats
288
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
289
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
290
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
291
+ */
292
+ async watchTicker(symbol, params = {}) {
293
+ await this.loadMarkets();
294
+ const market = this.market(symbol);
295
+ const request = {
296
+ 'channel': 'market_stats/' + market['id'],
297
+ };
298
+ const messageHash = this.getMessageHash('ticker', symbol);
299
+ return await this.subscribePublic(messageHash, this.extend(request, params));
300
+ }
301
+ /**
302
+ * @method
303
+ * @name lighter#unWatchTicker
304
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
305
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#market-stats
306
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
307
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
308
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
309
+ */
310
+ async unWatchTicker(symbol, params = {}) {
311
+ await this.loadMarkets();
312
+ const market = this.market(symbol);
313
+ const request = {
314
+ 'channel': 'market_stats/' + market['id'],
315
+ };
316
+ const messageHash = this.getMessageHash('unsubscribe', symbol);
317
+ return await this.unsubscribePublic(messageHash, this.extend(request, params));
318
+ }
319
+ /**
320
+ * @method
321
+ * @name lighter#watchTickers
322
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#market-stats
323
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
324
+ * @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
325
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
326
+ * @param {string} [params.channel] the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
327
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
328
+ */
329
+ async watchTickers(symbols = undefined, params = {}) {
330
+ await this.loadMarkets();
331
+ symbols = this.marketSymbols(symbols);
332
+ const request = {
333
+ 'channel': 'market_stats/all',
334
+ };
335
+ const messageHashes = [];
336
+ if (symbols === undefined || symbols.length === 0) {
337
+ messageHashes.push(this.getMessageHash('ticker'));
338
+ }
339
+ else {
340
+ for (let i = 0; i < symbols.length; i++) {
341
+ const symbol = symbols[i];
342
+ messageHashes.push(this.getMessageHash('ticker', symbol));
343
+ }
344
+ }
345
+ const newTicker = await this.subscribePublicMultiple(messageHashes, this.extend(request, params));
346
+ if (this.newUpdates) {
347
+ const result = {};
348
+ result[newTicker['symbol']] = newTicker;
349
+ return result;
350
+ }
351
+ return this.filterByArray(this.tickers, 'symbol', symbols);
352
+ }
353
+ /**
354
+ * @method
355
+ * @name lighter#unWatchTickers
356
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
357
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#market-stats
358
+ * @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
359
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
360
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
361
+ */
362
+ async unWatchTickers(symbols = undefined, params = {}) {
363
+ await this.loadMarkets();
364
+ const request = {
365
+ 'channel': 'market_stats/all',
366
+ };
367
+ const messageHash = this.getMessageHash('unsubscribe');
368
+ return await this.unsubscribePublic(messageHash, this.extend(request, params));
369
+ }
370
+ /**
371
+ * @method
372
+ * @name lighter#watchMarkPrice
373
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#market-stats
374
+ * @description watches a mark price
375
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
376
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
377
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
378
+ */
379
+ async watchMarkPrice(symbol, params = {}) {
380
+ return await this.watchTicker(symbol, params);
381
+ }
382
+ /**
383
+ * @method
384
+ * @name lighter#watchMarkPrices
385
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#market-stats
386
+ * @description watches mark prices
387
+ * @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
388
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
389
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
390
+ */
391
+ async watchMarkPrices(symbols = undefined, params = {}) {
392
+ return await this.watchTickers(symbols, params);
393
+ }
394
+ /**
395
+ * @method
396
+ * @name lighter#unWatchMarkPrice
397
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#market-stats
398
+ * @description unWatches a mark price
399
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
400
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
401
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
402
+ */
403
+ async unWatchMarkPrice(symbol, params = {}) {
404
+ return await this.unWatchTicker(symbol, params);
405
+ }
406
+ /**
407
+ * @method
408
+ * @name lighter#unWatchMarkPrices
409
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#market-stats
410
+ * @description unWatches mark prices
411
+ * @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
412
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
413
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
414
+ */
415
+ async unWatchMarkPrices(symbols = undefined, params = {}) {
416
+ return await this.unWatchTickers(symbols, params);
417
+ }
418
+ parseWsTrade(trade, market = undefined) {
419
+ //
420
+ // {
421
+ // "trade_id": 526801155,
422
+ // "tx_hash": "1998d9df580acb7540aa141cc369d6ef926d003b3062196d2007bca15f978ab208e0caae4ac5872b",
423
+ // "type": "trade",
424
+ // "market_id": 0,
425
+ // "size": "0.0346",
426
+ // "price": "3028.85",
427
+ // "usd_amount": "104.798210",
428
+ // "ask_id": 281475673670566,
429
+ // "bid_id": 562949291740362,
430
+ // "ask_client_id": 76303170,
431
+ // "bid_client_id": 27601,
432
+ // "ask_account_id": 99349,
433
+ // "bid_account_id": 243008,
434
+ // "is_maker_ask": false,
435
+ // "block_height": 102322769,
436
+ // "timestamp": 1763623734215,
437
+ // "taker_position_size_before": "0.0346",
438
+ // "taker_entry_quote_before": "104.359926",
439
+ // "taker_initial_margin_fraction_before": 500,
440
+ // "taker_position_sign_changed": true,
441
+ // "maker_fee": 20,
442
+ // "maker_position_size_before": "2.1277",
443
+ // "maker_entry_quote_before": "6444.179555",
444
+ // "maker_initial_margin_fraction_before": 200
445
+ // }
446
+ //
447
+ const timestamp = this.safeInteger(trade, 'timestamp');
448
+ const tradeId = this.safeString(trade, 'trade_id');
449
+ const priceString = this.safeString(trade, 'price');
450
+ const amountString = this.safeString(trade, 'size');
451
+ const isMakerAsk = this.safeBool(trade, 'is_maker_ask');
452
+ const side = (isMakerAsk === true) ? 'sell' : 'buy';
453
+ const makerFeeRate = this.safeString(market, 'maker_fee');
454
+ const maker = Precise["default"].stringDiv(makerFeeRate, '100');
455
+ const feeAmount = Precise["default"].stringMul(maker, makerFeeRate);
456
+ return this.safeTrade({
457
+ 'info': trade,
458
+ 'id': tradeId,
459
+ 'order': undefined,
460
+ 'timestamp': timestamp,
461
+ 'datetime': this.iso8601(timestamp),
462
+ 'symbol': this.safeSymbol(undefined, market),
463
+ 'type': undefined,
464
+ 'side': side,
465
+ 'takerOrMaker': 'maker',
466
+ 'price': priceString,
467
+ 'amount': amountString,
468
+ 'cost': this.safeString(trade, 'usd_amount'),
469
+ 'fee': {
470
+ 'cost': feeAmount,
471
+ 'currency': 'USDC',
472
+ },
473
+ }, market);
474
+ }
475
+ handleTrades(client, message) {
476
+ //
477
+ // {
478
+ // "channel": "trade:0",
479
+ // "liquidation_trades": [],
480
+ // "nonce": 3159738569,
481
+ // "trades": [
482
+ // {
483
+ // "trade_id": 526801155,
484
+ // "tx_hash": "1998d9df580acb7540aa141cc369d6ef926d003b3062196d2007bca15f978ab208e0caae4ac5872b",
485
+ // "type": "trade",
486
+ // "market_id": 0,
487
+ // "size": "0.0346",
488
+ // "price": "3028.85",
489
+ // "usd_amount": "104.798210",
490
+ // "ask_id": 281475673670566,
491
+ // "bid_id": 562949291740362,
492
+ // "ask_client_id": 76303170,
493
+ // "bid_client_id": 27601,
494
+ // "ask_account_id": 99349,
495
+ // "bid_account_id": 243008,
496
+ // "is_maker_ask": false,
497
+ // "block_height": 102322769,
498
+ // "timestamp": 1763623734215,
499
+ // "taker_position_size_before": "0.0346",
500
+ // "taker_entry_quote_before": "104.359926",
501
+ // "taker_initial_margin_fraction_before": 500,
502
+ // "taker_position_sign_changed": true,
503
+ // "maker_fee": 20,
504
+ // "maker_position_size_before": "2.1277",
505
+ // "maker_entry_quote_before": "6444.179555",
506
+ // "maker_initial_margin_fraction_before": 200
507
+ // }
508
+ // ],
509
+ // "type": "subscribed/trade"
510
+ // }
511
+ //
512
+ const liquidationData = this.safeList(message, 'liquidation_trades', []);
513
+ if (liquidationData.length > 0) {
514
+ this.handleLiquidation(client, message);
515
+ }
516
+ const data = this.safeList(message, 'trades', []);
517
+ const channel = this.safeString(message, 'channel', '');
518
+ const parts = channel.split(':');
519
+ const marketId = parts[1];
520
+ const market = this.safeMarket(marketId);
521
+ const symbol = market['symbol'];
522
+ let stored = this.safeValue(this.trades, symbol);
523
+ if (stored === undefined) {
524
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
525
+ stored = new Cache.ArrayCache(limit);
526
+ this.trades[symbol] = stored;
527
+ }
528
+ for (let i = 0; i < data.length; i++) {
529
+ const trade = this.parseWsTrade(data[i], market);
530
+ stored.append(trade);
531
+ }
532
+ const messageHash = this.getMessageHash('trade', symbol);
533
+ client.resolve(stored, messageHash);
534
+ }
535
+ /**
536
+ * @method
537
+ * @name lighter#watchTrades
538
+ * @description get the list of most recent trades for a particular symbol
539
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#trade
540
+ * @param {string} symbol unified symbol of the market to fetch trades for
541
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
542
+ * @param {int} [limit] the maximum amount of trades to fetch
543
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
544
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
545
+ */
546
+ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
547
+ await this.loadMarkets();
548
+ const market = this.market(symbol);
549
+ const request = {
550
+ 'channel': 'trade/' + market['id'],
551
+ };
552
+ const messageHash = this.getMessageHash('trade', symbol);
553
+ return await this.subscribePublic(messageHash, this.extend(request, params));
554
+ }
555
+ /**
556
+ * @method
557
+ * @name lighter#unWatchTrades
558
+ * @description unsubscribe from the trades channel
559
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#trade
560
+ * @param {string} symbol unified symbol of the market to fetch trades for
561
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
562
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
563
+ */
564
+ async unWatchTrades(symbol, params = {}) {
565
+ await this.loadMarkets();
566
+ const market = this.market(symbol);
567
+ const request = {
568
+ 'channel': 'trade/' + market['id'],
569
+ };
570
+ const messageHash = this.getMessageHash('unsubscribe', symbol);
571
+ return await this.unsubscribePublic(messageHash, this.extend(request, params));
572
+ }
573
+ parseWsLiquidation(liquidation, market = undefined) {
574
+ //
575
+ // {
576
+ // "trade_id": 526801155,
577
+ // "tx_hash": "1998d9df580acb7540aa141cc369d6ef926d003b3062196d2007bca15f978ab208e0caae4ac5872b",
578
+ // "type": "liquidation",
579
+ // "market_id": 0,
580
+ // "size": "0.0346",
581
+ // "price": "3028.85",
582
+ // "usd_amount": "104.798210",
583
+ // "ask_id": 281475673670566,
584
+ // "bid_id": 562949291740362,
585
+ // "ask_client_id": 76303170,
586
+ // "bid_client_id": 27601,
587
+ // "ask_account_id": 99349,
588
+ // "bid_account_id": 243008,
589
+ // "is_maker_ask": false,
590
+ // "block_height": 102322769,
591
+ // "timestamp": 1763623734215,
592
+ // "taker_position_size_before": "0.0346",
593
+ // "taker_entry_quote_before": "104.359926",
594
+ // "taker_initial_margin_fraction_before": 500,
595
+ // "taker_position_sign_changed": true,
596
+ // "maker_fee": 20,
597
+ // "maker_position_size_before": "2.1277",
598
+ // "maker_entry_quote_before": "6444.179555",
599
+ // "maker_initial_margin_fraction_before": 200
600
+ // }
601
+ //
602
+ const timestamp = this.safeInteger(liquidation, 'timestamp');
603
+ return this.safeLiquidation({
604
+ 'info': liquidation,
605
+ 'symbol': market['symbol'],
606
+ 'contracts': undefined,
607
+ 'contractSize': undefined,
608
+ 'price': this.safeString(liquidation, 'price'),
609
+ 'side': this.safeString(liquidation, 'size'),
610
+ 'baseValue': undefined,
611
+ 'quoteValue': undefined,
612
+ 'timestamp': timestamp,
613
+ 'datetime': this.iso8601(timestamp),
614
+ });
615
+ }
616
+ handleLiquidation(client, message) {
617
+ //
618
+ // {
619
+ // "channel": "trade:0",
620
+ // "liquidation_trades": [],
621
+ // "nonce": 3159738569,
622
+ // "trades": [
623
+ // {
624
+ // "trade_id": 526801155,
625
+ // "tx_hash": "1998d9df580acb7540aa141cc369d6ef926d003b3062196d2007bca15f978ab208e0caae4ac5872b",
626
+ // "type": "trade",
627
+ // "market_id": 0,
628
+ // "size": "0.0346",
629
+ // "price": "3028.85",
630
+ // "usd_amount": "104.798210",
631
+ // "ask_id": 281475673670566,
632
+ // "bid_id": 562949291740362,
633
+ // "ask_client_id": 76303170,
634
+ // "bid_client_id": 27601,
635
+ // "ask_account_id": 99349,
636
+ // "bid_account_id": 243008,
637
+ // "is_maker_ask": false,
638
+ // "block_height": 102322769,
639
+ // "timestamp": 1763623734215,
640
+ // "taker_position_size_before": "0.0346",
641
+ // "taker_entry_quote_before": "104.359926",
642
+ // "taker_initial_margin_fraction_before": 500,
643
+ // "taker_position_sign_changed": true,
644
+ // "maker_fee": 20,
645
+ // "maker_position_size_before": "2.1277",
646
+ // "maker_entry_quote_before": "6444.179555",
647
+ // "maker_initial_margin_fraction_before": 200
648
+ // }
649
+ // ],
650
+ // "type": "subscribed/trade"
651
+ // }
652
+ //
653
+ const data = this.safeList(message, 'liquidation_trades', []);
654
+ const channel = this.safeString(message, 'channel', '');
655
+ const parts = channel.split(':');
656
+ const marketId = parts[1];
657
+ const market = this.safeMarket(marketId);
658
+ const symbol = market['symbol'];
659
+ let stored = this.safeValue(this.liquidations, symbol);
660
+ if (stored === undefined) {
661
+ const limit = this.safeInteger(this.options, 'liquidationsLimit', 1000);
662
+ stored = new Cache.ArrayCache(limit);
663
+ this.liquidations[symbol] = stored;
664
+ }
665
+ for (let i = 0; i < data.length; i++) {
666
+ const liquidation = this.parseWsLiquidation(data[i], market);
667
+ stored.append(liquidation);
668
+ }
669
+ const messageHash = this.getMessageHash('liquidations', symbol);
670
+ client.resolve(stored, messageHash);
671
+ }
672
+ /**
673
+ * @method
674
+ * @name lighter#watchLiquidations
675
+ * @description watch the public liquidations of a trading pair
676
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#trade
677
+ * @param {string} symbol unified symbol of the market to fetch trades for
678
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
679
+ * @param {int} [limit] the maximum amount of trades to fetch
680
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
681
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
682
+ */
683
+ async watchLiquidations(symbol, since = undefined, limit = undefined, params = {}) {
684
+ await this.loadMarkets();
685
+ const market = this.market(symbol);
686
+ const request = {
687
+ 'channel': 'trade/' + market['id'],
688
+ };
689
+ const messageHash = this.getMessageHash('liquidations', symbol);
690
+ return await this.subscribePublic(messageHash, this.extend(request, params));
691
+ }
692
+ handleErrorMessage(client, message) {
693
+ //
694
+ // {
695
+ // "error": {
696
+ // "code": 30005,
697
+ // "message": "Invalid Channel: (marketId)"
698
+ // }
699
+ // }
700
+ //
701
+ const error = this.safeDict(message, 'error');
702
+ try {
703
+ if (error !== undefined) {
704
+ const code = this.safeString(message, 'code');
705
+ if (code !== undefined) {
706
+ const feedback = this.id + ' ' + this.json(message);
707
+ this.throwExactlyMatchedException(this.exceptions['exact'], code, feedback);
708
+ }
709
+ }
710
+ }
711
+ catch (e) {
712
+ client.reject(e);
713
+ }
714
+ return true;
715
+ }
716
+ handleMessage(client, message) {
717
+ if (!this.handleErrorMessage(client, message)) {
718
+ return;
719
+ }
720
+ const type = this.safeString(message, 'type', '');
721
+ if (type === 'ping') {
722
+ this.handlePing(client, message);
723
+ return;
724
+ }
725
+ const channel = this.safeString(message, 'channel', '');
726
+ if (channel.indexOf('order_book:') >= 0) {
727
+ this.handleOrderBook(client, message);
728
+ return;
729
+ }
730
+ if (channel.indexOf('market_stats:') >= 0) {
731
+ this.handleTicker(client, message);
732
+ return;
733
+ }
734
+ if (channel.indexOf('trade:') >= 0) {
735
+ this.handleTrades(client, message);
736
+ return;
737
+ }
738
+ if (channel === '') {
739
+ this.handleSubscriptionStatus(client, message);
740
+ }
741
+ }
742
+ handleSubscriptionStatus(client, message) {
743
+ //
744
+ // {
745
+ // "session_id": "8d354239-80e0-4b77-8763-87b6fef2f768",
746
+ // "type": "connected"
747
+ // }
748
+ //
749
+ // {
750
+ // "type": "unsubscribed",
751
+ // "channel": "order_book:0"
752
+ // }
753
+ //
754
+ const type = this.safeString(message, 'type', '');
755
+ const id = this.safeString(message, 'session_id');
756
+ const subscriptionsById = this.indexBy(client.subscriptions, 'id');
757
+ const subscription = this.safeDict(subscriptionsById, id, {});
758
+ if (type === 'unsubscribed') {
759
+ this.handleUnSubscription(client, subscription);
760
+ }
761
+ return message;
762
+ }
763
+ handleUnSubscription(client, subscription) {
764
+ const messageHashes = this.safeList(subscription, 'messageHashes', []);
765
+ const subMessageHashes = this.safeList(subscription, 'subMessageHashes', []);
766
+ for (let i = 0; i < messageHashes.length; i++) {
767
+ const unsubHash = messageHashes[i];
768
+ const subHash = subMessageHashes[i];
769
+ this.cleanUnsubscription(client, subHash, unsubHash);
770
+ }
771
+ this.cleanCache(subscription);
772
+ }
773
+ handlePing(client, message) {
774
+ //
775
+ // { "type": "ping" }
776
+ //
777
+ this.spawn(this.pong, client, message);
778
+ }
779
+ async pong(client, message) {
780
+ const request = {
781
+ 'type': 'pong',
782
+ };
783
+ await client.send(request);
784
+ }
785
+ }
786
+
787
+ exports["default"] = lighter;