@lifi/perps-sdk-provider-lighter 1.9.0 → 2.1.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/accountSummary.js +1 -1
- package/dist/cjs/accountSummary.js.map +1 -1
- package/dist/cjs/signers/LighterSigner.d.ts.map +1 -1
- package/dist/cjs/signers/LighterSigner.js +23 -0
- package/dist/cjs/signers/LighterSigner.js.map +1 -1
- package/dist/cjs/signers/signActions.d.ts.map +1 -1
- package/dist/cjs/signers/signActions.js +14 -8
- package/dist/cjs/signers/signActions.js.map +1 -1
- package/dist/cjs/types/ws.d.ts +7 -0
- package/dist/cjs/types/ws.d.ts.map +1 -1
- package/dist/cjs/websocket/LighterWsProvider.d.ts +1 -0
- package/dist/cjs/websocket/LighterWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/LighterWsProvider.js +41 -0
- package/dist/cjs/websocket/LighterWsProvider.js.map +1 -1
- package/dist/esm/accountSummary.d.ts +3 -3
- package/dist/esm/accountSummary.js +4 -4
- package/dist/esm/accountSummary.js.map +1 -1
- package/dist/esm/signers/LighterSigner.d.ts.map +1 -1
- package/dist/esm/signers/LighterSigner.js +32 -0
- package/dist/esm/signers/LighterSigner.js.map +1 -1
- package/dist/esm/signers/signActions.d.ts +7 -5
- package/dist/esm/signers/signActions.d.ts.map +1 -1
- package/dist/esm/signers/signActions.js +21 -13
- package/dist/esm/signers/signActions.js.map +1 -1
- package/dist/esm/types/ws.d.ts +11 -1
- package/dist/esm/types/ws.d.ts.map +1 -1
- package/dist/esm/websocket/LighterWsProvider.d.ts +1 -0
- package/dist/esm/websocket/LighterWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/LighterWsProvider.js +44 -0
- package/dist/esm/websocket/LighterWsProvider.js.map +1 -1
- package/dist/types/accountSummary.d.ts +3 -3
- package/dist/types/signers/LighterSigner.d.ts.map +1 -1
- package/dist/types/signers/signActions.d.ts +7 -5
- package/dist/types/signers/signActions.d.ts.map +1 -1
- package/dist/types/types/ws.d.ts +11 -1
- package/dist/types/types/ws.d.ts.map +1 -1
- package/dist/types/websocket/LighterWsProvider.d.ts +1 -0
- package/dist/types/websocket/LighterWsProvider.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/accountSummary.ts +4 -4
- package/src/signers/LighterSigner.ts +54 -0
- package/src/signers/signActions.ts +21 -13
- package/src/types/ws.ts +12 -1
- package/src/websocket/LighterWsProvider.ts +49 -0
|
@@ -310,11 +310,13 @@ async function requireApiKey(
|
|
|
310
310
|
* remaining legs. Each step's `txParams` carries chainId, target, function
|
|
311
311
|
* name, args, and a human-readable abi from the backend.
|
|
312
312
|
*
|
|
313
|
-
*
|
|
314
|
-
*
|
|
315
|
-
* the
|
|
316
|
-
*
|
|
317
|
-
*
|
|
313
|
+
* Before broadcasting a leg the SDK switches the wallet to the leg's
|
|
314
|
+
* `txParams.chainId` via `ctx.switchToChain`, re-reading the returned client so
|
|
315
|
+
* the broadcast lands on the right chain even when legs target different chains.
|
|
316
|
+
* When no switch capability is supplied (local/private-key signer, or no
|
|
317
|
+
* `switchChain` hook configured) a leg whose target chain differs from the
|
|
318
|
+
* wallet's active chain throws before broadcasting, so a token approve/deposit
|
|
319
|
+
* can never land on an unintended chain.
|
|
318
320
|
* @internal
|
|
319
321
|
*/
|
|
320
322
|
export async function signEvmTxActions(
|
|
@@ -330,30 +332,36 @@ export async function signEvmTxActions(
|
|
|
330
332
|
)
|
|
331
333
|
}
|
|
332
334
|
|
|
335
|
+
const switchToChain = ctx?.switchToChain
|
|
333
336
|
const signed: EvmTxSignedActionStep[] = []
|
|
337
|
+
let legSigner = walletSigner
|
|
334
338
|
for (const step of steps) {
|
|
335
339
|
const params = step.txParams
|
|
336
340
|
|
|
337
|
-
if (
|
|
341
|
+
if (legSigner.chain?.id !== params.chainId && switchToChain) {
|
|
342
|
+
legSigner = await switchToChain(params.chainId)
|
|
343
|
+
}
|
|
344
|
+
if (legSigner.chain?.id !== params.chainId) {
|
|
338
345
|
throw new PerpsError(
|
|
339
346
|
PerpsErrorCode.SDKError,
|
|
340
347
|
`EVM_TX leg '${step.action}' targets chain ${params.chainId}, but the ` +
|
|
341
|
-
`connected wallet is on chain ${
|
|
342
|
-
|
|
343
|
-
|
|
348
|
+
`connected wallet is on chain ${legSigner.chain?.id ?? 'unknown'} and ` +
|
|
349
|
+
'no chain switch was performed. Configure a switchChain hook via ' +
|
|
350
|
+
`setSwitchChain, or connect the wallet to chain ${params.chainId} ` +
|
|
351
|
+
'before signing.'
|
|
344
352
|
)
|
|
345
353
|
}
|
|
346
354
|
|
|
347
|
-
const txHash = await
|
|
355
|
+
const txHash = await legSigner.writeContract({
|
|
348
356
|
address: params.to,
|
|
349
357
|
abi: parseAbi(params.abi),
|
|
350
358
|
functionName: params.functionName,
|
|
351
359
|
args: params.args,
|
|
352
|
-
chain:
|
|
353
|
-
account:
|
|
360
|
+
chain: legSigner.chain,
|
|
361
|
+
account: legSigner.account,
|
|
354
362
|
})
|
|
355
363
|
|
|
356
|
-
const receipt = await waitForTransactionReceipt(
|
|
364
|
+
const receipt = await waitForTransactionReceipt(legSigner, {
|
|
357
365
|
hash: txHash,
|
|
358
366
|
})
|
|
359
367
|
if (receipt.status === 'reverted') {
|
package/src/types/ws.ts
CHANGED
|
@@ -149,7 +149,18 @@ export type LtWsAccountAllTradesMessage = LtWsMessage & {
|
|
|
149
149
|
data?: { trades?: Record<string, unknown[]> | unknown[] }
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
/**
|
|
152
|
+
/**
|
|
153
|
+
* `user_stats/{account_index}` frame; decimal strings in USD.
|
|
154
|
+
* @public
|
|
155
|
+
*/
|
|
156
|
+
export type LtWsUserStatsMessage = LtWsMessage & {
|
|
157
|
+
stats?: {
|
|
158
|
+
collateral?: string
|
|
159
|
+
portfolio_value?: string
|
|
160
|
+
available_balance?: string
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
153
164
|
export type LtWsAccountAllPositionsMessage = LtWsMessage & {
|
|
154
165
|
type: 'subscribed/account_all_positions' | 'update/account_all_positions'
|
|
155
166
|
positions?: Record<string, unknown>
|
|
@@ -40,6 +40,7 @@ import type {
|
|
|
40
40
|
LtWsSpotMarketStats,
|
|
41
41
|
LtWsSpotMarketStatsAllMessage,
|
|
42
42
|
LtWsTradeMessage,
|
|
43
|
+
LtWsUserStatsMessage,
|
|
43
44
|
} from '../types/index.js'
|
|
44
45
|
import { LIGHTER_RETRY_DEFAULTS, LighterApiClient } from '../utils/apiClient.js'
|
|
45
46
|
import {
|
|
@@ -310,6 +311,8 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
310
311
|
return `fills:${sub.address.toLowerCase()}`
|
|
311
312
|
case 'positions':
|
|
312
313
|
return `positions:${sub.address.toLowerCase()}`
|
|
314
|
+
case 'accountSummary':
|
|
315
|
+
return `accountSummary:${sub.address.toLowerCase()}`
|
|
313
316
|
// No live wire sub (openChannel returns a no-op), but a stable key is
|
|
314
317
|
// still needed so the base's fan-out registry can track/release it.
|
|
315
318
|
case 'candle':
|
|
@@ -369,6 +372,17 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
369
372
|
}
|
|
370
373
|
return [{ channel: `trade/${id}`, needsAuth: false }]
|
|
371
374
|
}
|
|
375
|
+
if (sub.channel === 'accountSummary') {
|
|
376
|
+
const accountIndex = await this.resolveAccountIndex(sub.address)
|
|
377
|
+
// `user_stats` is publicly readable; no token needed.
|
|
378
|
+
return [
|
|
379
|
+
{
|
|
380
|
+
channel: `user_stats/${accountIndex}`,
|
|
381
|
+
needsAuth: false,
|
|
382
|
+
address: sub.address,
|
|
383
|
+
},
|
|
384
|
+
]
|
|
385
|
+
}
|
|
372
386
|
if (
|
|
373
387
|
sub.channel === 'orderUpdates' ||
|
|
374
388
|
sub.channel === 'fills' ||
|
|
@@ -503,6 +517,14 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
503
517
|
return
|
|
504
518
|
}
|
|
505
519
|
|
|
520
|
+
if (
|
|
521
|
+
msg.type === 'subscribed/user_stats' ||
|
|
522
|
+
msg.type === 'update/user_stats'
|
|
523
|
+
) {
|
|
524
|
+
this.handleUserStats(msg as LtWsUserStatsMessage)
|
|
525
|
+
return
|
|
526
|
+
}
|
|
527
|
+
|
|
506
528
|
if (
|
|
507
529
|
msg.type === 'subscribed/account_all_positions' ||
|
|
508
530
|
msg.type === 'update/account_all_positions'
|
|
@@ -531,6 +553,33 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
531
553
|
})
|
|
532
554
|
}
|
|
533
555
|
|
|
556
|
+
private handleUserStats(msg: LtWsUserStatsMessage): void {
|
|
557
|
+
const address = this.addressFromChannel(msg.channel, 'user_stats')
|
|
558
|
+
if (!address) {
|
|
559
|
+
return
|
|
560
|
+
}
|
|
561
|
+
const stats = msg.stats
|
|
562
|
+
const portfolio = Number.parseFloat(stats?.portfolio_value ?? '')
|
|
563
|
+
const available = Number.parseFloat(stats?.available_balance ?? '')
|
|
564
|
+
if (!Number.isFinite(portfolio) || !Number.isFinite(available)) {
|
|
565
|
+
return
|
|
566
|
+
}
|
|
567
|
+
// Identities of the REST 'net' semantics: `available_balance` nets locked
|
|
568
|
+
// margin out with PnL marked in, and `collateral` is gross, PnL-exclusive.
|
|
569
|
+
const collateral = Number.parseFloat(stats?.collateral ?? '')
|
|
570
|
+
this.emit(`accountSummary:${address}`, {
|
|
571
|
+
channel: 'accountSummary',
|
|
572
|
+
data: {
|
|
573
|
+
portfolioValue: portfolio.toString(),
|
|
574
|
+
availableMargin: available.toString(),
|
|
575
|
+
marginUsed: Math.max(portfolio - available, 0).toString(),
|
|
576
|
+
unrealizedPnl: Number.isFinite(collateral)
|
|
577
|
+
? (portfolio - collateral).toString()
|
|
578
|
+
: '0',
|
|
579
|
+
},
|
|
580
|
+
})
|
|
581
|
+
}
|
|
582
|
+
|
|
534
583
|
private handleAccountTrades(msg: LtWsAccountAllTradesMessage): void {
|
|
535
584
|
const address = this.addressFromChannel(msg.channel, 'account_all_trades')
|
|
536
585
|
if (!address) {
|