@lifi/perps-sdk-provider-lighter 13.0.1 → 14.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/cjs/LighterProvider.d.ts.map +1 -1
- package/dist/cjs/LighterProvider.js +11 -10
- package/dist/cjs/LighterProvider.js.map +1 -1
- package/dist/cjs/constants.d.ts +0 -1
- package/dist/cjs/constants.d.ts.map +1 -1
- package/dist/cjs/constants.js +1 -2
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/signers/signActions.d.ts +6 -1
- package/dist/cjs/signers/signActions.d.ts.map +1 -1
- package/dist/cjs/signers/signActions.js +46 -1
- package/dist/cjs/signers/signActions.js.map +1 -1
- package/dist/cjs/utils/registeredApiKey.d.ts +8 -0
- package/dist/cjs/utils/registeredApiKey.d.ts.map +1 -0
- package/dist/cjs/utils/registeredApiKey.js +11 -0
- package/dist/cjs/utils/registeredApiKey.js.map +1 -0
- package/dist/esm/LighterProvider.d.ts.map +1 -1
- package/dist/esm/LighterProvider.js +15 -11
- package/dist/esm/LighterProvider.js.map +1 -1
- package/dist/esm/constants.d.ts +0 -10
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.js +0 -10
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/signers/LighterKeyStore.d.ts +1 -1
- package/dist/esm/signers/LighterKeyStore.d.ts.map +1 -1
- package/dist/esm/signers/signActions.d.ts +22 -1
- package/dist/esm/signers/signActions.d.ts.map +1 -1
- package/dist/esm/signers/signActions.js +67 -2
- package/dist/esm/signers/signActions.js.map +1 -1
- package/dist/esm/utils/registeredApiKey.d.ts +21 -0
- package/dist/esm/utils/registeredApiKey.d.ts.map +1 -0
- package/dist/esm/utils/registeredApiKey.js +13 -0
- package/dist/esm/utils/registeredApiKey.js.map +1 -0
- package/dist/types/LighterProvider.d.ts.map +1 -1
- package/dist/types/constants.d.ts +0 -10
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/signers/LighterKeyStore.d.ts +1 -1
- package/dist/types/signers/LighterKeyStore.d.ts.map +1 -1
- package/dist/types/signers/signActions.d.ts +22 -1
- package/dist/types/signers/signActions.d.ts.map +1 -1
- package/dist/types/utils/registeredApiKey.d.ts +21 -0
- package/dist/types/utils/registeredApiKey.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/LighterProvider.ts +22 -21
- package/src/constants.ts +0 -11
- package/src/index.ts +0 -1
- package/src/signers/LighterKeyStore.ts +1 -1
- package/src/signers/signActions.ts +117 -5
- package/src/utils/registeredApiKey.ts +34 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LighterProvider.d.ts","sourceRoot":"","sources":["../../src/LighterProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,mBAAmB,EAmBxB,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAA;AA6BxB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAGnC,OAAO,
|
|
1
|
+
{"version":3,"file":"LighterProvider.d.ts","sourceRoot":"","sources":["../../src/LighterProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,mBAAmB,EAmBxB,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAA;AA6BxB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAGnC,OAAO,EASL,KAAK,iBAAiB,EACvB,MAAM,gBAAgB,CAAA;AA2GvB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;IACrD,4FAA4F;IAC5F,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,4FAA4F;IAC5F,uBAAuB,CAAC,EAAE,MAAM,CAAA;CACjC;AAQD;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D;;;;;OAKG;IACH,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CAChE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,GAChC,YAAY,iBAAiB,EAC7B,UAAS,sBAA2B,KACnC,oBA4rCF,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAS,sBAA2B,KACnC,oBACyD,CAAA;AAE5D;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAS,sBAA2B,KACnC,oBAA6E,CAAA;AAEhF;;;;GAIG;AACH,eAAO,MAAM,OAAO,aA7BT,sBAAsB,KAC9B,oBA4BmC,CAAA"}
|
|
@@ -161,16 +161,6 @@ export declare const LIGHTER_ALL_MARKETS_WILDCARD = 255;
|
|
|
161
161
|
* @internal
|
|
162
162
|
*/
|
|
163
163
|
export declare const LIGHTER_HISTORY_PAGE_SIZE = 100;
|
|
164
|
-
/**
|
|
165
|
-
* Default API key slot — reused per account. Lighter's docs reserve indexes
|
|
166
|
-
* `{0,1,2,3}` for its own desktop/mobile interfaces; user keys start at 4
|
|
167
|
-
* (max 254, with 255 reserved as `NilApiKeyIndex`). 42 is the LI.FI-wide
|
|
168
|
-
* identifier so a user running both the Lighter app and the widget never
|
|
169
|
-
* collides with the app's session key.
|
|
170
|
-
*
|
|
171
|
-
* @public
|
|
172
|
-
*/
|
|
173
|
-
export declare const DEFAULT_API_KEY_INDEX = 42;
|
|
174
164
|
/** @internal */
|
|
175
165
|
declare const LIGHTER_CODE_ACCOUNT_NOT_FOUND = 21100;
|
|
176
166
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAGpE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,YAAY,CAAA;AAE7C;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,eAAe,CAAA;AAEnD;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,SAAS,CAAA;AAE9C;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,wCAAwC,CAAA;AAC7E;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,6CAA6C,CAAA;AAEhF;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,MAAM,CAAA;AAElD;;;;;GAKG;AACH,eAAO,MAAM,oCAAoC,2CACP,CAAA;AAE1C;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAC5C,kBAAkB,EAClB,sBAAsB,CAUvB,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,WAAW,EAAE,kBAAkB,CAAA;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,uFAAuF;IACvF,aAAa,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,UAAU,EAAE,sBAAsB,CAAA;IAClC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,iBAOvC,CAAA;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,+BAA+B,CAAA;AAC/D;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,oCAAoC,CAAA;AAElE;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,SAAS,CAAA;AAEhD;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,iBAOlC,CAAA;AAEF,gBAAgB;AAChB,eAAO,MAAM,oBAAoB,KAAK,CAAA;AAEtC;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,UAAY,CAAA;AAE/C;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,OAAoC,CAAA;AAExE;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAA;AAE/C;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAGpE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,YAAY,CAAA;AAE7C;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,eAAe,CAAA;AAEnD;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,SAAS,CAAA;AAE9C;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,wCAAwC,CAAA;AAC7E;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,6CAA6C,CAAA;AAEhF;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,MAAM,CAAA;AAElD;;;;;GAKG;AACH,eAAO,MAAM,oCAAoC,2CACP,CAAA;AAE1C;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAC5C,kBAAkB,EAClB,sBAAsB,CAUvB,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,WAAW,EAAE,kBAAkB,CAAA;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,uFAAuF;IACvF,aAAa,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,UAAU,EAAE,sBAAsB,CAAA;IAClC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,iBAOvC,CAAA;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,+BAA+B,CAAA;AAC/D;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,oCAAoC,CAAA;AAElE;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,SAAS,CAAA;AAEhD;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,iBAOlC,CAAA;AAEF,gBAAgB;AAChB,eAAO,MAAM,oBAAoB,KAAK,CAAA;AAEtC;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,UAAY,CAAA;AAE/C;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,OAAoC,CAAA;AAExE;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAA;AAE/C;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C,gBAAgB;AAChB,QAAA,MAAM,8BAA8B,QAAQ,CAAA;AAE5C;;;;GAIG;AACH,QAAA,MAAM,yBAAyB,QAAQ,CAAA;AAEvC;;;;;;GAMG;AACH,QAAA,MAAM,qBAAqB,aAAoB,CAAA;AAE/C;;;;;;GAMG;AACH,QAAA,MAAM,6BAA6B,MAAM,CAAA;AAEzC,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,EAC7B,qBAAqB,GACtB,CAAA"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
export { projectLighterConfigSettings } from './accountConfig.js';
|
|
13
13
|
export { getAccountSummary } from './accountSummary.js';
|
|
14
14
|
export type { LighterCollateralAsset, LighterDeployment, } from './constants.js';
|
|
15
|
-
export {
|
|
15
|
+
export { DEFAULT_LIGHTER_EXPLORER_TX_BASE_URL, DEFAULT_LIGHTER_REST_URL, DEFAULT_LIGHTER_WS_URL, LIGHTER_COLLATERAL_ASSETS, LIGHTER_MAINNET_DEPLOYMENT, LIGHTER_MAINNET_SIGNER_CHAIN_ID, LIGHTER_PROVIDER_KEY, LIGHTER_RH_DEPLOYMENT, LIGHTER_RH_PROVIDER_KEY, LIGHTER_RH_REST_URL, LIGHTER_RH_SIGNER_CHAIN_ID, LIGHTER_RH_WS_URL, LIGHTER_SPOT_CATEGORY_ID, } from './constants.js';
|
|
16
16
|
export { lighterDepositFlow } from './depositFlow.js';
|
|
17
17
|
export type { LighterPerpsProvider, LighterProviderOptions, } from './LighterProvider.js';
|
|
18
18
|
export { Lighter, lighterProvider, lighterRhProvider, } from './LighterProvider.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EACV,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EACV,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,oCAAoC,EACpC,wBAAwB,EACxB,sBAAsB,EACtB,yBAAyB,EACzB,0BAA0B,EAC1B,+BAA+B,EAC/B,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,EACnB,0BAA0B,EAC1B,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,YAAY,EACV,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,OAAO,EACP,eAAe,EACf,iBAAiB,GAClB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAEzD,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,YAAY,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAA;AAChF,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,iBAAiB,GAClB,MAAM,kCAAkC,CAAA"}
|
|
@@ -11,7 +11,7 @@ import type { Address } from 'viem';
|
|
|
11
11
|
export interface LighterApiKey {
|
|
12
12
|
/** Lighter account index, looked up once via accountsByL1Address. */
|
|
13
13
|
accountIndex: number;
|
|
14
|
-
/** API key slot (0-255)
|
|
14
|
+
/** API key slot (0-255), as named by the backend registration payload. */
|
|
15
15
|
apiKeyIndex: number;
|
|
16
16
|
/** Lighter-native private key (0x-prefixed hex). */
|
|
17
17
|
apiKeyPrivateKey: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LighterKeyStore.d.ts","sourceRoot":"","sources":["../../../src/signers/LighterKeyStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAC1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAWnC;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAA;IACpB,
|
|
1
|
+
{"version":3,"file":"LighterKeyStore.d.ts","sourceRoot":"","sources":["../../../src/signers/LighterKeyStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAC1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAWnC;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAA;IACpB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAA;IACnB,oDAAoD;IACpD,gBAAgB,EAAE,MAAM,CAAA;IACxB,6DAA6D;IAC7D,eAAe,EAAE,MAAM,CAAA;CACxB;AAoBD;;;;;;GAMG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,OAAO,CAAC,WAAW,CAAoB;IAEvC;;;;OAIG;gBAED,OAAO,EAAE,cAAc,EACvB,WAAW,GAAE,kBAAyC;IAMxD;;;;;OAKG;IACH,eAAe,CAAC,WAAW,EAAE,kBAAkB,GAAG,IAAI;IAMtD,OAAO,CAAC,UAAU;IAOlB;;;OAGG;IACG,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAc1D;;;OAGG;IACG,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhE;;;OAGG;IACG,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAK9C"}
|
|
@@ -3,7 +3,7 @@ import type { ActionStep, EvmTxActionStep, EvmTxSignedActionStep, SignedActionSt
|
|
|
3
3
|
import { SigningMethod } from '@lifi/perps-types';
|
|
4
4
|
import type { Address } from 'viem';
|
|
5
5
|
import type { LighterApiClient } from '../utils/apiClient.js';
|
|
6
|
-
import type { LighterKeyStore } from './LighterKeyStore.js';
|
|
6
|
+
import type { LighterApiKey, LighterKeyStore } from './LighterKeyStore.js';
|
|
7
7
|
import type { LighterSigner } from './LighterSigner.js';
|
|
8
8
|
/**
|
|
9
9
|
* Per-batch dependencies the Lighter `signActions` implementation needs:
|
|
@@ -21,6 +21,11 @@ export interface LighterSignActionsDeps {
|
|
|
21
21
|
* `changeAccountTier` / `referral/use` POSTs so their auth token never
|
|
22
22
|
* transits the LI.FI backend. */
|
|
23
23
|
apiClient: LighterApiClient;
|
|
24
|
+
/**
|
|
25
|
+
* Pre-sign guard that the stored API key still occupies its venue slot.
|
|
26
|
+
* Created once per provider instance so its freshness window spans batches.
|
|
27
|
+
*/
|
|
28
|
+
apiKeyFreshness: LighterApiKeyFreshness;
|
|
24
29
|
/**
|
|
25
30
|
* Resolve the user's Lighter `accountIndex` for an L1 address. Required
|
|
26
31
|
* by REGISTER_API_KEY so the ChangePubKey blob carries the right
|
|
@@ -29,6 +34,22 @@ export interface LighterSignActionsDeps {
|
|
|
29
34
|
*/
|
|
30
35
|
resolveAccountIndex(address: Address): Promise<number>;
|
|
31
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Pre-sign guard that the stored Lighter API key is still the key registered
|
|
39
|
+
* in its venue slot. Owns the freshness window, so one instance is created per
|
|
40
|
+
* provider instance and shared by every batch that instance signs.
|
|
41
|
+
*
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export interface LighterApiKeyFreshness {
|
|
45
|
+
assertStillRegistered(client: LighterApiClient, address: Address, apiKey: LighterApiKey): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build the guard {@link LighterSignActionsDeps.apiKeyFreshness} needs.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
export declare const createLighterApiKeyFreshness: () => LighterApiKeyFreshness;
|
|
32
53
|
/**
|
|
33
54
|
* Sign a `WASM_BLOB` batch (Lighter). Ensures the user's API keypair is
|
|
34
55
|
* registered first — generating one and running the REGISTER_API_KEY
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signActions.d.ts","sourceRoot":"","sources":["../../../src/signers/signActions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACzB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAA8B,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"signActions.d.ts","sourceRoot":"","sources":["../../../src/signers/signActions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACzB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAA8B,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAInC,OAAO,KAAK,EAAa,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAMxE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC1E,OAAO,KAAK,EAEV,aAAa,EAEd,MAAM,oBAAoB,CAAA;AAE3B;;;;;;;;GAQG;AACH,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,aAAa,CAAA;IACrB,QAAQ,EAAE,eAAe,CAAA;IACzB;;qCAEiC;IACjC,SAAS,EAAE,gBAAgB,CAAA;IAC3B;;;OAGG;IACH,eAAe,EAAE,sBAAsB,CAAA;IACvC;;;;;OAKG;IACH,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACvD;AAyBD;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,qBAAqB,CACnB,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAAA;CACjB;AAED;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,QAAO,sBAqD/C,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,sBAAsB,EAC5B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,kBAAkB,EAAE,EAC3B,GAAG,EAAE,kBAAkB,GAAG,SAAS,GAClC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAkCrC;AAsUD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,eAAe,EAAE,EACxB,GAAG,EAAE,kBAAkB,GAAG,SAAS,GAClC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CA6ElC;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,sBAAsB,EAC5B,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,EAAE,OAAO,EAChB,GAAG,CAAC,EAAE,kBAAkB,GACvB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAsB7B"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { LighterApiClient } from './apiClient.js';
|
|
2
|
+
/**
|
|
3
|
+
* One entry of Lighter's `/api/v1/apikeys` response: the public key the venue
|
|
4
|
+
* holds in an API-key slot.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export interface LighterRegisteredApiKey {
|
|
9
|
+
api_key_index: number;
|
|
10
|
+
public_key: string;
|
|
11
|
+
}
|
|
12
|
+
/** Compare Lighter public keys irrespective of `0x` prefix / casing. */
|
|
13
|
+
export declare const normalizeLighterPublicKey: (key: string) => string;
|
|
14
|
+
/**
|
|
15
|
+
* Read the public key Lighter holds in one API-key slot. Returns `undefined`
|
|
16
|
+
* when the response carries no entry for `apiKeyIndex`.
|
|
17
|
+
*
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export declare const fetchRegisteredApiKey: (client: LighterApiClient, accountIndex: number, apiKeyIndex: number) => Promise<LighterRegisteredApiKey | undefined>;
|
|
21
|
+
//# sourceMappingURL=registeredApiKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registeredApiKey.d.ts","sourceRoot":"","sources":["../../../src/utils/registeredApiKey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wEAAwE;AACxE,eAAO,MAAM,yBAAyB,GAAI,KAAK,MAAM,KAAG,MACjB,CAAA;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,gBAAgB,EACxB,cAAc,MAAM,EACpB,aAAa,MAAM,KAClB,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAM7C,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifi/perps-sdk-provider-lighter",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "14.0.0",
|
|
4
4
|
"description": "Lighter provider plugin for @lifi/perps-sdk",
|
|
5
5
|
"homepage": "https://github.com/lifinance/perps-sdk",
|
|
6
6
|
"bugs": {
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"big.js": "^7.0.1",
|
|
46
46
|
"viem": "^2.55.18",
|
|
47
|
-
"@lifi/perps-types": "^
|
|
47
|
+
"@lifi/perps-types": "^8.0.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@lifi/perps-sdk": "^7.0.
|
|
50
|
+
"@lifi/perps-sdk": "^7.0.1"
|
|
51
51
|
},
|
|
52
52
|
"publishConfig": {
|
|
53
53
|
"access": "public"
|
package/src/LighterProvider.ts
CHANGED
|
@@ -60,7 +60,6 @@ import type { Address } from 'viem'
|
|
|
60
60
|
import { projectLighterConfigSettings } from './accountConfig.js'
|
|
61
61
|
import { getAccountSummary } from './accountSummary.js'
|
|
62
62
|
import {
|
|
63
|
-
DEFAULT_API_KEY_INDEX,
|
|
64
63
|
DEFAULT_TRADES_LIMIT,
|
|
65
64
|
LIGHTER_ALL_MARKETS_WILDCARD,
|
|
66
65
|
LIGHTER_BASE_FEE_TIER,
|
|
@@ -76,7 +75,10 @@ import { createAuthToken } from './signers/createAuthToken.js'
|
|
|
76
75
|
import { LighterKeyStore } from './signers/LighterKeyStore.js'
|
|
77
76
|
import { LighterReadOnlyTokenManager } from './signers/LighterReadOnlyTokenManager.js'
|
|
78
77
|
import { LighterSigner } from './signers/LighterSigner.js'
|
|
79
|
-
import {
|
|
78
|
+
import {
|
|
79
|
+
createLighterApiKeyFreshness,
|
|
80
|
+
lighterSignActions,
|
|
81
|
+
} from './signers/signActions.js'
|
|
80
82
|
import type {
|
|
81
83
|
LtAccountLimits,
|
|
82
84
|
LtDepositHistoryResponse,
|
|
@@ -119,6 +121,10 @@ import {
|
|
|
119
121
|
toRequiredBig,
|
|
120
122
|
} from './utils/index.js'
|
|
121
123
|
import { mapRunningTwap } from './utils/mapTwap.js'
|
|
124
|
+
import {
|
|
125
|
+
fetchRegisteredApiKey,
|
|
126
|
+
normalizeLighterPublicKey,
|
|
127
|
+
} from './utils/registeredApiKey.js'
|
|
122
128
|
|
|
123
129
|
const ZERO_FEE_TIER = { maker: '0', taker: '0' }
|
|
124
130
|
|
|
@@ -170,10 +176,6 @@ interface ReadOnlyCreationBackoff {
|
|
|
170
176
|
attempt: number
|
|
171
177
|
}
|
|
172
178
|
|
|
173
|
-
/** Compare Lighter public keys irrespective of `0x` prefix / casing. */
|
|
174
|
-
const normalizeLighterPublicKey = (key: string): string =>
|
|
175
|
-
key.replace(/^0x/i, '').toLowerCase()
|
|
176
|
-
|
|
177
179
|
/**
|
|
178
180
|
* Consumer-level overrides for a ready-made Lighter provider plugin. Every
|
|
179
181
|
* deployment fact — provider key, endpoints, signing chain id, collateral
|
|
@@ -285,6 +287,7 @@ export const createLighterProvider = (
|
|
|
285
287
|
collateralAssetIndex: collateral.assetIndex,
|
|
286
288
|
})
|
|
287
289
|
const keyStore = new LighterKeyStore(storage, providerKey)
|
|
290
|
+
const apiKeyFreshness = createLighterApiKeyFreshness()
|
|
288
291
|
const readOnlyTokenManager = new LighterReadOnlyTokenManager({
|
|
289
292
|
storage,
|
|
290
293
|
providerKey,
|
|
@@ -518,18 +521,6 @@ export const createLighterProvider = (
|
|
|
518
521
|
}
|
|
519
522
|
}
|
|
520
523
|
|
|
521
|
-
const fetchRegisteredApiKey = async (
|
|
522
|
-
client: LighterApiClient,
|
|
523
|
-
accountIndex: number,
|
|
524
|
-
apiKeyIndex: number
|
|
525
|
-
): Promise<{ api_key_index: number; public_key: string } | undefined> => {
|
|
526
|
-
const response = await client.get<{
|
|
527
|
-
code: number
|
|
528
|
-
api_keys: Array<{ api_key_index: number; public_key: string }>
|
|
529
|
-
}>('/api/v1/apikeys', { account_index: accountIndex })
|
|
530
|
-
return response.api_keys?.find((k) => k.api_key_index === apiKeyIndex)
|
|
531
|
-
}
|
|
532
|
-
|
|
533
524
|
const fetchAccountLimits = (
|
|
534
525
|
client: LighterApiClient,
|
|
535
526
|
accountIndex: number,
|
|
@@ -714,6 +705,9 @@ export const createLighterProvider = (
|
|
|
714
705
|
// Shared promise: the referral read below awaits this instance's runtime
|
|
715
706
|
// metadata off the same `/providers` fetch — no second request.
|
|
716
707
|
const providersPromise = getProviders(requireClient())
|
|
708
|
+
// Shared promise: the registered-key read names the slot off the local
|
|
709
|
+
// record, and the config readout reports the record — one storage read.
|
|
710
|
+
const localKeyPromise = keyStore.get(params.address)
|
|
717
711
|
const [
|
|
718
712
|
{ providers },
|
|
719
713
|
,
|
|
@@ -727,7 +721,13 @@ export const createLighterProvider = (
|
|
|
727
721
|
providersPromise,
|
|
728
722
|
registry.sync(),
|
|
729
723
|
assetRegistry.sync(),
|
|
730
|
-
|
|
724
|
+
// The local record names the only slot worth reading: no record means
|
|
725
|
+
// nothing to compare the registered key against, so the read is skipped.
|
|
726
|
+
localKeyPromise.then((key) =>
|
|
727
|
+
key === null
|
|
728
|
+
? undefined
|
|
729
|
+
: fetchRegisteredApiKey(client, account.index, key.apiKeyIndex)
|
|
730
|
+
),
|
|
731
731
|
// No token is a legitimate unauthenticated read → undefined → zero fee
|
|
732
732
|
// tier. A generic fetch error is NOT: it must propagate, never be
|
|
733
733
|
// coerced to a fabricated 0%/0% fee tier. One carve-out: a token the
|
|
@@ -742,7 +742,7 @@ export const createLighterProvider = (
|
|
|
742
742
|
fetchAccountLimits(client, account.index, t)
|
|
743
743
|
)
|
|
744
744
|
),
|
|
745
|
-
|
|
745
|
+
localKeyPromise,
|
|
746
746
|
readOnlyTokenManager.get(params.address, account.index),
|
|
747
747
|
// The expected code is backend-owned runtime metadata on this
|
|
748
748
|
// instance's own provider descriptor (keyed by `providerKey`, so the
|
|
@@ -850,7 +850,7 @@ export const createLighterProvider = (
|
|
|
850
850
|
const config: LighterAccountConfig = {
|
|
851
851
|
provider: providerKey,
|
|
852
852
|
accountIndex: account.index,
|
|
853
|
-
apiKeyIndex:
|
|
853
|
+
apiKeyIndex: localKey?.apiKeyIndex,
|
|
854
854
|
apiKeyRegistered,
|
|
855
855
|
accountType: account.account_type,
|
|
856
856
|
accountTradingMode: account.account_trading_mode,
|
|
@@ -1449,6 +1449,7 @@ export const createLighterProvider = (
|
|
|
1449
1449
|
signer,
|
|
1450
1450
|
keyStore,
|
|
1451
1451
|
apiClient: apiClient(),
|
|
1452
|
+
apiKeyFreshness,
|
|
1452
1453
|
resolveAccountIndex: async (addr) => {
|
|
1453
1454
|
const apiKey = await keyStore.get(addr)
|
|
1454
1455
|
if (apiKey !== null) {
|
package/src/constants.ts
CHANGED
|
@@ -208,17 +208,6 @@ export const LIGHTER_ALL_MARKETS_WILDCARD = 255
|
|
|
208
208
|
*/
|
|
209
209
|
export const LIGHTER_HISTORY_PAGE_SIZE = 100
|
|
210
210
|
|
|
211
|
-
/**
|
|
212
|
-
* Default API key slot — reused per account. Lighter's docs reserve indexes
|
|
213
|
-
* `{0,1,2,3}` for its own desktop/mobile interfaces; user keys start at 4
|
|
214
|
-
* (max 254, with 255 reserved as `NilApiKeyIndex`). 42 is the LI.FI-wide
|
|
215
|
-
* identifier so a user running both the Lighter app and the widget never
|
|
216
|
-
* collides with the app's session key.
|
|
217
|
-
*
|
|
218
|
-
* @public
|
|
219
|
-
*/
|
|
220
|
-
export const DEFAULT_API_KEY_INDEX = 42
|
|
221
|
-
|
|
222
211
|
/** @internal */
|
|
223
212
|
const LIGHTER_CODE_ACCOUNT_NOT_FOUND = 21100
|
|
224
213
|
|
package/src/index.ts
CHANGED
|
@@ -21,7 +21,7 @@ const STORAGE_PREFIX = 'lifi-perps-lighter-key'
|
|
|
21
21
|
export interface LighterApiKey {
|
|
22
22
|
/** Lighter account index, looked up once via accountsByL1Address. */
|
|
23
23
|
accountIndex: number
|
|
24
|
-
/** API key slot (0-255)
|
|
24
|
+
/** API key slot (0-255), as named by the backend registration payload. */
|
|
25
25
|
apiKeyIndex: number
|
|
26
26
|
/** Lighter-native private key (0x-prefixed hex). */
|
|
27
27
|
apiKeyPrivateKey: string
|
|
@@ -11,11 +11,13 @@ 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 {
|
|
15
|
-
DEFAULT_API_KEY_INDEX,
|
|
16
|
-
LIGHTER_MUTATION_SUCCESS_CODE,
|
|
17
|
-
} from '../constants.js'
|
|
14
|
+
import { LIGHTER_MUTATION_SUCCESS_CODE } from '../constants.js'
|
|
18
15
|
import type { ApiParams, LighterApiClient } from '../utils/apiClient.js'
|
|
16
|
+
import {
|
|
17
|
+
fetchRegisteredApiKey,
|
|
18
|
+
type LighterRegisteredApiKey,
|
|
19
|
+
normalizeLighterPublicKey,
|
|
20
|
+
} from '../utils/registeredApiKey.js'
|
|
19
21
|
import type { LighterApiKey, LighterKeyStore } from './LighterKeyStore.js'
|
|
20
22
|
import type {
|
|
21
23
|
LighterSignedBlob,
|
|
@@ -39,6 +41,11 @@ export interface LighterSignActionsDeps {
|
|
|
39
41
|
* `changeAccountTier` / `referral/use` POSTs so their auth token never
|
|
40
42
|
* transits the LI.FI backend. */
|
|
41
43
|
apiClient: LighterApiClient
|
|
44
|
+
/**
|
|
45
|
+
* Pre-sign guard that the stored API key still occupies its venue slot.
|
|
46
|
+
* Created once per provider instance so its freshness window spans batches.
|
|
47
|
+
*/
|
|
48
|
+
apiKeyFreshness: LighterApiKeyFreshness
|
|
42
49
|
/**
|
|
43
50
|
* Resolve the user's Lighter `accountIndex` for an L1 address. Required
|
|
44
51
|
* by REGISTER_API_KEY so the ChangePubKey blob carries the right
|
|
@@ -63,6 +70,89 @@ const TOKEN_AUTH_MUTATION_KINDS = new Set(['changeAccountTier', 'referralUse'])
|
|
|
63
70
|
*/
|
|
64
71
|
const TOKEN_AUTH_MUTATION_DEADLINE_SECONDS = 5 * 60
|
|
65
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Window in which one `/apikeys` read stands for the next. 30s keeps a burst
|
|
75
|
+
* of batches — several orders submitted back to back, a close-then-reduce
|
|
76
|
+
* sequence — at one read, and still surfaces a key rotated on another device
|
|
77
|
+
* on the user's next action instead of after a venue rejection.
|
|
78
|
+
*/
|
|
79
|
+
const API_KEY_FRESHNESS_WINDOW_MS = 30_000
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Pre-sign guard that the stored Lighter API key is still the key registered
|
|
83
|
+
* in its venue slot. Owns the freshness window, so one instance is created per
|
|
84
|
+
* provider instance and shared by every batch that instance signs.
|
|
85
|
+
*
|
|
86
|
+
* @internal
|
|
87
|
+
*/
|
|
88
|
+
export interface LighterApiKeyFreshness {
|
|
89
|
+
assertStillRegistered(
|
|
90
|
+
client: LighterApiClient,
|
|
91
|
+
address: Address,
|
|
92
|
+
apiKey: LighterApiKey
|
|
93
|
+
): Promise<void>
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Build the guard {@link LighterSignActionsDeps.apiKeyFreshness} needs.
|
|
98
|
+
*
|
|
99
|
+
* @internal
|
|
100
|
+
*/
|
|
101
|
+
export const createLighterApiKeyFreshness = (): LighterApiKeyFreshness => {
|
|
102
|
+
const checkedAtMs = new Map<string, number>()
|
|
103
|
+
return {
|
|
104
|
+
async assertStillRegistered(client, address, apiKey) {
|
|
105
|
+
const storedKey = normalizeLighterPublicKey(apiKey.apiKeyPublicKey)
|
|
106
|
+
// Keyed on the stored key, so a rotation retires the entry by itself.
|
|
107
|
+
const windowKey = `${apiKey.accountIndex}:${apiKey.apiKeyIndex}:${storedKey}`
|
|
108
|
+
const checkedAt = checkedAtMs.get(windowKey)
|
|
109
|
+
if (
|
|
110
|
+
checkedAt !== undefined &&
|
|
111
|
+
Date.now() - checkedAt < API_KEY_FRESHNESS_WINDOW_MS
|
|
112
|
+
) {
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let registered: LighterRegisteredApiKey | undefined
|
|
117
|
+
try {
|
|
118
|
+
registered = await fetchRegisteredApiKey(
|
|
119
|
+
client,
|
|
120
|
+
apiKey.accountIndex,
|
|
121
|
+
apiKey.apiKeyIndex
|
|
122
|
+
)
|
|
123
|
+
} catch (err) {
|
|
124
|
+
// A transport failure or a non-success body proves nothing about the
|
|
125
|
+
// slot, so the venue decides. A failed check never blocks a signature.
|
|
126
|
+
// The code names the failure without the response body, which lists
|
|
127
|
+
// the account's other key slots.
|
|
128
|
+
console.warn(
|
|
129
|
+
'[lighter] could not read the registered API key before signing; ' +
|
|
130
|
+
'signing anyway and letting the venue decide.',
|
|
131
|
+
err instanceof PerpsError ? err.code : String(err)
|
|
132
|
+
)
|
|
133
|
+
checkedAtMs.set(windowKey, Date.now())
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
// A slot carrying no entry leaves nothing to compare against.
|
|
137
|
+
if (
|
|
138
|
+
registered !== undefined &&
|
|
139
|
+
normalizeLighterPublicKey(registered.public_key) !== storedKey
|
|
140
|
+
) {
|
|
141
|
+
throw new PerpsError(
|
|
142
|
+
PerpsErrorCode.SDKError,
|
|
143
|
+
`The Lighter API key stored for ${address} is no longer registered: ` +
|
|
144
|
+
`API-key slot ${apiKey.apiKeyIndex} now holds a different key. ` +
|
|
145
|
+
'Run prepareAccount / REGISTER_API_KEY to register a fresh key.'
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
// Every read the venue answered counts against the window, so a burst
|
|
149
|
+
// costs one read whatever the verdict. A mismatch throws above, so it
|
|
150
|
+
// never records and the next batch reads again.
|
|
151
|
+
checkedAtMs.set(windowKey, Date.now())
|
|
152
|
+
},
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
66
156
|
/**
|
|
67
157
|
* Sign a `WASM_BLOB` batch (Lighter). Ensures the user's API keypair is
|
|
68
158
|
* registered first — generating one and running the REGISTER_API_KEY
|
|
@@ -82,6 +172,22 @@ export async function signWasmBlobActions(
|
|
|
82
172
|
steps: WasmBlobActionStep[],
|
|
83
173
|
ctx: SignActionsContext | undefined
|
|
84
174
|
): Promise<WasmBlobSignedActionStep[]> {
|
|
175
|
+
// REGISTER_API_KEY replaces the slot's key, so for such a batch the stored
|
|
176
|
+
// key is expected to differ from the registered one.
|
|
177
|
+
const replacesApiKey = steps.some(
|
|
178
|
+
(step) => step.action === ActionType.REGISTER_API_KEY
|
|
179
|
+
)
|
|
180
|
+
if (!replacesApiKey) {
|
|
181
|
+
const storedKey = await deps.keyStore.get(address)
|
|
182
|
+
if (storedKey !== null) {
|
|
183
|
+
await deps.apiKeyFreshness.assertStillRegistered(
|
|
184
|
+
deps.apiClient,
|
|
185
|
+
address,
|
|
186
|
+
storedKey
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
85
191
|
const signed: WasmBlobSignedActionStep[] = []
|
|
86
192
|
for (const step of steps) {
|
|
87
193
|
if (step.action === ActionType.REGISTER_API_KEY) {
|
|
@@ -151,7 +257,13 @@ async function signRegisterApiKey(
|
|
|
151
257
|
nonce?: number
|
|
152
258
|
skip_nonce?: 0 | 1
|
|
153
259
|
}
|
|
154
|
-
const apiKeyIndex = params.api_key_index
|
|
260
|
+
const apiKeyIndex = params.api_key_index
|
|
261
|
+
if (typeof apiKeyIndex !== 'number') {
|
|
262
|
+
throw new PerpsError(
|
|
263
|
+
PerpsErrorCode.SDKError,
|
|
264
|
+
'REGISTER_API_KEY wasmSignParams is missing `api_key_index`.'
|
|
265
|
+
)
|
|
266
|
+
}
|
|
155
267
|
const nonce = params.nonce
|
|
156
268
|
if (typeof nonce !== 'number') {
|
|
157
269
|
throw new PerpsError(
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { LighterApiClient } from './apiClient.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* One entry of Lighter's `/api/v1/apikeys` response: the public key the venue
|
|
5
|
+
* holds in an API-key slot.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export interface LighterRegisteredApiKey {
|
|
10
|
+
api_key_index: number
|
|
11
|
+
public_key: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Compare Lighter public keys irrespective of `0x` prefix / casing. */
|
|
15
|
+
export const normalizeLighterPublicKey = (key: string): string =>
|
|
16
|
+
key.replace(/^0x/i, '').toLowerCase()
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Read the public key Lighter holds in one API-key slot. Returns `undefined`
|
|
20
|
+
* when the response carries no entry for `apiKeyIndex`.
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export const fetchRegisteredApiKey = async (
|
|
25
|
+
client: LighterApiClient,
|
|
26
|
+
accountIndex: number,
|
|
27
|
+
apiKeyIndex: number
|
|
28
|
+
): Promise<LighterRegisteredApiKey | undefined> => {
|
|
29
|
+
const response = await client.get<{
|
|
30
|
+
code: number
|
|
31
|
+
api_keys: LighterRegisteredApiKey[]
|
|
32
|
+
}>('/api/v1/apikeys', { account_index: accountIndex })
|
|
33
|
+
return response.api_keys?.find((k) => k.api_key_index === apiKeyIndex)
|
|
34
|
+
}
|