@luxfi/dex 1.2.1

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.
@@ -0,0 +1,351 @@
1
+ /**
2
+ * Market data, liquidation, and settlement features for LX TypeScript SDK
3
+ */
4
+
5
+ import WebSocket from 'ws';
6
+
7
+ export interface MarketDataSource {
8
+ name: string;
9
+ symbol: string;
10
+ price: number;
11
+ bid: number;
12
+ ask: number;
13
+ volume: number;
14
+ latencyNs: number;
15
+ provider: string;
16
+ }
17
+
18
+ export interface LiquidationInfo {
19
+ userId: string;
20
+ positionId: string;
21
+ symbol: string;
22
+ size: number;
23
+ liquidationPrice: number;
24
+ markPrice: number;
25
+ status: string;
26
+ timestamp: Date;
27
+ }
28
+
29
+ export interface SettlementBatch {
30
+ batchId: number;
31
+ orderIds: number[];
32
+ status: string;
33
+ txHash?: string;
34
+ gasUsed?: number;
35
+ timestamp: Date;
36
+ }
37
+
38
+ export interface MarginInfo {
39
+ userId: string;
40
+ initialMargin: number;
41
+ maintenanceMargin: number;
42
+ marginRatio: number;
43
+ freeMargin: number;
44
+ marginLevel: number;
45
+ }
46
+
47
+ export interface InsuranceFundStatus {
48
+ totalFund: number;
49
+ availableFund: number;
50
+ usedFund: number;
51
+ pendingClaims: number;
52
+ lastUpdate: Date;
53
+ }
54
+
55
+ export interface MarketStats {
56
+ symbol: string;
57
+ volume24h: number;
58
+ high24h: number;
59
+ low24h: number;
60
+ priceChange24h: number;
61
+ priceChangePercent24h: number;
62
+ openInterest: number;
63
+ fundingRate: number;
64
+ nextFundingTime: Date;
65
+ }
66
+
67
+ export interface LiquidationRisk {
68
+ userId: string;
69
+ riskLevel: 'low' | 'medium' | 'high' | 'critical';
70
+ marginLevel: number;
71
+ liquidationPrice: number;
72
+ timeToLiquidation: number | null;
73
+ recommendations: string[];
74
+ }
75
+
76
+ export class MarketDataClient {
77
+ private jsonRpc: any;
78
+
79
+ constructor(jsonRpcClient: any) {
80
+ this.jsonRpc = jsonRpcClient;
81
+ }
82
+
83
+ /**
84
+ * Get market data from a specific source
85
+ */
86
+ async getMarketData(symbol: string, source: string): Promise<MarketDataSource> {
87
+ const result = await this.jsonRpc.call('market_data.get', {
88
+ symbol,
89
+ source
90
+ });
91
+
92
+ return {
93
+ name: result.name,
94
+ symbol: result.symbol,
95
+ price: result.price,
96
+ bid: result.bid,
97
+ ask: result.ask,
98
+ volume: result.volume,
99
+ latencyNs: result.latency_ns,
100
+ provider: result.provider
101
+ };
102
+ }
103
+
104
+ /**
105
+ * Get aggregated market data from all sources
106
+ */
107
+ async getAggregatedMarketData(symbol: string): Promise<MarketDataSource[]> {
108
+ const result = await this.jsonRpc.call('market_data.aggregate', {
109
+ symbol
110
+ });
111
+
112
+ return result.map((data: any) => ({
113
+ name: data.name,
114
+ symbol: data.symbol,
115
+ price: data.price,
116
+ bid: data.bid,
117
+ ask: data.ask,
118
+ volume: data.volume,
119
+ latencyNs: data.latency_ns,
120
+ provider: data.provider
121
+ }));
122
+ }
123
+
124
+ /**
125
+ * Get recent liquidations
126
+ */
127
+ async getLiquidations(symbol: string, limit: number = 100): Promise<LiquidationInfo[]> {
128
+ const result = await this.jsonRpc.call('liquidations.get', {
129
+ symbol,
130
+ limit
131
+ });
132
+
133
+ return result.map((liq: any) => ({
134
+ userId: liq.user_id,
135
+ positionId: liq.position_id,
136
+ symbol: liq.symbol,
137
+ size: liq.size,
138
+ liquidationPrice: liq.liquidation_price,
139
+ markPrice: liq.mark_price,
140
+ status: liq.status,
141
+ timestamp: new Date(liq.timestamp)
142
+ }));
143
+ }
144
+
145
+ /**
146
+ * Get settlement batch information
147
+ */
148
+ async getSettlementBatch(batchId: number): Promise<SettlementBatch> {
149
+ const result = await this.jsonRpc.call('settlement.batch', {
150
+ batch_id: batchId
151
+ });
152
+
153
+ return {
154
+ batchId: result.batch_id,
155
+ orderIds: result.order_ids,
156
+ status: result.status,
157
+ txHash: result.tx_hash,
158
+ gasUsed: result.gas_used,
159
+ timestamp: new Date(result.timestamp)
160
+ };
161
+ }
162
+
163
+ /**
164
+ * Get margin information for a user
165
+ */
166
+ async getMarginInfo(userId: string): Promise<MarginInfo> {
167
+ const result = await this.jsonRpc.call('margin.info', {
168
+ user_id: userId
169
+ });
170
+
171
+ return {
172
+ userId: result.user_id,
173
+ initialMargin: result.initial_margin,
174
+ maintenanceMargin: result.maintenance_margin,
175
+ marginRatio: result.margin_ratio,
176
+ freeMargin: result.free_margin,
177
+ marginLevel: result.margin_level
178
+ };
179
+ }
180
+
181
+ /**
182
+ * Check liquidation risk for a user
183
+ */
184
+ async checkLiquidationRisk(userId: string): Promise<LiquidationRisk> {
185
+ const result = await this.jsonRpc.call('margin.liquidation_risk', {
186
+ user_id: userId
187
+ });
188
+
189
+ return {
190
+ userId: result.user_id,
191
+ riskLevel: result.risk_level,
192
+ marginLevel: result.margin_level,
193
+ liquidationPrice: result.liquidation_price,
194
+ timeToLiquidation: result.time_to_liquidation,
195
+ recommendations: result.recommendations || []
196
+ };
197
+ }
198
+
199
+ /**
200
+ * Get insurance fund status
201
+ */
202
+ async getInsuranceFundStatus(): Promise<InsuranceFundStatus> {
203
+ const result = await this.jsonRpc.call('insurance_fund.status');
204
+
205
+ return {
206
+ totalFund: result.total_fund,
207
+ availableFund: result.available_fund,
208
+ usedFund: result.used_fund,
209
+ pendingClaims: result.pending_claims,
210
+ lastUpdate: new Date(result.last_update)
211
+ };
212
+ }
213
+
214
+ /**
215
+ * Get list of available market data sources
216
+ */
217
+ async getMarketDataSources(): Promise<string[]> {
218
+ return await this.jsonRpc.call('market_data.sources');
219
+ }
220
+
221
+ /**
222
+ * Get comprehensive market statistics
223
+ */
224
+ async getMarketStats(symbol: string): Promise<MarketStats> {
225
+ const result = await this.jsonRpc.call('market.stats', {
226
+ symbol
227
+ });
228
+
229
+ return {
230
+ symbol: result.symbol,
231
+ volume24h: result.volume_24h,
232
+ high24h: result.high_24h,
233
+ low24h: result.low_24h,
234
+ priceChange24h: result.price_change_24h,
235
+ priceChangePercent24h: result.price_change_percent_24h,
236
+ openInterest: result.open_interest,
237
+ fundingRate: result.funding_rate,
238
+ nextFundingTime: new Date(result.next_funding_time)
239
+ };
240
+ }
241
+ }
242
+
243
+ export class LiquidationMonitor {
244
+ private ws: WebSocket | null;
245
+ private callbacks: Map<string, Function[]> = new Map();
246
+
247
+ constructor(wsConnection: WebSocket | null) {
248
+ this.ws = wsConnection;
249
+ }
250
+
251
+ /**
252
+ * Set WebSocket connection
253
+ */
254
+ setWebSocket(ws: WebSocket): void {
255
+ this.ws = ws;
256
+ }
257
+
258
+ /**
259
+ * Subscribe to liquidation events
260
+ */
261
+ subscribeLiquidations(callback: (liquidation: LiquidationInfo) => void): void {
262
+ if (!this.callbacks.has('liquidations')) {
263
+ this.callbacks.set('liquidations', []);
264
+ }
265
+ this.callbacks.get('liquidations')!.push(callback);
266
+
267
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
268
+ this.ws.send(JSON.stringify({
269
+ type: 'subscribe',
270
+ channel: 'liquidations'
271
+ }));
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Subscribe to settlement events
277
+ */
278
+ subscribeSettlements(callback: (settlement: SettlementBatch) => void): void {
279
+ if (!this.callbacks.has('settlements')) {
280
+ this.callbacks.set('settlements', []);
281
+ }
282
+ this.callbacks.get('settlements')!.push(callback);
283
+
284
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
285
+ this.ws.send(JSON.stringify({
286
+ type: 'subscribe',
287
+ channel: 'settlements'
288
+ }));
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Subscribe to margin call events for a user
294
+ */
295
+ subscribeMarginCalls(userId: string, callback: (marginCall: any) => void): void {
296
+ const channel = `margin_calls:${userId}`;
297
+ if (!this.callbacks.has(channel)) {
298
+ this.callbacks.set(channel, []);
299
+ }
300
+ this.callbacks.get(channel)!.push(callback);
301
+
302
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
303
+ this.ws.send(JSON.stringify({
304
+ type: 'subscribe',
305
+ channel
306
+ }));
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Unsubscribe from a channel
312
+ */
313
+ unsubscribe(channel: string): void {
314
+ this.callbacks.delete(channel);
315
+
316
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
317
+ this.ws.send(JSON.stringify({
318
+ type: 'unsubscribe',
319
+ channel
320
+ }));
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Handle incoming message
326
+ */
327
+ handleMessage(channel: string, data: any): void {
328
+ const callbacks = this.callbacks.get(channel);
329
+ if (callbacks) {
330
+ callbacks.forEach(cb => cb(data));
331
+ }
332
+ }
333
+ }
334
+
335
+ /**
336
+ * Market data sources supported by LX
337
+ */
338
+ export const MarketDataProviders = {
339
+ ALPACA: 'alpaca',
340
+ NYSE_ARCA: 'nyse_arca',
341
+ IEX_CLOUD: 'iex',
342
+ POLYGON: 'polygon',
343
+ CME_GROUP: 'cme',
344
+ REFINITIV: 'refinitiv',
345
+ ICE_DATA: 'ice',
346
+ BLOOMBERG: 'bloomberg',
347
+ NASDAQ_TOTALVIEW: 'nasdaq',
348
+ COINBASE_PRO: 'coinbase'
349
+ } as const;
350
+
351
+ export type MarketDataProvider = typeof MarketDataProviders[keyof typeof MarketDataProviders];
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "lib": ["ES2020"],
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "outDir": "./dist",
9
+ "rootDir": "./src",
10
+ "strict": true,
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "resolveJsonModule": true,
15
+ "moduleResolution": "node"
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }