@luxfi/dex 1.2.1 → 2.0.0
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.
- package/dist/client/clob.d.ts +52 -0
- package/dist/client/clob.d.ts.map +1 -0
- package/dist/client/clob.js +196 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +6 -0
- package/dist/client/types.d.ts +126 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +5 -0
- package/dist/hooks/index.d.ts +22 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +25 -0
- package/dist/hooks/use-lxbook.d.ts +95 -0
- package/dist/hooks/use-lxbook.d.ts.map +1 -0
- package/dist/hooks/use-lxbook.js +213 -0
- package/dist/hooks/use-lxfeed.d.ts +111 -0
- package/dist/hooks/use-lxfeed.d.ts.map +1 -0
- package/dist/hooks/use-lxfeed.js +152 -0
- package/dist/hooks/use-lxvault.d.ts +137 -0
- package/dist/hooks/use-lxvault.d.ts.map +1 -0
- package/dist/hooks/use-lxvault.js +227 -0
- package/dist/hooks/use-quote.d.ts +18 -0
- package/dist/hooks/use-quote.d.ts.map +1 -0
- package/dist/hooks/use-quote.js +65 -0
- package/dist/hooks/use-swap.d.ts +17 -0
- package/dist/hooks/use-swap.d.ts.map +1 -0
- package/dist/hooks/use-swap.js +75 -0
- package/dist/index.d.ts +50 -115
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +72 -225
- package/dist/precompile/abis.d.ts +991 -0
- package/dist/precompile/abis.d.ts.map +1 -0
- package/dist/precompile/abis.js +743 -0
- package/dist/precompile/addresses.d.ts +129 -0
- package/dist/precompile/addresses.d.ts.map +1 -0
- package/dist/precompile/addresses.js +117 -0
- package/dist/precompile/index.d.ts +19 -0
- package/dist/precompile/index.d.ts.map +1 -0
- package/dist/precompile/index.js +18 -0
- package/dist/precompile/types.d.ts +246 -0
- package/dist/precompile/types.d.ts.map +1 -0
- package/dist/precompile/types.js +84 -0
- package/dist/router/index.d.ts +7 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +6 -0
- package/dist/router/router.d.ts +58 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +272 -0
- package/dist/router/types.d.ts +76 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +1 -0
- package/package.json +55 -29
- package/src/client/clob.ts +256 -0
- package/src/client/index.ts +6 -0
- package/src/client/types.ts +148 -0
- package/src/hooks/index.ts +29 -0
- package/src/hooks/use-lxbook.ts +343 -0
- package/src/hooks/use-lxfeed.ts +179 -0
- package/src/hooks/use-lxvault.ts +318 -0
- package/src/hooks/use-quote.ts +92 -0
- package/src/hooks/use-swap.ts +103 -0
- package/src/index.ts +142 -309
- package/src/precompile/abis.ts +755 -0
- package/src/precompile/addresses.ts +153 -0
- package/src/precompile/index.ts +18 -0
- package/src/precompile/types.ts +295 -0
- package/src/router/index.ts +6 -0
- package/src/router/router.ts +338 -0
- package/src/router/types.ts +87 -0
- package/dist/marketData.d.ts +0 -152
- package/dist/marketData.d.ts.map +0 -1
- package/dist/marketData.js +0 -253
- package/src/marketData.ts +0 -351
- package/tsconfig.json +0 -19
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLOB Client
|
|
3
|
+
* WebSocket client for lux/dex order book
|
|
4
|
+
*/
|
|
5
|
+
import type {
|
|
6
|
+
ICLOBClient,
|
|
7
|
+
OrderRequest,
|
|
8
|
+
Order,
|
|
9
|
+
OrderBook,
|
|
10
|
+
Trade,
|
|
11
|
+
Position,
|
|
12
|
+
Balance
|
|
13
|
+
} from './types'
|
|
14
|
+
|
|
15
|
+
interface CLOBClientOptions {
|
|
16
|
+
url: string
|
|
17
|
+
debug?: boolean
|
|
18
|
+
reconnect?: boolean
|
|
19
|
+
reconnectInterval?: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type MessageHandler = (data: any) => void
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Central Limit Order Book client
|
|
26
|
+
* Connects to lux/dex WebSocket server
|
|
27
|
+
*/
|
|
28
|
+
export class CLOBClient implements ICLOBClient {
|
|
29
|
+
private ws: WebSocket | null = null
|
|
30
|
+
private url: string
|
|
31
|
+
private debug: boolean
|
|
32
|
+
private reconnect: boolean
|
|
33
|
+
private reconnectInterval: number
|
|
34
|
+
private connected: boolean = false
|
|
35
|
+
private authenticated: boolean = false
|
|
36
|
+
private requestId: number = 0
|
|
37
|
+
private pendingRequests: Map<number, { resolve: Function; reject: Function }> = new Map()
|
|
38
|
+
private subscriptions: Map<string, Set<MessageHandler>> = new Map()
|
|
39
|
+
|
|
40
|
+
constructor(options: CLOBClientOptions) {
|
|
41
|
+
this.url = options.url
|
|
42
|
+
this.debug = options.debug ?? false
|
|
43
|
+
this.reconnect = options.reconnect ?? true
|
|
44
|
+
this.reconnectInterval = options.reconnectInterval ?? 5000
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private log(...args: any[]) {
|
|
48
|
+
if (this.debug) {
|
|
49
|
+
console.log('[CLOBClient]', ...args)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async connect(): Promise<void> {
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
try {
|
|
56
|
+
this.ws = new WebSocket(this.url)
|
|
57
|
+
|
|
58
|
+
this.ws.onopen = () => {
|
|
59
|
+
this.connected = true
|
|
60
|
+
this.log('Connected to', this.url)
|
|
61
|
+
resolve()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this.ws.onclose = () => {
|
|
65
|
+
this.connected = false
|
|
66
|
+
this.authenticated = false
|
|
67
|
+
this.log('Disconnected')
|
|
68
|
+
|
|
69
|
+
if (this.reconnect) {
|
|
70
|
+
setTimeout(() => this.connect(), this.reconnectInterval)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
this.ws.onerror = (error) => {
|
|
75
|
+
this.log('Error:', error)
|
|
76
|
+
reject(error)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this.ws.onmessage = (event) => {
|
|
80
|
+
this.handleMessage(event.data)
|
|
81
|
+
}
|
|
82
|
+
} catch (error) {
|
|
83
|
+
reject(error)
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async disconnect(): Promise<void> {
|
|
89
|
+
this.reconnect = false
|
|
90
|
+
this.ws?.close()
|
|
91
|
+
this.ws = null
|
|
92
|
+
this.connected = false
|
|
93
|
+
this.authenticated = false
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
isConnected(): boolean {
|
|
97
|
+
return this.connected
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private handleMessage(data: string) {
|
|
101
|
+
try {
|
|
102
|
+
const message = JSON.parse(data)
|
|
103
|
+
this.log('Received:', message)
|
|
104
|
+
|
|
105
|
+
// Handle response to request
|
|
106
|
+
if (message.id && this.pendingRequests.has(message.id)) {
|
|
107
|
+
const { resolve, reject } = this.pendingRequests.get(message.id)!
|
|
108
|
+
this.pendingRequests.delete(message.id)
|
|
109
|
+
|
|
110
|
+
if (message.error) {
|
|
111
|
+
reject(new Error(message.error))
|
|
112
|
+
} else {
|
|
113
|
+
resolve(message.result || message)
|
|
114
|
+
}
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Handle subscription updates
|
|
119
|
+
const type = message.type || message.channel
|
|
120
|
+
if (type && this.subscriptions.has(type)) {
|
|
121
|
+
this.subscriptions.get(type)!.forEach(handler => handler(message))
|
|
122
|
+
}
|
|
123
|
+
} catch (error) {
|
|
124
|
+
this.log('Parse error:', error)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private async request<T>(method: string, params?: any): Promise<T> {
|
|
129
|
+
if (!this.connected) {
|
|
130
|
+
throw new Error('Not connected')
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const id = ++this.requestId
|
|
134
|
+
const message = {
|
|
135
|
+
jsonrpc: '2.0',
|
|
136
|
+
id,
|
|
137
|
+
method,
|
|
138
|
+
params,
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return new Promise((resolve, reject) => {
|
|
142
|
+
this.pendingRequests.set(id, { resolve, reject })
|
|
143
|
+
this.ws!.send(JSON.stringify(message))
|
|
144
|
+
this.log('Sent:', message)
|
|
145
|
+
|
|
146
|
+
// Timeout after 30 seconds
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
if (this.pendingRequests.has(id)) {
|
|
149
|
+
this.pendingRequests.delete(id)
|
|
150
|
+
reject(new Error('Request timeout'))
|
|
151
|
+
}
|
|
152
|
+
}, 30000)
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async authenticate(apiKey: string, apiSecret: string): Promise<void> {
|
|
157
|
+
await this.request('authenticate', { apiKey, apiSecret })
|
|
158
|
+
this.authenticated = true
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async placeOrder(order: OrderRequest): Promise<Order> {
|
|
162
|
+
return this.request('placeOrder', order)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async cancelOrder(orderId: string): Promise<void> {
|
|
166
|
+
await this.request('cancelOrder', { orderId })
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async getOrder(orderId: string): Promise<Order> {
|
|
170
|
+
return this.request('getOrder', { orderId })
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async getOrders(symbol?: string): Promise<Order[]> {
|
|
174
|
+
return this.request('getOrders', { symbol })
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async getOrderBook(symbol: string, depth: number = 20): Promise<OrderBook> {
|
|
178
|
+
return this.request('getOrderBook', { symbol, depth })
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async getTrades(symbol: string, limit: number = 100): Promise<Trade[]> {
|
|
182
|
+
return this.request('getTrades', { symbol, limit })
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async getPositions(): Promise<Position[]> {
|
|
186
|
+
return this.request('getPositions', {})
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async getBalances(): Promise<Balance[]> {
|
|
190
|
+
return this.request('getBalances', {})
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
subscribeOrderBook(symbol: string, callback: (book: OrderBook) => void): () => void {
|
|
194
|
+
const channel = `orderbook:${symbol}`
|
|
195
|
+
|
|
196
|
+
if (!this.subscriptions.has(channel)) {
|
|
197
|
+
this.subscriptions.set(channel, new Set())
|
|
198
|
+
this.request('subscribe', { channel: 'orderbook', symbol }).catch(console.error)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
this.subscriptions.get(channel)!.add(callback)
|
|
202
|
+
|
|
203
|
+
return () => {
|
|
204
|
+
this.subscriptions.get(channel)?.delete(callback)
|
|
205
|
+
if (this.subscriptions.get(channel)?.size === 0) {
|
|
206
|
+
this.subscriptions.delete(channel)
|
|
207
|
+
this.request('unsubscribe', { channel: 'orderbook', symbol }).catch(console.error)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
subscribeTrades(symbol: string, callback: (trade: Trade) => void): () => void {
|
|
213
|
+
const channel = `trades:${symbol}`
|
|
214
|
+
|
|
215
|
+
if (!this.subscriptions.has(channel)) {
|
|
216
|
+
this.subscriptions.set(channel, new Set())
|
|
217
|
+
this.request('subscribe', { channel: 'trades', symbol }).catch(console.error)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
this.subscriptions.get(channel)!.add(callback)
|
|
221
|
+
|
|
222
|
+
return () => {
|
|
223
|
+
this.subscriptions.get(channel)?.delete(callback)
|
|
224
|
+
if (this.subscriptions.get(channel)?.size === 0) {
|
|
225
|
+
this.subscriptions.delete(channel)
|
|
226
|
+
this.request('unsubscribe', { channel: 'trades', symbol }).catch(console.error)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
subscribeOrders(callback: (order: Order) => void): () => void {
|
|
232
|
+
const channel = 'orders'
|
|
233
|
+
|
|
234
|
+
if (!this.subscriptions.has(channel)) {
|
|
235
|
+
this.subscriptions.set(channel, new Set())
|
|
236
|
+
this.request('subscribe', { channel: 'orders' }).catch(console.error)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
this.subscriptions.get(channel)!.add(callback)
|
|
240
|
+
|
|
241
|
+
return () => {
|
|
242
|
+
this.subscriptions.get(channel)?.delete(callback)
|
|
243
|
+
if (this.subscriptions.get(channel)?.size === 0) {
|
|
244
|
+
this.subscriptions.delete(channel)
|
|
245
|
+
this.request('unsubscribe', { channel: 'orders' }).catch(console.error)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Create a CLOB client
|
|
253
|
+
*/
|
|
254
|
+
export function createCLOBClient(url: string, debug: boolean = false): ICLOBClient {
|
|
255
|
+
return new CLOBClient({ url, debug })
|
|
256
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLOB Client Types
|
|
3
|
+
* Interfaces for Central Limit Order Book operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Order side
|
|
8
|
+
*/
|
|
9
|
+
export type OrderSide = 'buy' | 'sell'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Order type
|
|
13
|
+
*/
|
|
14
|
+
export type OrderType = 'limit' | 'market' | 'stop' | 'stop_limit'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Order status
|
|
18
|
+
*/
|
|
19
|
+
export type OrderStatus = 'pending' | 'open' | 'partial' | 'filled' | 'cancelled' | 'rejected'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Time in force
|
|
23
|
+
*/
|
|
24
|
+
export type TimeInForce = 'GTC' | 'IOC' | 'FOK' | 'GTD'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Order request
|
|
28
|
+
*/
|
|
29
|
+
export interface OrderRequest {
|
|
30
|
+
symbol: string
|
|
31
|
+
side: OrderSide
|
|
32
|
+
type: OrderType
|
|
33
|
+
price?: number // Required for limit orders
|
|
34
|
+
size: number
|
|
35
|
+
timeInForce?: TimeInForce
|
|
36
|
+
clientOrderId?: string
|
|
37
|
+
reduceOnly?: boolean
|
|
38
|
+
postOnly?: boolean
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Order response
|
|
43
|
+
*/
|
|
44
|
+
export interface Order {
|
|
45
|
+
orderId: string
|
|
46
|
+
clientOrderId?: string
|
|
47
|
+
symbol: string
|
|
48
|
+
side: OrderSide
|
|
49
|
+
type: OrderType
|
|
50
|
+
price: number
|
|
51
|
+
size: number
|
|
52
|
+
filledSize: number
|
|
53
|
+
remainingSize: number
|
|
54
|
+
status: OrderStatus
|
|
55
|
+
timeInForce: TimeInForce
|
|
56
|
+
createdAt: number
|
|
57
|
+
updatedAt: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Order book entry
|
|
62
|
+
*/
|
|
63
|
+
export interface OrderBookEntry {
|
|
64
|
+
price: number
|
|
65
|
+
size: number
|
|
66
|
+
count: number
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Order book
|
|
71
|
+
*/
|
|
72
|
+
export interface OrderBook {
|
|
73
|
+
symbol: string
|
|
74
|
+
bids: OrderBookEntry[]
|
|
75
|
+
asks: OrderBookEntry[]
|
|
76
|
+
timestamp: number
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Trade
|
|
81
|
+
*/
|
|
82
|
+
export interface Trade {
|
|
83
|
+
tradeId: string
|
|
84
|
+
symbol: string
|
|
85
|
+
side: OrderSide
|
|
86
|
+
price: number
|
|
87
|
+
size: number
|
|
88
|
+
timestamp: number
|
|
89
|
+
makerOrderId: string
|
|
90
|
+
takerOrderId: string
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Position
|
|
95
|
+
*/
|
|
96
|
+
export interface Position {
|
|
97
|
+
symbol: string
|
|
98
|
+
side: 'long' | 'short'
|
|
99
|
+
size: number
|
|
100
|
+
entryPrice: number
|
|
101
|
+
markPrice: number
|
|
102
|
+
liquidationPrice: number
|
|
103
|
+
unrealizedPnl: number
|
|
104
|
+
margin: number
|
|
105
|
+
leverage: number
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Balance
|
|
110
|
+
*/
|
|
111
|
+
export interface Balance {
|
|
112
|
+
currency: string
|
|
113
|
+
available: number
|
|
114
|
+
locked: number
|
|
115
|
+
total: number
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* CLOB client interface
|
|
120
|
+
*/
|
|
121
|
+
export interface ICLOBClient {
|
|
122
|
+
// Connection
|
|
123
|
+
connect(): Promise<void>
|
|
124
|
+
disconnect(): Promise<void>
|
|
125
|
+
isConnected(): boolean
|
|
126
|
+
|
|
127
|
+
// Authentication
|
|
128
|
+
authenticate(apiKey: string, apiSecret: string): Promise<void>
|
|
129
|
+
|
|
130
|
+
// Orders
|
|
131
|
+
placeOrder(order: OrderRequest): Promise<Order>
|
|
132
|
+
cancelOrder(orderId: string): Promise<void>
|
|
133
|
+
getOrder(orderId: string): Promise<Order>
|
|
134
|
+
getOrders(symbol?: string): Promise<Order[]>
|
|
135
|
+
|
|
136
|
+
// Market data
|
|
137
|
+
getOrderBook(symbol: string, depth?: number): Promise<OrderBook>
|
|
138
|
+
getTrades(symbol: string, limit?: number): Promise<Trade[]>
|
|
139
|
+
|
|
140
|
+
// Account
|
|
141
|
+
getPositions(): Promise<Position[]>
|
|
142
|
+
getBalances(): Promise<Balance[]>
|
|
143
|
+
|
|
144
|
+
// Subscriptions
|
|
145
|
+
subscribeOrderBook(symbol: string, callback: (book: OrderBook) => void): () => void
|
|
146
|
+
subscribeTrades(symbol: string, callback: (trade: Trade) => void): () => void
|
|
147
|
+
subscribeOrders(callback: (order: Order) => void): () => void
|
|
148
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LX Hooks Exports
|
|
3
|
+
* React hooks for DEX integration
|
|
4
|
+
*
|
|
5
|
+
* AMM (LP-9010):
|
|
6
|
+
* - useQuote, useSwap
|
|
7
|
+
*
|
|
8
|
+
* CLOB (LP-9020):
|
|
9
|
+
* - useLXBookL1, useLXBookPlaceOrder, useLXBookCancelOrder
|
|
10
|
+
*
|
|
11
|
+
* Vault (LP-9030):
|
|
12
|
+
* - useLXVault, useLXVaultPosition, useLXVaultMargin
|
|
13
|
+
*
|
|
14
|
+
* Feeds (LP-9040):
|
|
15
|
+
* - useLXFeedMarkPrice, useLXFeedFundingRate, useLXMarketPrices
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// AMM hooks
|
|
19
|
+
export * from './use-quote'
|
|
20
|
+
export * from './use-swap'
|
|
21
|
+
|
|
22
|
+
// LXBook hooks (LP-9020) - CLOB trading
|
|
23
|
+
export * from './use-lxbook'
|
|
24
|
+
|
|
25
|
+
// LXVault hooks (LP-9030) - Custody and margin
|
|
26
|
+
export * from './use-lxvault'
|
|
27
|
+
|
|
28
|
+
// LXFeed hooks (LP-9040) - Price feeds
|
|
29
|
+
export * from './use-lxfeed'
|