@lifi/perps-sdk-provider-lighter 7.0.0 → 8.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.
- package/dist/cjs/LighterProvider.d.ts.map +1 -1
- package/dist/cjs/LighterProvider.js +60 -27
- package/dist/cjs/LighterProvider.js.map +1 -1
- package/dist/cjs/accountSummary.d.ts.map +1 -1
- package/dist/cjs/accountSummary.js +33 -2
- package/dist/cjs/accountSummary.js.map +1 -1
- package/dist/cjs/constants.d.ts.map +1 -1
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/signers/LighterKeyStore.d.ts.map +1 -1
- package/dist/cjs/signers/LighterKeyStore.js.map +1 -1
- package/dist/cjs/signers/LighterReadOnlyTokenManager.d.ts.map +1 -1
- package/dist/cjs/signers/LighterReadOnlyTokenManager.js.map +1 -1
- package/dist/cjs/signers/LighterSigner.d.ts.map +1 -1
- package/dist/cjs/signers/LighterSigner.js.map +1 -1
- package/dist/cjs/signers/createAuthToken.d.ts.map +1 -1
- package/dist/cjs/signers/createAuthToken.js.map +1 -1
- package/dist/cjs/signers/wasmLoader.d.ts.map +1 -1
- package/dist/cjs/signers/wasmLoader.js.map +1 -1
- package/dist/cjs/types/account.d.ts +1 -0
- package/dist/cjs/types/account.d.ts.map +1 -1
- package/dist/cjs/types/action.d.ts.map +1 -1
- package/dist/cjs/types/action.js.map +1 -1
- package/dist/cjs/types/activity.d.ts.map +1 -1
- package/dist/cjs/types/asset.d.ts.map +1 -1
- package/dist/cjs/types/fill.d.ts.map +1 -1
- package/dist/cjs/types/order.d.ts.map +1 -1
- package/dist/cjs/types/submit.d.ts.map +1 -1
- package/dist/cjs/types/ws.d.ts +5 -0
- package/dist/cjs/types/ws.d.ts.map +1 -1
- package/dist/cjs/utils/decimal.d.ts +5 -0
- package/dist/cjs/utils/decimal.d.ts.map +1 -0
- package/dist/cjs/utils/decimal.js +38 -0
- package/dist/cjs/utils/decimal.js.map +1 -0
- package/dist/cjs/utils/index.d.ts +3 -1
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +7 -1
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/lighterAsset.d.ts.map +1 -1
- package/dist/cjs/utils/lighterAsset.js.map +1 -1
- package/dist/cjs/utils/mapOpenPositions.d.ts +2 -2
- package/dist/cjs/utils/mapOpenPositions.d.ts.map +1 -1
- package/dist/cjs/utils/mapOpenPositions.js.map +1 -1
- package/dist/cjs/utils/mapPosition.d.ts +3 -2
- package/dist/cjs/utils/mapPosition.d.ts.map +1 -1
- package/dist/cjs/utils/mapPosition.js +30 -9
- package/dist/cjs/utils/mapPosition.js.map +1 -1
- package/dist/cjs/utils/ohlcvInterval.d.ts.map +1 -1
- package/dist/cjs/utils/ohlcvInterval.js.map +1 -1
- package/dist/cjs/utils/transferMargin.d.ts +3 -0
- package/dist/cjs/utils/transferMargin.d.ts.map +1 -0
- package/dist/cjs/utils/transferMargin.js +16 -0
- package/dist/cjs/utils/transferMargin.js.map +1 -0
- package/dist/cjs/utils/wireEncoding.d.ts.map +1 -1
- package/dist/cjs/utils/wireEncoding.js.map +1 -1
- package/dist/cjs/websocket/LighterWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/LighterWsProvider.js +20 -9
- package/dist/cjs/websocket/LighterWsProvider.js.map +1 -1
- package/dist/esm/LighterProvider.d.ts.map +1 -1
- package/dist/esm/LighterProvider.js +49 -11
- package/dist/esm/LighterProvider.js.map +1 -1
- package/dist/esm/accountSummary.d.ts +5 -4
- package/dist/esm/accountSummary.d.ts.map +1 -1
- package/dist/esm/accountSummary.js +35 -6
- package/dist/esm/accountSummary.js.map +1 -1
- package/dist/esm/constants.d.ts +15 -2
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.js +15 -2
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/signers/LighterKeyStore.d.ts +31 -2
- package/dist/esm/signers/LighterKeyStore.d.ts.map +1 -1
- package/dist/esm/signers/LighterKeyStore.js +24 -1
- package/dist/esm/signers/LighterKeyStore.js.map +1 -1
- package/dist/esm/signers/LighterReadOnlyTokenManager.d.ts +23 -3
- package/dist/esm/signers/LighterReadOnlyTokenManager.d.ts.map +1 -1
- package/dist/esm/signers/LighterReadOnlyTokenManager.js +4 -0
- package/dist/esm/signers/LighterReadOnlyTokenManager.js.map +1 -1
- package/dist/esm/signers/LighterSigner.d.ts +49 -7
- package/dist/esm/signers/LighterSigner.d.ts.map +1 -1
- package/dist/esm/signers/LighterSigner.js +11 -1
- package/dist/esm/signers/LighterSigner.js.map +1 -1
- package/dist/esm/signers/createAuthToken.d.ts +8 -2
- package/dist/esm/signers/createAuthToken.d.ts.map +1 -1
- package/dist/esm/signers/createAuthToken.js.map +1 -1
- package/dist/esm/signers/wasmLoader.d.ts +14 -2
- package/dist/esm/signers/wasmLoader.d.ts.map +1 -1
- package/dist/esm/signers/wasmLoader.js.map +1 -1
- package/dist/esm/types/account.d.ts +61 -8
- package/dist/esm/types/account.d.ts.map +1 -1
- package/dist/esm/types/action.d.ts +72 -18
- package/dist/esm/types/action.d.ts.map +1 -1
- package/dist/esm/types/action.js +72 -18
- package/dist/esm/types/action.js.map +1 -1
- package/dist/esm/types/activity.d.ts +64 -10
- package/dist/esm/types/activity.d.ts.map +1 -1
- package/dist/esm/types/asset.d.ts +72 -12
- package/dist/esm/types/asset.d.ts.map +1 -1
- package/dist/esm/types/fill.d.ts +14 -2
- package/dist/esm/types/fill.d.ts.map +1 -1
- package/dist/esm/types/order.d.ts +27 -4
- package/dist/esm/types/order.d.ts.map +1 -1
- package/dist/esm/types/submit.d.ts +26 -4
- package/dist/esm/types/submit.d.ts.map +1 -1
- package/dist/esm/types/ws.d.ts +65 -9
- package/dist/esm/types/ws.d.ts.map +1 -1
- package/dist/esm/utils/decimal.d.ts +15 -0
- package/dist/esm/utils/decimal.d.ts.map +1 -0
- package/dist/esm/utils/decimal.js +39 -0
- package/dist/esm/utils/decimal.js.map +1 -0
- package/dist/esm/utils/index.d.ts +3 -1
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +3 -1
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/lighterAsset.d.ts +7 -1
- package/dist/esm/utils/lighterAsset.d.ts.map +1 -1
- package/dist/esm/utils/lighterAsset.js +7 -1
- package/dist/esm/utils/lighterAsset.js.map +1 -1
- package/dist/esm/utils/mapOpenPositions.d.ts +2 -2
- package/dist/esm/utils/mapOpenPositions.d.ts.map +1 -1
- package/dist/esm/utils/mapOpenPositions.js.map +1 -1
- package/dist/esm/utils/mapPosition.d.ts +10 -2
- package/dist/esm/utils/mapPosition.d.ts.map +1 -1
- package/dist/esm/utils/mapPosition.js +32 -11
- package/dist/esm/utils/mapPosition.js.map +1 -1
- package/dist/esm/utils/ohlcvInterval.d.ts +6 -1
- package/dist/esm/utils/ohlcvInterval.d.ts.map +1 -1
- package/dist/esm/utils/ohlcvInterval.js +6 -1
- package/dist/esm/utils/ohlcvInterval.js.map +1 -1
- package/dist/esm/utils/transferMargin.d.ts +11 -0
- package/dist/esm/utils/transferMargin.d.ts.map +1 -0
- package/dist/esm/utils/transferMargin.js +21 -0
- package/dist/esm/utils/transferMargin.js.map +1 -0
- package/dist/esm/utils/wireEncoding.d.ts +58 -23
- package/dist/esm/utils/wireEncoding.d.ts.map +1 -1
- package/dist/esm/utils/wireEncoding.js +58 -23
- package/dist/esm/utils/wireEncoding.js.map +1 -1
- package/dist/esm/websocket/LighterWsProvider.d.ts +6 -0
- package/dist/esm/websocket/LighterWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/LighterWsProvider.js +30 -13
- package/dist/esm/websocket/LighterWsProvider.js.map +1 -1
- package/dist/types/LighterProvider.d.ts.map +1 -1
- package/dist/types/accountSummary.d.ts +5 -4
- package/dist/types/accountSummary.d.ts.map +1 -1
- package/dist/types/constants.d.ts +15 -2
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/signers/LighterKeyStore.d.ts +31 -2
- package/dist/types/signers/LighterKeyStore.d.ts.map +1 -1
- package/dist/types/signers/LighterReadOnlyTokenManager.d.ts +23 -3
- package/dist/types/signers/LighterReadOnlyTokenManager.d.ts.map +1 -1
- package/dist/types/signers/LighterSigner.d.ts +49 -7
- package/dist/types/signers/LighterSigner.d.ts.map +1 -1
- package/dist/types/signers/createAuthToken.d.ts +8 -2
- package/dist/types/signers/createAuthToken.d.ts.map +1 -1
- package/dist/types/signers/wasmLoader.d.ts +14 -2
- package/dist/types/signers/wasmLoader.d.ts.map +1 -1
- package/dist/types/types/account.d.ts +61 -8
- package/dist/types/types/account.d.ts.map +1 -1
- package/dist/types/types/action.d.ts +72 -18
- package/dist/types/types/action.d.ts.map +1 -1
- package/dist/types/types/activity.d.ts +64 -10
- package/dist/types/types/activity.d.ts.map +1 -1
- package/dist/types/types/asset.d.ts +72 -12
- package/dist/types/types/asset.d.ts.map +1 -1
- package/dist/types/types/fill.d.ts +14 -2
- package/dist/types/types/fill.d.ts.map +1 -1
- package/dist/types/types/order.d.ts +27 -4
- package/dist/types/types/order.d.ts.map +1 -1
- package/dist/types/types/submit.d.ts +26 -4
- package/dist/types/types/submit.d.ts.map +1 -1
- package/dist/types/types/ws.d.ts +65 -9
- package/dist/types/types/ws.d.ts.map +1 -1
- package/dist/types/utils/decimal.d.ts +15 -0
- package/dist/types/utils/decimal.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +3 -1
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/lighterAsset.d.ts +7 -1
- package/dist/types/utils/lighterAsset.d.ts.map +1 -1
- package/dist/types/utils/mapOpenPositions.d.ts +2 -2
- package/dist/types/utils/mapOpenPositions.d.ts.map +1 -1
- package/dist/types/utils/mapPosition.d.ts +10 -2
- package/dist/types/utils/mapPosition.d.ts.map +1 -1
- package/dist/types/utils/ohlcvInterval.d.ts +6 -1
- package/dist/types/utils/ohlcvInterval.d.ts.map +1 -1
- package/dist/types/utils/transferMargin.d.ts +11 -0
- package/dist/types/utils/transferMargin.d.ts.map +1 -0
- package/dist/types/utils/wireEncoding.d.ts +58 -23
- package/dist/types/utils/wireEncoding.d.ts.map +1 -1
- package/dist/types/websocket/LighterWsProvider.d.ts +6 -0
- package/dist/types/websocket/LighterWsProvider.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/LighterProvider.ts +75 -9
- package/src/accountSummary.ts +38 -6
- package/src/constants.ts +15 -2
- package/src/signers/LighterKeyStore.ts +31 -2
- package/src/signers/LighterReadOnlyTokenManager.ts +23 -3
- package/src/signers/LighterSigner.ts +49 -7
- package/src/signers/createAuthToken.ts +8 -2
- package/src/signers/wasmLoader.ts +14 -2
- package/src/types/account.ts +61 -8
- package/src/types/action.ts +72 -18
- package/src/types/activity.ts +64 -10
- package/src/types/asset.ts +72 -12
- package/src/types/fill.ts +14 -2
- package/src/types/order.ts +27 -4
- package/src/types/submit.ts +26 -4
- package/src/types/ws.ts +65 -9
- package/src/utils/decimal.ts +52 -0
- package/src/utils/index.ts +3 -1
- package/src/utils/lighterAsset.ts +7 -1
- package/src/utils/mapOpenPositions.ts +2 -2
- package/src/utils/mapPosition.ts +40 -14
- package/src/utils/ohlcvInterval.ts +6 -1
- package/src/utils/transferMargin.ts +31 -0
- package/src/utils/wireEncoding.ts +58 -23
- package/src/websocket/LighterWsProvider.ts +47 -11
package/src/types/submit.ts
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
// Lighter submit/execute-path wire shapes (sendTx, fastwithdraw, changeAccountTier).
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Request body for Lighter's `/api/v1/sendTx` endpoint. `tx_type` and
|
|
5
|
+
* `tx_info` are the signed WASM transaction envelope; `price_protection` is an
|
|
6
|
+
* optional venue-side execution guard.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
4
10
|
export interface LtSendTxRequest {
|
|
5
11
|
tx_type: number
|
|
6
12
|
tx_info: string
|
|
7
13
|
price_protection?: boolean
|
|
8
14
|
}
|
|
9
15
|
|
|
10
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Response from Lighter's `/api/v1/sendTx` endpoint. `tx_hash` identifies the
|
|
18
|
+
* submitted transaction; timing and quota fields are optional venue estimates.
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
11
22
|
export interface LtSendTxResponse {
|
|
12
23
|
code: number
|
|
13
24
|
message: string
|
|
@@ -16,13 +27,24 @@ export interface LtSendTxResponse {
|
|
|
16
27
|
volume_quota_remaining?: number
|
|
17
28
|
}
|
|
18
29
|
|
|
19
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Batch request body for Lighter's transaction submission endpoint.
|
|
32
|
+
* `tx_types` is a JSON-encoded number array and `tx_infos` a JSON-encoded
|
|
33
|
+
* string array; corresponding entries are submitted in array order.
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
20
37
|
export interface LtSendTxBatchRequest {
|
|
21
38
|
tx_types: string // JSON-encoded number[]
|
|
22
39
|
tx_infos: string // JSON-encoded string[]
|
|
23
40
|
}
|
|
24
41
|
|
|
25
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Batch submission response from Lighter. Each `tx_hash` corresponds to the
|
|
44
|
+
* transaction at the same index in the submitted batch.
|
|
45
|
+
*
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
26
48
|
export interface LtSendTxBatchResponse {
|
|
27
49
|
code: number
|
|
28
50
|
message: string
|
package/src/types/ws.ts
CHANGED
|
@@ -10,16 +10,33 @@
|
|
|
10
10
|
// - spot_market_stats/{id} → context for one spot market
|
|
11
11
|
// - order_book/{market_id} → bids/asks per market (stateful with deltas)
|
|
12
12
|
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Common envelope fields on every Lighter WebSocket frame.
|
|
15
|
+
*
|
|
16
|
+
* `channel` identifies the subscribed stream when present; `type` is the
|
|
17
|
+
* subscription, update, or control-frame discriminator.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
14
21
|
export type LtWsMessage = {
|
|
15
22
|
channel?: string
|
|
16
23
|
type: string
|
|
17
24
|
}
|
|
18
25
|
|
|
19
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Lighter WebSocket keepalive frame.
|
|
28
|
+
*
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
20
31
|
export type LtWsPingMessage = LtWsMessage & { type: 'ping' }
|
|
21
32
|
|
|
22
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Perpetual-market statistics pushed by Lighter's `market_stats` channels.
|
|
35
|
+
* Price, interest, volume, and funding values are decimal strings; the funding
|
|
36
|
+
* timestamp is a Unix timestamp in milliseconds.
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
23
40
|
export type LtWsMarketStats = {
|
|
24
41
|
market_id: number
|
|
25
42
|
index_price: string
|
|
@@ -75,20 +92,34 @@ export type LtWsSpotMarketStatsAllMessage = LtWsMessage & {
|
|
|
75
92
|
spot_market_stats?: LtWsSpotMarketStats | Record<string, LtWsSpotMarketStats>
|
|
76
93
|
}
|
|
77
94
|
|
|
78
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* One bid or ask level in a Lighter order-book snapshot or delta. Price and
|
|
97
|
+
* size are decimal strings in the market's native precision.
|
|
98
|
+
*
|
|
99
|
+
* @public
|
|
100
|
+
*/
|
|
79
101
|
export type LtWsOrderBookLevel = {
|
|
80
102
|
price: string
|
|
81
103
|
size: string
|
|
82
104
|
}
|
|
83
105
|
|
|
84
|
-
/**
|
|
106
|
+
/**
|
|
107
|
+
* Lighter order-book state containing ask and bid levels. `offset`, when
|
|
108
|
+
* present, identifies the sequence offset used for stateful delta updates.
|
|
109
|
+
*
|
|
110
|
+
* @public
|
|
111
|
+
*/
|
|
85
112
|
export type LtWsOrderBook = {
|
|
86
113
|
asks: LtWsOrderBookLevel[]
|
|
87
114
|
bids: LtWsOrderBookLevel[]
|
|
88
115
|
offset?: number
|
|
89
116
|
}
|
|
90
117
|
|
|
91
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* Subscription or update frame carrying a Lighter order-book snapshot/delta.
|
|
120
|
+
*
|
|
121
|
+
* @public
|
|
122
|
+
*/
|
|
92
123
|
export type LtWsOrderBookMessage = LtWsMessage & {
|
|
93
124
|
type: 'subscribed/order_book' | 'update/order_book'
|
|
94
125
|
order_book: LtWsOrderBook
|
|
@@ -109,7 +140,11 @@ export type LtWsTrade = {
|
|
|
109
140
|
timestamp: number
|
|
110
141
|
}
|
|
111
142
|
|
|
112
|
-
/**
|
|
143
|
+
/**
|
|
144
|
+
* Subscription or update frame carrying public trades from a Lighter market.
|
|
145
|
+
*
|
|
146
|
+
* @public
|
|
147
|
+
*/
|
|
113
148
|
export type LtWsTradeMessage = LtWsMessage & {
|
|
114
149
|
type: 'subscribed/trade' | 'update/trade'
|
|
115
150
|
trades?: LtWsTrade[]
|
|
@@ -138,7 +173,13 @@ export type LtWsAccountAllOrdersMessage = LtWsMessage & {
|
|
|
138
173
|
data?: { orders?: Record<string, unknown[]> | unknown[] }
|
|
139
174
|
}
|
|
140
175
|
|
|
141
|
-
/**
|
|
176
|
+
/**
|
|
177
|
+
* Authenticated account trade-history frame. Trade arrays may be flat or
|
|
178
|
+
* market-indexed depending on whether the frame is an initial snapshot or
|
|
179
|
+
* update.
|
|
180
|
+
*
|
|
181
|
+
* @public
|
|
182
|
+
*/
|
|
142
183
|
export type LtWsAccountAllTradesMessage = LtWsMessage & {
|
|
143
184
|
type: 'subscribed/account_all_trades' | 'update/account_all_trades'
|
|
144
185
|
trades?: Record<string, unknown[]> | unknown[]
|
|
@@ -150,7 +191,10 @@ export type LtWsAccountAllTradesMessage = LtWsMessage & {
|
|
|
150
191
|
}
|
|
151
192
|
|
|
152
193
|
/**
|
|
153
|
-
* `user_stats/{account_index}` frame; decimal strings in USD.
|
|
194
|
+
* `user_stats/{account_index}` frame; decimal strings in USD. The top-level
|
|
195
|
+
* figures span the whole account (`available_balance` = total withdrawable,
|
|
196
|
+
* including isolated positions' excess margin); `cross_stats` scopes them to
|
|
197
|
+
* the cross pool, whose `available_balance` is the free tradable collateral.
|
|
154
198
|
* @public
|
|
155
199
|
*/
|
|
156
200
|
export type LtWsUserStatsMessage = LtWsMessage & {
|
|
@@ -158,9 +202,21 @@ export type LtWsUserStatsMessage = LtWsMessage & {
|
|
|
158
202
|
collateral?: string
|
|
159
203
|
portfolio_value?: string
|
|
160
204
|
available_balance?: string
|
|
205
|
+
cross_stats?: {
|
|
206
|
+
collateral: string
|
|
207
|
+
portfolio_value: string
|
|
208
|
+
available_balance: string
|
|
209
|
+
}
|
|
161
210
|
}
|
|
162
211
|
}
|
|
163
212
|
|
|
213
|
+
/**
|
|
214
|
+
* Authenticated account-position frame. Position and funding maps are keyed
|
|
215
|
+
* by Lighter market index; the provider normalizes the payload before emitting
|
|
216
|
+
* account updates.
|
|
217
|
+
*
|
|
218
|
+
* @public
|
|
219
|
+
*/
|
|
164
220
|
export type LtWsAccountAllPositionsMessage = LtWsMessage & {
|
|
165
221
|
type: 'subscribed/account_all_positions' | 'update/account_all_positions'
|
|
166
222
|
positions?: Record<string, unknown>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { PerpsError } from '@lifi/perps-sdk'
|
|
2
|
+
import { PerpsErrorCode } from '@lifi/perps-types'
|
|
3
|
+
import Big from 'big.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Exact-decimal parse of a venue decimal string; null when absent or
|
|
7
|
+
* unparsable, so callers can gate on presence before deriving.
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export const toBigOrNull = (value: string | undefined): Big | null => {
|
|
11
|
+
if (value === undefined) {
|
|
12
|
+
return null
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
return new Big(value)
|
|
16
|
+
} catch {
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Parse a required venue decimal and identify the bad field on failure.
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
export const toRequiredBig = (
|
|
26
|
+
value: string | undefined,
|
|
27
|
+
field: string
|
|
28
|
+
): Big => {
|
|
29
|
+
const parsed = toBigOrNull(value)
|
|
30
|
+
if (parsed !== null) {
|
|
31
|
+
return parsed
|
|
32
|
+
}
|
|
33
|
+
throw new PerpsError(
|
|
34
|
+
PerpsErrorCode.SDKError,
|
|
35
|
+
`Lighter field \`${field}\` is not a valid decimal.`
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Parse a required venue decimal that must be greater than zero. */
|
|
40
|
+
export const toPositiveRequiredBig = (
|
|
41
|
+
value: string | undefined,
|
|
42
|
+
field: string
|
|
43
|
+
): Big => {
|
|
44
|
+
const parsed = toRequiredBig(value, field)
|
|
45
|
+
if (parsed.lte(0)) {
|
|
46
|
+
throw new PerpsError(
|
|
47
|
+
PerpsErrorCode.SDKError,
|
|
48
|
+
`Lighter field \`${field}\` must be greater than zero.`
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
return parsed
|
|
52
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ export {
|
|
|
9
9
|
} from './activityCursor.js'
|
|
10
10
|
export { LighterApiClient } from './apiClient.js'
|
|
11
11
|
export { assetMarginModeInt, isAssetMarginEnabled } from './assetCollateral.js'
|
|
12
|
+
export { toBigOrNull, toRequiredBig } from './decimal.js'
|
|
12
13
|
export { fetchDetailedAccount } from './fetchDetailedAccount.js'
|
|
13
14
|
export { lighterAsset } from './lighterAsset.js'
|
|
14
15
|
export { estimateLiquidationPrice } from './liquidation.js'
|
|
@@ -24,10 +25,11 @@ export {
|
|
|
24
25
|
mapStatusReason,
|
|
25
26
|
mapTriggerOrder,
|
|
26
27
|
} from './mapOrder.js'
|
|
27
|
-
export { mapPosition } from './mapPosition.js'
|
|
28
|
+
export { leverageFromImf, mapPosition } from './mapPosition.js'
|
|
28
29
|
export { mapInterval } from './ohlcvInterval.js'
|
|
29
30
|
export { formatOrderPrice, formatOrderSize } from './orderFormatting.js'
|
|
30
31
|
export { toIsoFromMs, toIsoFromSeconds } from './time.js'
|
|
32
|
+
export { positionMarginConstraints } from './transferMargin.js'
|
|
31
33
|
export {
|
|
32
34
|
leverageToFraction,
|
|
33
35
|
mapOrderTypeToInt,
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { Asset } from '@lifi/perps-types'
|
|
2
2
|
import { LIGHTER_PROVIDER_KEY } from '../constants.js'
|
|
3
3
|
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Create the SDK asset descriptor for a Lighter asset identifier and display
|
|
6
|
+
* symbol. Lighter assets do not provide a package-level logo URI, so this
|
|
7
|
+
* helper leaves that field empty.
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
5
11
|
export const lighterAsset = (id: string, displaySymbol: string): Asset => ({
|
|
6
12
|
providerId: LIGHTER_PROVIDER_KEY,
|
|
7
13
|
id,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PerpsMarketDisplay, Position } from '@lifi/perps-types'
|
|
2
2
|
import type { LtAccountPosition } from '../types/index.js'
|
|
3
3
|
import { mapPosition } from './mapPosition.js'
|
|
4
4
|
|
|
@@ -11,7 +11,7 @@ import { mapPosition } from './mapPosition.js'
|
|
|
11
11
|
*/
|
|
12
12
|
export const mapOpenPositions = (
|
|
13
13
|
positions: LtAccountPosition[],
|
|
14
|
-
resolveMarket: (marketId: number) =>
|
|
14
|
+
resolveMarket: (marketId: number) => PerpsMarketDisplay
|
|
15
15
|
): Position[] =>
|
|
16
16
|
positions
|
|
17
17
|
.filter((p) => Number.parseFloat(p.position) !== 0)
|
package/src/utils/mapPosition.ts
CHANGED
|
@@ -1,7 +1,29 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PerpsMarketDisplay, Position } from '@lifi/perps-types'
|
|
2
2
|
import { MarginMode, PositionSide } from '@lifi/perps-types'
|
|
3
|
+
import Big from 'big.js'
|
|
3
4
|
import type { LtAccountPosition } from '../types/index.js'
|
|
4
5
|
import { LT_MARGIN_MODE_ISOLATED } from '../types/index.js'
|
|
6
|
+
import { toPositiveRequiredBig, toRequiredBig } from './decimal.js'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Display leverage from an IMF percent string: `100 / IMF` in exact decimal
|
|
10
|
+
* arithmetic before conversion to `number`. This value is for displaying the
|
|
11
|
+
* venue setting; provider risk calculations consume the original decimal IMF
|
|
12
|
+
* instead. `undefined` for a non-positive or unparsable IMF.
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
export const leverageFromImf = (imf: string): number | undefined => {
|
|
16
|
+
let parsed: Big
|
|
17
|
+
try {
|
|
18
|
+
parsed = new Big(imf)
|
|
19
|
+
} catch {
|
|
20
|
+
return undefined
|
|
21
|
+
}
|
|
22
|
+
if (parsed.lte(0)) {
|
|
23
|
+
return undefined
|
|
24
|
+
}
|
|
25
|
+
return new Big(100).div(parsed).toNumber()
|
|
26
|
+
}
|
|
5
27
|
|
|
6
28
|
/**
|
|
7
29
|
* Map a raw Lighter account position to the generic Position type.
|
|
@@ -10,33 +32,37 @@ import { LT_MARGIN_MODE_ISOLATED } from '../types/index.js'
|
|
|
10
32
|
*/
|
|
11
33
|
export const mapPosition = (
|
|
12
34
|
pos: LtAccountPosition,
|
|
13
|
-
market:
|
|
35
|
+
market: PerpsMarketDisplay
|
|
14
36
|
): Position => {
|
|
15
|
-
const size =
|
|
37
|
+
const size = toRequiredBig(pos.position, 'position')
|
|
16
38
|
const isIsolated = pos.margin_mode === LT_MARGIN_MODE_ISOLATED
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
39
|
+
const positionValue = toRequiredBig(
|
|
40
|
+
pos.position_value,
|
|
41
|
+
'position_value'
|
|
42
|
+
).abs()
|
|
43
|
+
const imf = toPositiveRequiredBig(
|
|
44
|
+
pos.initial_margin_fraction,
|
|
45
|
+
'initial_margin_fraction'
|
|
46
|
+
)
|
|
47
|
+
const initialMarginRequirement = positionValue.times(imf).div(100)
|
|
23
48
|
const marginUsed = isIsolated
|
|
24
49
|
? pos.allocated_margin
|
|
25
|
-
:
|
|
50
|
+
: initialMarginRequirement.toFixed()
|
|
26
51
|
|
|
27
52
|
return {
|
|
28
53
|
market,
|
|
29
54
|
side: pos.sign >= 0 ? PositionSide.LONG : PositionSide.SHORT,
|
|
30
|
-
size:
|
|
55
|
+
size: size.abs().toFixed(),
|
|
31
56
|
entryPrice: pos.avg_entry_price,
|
|
32
57
|
markPrice:
|
|
33
|
-
|
|
58
|
+
positionValue.eq(0) || size.eq(0)
|
|
34
59
|
? '0'
|
|
35
|
-
: (
|
|
60
|
+
: positionValue.div(size.abs()).toFixed(),
|
|
36
61
|
liquidationPrice: pos.liquidation_price,
|
|
37
62
|
unrealizedPnl: pos.unrealized_pnl,
|
|
38
|
-
leverage:
|
|
63
|
+
leverage: leverageFromImf(pos.initial_margin_fraction) ?? 1,
|
|
39
64
|
marginUsed,
|
|
65
|
+
initialMarginRequirement: initialMarginRequirement.toFixed(),
|
|
40
66
|
marginMode: isIsolated ? MarginMode.ISOLATED : MarginMode.CROSS,
|
|
41
67
|
}
|
|
42
68
|
}
|
|
@@ -20,7 +20,12 @@ const LIGHTER_SUPPORTED_INTERVALS: Record<string, string> = {
|
|
|
20
20
|
'1w': '1w',
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Validate and map an SDK OHLCV interval to Lighter's resolution string.
|
|
25
|
+
* Unsupported intervals raise a validation error instead of being rounded.
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
24
29
|
export const mapInterval = (interval: string): string => {
|
|
25
30
|
const resolution = LIGHTER_SUPPORTED_INTERVALS[interval]
|
|
26
31
|
if (!resolution) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Position,
|
|
3
|
+
type PositionMarginConstraints,
|
|
4
|
+
positionSupportsMarginAdjustment,
|
|
5
|
+
} from '@lifi/perps-types'
|
|
6
|
+
import { toPositiveRequiredBig } from './decimal.js'
|
|
7
|
+
|
|
8
|
+
const AMOUNT_INCREMENT = '0.000001'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Lighter's exact isolated-margin requirement. Lighter publishes no separate
|
|
12
|
+
* notional floor, so the provider-normalized initial-margin requirement is
|
|
13
|
+
* the retained amount.
|
|
14
|
+
*
|
|
15
|
+
* @see https://docs.lighter.xyz/trading/liquidations-and-llp-insurance-fund
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export function positionMarginConstraints(
|
|
19
|
+
position: Position
|
|
20
|
+
): PositionMarginConstraints | undefined {
|
|
21
|
+
if (!positionSupportsMarginAdjustment(position)) {
|
|
22
|
+
return undefined
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
minimumMarginRequirement: toPositiveRequiredBig(
|
|
26
|
+
position.initialMarginRequirement,
|
|
27
|
+
'initialMarginRequirement'
|
|
28
|
+
).toFixed(),
|
|
29
|
+
amountIncrement: AMOUNT_INCREMENT,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lighter wire encoding for the WASM signer:
|
|
3
|
-
*
|
|
4
|
-
* mirroring the lighter-go signer's rules.
|
|
2
|
+
* Lighter wire encoding for the WASM signer: basis-point margin fractions and
|
|
3
|
+
* order-type/time-in-force/expiry resolution mirroring lighter-go's rules.
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
import { PerpsError } from '@lifi/perps-sdk'
|
|
@@ -20,8 +19,15 @@ import {
|
|
|
20
19
|
} from '../types/action.js'
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
|
-
* Lighter
|
|
24
|
-
*
|
|
22
|
+
* Convert Lighter's initial-margin fraction to the largest whole-number
|
|
23
|
+
* leverage exposed by the provider.
|
|
24
|
+
*
|
|
25
|
+
* Lighter expresses margin fractions in basis points (`10_000` = 100%), so
|
|
26
|
+
* the conversion is `floor(10_000 / fraction)`. Non-finite or non-positive
|
|
27
|
+
* input uses the safe `1x` fallback.
|
|
28
|
+
*
|
|
29
|
+
* @param fraction - Lighter's basis-point initial-margin fraction.
|
|
30
|
+
* @returns The floored maximum leverage, or `1` for invalid input.
|
|
25
31
|
* @public
|
|
26
32
|
*/
|
|
27
33
|
export const marginFractionToMaxLeverage = (fraction: number): number => {
|
|
@@ -32,7 +38,15 @@ export const marginFractionToMaxLeverage = (fraction: number): number => {
|
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
/**
|
|
35
|
-
* Convert leverage to
|
|
41
|
+
* Convert requested leverage to Lighter's basis-point margin fraction.
|
|
42
|
+
*
|
|
43
|
+
* The signer expects `round(10_000 / leverage)`, where the result is the
|
|
44
|
+
* margin requirement in basis points.
|
|
45
|
+
*
|
|
46
|
+
* @param leverage - Requested leverage multiplier.
|
|
47
|
+
* @returns The rounded basis-point margin fraction.
|
|
48
|
+
* @throws {PerpsError} With `ValidationError` when leverage is less than
|
|
49
|
+
* or equal to zero.
|
|
36
50
|
* @public
|
|
37
51
|
*/
|
|
38
52
|
export const leverageToFraction = (leverage: number): number => {
|
|
@@ -46,7 +60,14 @@ export const leverageToFraction = (leverage: number): number => {
|
|
|
46
60
|
}
|
|
47
61
|
|
|
48
62
|
/**
|
|
49
|
-
* Map
|
|
63
|
+
* Map a LI.FI `OrderType` value to Lighter's integer wire type.
|
|
64
|
+
*
|
|
65
|
+
* Supported mappings are LIMIT → 0, MARKET → 1, STOP_MARKET → 2,
|
|
66
|
+
* STOP_LIMIT → 3, TAKE_PROFIT_MARKET → 4, and TAKE_PROFIT_LIMIT → 5.
|
|
67
|
+
* Omitted or unknown values fall back to LIMIT.
|
|
68
|
+
*
|
|
69
|
+
* @param type - LI.FI order type value.
|
|
70
|
+
* @returns The corresponding Lighter order-type integer.
|
|
50
71
|
* @public
|
|
51
72
|
*/
|
|
52
73
|
export const mapOrderTypeToInt = (type?: string): number => {
|
|
@@ -62,13 +83,18 @@ export const mapOrderTypeToInt = (type?: string): number => {
|
|
|
62
83
|
}
|
|
63
84
|
|
|
64
85
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
86
|
+
* Resolve a Lighter `time_in_force` value that is valid for an order type.
|
|
87
|
+
*
|
|
88
|
+
* Market-style orders (MARKET, STOP_MARKET, TAKE_PROFIT_MARKET) are IOC-only.
|
|
89
|
+
* Limit-style orders default to GTC when no TIF is supplied. An explicit
|
|
90
|
+
* non-IOC TIF on a market-style order raises a validation error. For
|
|
91
|
+
* limit-style orders, unknown TIF strings use the GTC fallback from
|
|
92
|
+
* {@link mapTimeInForceToInt}.
|
|
93
|
+
*
|
|
94
|
+
* @param orderTypeInt - Lighter order-type integer.
|
|
95
|
+
* @param tif - Optional LI.FI time-in-force value.
|
|
96
|
+
* @returns The validated Lighter time-in-force integer.
|
|
97
|
+
* @throws {PerpsError} With `ValidationError` for a market-style/TIF mismatch.
|
|
72
98
|
* @public
|
|
73
99
|
*/
|
|
74
100
|
export const resolveTimeInForce = (
|
|
@@ -93,7 +119,13 @@ export const resolveTimeInForce = (
|
|
|
93
119
|
}
|
|
94
120
|
|
|
95
121
|
/**
|
|
96
|
-
* Map
|
|
122
|
+
* Map a LI.FI time-in-force value to Lighter's integer wire value.
|
|
123
|
+
*
|
|
124
|
+
* IOC maps to 0, GTC maps to 1, and POST_ONLY maps to 2. Omitted or unknown
|
|
125
|
+
* values fall back to GTC.
|
|
126
|
+
*
|
|
127
|
+
* @param tif - LI.FI time-in-force value.
|
|
128
|
+
* @returns The corresponding Lighter time-in-force integer.
|
|
97
129
|
* @public
|
|
98
130
|
*/
|
|
99
131
|
export const mapTimeInForceToInt = (tif?: string): number => {
|
|
@@ -106,14 +138,17 @@ export const mapTimeInForceToInt = (tif?: string): number => {
|
|
|
106
138
|
}
|
|
107
139
|
|
|
108
140
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
141
|
+
* Select the `order_expiry` sentinel required for a regular Lighter limit
|
|
142
|
+
* order from its resolved time-in-force.
|
|
143
|
+
*
|
|
144
|
+
* IOC uses Lighter's nil expiry (`0`). Every other TIF uses
|
|
145
|
+
* `LT_DEFAULT_ORDER_EXPIRY` (`-1`), which the WASM signer expands to its
|
|
146
|
+
* canonical future expiry (`now + 28d`) as an absolute Unix-millisecond
|
|
147
|
+
* timestamp. Trigger-order expiry handling is provider-specific; see
|
|
148
|
+
* {@link LT_DEFAULT_ORDER_EXPIRY} and its call sites.
|
|
149
|
+
*
|
|
150
|
+
* @param tifInt - Lighter time-in-force integer.
|
|
151
|
+
* @returns `0` for IOC, otherwise the default-expiry sentinel.
|
|
117
152
|
* @public
|
|
118
153
|
*/
|
|
119
154
|
export const orderExpiryForTif = (tifInt: number): number => {
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
ReconnectingWebSocket,
|
|
10
10
|
resolveRetryPolicy,
|
|
11
11
|
resolveSubscribeQuote,
|
|
12
|
+
toPerpsMarketDisplay,
|
|
12
13
|
WsProviderBase,
|
|
13
14
|
type WsProviderFactory,
|
|
14
15
|
wsLog,
|
|
@@ -51,6 +52,7 @@ import {
|
|
|
51
52
|
mapFill,
|
|
52
53
|
mapMarketContext,
|
|
53
54
|
mapPosition,
|
|
55
|
+
toRequiredBig,
|
|
54
56
|
} from '../utils/index.js'
|
|
55
57
|
|
|
56
58
|
// Public channels: `marketsContext` (market_stats/all + spot_market_stats/all),
|
|
@@ -225,6 +227,12 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
225
227
|
return undefined
|
|
226
228
|
}
|
|
227
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Subscribe to a live quote stream resolved through the registered Lighter
|
|
232
|
+
* market registry. Returns an unsubscribe function; quote subscription
|
|
233
|
+
* requires the provider to be constructed through `lighterWsProvider` with a
|
|
234
|
+
* bound {@link PerpsSDKClient}.
|
|
235
|
+
*/
|
|
228
236
|
async subscribeQuote(
|
|
229
237
|
params: ProviderGetQuoteParams,
|
|
230
238
|
onQuote: QuoteListener
|
|
@@ -588,23 +596,51 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
588
596
|
return
|
|
589
597
|
}
|
|
590
598
|
const stats = msg.stats
|
|
591
|
-
|
|
592
|
-
const available = Number.parseFloat(stats?.available_balance ?? '')
|
|
593
|
-
if (!Number.isFinite(portfolio) || !Number.isFinite(available)) {
|
|
599
|
+
if (stats === undefined) {
|
|
594
600
|
return
|
|
595
601
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
602
|
+
|
|
603
|
+
const portfolio = toRequiredBig(
|
|
604
|
+
stats.portfolio_value,
|
|
605
|
+
'stats.portfolio_value'
|
|
606
|
+
)
|
|
607
|
+
const collateral = toRequiredBig(stats.collateral, 'stats.collateral')
|
|
608
|
+
|
|
609
|
+
let available: Big
|
|
610
|
+
let marginUsed: Big
|
|
611
|
+
if (stats.cross_stats === undefined) {
|
|
612
|
+
// Compatibility with legacy gateways that omitted the entire
|
|
613
|
+
// cross_stats object.
|
|
614
|
+
available = toRequiredBig(
|
|
615
|
+
stats.available_balance,
|
|
616
|
+
'stats.available_balance'
|
|
617
|
+
)
|
|
618
|
+
marginUsed = portfolio.minus(available)
|
|
619
|
+
} else {
|
|
620
|
+
const crossCollateral = toRequiredBig(
|
|
621
|
+
stats.cross_stats.collateral,
|
|
622
|
+
'stats.cross_stats.collateral'
|
|
623
|
+
)
|
|
624
|
+
const crossPortfolio = toRequiredBig(
|
|
625
|
+
stats.cross_stats.portfolio_value,
|
|
626
|
+
'stats.cross_stats.portfolio_value'
|
|
627
|
+
)
|
|
628
|
+
available = toRequiredBig(
|
|
629
|
+
stats.cross_stats.available_balance,
|
|
630
|
+
'stats.cross_stats.available_balance'
|
|
631
|
+
)
|
|
632
|
+
const isolatedMargin = collateral.minus(crossCollateral)
|
|
633
|
+
const crossMargin = crossPortfolio.minus(available)
|
|
634
|
+
marginUsed = isolatedMargin.plus(crossMargin)
|
|
635
|
+
}
|
|
636
|
+
|
|
599
637
|
this.emit(`accountSummary:${address}`, {
|
|
600
638
|
channel: 'accountSummary',
|
|
601
639
|
data: {
|
|
602
640
|
portfolioValue: portfolio.toString(),
|
|
603
641
|
availableMargin: available.toString(),
|
|
604
|
-
marginUsed:
|
|
605
|
-
unrealizedPnl:
|
|
606
|
-
? (portfolio - collateral).toString()
|
|
607
|
-
: '0',
|
|
642
|
+
marginUsed: marginUsed.toString(),
|
|
643
|
+
unrealizedPnl: portfolio.minus(collateral).toString(),
|
|
608
644
|
},
|
|
609
645
|
})
|
|
610
646
|
}
|
|
@@ -649,7 +685,7 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
649
685
|
} else {
|
|
650
686
|
const market = this.registry?.get(String(p.market_id))
|
|
651
687
|
if (market) {
|
|
652
|
-
state.set(p.market_id, mapPosition(p, market))
|
|
688
|
+
state.set(p.market_id, mapPosition(p, toPerpsMarketDisplay(market)))
|
|
653
689
|
}
|
|
654
690
|
}
|
|
655
691
|
}
|