@luxfi/dex 1.3.0 → 2.0.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.
Files changed (37) hide show
  1. package/dist/hooks/index.d.ts +16 -1
  2. package/dist/hooks/index.d.ts.map +1 -1
  3. package/dist/hooks/index.js +20 -1
  4. package/dist/hooks/use-lxbook.d.ts +84 -0
  5. package/dist/hooks/use-lxbook.d.ts.map +1 -0
  6. package/dist/hooks/use-lxbook.js +213 -0
  7. package/dist/hooks/use-lxfeed.d.ts +42 -0
  8. package/dist/hooks/use-lxfeed.d.ts.map +1 -0
  9. package/dist/hooks/use-lxfeed.js +152 -0
  10. package/dist/hooks/use-lxvault.d.ts +75 -0
  11. package/dist/hooks/use-lxvault.d.ts.map +1 -0
  12. package/dist/hooks/use-lxvault.js +227 -0
  13. package/dist/index.d.ts +38 -21
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +57 -26
  16. package/dist/precompile/abis.d.ts +593 -2
  17. package/dist/precompile/abis.d.ts.map +1 -1
  18. package/dist/precompile/abis.js +458 -2
  19. package/dist/precompile/addresses.d.ts +89 -25
  20. package/dist/precompile/addresses.d.ts.map +1 -1
  21. package/dist/precompile/addresses.js +86 -21
  22. package/dist/precompile/index.d.ts +13 -2
  23. package/dist/precompile/index.d.ts.map +1 -1
  24. package/dist/precompile/index.js +13 -2
  25. package/dist/precompile/types.d.ts +171 -1
  26. package/dist/precompile/types.d.ts.map +1 -1
  27. package/dist/precompile/types.js +67 -0
  28. package/package.json +2 -2
  29. package/src/hooks/index.ts +24 -1
  30. package/src/hooks/use-lxbook.ts +343 -0
  31. package/src/hooks/use-lxfeed.ts +179 -0
  32. package/src/hooks/use-lxvault.ts +318 -0
  33. package/src/index.ts +92 -26
  34. package/src/precompile/abis.ts +466 -2
  35. package/src/precompile/addresses.ts +109 -28
  36. package/src/precompile/index.ts +13 -2
  37. package/src/precompile/types.ts +200 -1
@@ -0,0 +1,343 @@
1
+ /**
2
+ * LXBook Hooks (LP-9020)
3
+ * React hooks for CLOB trading via LXBook precompile
4
+ */
5
+ import { useCallback, useMemo } from 'react'
6
+ import { useReadContract, useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
7
+ import type { Address } from 'viem'
8
+ import { encodeFunctionData } from 'viem'
9
+ import { LX } from '../precompile/addresses'
10
+ import { LX_BOOK_ABI } from '../precompile/abis'
11
+ import {
12
+ type LXOrder,
13
+ type LXAction,
14
+ type LXPlaceResult,
15
+ type LXL1,
16
+ ActionType,
17
+ TIF,
18
+ OrderKind,
19
+ } from '../precompile/types'
20
+
21
+ /**
22
+ * Hook to get L1 (best bid/ask) for a market
23
+ */
24
+ export function useLXBookL1(marketId: number): any {
25
+ const { data, isLoading, error, refetch } = useReadContract({
26
+ address: LX.LX_BOOK,
27
+ abi: LX_BOOK_ABI,
28
+ functionName: 'getL1',
29
+ args: [marketId],
30
+ })
31
+
32
+ return {
33
+ l1: data as LXL1 | undefined,
34
+ isLoading,
35
+ error,
36
+ refetch,
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Hook to get market config
42
+ */
43
+ export function useLXBookMarket(marketId: number) {
44
+ const { data, isLoading, error } = useReadContract({
45
+ address: LX.LX_BOOK,
46
+ abi: LX_BOOK_ABI,
47
+ functionName: 'getMarketConfig',
48
+ args: [marketId],
49
+ })
50
+
51
+ return {
52
+ config: data,
53
+ isLoading,
54
+ error,
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Hook to get market status
60
+ */
61
+ export function useLXBookMarketStatus(marketId: number) {
62
+ const { data, isLoading, error } = useReadContract({
63
+ address: LX.LX_BOOK,
64
+ abi: LX_BOOK_ABI,
65
+ functionName: 'getMarketStatus',
66
+ args: [marketId],
67
+ })
68
+
69
+ return {
70
+ status: data as number | undefined,
71
+ isLoading,
72
+ error,
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Build action payload for execute()
78
+ */
79
+ function buildAction(
80
+ actionType: ActionType,
81
+ nonce: bigint,
82
+ expiresAfter: bigint,
83
+ data: `0x${string}`
84
+ ): LXAction {
85
+ return {
86
+ actionType,
87
+ nonce,
88
+ expiresAfter,
89
+ data,
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Encode order data for placement
95
+ */
96
+ function encodeOrderData(order: LXOrder): `0x${string}` {
97
+ // Pack order into bytes - this matches the Go/Solidity struct layout
98
+ const encoded = encodeFunctionData({
99
+ abi: [{
100
+ type: 'function',
101
+ name: 'encodeOrder',
102
+ inputs: [{
103
+ name: 'order',
104
+ type: 'tuple',
105
+ components: [
106
+ { name: 'marketId', type: 'uint32' },
107
+ { name: 'isBuy', type: 'bool' },
108
+ { name: 'kind', type: 'uint8' },
109
+ { name: 'sizeX18', type: 'uint128' },
110
+ { name: 'limitPxX18', type: 'uint128' },
111
+ { name: 'triggerPxX18', type: 'uint128' },
112
+ { name: 'reduceOnly', type: 'bool' },
113
+ { name: 'tif', type: 'uint8' },
114
+ { name: 'cloid', type: 'bytes16' },
115
+ { name: 'groupId', type: 'bytes16' },
116
+ { name: 'groupType', type: 'uint8' },
117
+ ],
118
+ }],
119
+ outputs: [],
120
+ stateMutability: 'pure',
121
+ }],
122
+ functionName: 'encodeOrder',
123
+ args: [order],
124
+ })
125
+ // Strip function selector (first 4 bytes)
126
+ return `0x${encoded.slice(10)}` as `0x${string}`
127
+ }
128
+
129
+ interface UseLXBookExecuteResult {
130
+ execute: (action: LXAction) => void
131
+ executeBatch: (actions: LXAction[]) => void
132
+ hash: `0x${string}` | undefined
133
+ isPending: boolean
134
+ isConfirming: boolean
135
+ isSuccess: boolean
136
+ error: Error | null
137
+ }
138
+
139
+ /**
140
+ * Hook for placing orders via LXBook execute()
141
+ */
142
+ export function useLXBookExecute(): UseLXBookExecuteResult {
143
+ const { writeContract, data: hash, isPending, error } = useWriteContract()
144
+ const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash })
145
+
146
+ const execute = useCallback(
147
+ (action: LXAction) => {
148
+ writeContract({
149
+ address: LX.LX_BOOK,
150
+ abi: LX_BOOK_ABI,
151
+ functionName: 'execute',
152
+ args: [action],
153
+ })
154
+ },
155
+ [writeContract]
156
+ )
157
+
158
+ const executeBatch = useCallback(
159
+ (actions: LXAction[]) => {
160
+ writeContract({
161
+ address: LX.LX_BOOK,
162
+ abi: LX_BOOK_ABI,
163
+ functionName: 'executeBatch',
164
+ args: [actions],
165
+ })
166
+ },
167
+ [writeContract]
168
+ )
169
+
170
+ return {
171
+ execute,
172
+ executeBatch,
173
+ hash,
174
+ isPending,
175
+ isConfirming,
176
+ isSuccess,
177
+ error,
178
+ }
179
+ }
180
+
181
+ interface UseLXBookPlaceOrderResult {
182
+ placeOrder: (params: {
183
+ marketId: number
184
+ isBuy: boolean
185
+ size: bigint
186
+ price: bigint
187
+ tif?: TIF
188
+ reduceOnly?: boolean
189
+ cloid?: `0x${string}`
190
+ }) => void
191
+ placeMarketOrder: (params: {
192
+ marketId: number
193
+ isBuy: boolean
194
+ size: bigint
195
+ reduceOnly?: boolean
196
+ }) => void
197
+ hash: `0x${string}` | undefined
198
+ isPending: boolean
199
+ isConfirming: boolean
200
+ isSuccess: boolean
201
+ error: Error | null
202
+ }
203
+
204
+ /**
205
+ * Hook for placing limit orders
206
+ */
207
+ export function useLXBookPlaceOrder(): UseLXBookPlaceOrderResult {
208
+ const { execute, hash, isPending, isConfirming, isSuccess, error } = useLXBookExecute()
209
+
210
+ const placeOrder = useCallback(
211
+ async (params: {
212
+ marketId: number
213
+ isBuy: boolean
214
+ size: bigint
215
+ price: bigint
216
+ tif?: TIF
217
+ reduceOnly?: boolean
218
+ cloid?: `0x${string}`
219
+ }) => {
220
+ const order: LXOrder = {
221
+ marketId: params.marketId,
222
+ isBuy: params.isBuy,
223
+ kind: OrderKind.LIMIT,
224
+ sizeX18: params.size,
225
+ limitPxX18: params.price,
226
+ triggerPxX18: 0n,
227
+ reduceOnly: params.reduceOnly ?? false,
228
+ tif: params.tif ?? TIF.GTC,
229
+ cloid: params.cloid ?? '0x00000000000000000000000000000000',
230
+ groupId: '0x00000000000000000000000000000000',
231
+ groupType: 0,
232
+ }
233
+
234
+ const action = buildAction(
235
+ ActionType.PLACE,
236
+ BigInt(Date.now()),
237
+ BigInt(Math.floor(Date.now() / 1000) + 300), // 5 min expiry
238
+ encodeOrderData(order)
239
+ )
240
+
241
+ return execute(action)
242
+ },
243
+ [execute]
244
+ )
245
+
246
+ const placeMarketOrder = useCallback(
247
+ async (params: {
248
+ marketId: number
249
+ isBuy: boolean
250
+ size: bigint
251
+ reduceOnly?: boolean
252
+ }) => {
253
+ const order: LXOrder = {
254
+ marketId: params.marketId,
255
+ isBuy: params.isBuy,
256
+ kind: OrderKind.MARKET,
257
+ sizeX18: params.size,
258
+ limitPxX18: 0n, // Market order - no limit
259
+ triggerPxX18: 0n,
260
+ reduceOnly: params.reduceOnly ?? false,
261
+ tif: TIF.IOC,
262
+ cloid: '0x00000000000000000000000000000000',
263
+ groupId: '0x00000000000000000000000000000000',
264
+ groupType: 0,
265
+ }
266
+
267
+ const action = buildAction(
268
+ ActionType.PLACE,
269
+ BigInt(Date.now()),
270
+ BigInt(Math.floor(Date.now() / 1000) + 60), // 1 min expiry for market
271
+ encodeOrderData(order)
272
+ )
273
+
274
+ return execute(action)
275
+ },
276
+ [execute]
277
+ )
278
+
279
+ return {
280
+ placeOrder,
281
+ placeMarketOrder,
282
+ hash,
283
+ isPending,
284
+ isConfirming,
285
+ isSuccess,
286
+ error,
287
+ }
288
+ }
289
+
290
+ interface UseLXBookCancelOrderResult {
291
+ cancelByOid: (oid: bigint) => void
292
+ cancelByCloid: (cloid: `0x${string}`) => void
293
+ hash: `0x${string}` | undefined
294
+ isPending: boolean
295
+ isConfirming: boolean
296
+ isSuccess: boolean
297
+ error: Error | null
298
+ }
299
+
300
+ /**
301
+ * Hook for canceling orders
302
+ */
303
+ export function useLXBookCancelOrder(): UseLXBookCancelOrderResult {
304
+ const { execute, hash, isPending, isConfirming, isSuccess, error } = useLXBookExecute()
305
+
306
+ const cancelByOid = useCallback(
307
+ async (oid: bigint) => {
308
+ // Encode oid as bytes
309
+ const data = `0x${oid.toString(16).padStart(64, '0')}` as `0x${string}`
310
+ const action = buildAction(
311
+ ActionType.CANCEL,
312
+ BigInt(Date.now()),
313
+ BigInt(Math.floor(Date.now() / 1000) + 60),
314
+ data
315
+ )
316
+ return execute(action)
317
+ },
318
+ [execute]
319
+ )
320
+
321
+ const cancelByCloid = useCallback(
322
+ async (cloid: `0x${string}`) => {
323
+ const action = buildAction(
324
+ ActionType.CANCEL_BY_CLOID,
325
+ BigInt(Date.now()),
326
+ BigInt(Math.floor(Date.now() / 1000) + 60),
327
+ cloid
328
+ )
329
+ return execute(action)
330
+ },
331
+ [execute]
332
+ )
333
+
334
+ return {
335
+ cancelByOid,
336
+ cancelByCloid,
337
+ hash,
338
+ isPending,
339
+ isConfirming,
340
+ isSuccess,
341
+ error,
342
+ }
343
+ }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * LXFeed Hooks (LP-9040)
3
+ * React hooks for price feeds, mark price, and funding rates
4
+ */
5
+ import { useReadContract } from 'wagmi'
6
+ import type { Address } from 'viem'
7
+ import { LX } from '../precompile/addresses'
8
+ import { LX_FEED_ABI, LX_ORACLE_ABI } from '../precompile/abis'
9
+ import type { LXMarkPrice, LXFundingRate } from '../precompile/types'
10
+
11
+ /**
12
+ * Hook to get mark price for a market
13
+ */
14
+ export function useLXFeedMarkPrice(marketId: number): any {
15
+ const { data, isLoading, error, refetch } = useReadContract({
16
+ address: LX.LX_FEED,
17
+ abi: LX_FEED_ABI,
18
+ functionName: 'getMarkPrice',
19
+ args: [marketId],
20
+ })
21
+
22
+ return {
23
+ markPrice: data as LXMarkPrice | undefined,
24
+ isLoading,
25
+ error,
26
+ refetch,
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Hook to get index price for a market
32
+ */
33
+ export function useLXFeedIndexPrice(marketId: number): any {
34
+ const { data, isLoading, error, refetch } = useReadContract({
35
+ address: LX.LX_FEED,
36
+ abi: LX_FEED_ABI,
37
+ functionName: 'getIndexPrice',
38
+ args: [marketId],
39
+ })
40
+
41
+ const result = data as [bigint, bigint] | undefined
42
+
43
+ return {
44
+ priceX18: result?.[0],
45
+ timestamp: result?.[1],
46
+ isLoading,
47
+ error,
48
+ refetch,
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Hook to get funding rate for a market
54
+ */
55
+ export function useLXFeedFundingRate(marketId: number): any {
56
+ const { data, isLoading, error, refetch } = useReadContract({
57
+ address: LX.LX_FEED,
58
+ abi: LX_FEED_ABI,
59
+ functionName: 'getFundingRate',
60
+ args: [marketId],
61
+ })
62
+
63
+ const result = data as [bigint, bigint] | undefined
64
+
65
+ return {
66
+ rateX18: result?.[0],
67
+ nextFundingTime: result?.[1],
68
+ isLoading,
69
+ error,
70
+ refetch,
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Hook to get trigger price for stop/take orders
76
+ */
77
+ export function useLXFeedTriggerPrice(marketId: number, isBuy: boolean): any {
78
+ const { data, isLoading, error, refetch } = useReadContract({
79
+ address: LX.LX_FEED,
80
+ abi: LX_FEED_ABI,
81
+ functionName: 'getTriggerPrice',
82
+ args: [marketId, isBuy],
83
+ })
84
+
85
+ return {
86
+ triggerPriceX18: data as bigint | undefined,
87
+ isLoading,
88
+ error,
89
+ refetch,
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Hook to get oracle price for token pair
95
+ */
96
+ export function useLXOraclePrice(baseToken: Address, quoteToken: Address): any {
97
+ const { data, isLoading, error, refetch } = useReadContract({
98
+ address: LX.LX_ORACLE,
99
+ abi: LX_ORACLE_ABI,
100
+ functionName: 'getPrice',
101
+ args: [baseToken, quoteToken],
102
+ })
103
+
104
+ return {
105
+ price: data,
106
+ isLoading,
107
+ error,
108
+ refetch,
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Hook to get aggregated oracle price with deviation info
114
+ */
115
+ export function useLXOracleAggregatedPrice(
116
+ baseToken: Address,
117
+ quoteToken: Address,
118
+ maxStaleness: bigint = 3600n // 1 hour default
119
+ ): any {
120
+ const { data, isLoading, error, refetch } = useReadContract({
121
+ address: LX.LX_ORACLE,
122
+ abi: LX_ORACLE_ABI,
123
+ functionName: 'getAggregatedPrice',
124
+ args: [baseToken, quoteToken, maxStaleness],
125
+ })
126
+
127
+ return {
128
+ aggregated: data,
129
+ isLoading,
130
+ error,
131
+ refetch,
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Hook to check if oracle price is fresh
137
+ */
138
+ export function useLXOraclePriceFresh(
139
+ baseToken: Address,
140
+ quoteToken: Address,
141
+ maxStaleness: bigint = 3600n
142
+ ): any {
143
+ const { data, isLoading, error, refetch } = useReadContract({
144
+ address: LX.LX_ORACLE,
145
+ abi: LX_ORACLE_ABI,
146
+ functionName: 'isPriceFresh',
147
+ args: [baseToken, quoteToken, maxStaleness],
148
+ })
149
+
150
+ return {
151
+ isFresh: data as boolean | undefined,
152
+ isLoading,
153
+ error,
154
+ refetch,
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Combined hook for market price data
160
+ */
161
+ export function useLXMarketPrices(marketId: number) {
162
+ const mark = useLXFeedMarkPrice(marketId)
163
+ const index = useLXFeedIndexPrice(marketId)
164
+ const funding = useLXFeedFundingRate(marketId)
165
+
166
+ return {
167
+ markPrice: mark.markPrice,
168
+ indexPrice: index.priceX18,
169
+ fundingRate: funding.rateX18,
170
+ nextFundingTime: funding.nextFundingTime,
171
+ isLoading: mark.isLoading || index.isLoading || funding.isLoading,
172
+ error: mark.error || index.error || funding.error,
173
+ refetch: () => {
174
+ mark.refetch()
175
+ index.refetch()
176
+ funding.refetch()
177
+ },
178
+ }
179
+ }