@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.
Files changed (58) hide show
  1. package/dist/cjs/LighterProvider.d.ts.map +1 -1
  2. package/dist/cjs/LighterProvider.js +11 -10
  3. package/dist/cjs/LighterProvider.js.map +1 -1
  4. package/dist/cjs/constants.d.ts +0 -1
  5. package/dist/cjs/constants.d.ts.map +1 -1
  6. package/dist/cjs/constants.js +1 -2
  7. package/dist/cjs/constants.js.map +1 -1
  8. package/dist/cjs/index.d.ts +1 -1
  9. package/dist/cjs/index.d.ts.map +1 -1
  10. package/dist/cjs/index.js +1 -2
  11. package/dist/cjs/index.js.map +1 -1
  12. package/dist/cjs/signers/signActions.d.ts +6 -1
  13. package/dist/cjs/signers/signActions.d.ts.map +1 -1
  14. package/dist/cjs/signers/signActions.js +46 -1
  15. package/dist/cjs/signers/signActions.js.map +1 -1
  16. package/dist/cjs/utils/registeredApiKey.d.ts +8 -0
  17. package/dist/cjs/utils/registeredApiKey.d.ts.map +1 -0
  18. package/dist/cjs/utils/registeredApiKey.js +11 -0
  19. package/dist/cjs/utils/registeredApiKey.js.map +1 -0
  20. package/dist/esm/LighterProvider.d.ts.map +1 -1
  21. package/dist/esm/LighterProvider.js +15 -11
  22. package/dist/esm/LighterProvider.js.map +1 -1
  23. package/dist/esm/constants.d.ts +0 -10
  24. package/dist/esm/constants.d.ts.map +1 -1
  25. package/dist/esm/constants.js +0 -10
  26. package/dist/esm/constants.js.map +1 -1
  27. package/dist/esm/index.d.ts +1 -1
  28. package/dist/esm/index.d.ts.map +1 -1
  29. package/dist/esm/index.js +1 -1
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/signers/LighterKeyStore.d.ts +1 -1
  32. package/dist/esm/signers/LighterKeyStore.d.ts.map +1 -1
  33. package/dist/esm/signers/signActions.d.ts +22 -1
  34. package/dist/esm/signers/signActions.d.ts.map +1 -1
  35. package/dist/esm/signers/signActions.js +67 -2
  36. package/dist/esm/signers/signActions.js.map +1 -1
  37. package/dist/esm/utils/registeredApiKey.d.ts +21 -0
  38. package/dist/esm/utils/registeredApiKey.d.ts.map +1 -0
  39. package/dist/esm/utils/registeredApiKey.js +13 -0
  40. package/dist/esm/utils/registeredApiKey.js.map +1 -0
  41. package/dist/types/LighterProvider.d.ts.map +1 -1
  42. package/dist/types/constants.d.ts +0 -10
  43. package/dist/types/constants.d.ts.map +1 -1
  44. package/dist/types/index.d.ts +1 -1
  45. package/dist/types/index.d.ts.map +1 -1
  46. package/dist/types/signers/LighterKeyStore.d.ts +1 -1
  47. package/dist/types/signers/LighterKeyStore.d.ts.map +1 -1
  48. package/dist/types/signers/signActions.d.ts +22 -1
  49. package/dist/types/signers/signActions.d.ts.map +1 -1
  50. package/dist/types/utils/registeredApiKey.d.ts +21 -0
  51. package/dist/types/utils/registeredApiKey.d.ts.map +1 -0
  52. package/package.json +3 -3
  53. package/src/LighterProvider.ts +22 -21
  54. package/src/constants.ts +0 -11
  55. package/src/index.ts +0 -1
  56. package/src/signers/LighterKeyStore.ts +1 -1
  57. package/src/signers/signActions.ts +117 -5
  58. 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,EAUL,KAAK,iBAAiB,EACvB,MAAM,gBAAgB,CAAA;AAwGvB;;;;;;;;;;;;;;;;;;;;;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,oBA6rCF,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"}
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;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAA;AAEvC,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"}
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"}
@@ -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 { DEFAULT_API_KEY_INDEX, 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';
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,qBAAqB,EACrB,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"}
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). Defaults to {@link DEFAULT_API_KEY_INDEX}. */
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,uEAAuE;IACvE,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"}
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;AAOnC,OAAO,KAAK,EAAa,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxE,OAAO,KAAK,EAAiB,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;;;;;OAKG;IACH,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACvD;AAiBD;;;;;;;;;;;;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,CAkBrC;AAgUD;;;;;;;;;;;;;;;;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"}
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": "13.0.1",
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": "^7.0.0"
47
+ "@lifi/perps-types": "^8.0.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "@lifi/perps-sdk": "^7.0.0"
50
+ "@lifi/perps-sdk": "^7.0.1"
51
51
  },
52
52
  "publishConfig": {
53
53
  "access": "public"
@@ -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 { lighterSignActions } from './signers/signActions.js'
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
- fetchRegisteredApiKey(client, account.index, DEFAULT_API_KEY_INDEX),
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
- keyStore.get(params.address),
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: DEFAULT_API_KEY_INDEX,
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
@@ -20,7 +20,6 @@ export type {
20
20
  LighterDeployment,
21
21
  } from './constants.js'
22
22
  export {
23
- DEFAULT_API_KEY_INDEX,
24
23
  DEFAULT_LIGHTER_EXPLORER_TX_BASE_URL,
25
24
  DEFAULT_LIGHTER_REST_URL,
26
25
  DEFAULT_LIGHTER_WS_URL,
@@ -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). Defaults to {@link DEFAULT_API_KEY_INDEX}. */
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 ?? DEFAULT_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
+ }