@lifi/perps-sdk-provider-lighter 1.5.6 → 1.7.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/cjs/LighterProvider.d.ts.map +1 -1
- package/dist/cjs/LighterProvider.js +2 -0
- package/dist/cjs/LighterProvider.js.map +1 -1
- package/dist/cjs/accountConfig.d.ts.map +1 -1
- package/dist/cjs/accountConfig.js +15 -2
- package/dist/cjs/accountConfig.js.map +1 -1
- package/dist/cjs/constants.d.ts +2 -1
- package/dist/cjs/constants.d.ts.map +1 -1
- package/dist/cjs/constants.js +3 -1
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/signers/LighterSigner.d.ts.map +1 -1
- package/dist/cjs/signers/LighterSigner.js +13 -2
- package/dist/cjs/signers/LighterSigner.js.map +1 -1
- package/dist/cjs/signers/signActions.d.ts +2 -0
- package/dist/cjs/signers/signActions.d.ts.map +1 -1
- package/dist/cjs/signers/signActions.js +37 -19
- package/dist/cjs/signers/signActions.js.map +1 -1
- package/dist/cjs/signers/wasmLoader.d.ts +2 -0
- package/dist/cjs/signers/wasmLoader.d.ts.map +1 -1
- package/dist/cjs/signers/wasmLoader.js +2 -0
- package/dist/cjs/signers/wasmLoader.js.map +1 -1
- package/dist/cjs/utils/apiClient.d.ts +4 -0
- package/dist/cjs/utils/apiClient.d.ts.map +1 -1
- package/dist/cjs/utils/apiClient.js +15 -0
- package/dist/cjs/utils/apiClient.js.map +1 -1
- package/dist/esm/LighterProvider.d.ts.map +1 -1
- package/dist/esm/LighterProvider.js +2 -0
- package/dist/esm/LighterProvider.js.map +1 -1
- package/dist/esm/accountConfig.d.ts.map +1 -1
- package/dist/esm/accountConfig.js +27 -7
- package/dist/esm/accountConfig.js.map +1 -1
- package/dist/esm/constants.d.ts +9 -1
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.js +9 -1
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/signers/LighterSigner.d.ts +3 -2
- package/dist/esm/signers/LighterSigner.d.ts.map +1 -1
- package/dist/esm/signers/LighterSigner.js +16 -4
- package/dist/esm/signers/LighterSigner.js.map +1 -1
- package/dist/esm/signers/signActions.d.ts +13 -5
- package/dist/esm/signers/signActions.d.ts.map +1 -1
- package/dist/esm/signers/signActions.js +68 -38
- package/dist/esm/signers/signActions.js.map +1 -1
- package/dist/esm/signers/wasmLoader.d.ts +13 -0
- package/dist/esm/signers/wasmLoader.d.ts.map +1 -1
- package/dist/esm/signers/wasmLoader.js +2 -0
- package/dist/esm/signers/wasmLoader.js.map +1 -1
- package/dist/esm/utils/apiClient.d.ts +10 -0
- package/dist/esm/utils/apiClient.d.ts.map +1 -1
- package/dist/esm/utils/apiClient.js +21 -0
- package/dist/esm/utils/apiClient.js.map +1 -1
- package/dist/types/LighterProvider.d.ts.map +1 -1
- package/dist/types/accountConfig.d.ts.map +1 -1
- package/dist/types/constants.d.ts +9 -1
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/signers/LighterSigner.d.ts +3 -2
- package/dist/types/signers/LighterSigner.d.ts.map +1 -1
- package/dist/types/signers/signActions.d.ts +13 -5
- package/dist/types/signers/signActions.d.ts.map +1 -1
- package/dist/types/signers/wasmLoader.d.ts +13 -0
- package/dist/types/signers/wasmLoader.d.ts.map +1 -1
- package/dist/types/utils/apiClient.d.ts +10 -0
- package/dist/types/utils/apiClient.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/LighterProvider.ts +2 -0
- package/src/accountConfig.ts +30 -7
- package/src/constants.ts +10 -0
- package/src/signers/LighterSigner.ts +66 -8
- package/src/signers/signActions.ts +112 -44
- package/src/signers/wasmLoader.ts +15 -0
- package/src/utils/apiClient.ts +25 -0
package/src/constants.ts
CHANGED
|
@@ -83,8 +83,18 @@ const LIGHTER_INVALID_AUTH_CODE = 20013
|
|
|
83
83
|
*/
|
|
84
84
|
const LIGHTER_SUCCESS_CODES = new Set([0, 200])
|
|
85
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Lighter body `code` meaning "operation succeeded" on the non-`/sendTx`
|
|
88
|
+
* mutation endpoints (`/changeAccountTier`, `/referral/use`). Any other code is
|
|
89
|
+
* a business-rule rejection surfaced verbatim to the caller.
|
|
90
|
+
*
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
const LIGHTER_MUTATION_SUCCESS_CODE = 200
|
|
94
|
+
|
|
86
95
|
export {
|
|
87
96
|
LIGHTER_CODE_ACCOUNT_NOT_FOUND,
|
|
88
97
|
LIGHTER_INVALID_AUTH_CODE,
|
|
98
|
+
LIGHTER_MUTATION_SUCCESS_CODE,
|
|
89
99
|
LIGHTER_SUCCESS_CODES,
|
|
90
100
|
}
|
|
@@ -263,8 +263,9 @@ export class LighterSigner {
|
|
|
263
263
|
/**
|
|
264
264
|
* Map an ActionType + backend-provided params object to the positional-arg
|
|
265
265
|
* WASM call. The Go signer exports take primitives in order, not an object
|
|
266
|
-
* — so we pick fields in the exact order the Go side expects.
|
|
267
|
-
* fields
|
|
266
|
+
* — so we pick fields in the exact order the Go side expects. Integrator
|
|
267
|
+
* fee fields pass through when present, falling back to the nil sentinels
|
|
268
|
+
* when absent; unrecognised fields are ignored.
|
|
268
269
|
*/
|
|
269
270
|
private dispatch(
|
|
270
271
|
wasm: LighterWasmExports,
|
|
@@ -290,9 +291,21 @@ export class LighterSigner {
|
|
|
290
291
|
numberField(p, 'reduce_only'),
|
|
291
292
|
numberField(p, 'trigger_price'),
|
|
292
293
|
numberField(p, 'order_expiry'),
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
294
|
+
optionalNumberField(
|
|
295
|
+
p,
|
|
296
|
+
'integrator_account_index',
|
|
297
|
+
NIL_INTEGRATOR_INDEX
|
|
298
|
+
),
|
|
299
|
+
optionalNumberField(
|
|
300
|
+
p,
|
|
301
|
+
'integrator_taker_fee',
|
|
302
|
+
NIL_INTEGRATOR_TAKER_FEE
|
|
303
|
+
),
|
|
304
|
+
optionalNumberField(
|
|
305
|
+
p,
|
|
306
|
+
'integrator_maker_fee',
|
|
307
|
+
NIL_INTEGRATOR_MAKER_FEE
|
|
308
|
+
),
|
|
296
309
|
SELF_TRADE_BEHAVIOR_EXPIRE_MAKER,
|
|
297
310
|
SELF_TRADE_EQUALITY_ACCOUNT_INDEX,
|
|
298
311
|
SKIP_NONCE_DISABLED,
|
|
@@ -326,9 +339,21 @@ export class LighterSigner {
|
|
|
326
339
|
numberField(p, 'base_amount'),
|
|
327
340
|
numberField(p, 'price'),
|
|
328
341
|
numberField(p, 'trigger_price'),
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
342
|
+
optionalNumberField(
|
|
343
|
+
p,
|
|
344
|
+
'integrator_account_index',
|
|
345
|
+
NIL_INTEGRATOR_INDEX
|
|
346
|
+
),
|
|
347
|
+
optionalNumberField(
|
|
348
|
+
p,
|
|
349
|
+
'integrator_taker_fee',
|
|
350
|
+
NIL_INTEGRATOR_TAKER_FEE
|
|
351
|
+
),
|
|
352
|
+
optionalNumberField(
|
|
353
|
+
p,
|
|
354
|
+
'integrator_maker_fee',
|
|
355
|
+
NIL_INTEGRATOR_MAKER_FEE
|
|
356
|
+
),
|
|
332
357
|
SELF_TRADE_BEHAVIOR_EXPIRE_MAKER,
|
|
333
358
|
SELF_TRADE_EQUALITY_ACCOUNT_INDEX,
|
|
334
359
|
SKIP_NONCE_DISABLED,
|
|
@@ -387,6 +412,27 @@ export class LighterSigner {
|
|
|
387
412
|
ctx.apiKeyIndex,
|
|
388
413
|
ctx.accountIndex
|
|
389
414
|
)
|
|
415
|
+
case ActionType.APPROVE_INTEGRATOR:
|
|
416
|
+
return wasm.SignApproveIntegrator(
|
|
417
|
+
numberField(p, 'integrator_account_index'),
|
|
418
|
+
numberField(p, 'max_perps_taker_fee'),
|
|
419
|
+
numberField(p, 'max_perps_maker_fee'),
|
|
420
|
+
numberField(p, 'max_spot_taker_fee'),
|
|
421
|
+
numberField(p, 'max_spot_maker_fee'),
|
|
422
|
+
numberField(p, 'approval_expiry'),
|
|
423
|
+
SKIP_NONCE_DISABLED,
|
|
424
|
+
nonce,
|
|
425
|
+
ctx.apiKeyIndex,
|
|
426
|
+
ctx.accountIndex
|
|
427
|
+
)
|
|
428
|
+
case ActionType.ACCOUNT_MODE:
|
|
429
|
+
return wasm.SignUpdateAccountConfig(
|
|
430
|
+
numberField(p, 'account_trading_mode'),
|
|
431
|
+
SKIP_NONCE_DISABLED,
|
|
432
|
+
nonce,
|
|
433
|
+
ctx.apiKeyIndex,
|
|
434
|
+
ctx.accountIndex
|
|
435
|
+
)
|
|
390
436
|
default:
|
|
391
437
|
throw new Error(
|
|
392
438
|
`Lighter WASM signer does not support action: ${action}`
|
|
@@ -431,6 +477,18 @@ function numberField(p: Record<string, unknown>, key: string): number {
|
|
|
431
477
|
)
|
|
432
478
|
}
|
|
433
479
|
|
|
480
|
+
function optionalNumberField(
|
|
481
|
+
p: Record<string, unknown>,
|
|
482
|
+
key: string,
|
|
483
|
+
fallback: number
|
|
484
|
+
): number {
|
|
485
|
+
const v = p[key]
|
|
486
|
+
if (v === undefined || v === null) {
|
|
487
|
+
return fallback
|
|
488
|
+
}
|
|
489
|
+
return numberField(p, key)
|
|
490
|
+
}
|
|
491
|
+
|
|
434
492
|
function stringField(p: Record<string, unknown>, key: string): string {
|
|
435
493
|
const v = p[key]
|
|
436
494
|
if (typeof v === 'string' && v !== '') {
|
|
@@ -11,20 +11,29 @@ import { ActionType, PerpsErrorCode, SigningMethod } from '@lifi/perps-types'
|
|
|
11
11
|
import type { Address } from 'viem'
|
|
12
12
|
import { parseAbi } from 'viem'
|
|
13
13
|
import { waitForTransactionReceipt } from 'viem/actions'
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
DEFAULT_API_KEY_INDEX,
|
|
16
|
+
LIGHTER_MUTATION_SUCCESS_CODE,
|
|
17
|
+
} from '../constants.js'
|
|
18
|
+
import type { ApiParams, LighterApiClient } from '../utils/apiClient.js'
|
|
15
19
|
import type { LighterApiKey, LighterKeyStore } from './LighterKeyStore.js'
|
|
16
20
|
import type { LighterSigner } from './LighterSigner.js'
|
|
17
21
|
|
|
18
22
|
/**
|
|
19
23
|
* Per-batch dependencies the Lighter `signActions` implementation needs:
|
|
20
24
|
* a WASM signer (`LighterSigner`), the API-key store keyed on L1 address,
|
|
21
|
-
*
|
|
22
|
-
*
|
|
25
|
+
* a REST client for the token-authenticated venue mutations that execute
|
|
26
|
+
* client-side, and a reference to the host SDK client for descriptor/account
|
|
27
|
+
* fetches within the REGISTER_API_KEY hybrid flow.
|
|
23
28
|
* @internal
|
|
24
29
|
*/
|
|
25
30
|
export interface LighterSignActionsDeps {
|
|
26
31
|
signer: LighterSigner
|
|
27
32
|
keyStore: LighterKeyStore
|
|
33
|
+
/** REST client bound to the user's Lighter base URL, used for the direct
|
|
34
|
+
* `changeAccountTier` / `referral/use` POSTs so their auth token never
|
|
35
|
+
* transits the LI.FI backend. */
|
|
36
|
+
apiClient: LighterApiClient
|
|
28
37
|
/**
|
|
29
38
|
* Resolve the user's Lighter `accountIndex` for an L1 address. Required
|
|
30
39
|
* by REGISTER_API_KEY so the ChangePubKey blob carries the right
|
|
@@ -34,15 +43,32 @@ export interface LighterSignActionsDeps {
|
|
|
34
43
|
resolveAccountIndex(address: Address): Promise<number>
|
|
35
44
|
}
|
|
36
45
|
|
|
46
|
+
/**
|
|
47
|
+
* `wasmSignParams.kind` values for the Lighter mutations that authenticate with
|
|
48
|
+
* a short-lived auth token instead of a wasm-signed transaction. Both execute
|
|
49
|
+
* client-side (SDK → Lighter REST) so the token never reaches the backend.
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
const TOKEN_AUTH_MUTATION_KINDS = new Set(['changeAccountTier', 'referralUse'])
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Lifetime of the per-call auth token minted for a token-authenticated venue
|
|
56
|
+
* mutation. Minutes, not the read endpoints' hours: it authenticates one POST
|
|
57
|
+
* that completes immediately, so it never lingers usable.
|
|
58
|
+
*/
|
|
59
|
+
const TOKEN_AUTH_MUTATION_DEADLINE_SECONDS = 5 * 60
|
|
60
|
+
|
|
37
61
|
/**
|
|
38
62
|
* Sign a `WASM_BLOB` batch (Lighter). Ensures the user's API keypair is
|
|
39
63
|
* registered first — generating one and running the REGISTER_API_KEY
|
|
40
64
|
* hybrid flow via the L1 signer if not — then feeds each subsequent step
|
|
41
65
|
* through the WASM signer.
|
|
42
66
|
*
|
|
43
|
-
* `ACCOUNT_TYPE`
|
|
44
|
-
*
|
|
45
|
-
*
|
|
67
|
+
* The token-authenticated mutations (`ACCOUNT_TYPE` → `/changeAccountTier`,
|
|
68
|
+
* `SET_REFERRAL` → `/referral/use`) are NOT wasm-signed: they execute
|
|
69
|
+
* client-side here via a direct Lighter POST authenticated with a short-lived
|
|
70
|
+
* auth token, so the token never transits the LI.FI backend. They produce no
|
|
71
|
+
* backend-bound step and are omitted from the returned array.
|
|
46
72
|
* @internal
|
|
47
73
|
*/
|
|
48
74
|
export async function signWasmBlobActions(
|
|
@@ -55,8 +81,10 @@ export async function signWasmBlobActions(
|
|
|
55
81
|
for (const step of steps) {
|
|
56
82
|
if (step.action === ActionType.REGISTER_API_KEY) {
|
|
57
83
|
signed.push(await signRegisterApiKey(deps, address, step, ctx))
|
|
58
|
-
} else if (
|
|
59
|
-
|
|
84
|
+
} else if (
|
|
85
|
+
TOKEN_AUTH_MUTATION_KINDS.has(step.wasmSignParams.kind as string)
|
|
86
|
+
) {
|
|
87
|
+
await executeTokenAuthMutation(deps, address, step)
|
|
60
88
|
} else {
|
|
61
89
|
signed.push(await signStandardWasmAction(deps, address, step))
|
|
62
90
|
}
|
|
@@ -169,44 +197,94 @@ async function signRegisterApiKey(
|
|
|
169
197
|
}
|
|
170
198
|
|
|
171
199
|
/**
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* Lighter's `/api/v1/changeAccountTier` is an HTTP-only mutation —
|
|
175
|
-
* Lighter does NOT consume a wasm-signed transaction here; it
|
|
176
|
-
* authenticates the request with the same auth token its read endpoints
|
|
177
|
-
* use, and enforces anti-replay business rules server-side. The backend
|
|
178
|
-
* declares the step as a `WasmBlobActionStep` with
|
|
179
|
-
* `wasmSignParams.kind = 'changeAccountTier'` and expects the SDK to create
|
|
180
|
-
* an auth token in lieu of a transaction signature; the executor reads
|
|
181
|
-
* `signedTx.txInfo` as the `auth` form parameter.
|
|
200
|
+
* Execute a token-authenticated Lighter mutation (`ACCOUNT_TYPE` →
|
|
201
|
+
* `/changeAccountTier`, `SET_REFERRAL` → `/referral/use`) client-side.
|
|
182
202
|
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
203
|
+
* Neither endpoint consumes a wasm-signed transaction — both authenticate with
|
|
204
|
+
* a Lighter auth token and enforce their business rules (open positions,
|
|
205
|
+
* pending orders, 24h tier cooldown) server-side. We mint a fresh short-lived
|
|
206
|
+
* token per call (never the stored read-only token, never persisted) and POST
|
|
207
|
+
* the mirror of the backend's form body directly to Lighter, so no auth token
|
|
208
|
+
* ever transits the LI.FI backend. A non-success verdict surfaces Lighter's
|
|
209
|
+
* `code`/`message` verbatim as an {@link PerpsErrorCode.ExchangeRejected}.
|
|
186
210
|
*/
|
|
187
|
-
async function
|
|
211
|
+
async function executeTokenAuthMutation(
|
|
188
212
|
deps: LighterSignActionsDeps,
|
|
189
213
|
address: Address,
|
|
190
214
|
step: WasmBlobActionStep
|
|
191
|
-
): Promise<
|
|
215
|
+
): Promise<void> {
|
|
192
216
|
const apiKey = await requireApiKey(deps, address)
|
|
193
|
-
const deadline =
|
|
217
|
+
const deadline =
|
|
218
|
+
Math.floor(Date.now() / 1000) + TOKEN_AUTH_MUTATION_DEADLINE_SECONDS
|
|
194
219
|
const authToken = await deps.signer.createAuthToken(deadline, {
|
|
195
220
|
apiKeyPrivateKey: apiKey.apiKeyPrivateKey,
|
|
196
221
|
apiKeyIndex: apiKey.apiKeyIndex,
|
|
197
222
|
accountIndex: apiKey.accountIndex,
|
|
198
223
|
})
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
224
|
+
|
|
225
|
+
const { path, params } = buildTokenAuthMutationRequest(step, authToken)
|
|
226
|
+
const { status, data } = await deps.apiClient.postForm<{
|
|
227
|
+
code?: number
|
|
228
|
+
message?: string
|
|
229
|
+
}>(path, params)
|
|
230
|
+
|
|
231
|
+
const code = data?.code
|
|
232
|
+
if (status < 200 || status >= 300 || code !== LIGHTER_MUTATION_SUCCESS_CODE) {
|
|
233
|
+
const suffix = data?.message ? `: ${data.message}` : ''
|
|
234
|
+
throw new PerpsError(
|
|
235
|
+
PerpsErrorCode.ExchangeRejected,
|
|
236
|
+
`Lighter ${step.action} rejected (code ${code ?? status})${suffix}`
|
|
237
|
+
)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Map a token-authenticated mutation step to its Lighter endpoint and
|
|
243
|
+
* form body, mirroring the backend's request contract. The auth token is the
|
|
244
|
+
* `auth` field; the remaining fields come from `wasmSignParams`.
|
|
245
|
+
*/
|
|
246
|
+
function buildTokenAuthMutationRequest(
|
|
247
|
+
step: WasmBlobActionStep,
|
|
248
|
+
authToken: string
|
|
249
|
+
): { path: string; params: ApiParams } {
|
|
250
|
+
const kind = step.wasmSignParams.kind
|
|
251
|
+
if (kind === 'changeAccountTier') {
|
|
252
|
+
const { account_index, new_tier } = step.wasmSignParams as {
|
|
253
|
+
account_index?: number
|
|
254
|
+
new_tier?: string
|
|
255
|
+
}
|
|
256
|
+
if (account_index == null || new_tier == null) {
|
|
257
|
+
throw new PerpsError(
|
|
258
|
+
PerpsErrorCode.SDKError,
|
|
259
|
+
'Lighter ACCOUNT_TYPE wasmSignParams missing account_index or new_tier'
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
path: '/api/v1/changeAccountTier',
|
|
264
|
+
params: { auth: authToken, account_index, new_tier },
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (kind === 'referralUse') {
|
|
268
|
+
const { l1_address, referral_code, x } = step.wasmSignParams as {
|
|
269
|
+
l1_address?: string
|
|
270
|
+
referral_code?: string
|
|
271
|
+
x?: string
|
|
272
|
+
}
|
|
273
|
+
if (l1_address == null || referral_code == null || x == null) {
|
|
274
|
+
throw new PerpsError(
|
|
275
|
+
PerpsErrorCode.SDKError,
|
|
276
|
+
'Lighter SET_REFERRAL wasmSignParams missing l1_address, referral_code, or x'
|
|
277
|
+
)
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
path: '/api/v1/referral/use',
|
|
281
|
+
params: { auth: authToken, l1_address, referral_code, x },
|
|
282
|
+
}
|
|
209
283
|
}
|
|
284
|
+
throw new PerpsError(
|
|
285
|
+
PerpsErrorCode.SDKError,
|
|
286
|
+
`Lighter token-auth mutation: unknown wasmSignParams.kind '${String(kind)}'`
|
|
287
|
+
)
|
|
210
288
|
}
|
|
211
289
|
|
|
212
290
|
async function requireApiKey(
|
|
@@ -266,16 +344,6 @@ export async function signEvmTxActions(
|
|
|
266
344
|
)
|
|
267
345
|
}
|
|
268
346
|
|
|
269
|
-
if (walletSigner.chain?.id !== params.chainId) {
|
|
270
|
-
throw new PerpsError(
|
|
271
|
-
PerpsErrorCode.SDKError,
|
|
272
|
-
`EVM_TX leg '${step.action}' targets chain ${params.chainId}, but the ` +
|
|
273
|
-
`connected wallet is on chain ${walletSigner.chain?.id ?? 'unknown'}. ` +
|
|
274
|
-
`Switch the wallet to chain ${params.chainId} before signing — the ` +
|
|
275
|
-
"SDK broadcasts on the wallet's active chain and does not switch it."
|
|
276
|
-
)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
347
|
const txHash = await walletSigner.writeContract({
|
|
280
348
|
address: params.to,
|
|
281
349
|
abi: parseAbi(params.abi),
|
|
@@ -159,6 +159,19 @@ export interface LighterWasmExports {
|
|
|
159
159
|
* three.
|
|
160
160
|
*/
|
|
161
161
|
SignUpdateMargin: (...args: unknown[]) => SignResult
|
|
162
|
+
/**
|
|
163
|
+
* 10 args: integratorAccountIndex, maxPerpsTakerFee, maxPerpsMakerFee,
|
|
164
|
+
* maxSpotTakerFee, maxSpotMakerFee, approvalExpiry, skipNonce, then the
|
|
165
|
+
* trailing three. Fees are uint32 ppm of `FeeTick` (1_000_000); a non-nil
|
|
166
|
+
* fee requires a non-nil integrator index.
|
|
167
|
+
*/
|
|
168
|
+
SignApproveIntegrator: (...args: unknown[]) => SignResult
|
|
169
|
+
/**
|
|
170
|
+
* 5 args: accountTradingMode (0 = Classic/Simple, 1 = Unified), skipNonce,
|
|
171
|
+
* then the trailing three. `accountTradingMode` is validated to {0, 1} by
|
|
172
|
+
* lighter-go before signing.
|
|
173
|
+
*/
|
|
174
|
+
SignUpdateAccountConfig: (...args: unknown[]) => SignResult
|
|
162
175
|
}
|
|
163
176
|
|
|
164
177
|
/** @internal */
|
|
@@ -183,6 +196,8 @@ const WASM_FUNCTION_NAMES = [
|
|
|
183
196
|
'SignUpdateLeverage',
|
|
184
197
|
'SignModifyOrder',
|
|
185
198
|
'SignUpdateMargin',
|
|
199
|
+
'SignApproveIntegrator',
|
|
200
|
+
'SignUpdateAccountConfig',
|
|
186
201
|
] as const
|
|
187
202
|
|
|
188
203
|
type GoClass = new () => {
|
package/src/utils/apiClient.ts
CHANGED
|
@@ -160,6 +160,31 @@ export class LighterApiClient {
|
|
|
160
160
|
return { status: response.status, data }
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Form-encoded POST to a Lighter mutation endpoint. Single-shot — never
|
|
165
|
+
* retried, since these are money/state writes whose outcome is unknown on a
|
|
166
|
+
* transport failure. Surfaces the raw `{status, body}` pair so the caller can
|
|
167
|
+
* map Lighter's per-endpoint business-rule `code` to a domain error verbatim.
|
|
168
|
+
*/
|
|
169
|
+
async postForm<T>(
|
|
170
|
+
path: string,
|
|
171
|
+
params: ApiParams
|
|
172
|
+
): Promise<{ status: number; data: T }> {
|
|
173
|
+
const body = new URLSearchParams()
|
|
174
|
+
for (const [k, v] of Object.entries(params)) {
|
|
175
|
+
body.set(k, String(v))
|
|
176
|
+
}
|
|
177
|
+
const fetchImpl = this.fetchImpl ?? fetch
|
|
178
|
+
const response = await fetchImpl(`${this.baseUrl}${path}`, {
|
|
179
|
+
method: 'POST',
|
|
180
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
181
|
+
body: body.toString(),
|
|
182
|
+
signal: this.signal,
|
|
183
|
+
})
|
|
184
|
+
const data = (await response.json().catch(() => undefined)) as T
|
|
185
|
+
return { status: response.status, data }
|
|
186
|
+
}
|
|
187
|
+
|
|
163
188
|
private async getChecked<T>(path: string, params?: ApiParams): Promise<T> {
|
|
164
189
|
const { status, data } = await this.getWithStatus<unknown>(path, params)
|
|
165
190
|
this.assertOk(path, status, data)
|