@lifi/perps-sdk-provider-lighter 4.0.1 → 5.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.
Files changed (61) hide show
  1. package/dist/cjs/LighterProvider.d.ts +3 -0
  2. package/dist/cjs/LighterProvider.d.ts.map +1 -1
  3. package/dist/cjs/LighterProvider.js +36 -29
  4. package/dist/cjs/LighterProvider.js.map +1 -1
  5. package/dist/cjs/constants.d.ts +19 -1
  6. package/dist/cjs/constants.d.ts.map +1 -1
  7. package/dist/cjs/constants.js +21 -1
  8. package/dist/cjs/constants.js.map +1 -1
  9. package/dist/cjs/index.d.ts +2 -1
  10. package/dist/cjs/index.d.ts.map +1 -1
  11. package/dist/cjs/index.js +9 -1
  12. package/dist/cjs/index.js.map +1 -1
  13. package/dist/cjs/signers/LighterReadOnlyTokenManager.d.ts +3 -1
  14. package/dist/cjs/signers/LighterReadOnlyTokenManager.d.ts.map +1 -1
  15. package/dist/cjs/signers/LighterReadOnlyTokenManager.js +4 -3
  16. package/dist/cjs/signers/LighterReadOnlyTokenManager.js.map +1 -1
  17. package/dist/cjs/signers/LighterSigner.d.ts.map +1 -1
  18. package/dist/cjs/signers/LighterSigner.js +1 -2
  19. package/dist/cjs/signers/LighterSigner.js.map +1 -1
  20. package/dist/cjs/websocket/LighterWsProvider.d.ts.map +1 -1
  21. package/dist/cjs/websocket/LighterWsProvider.js +5 -5
  22. package/dist/cjs/websocket/LighterWsProvider.js.map +1 -1
  23. package/dist/esm/LighterProvider.d.ts +15 -0
  24. package/dist/esm/LighterProvider.d.ts.map +1 -1
  25. package/dist/esm/LighterProvider.js +38 -31
  26. package/dist/esm/LighterProvider.js.map +1 -1
  27. package/dist/esm/constants.d.ts +81 -1
  28. package/dist/esm/constants.d.ts.map +1 -1
  29. package/dist/esm/constants.js +50 -0
  30. package/dist/esm/constants.js.map +1 -1
  31. package/dist/esm/index.d.ts +2 -1
  32. package/dist/esm/index.d.ts.map +1 -1
  33. package/dist/esm/index.js +1 -1
  34. package/dist/esm/index.js.map +1 -1
  35. package/dist/esm/signers/LighterReadOnlyTokenManager.d.ts +9 -1
  36. package/dist/esm/signers/LighterReadOnlyTokenManager.d.ts.map +1 -1
  37. package/dist/esm/signers/LighterReadOnlyTokenManager.js +5 -4
  38. package/dist/esm/signers/LighterReadOnlyTokenManager.js.map +1 -1
  39. package/dist/esm/signers/LighterSigner.d.ts.map +1 -1
  40. package/dist/esm/signers/LighterSigner.js +2 -3
  41. package/dist/esm/signers/LighterSigner.js.map +1 -1
  42. package/dist/esm/websocket/LighterWsProvider.d.ts.map +1 -1
  43. package/dist/esm/websocket/LighterWsProvider.js +5 -5
  44. package/dist/esm/websocket/LighterWsProvider.js.map +1 -1
  45. package/dist/types/LighterProvider.d.ts +15 -0
  46. package/dist/types/LighterProvider.d.ts.map +1 -1
  47. package/dist/types/constants.d.ts +81 -1
  48. package/dist/types/constants.d.ts.map +1 -1
  49. package/dist/types/index.d.ts +2 -1
  50. package/dist/types/index.d.ts.map +1 -1
  51. package/dist/types/signers/LighterReadOnlyTokenManager.d.ts +9 -1
  52. package/dist/types/signers/LighterReadOnlyTokenManager.d.ts.map +1 -1
  53. package/dist/types/signers/LighterSigner.d.ts.map +1 -1
  54. package/dist/types/websocket/LighterWsProvider.d.ts.map +1 -1
  55. package/package.json +3 -3
  56. package/src/LighterProvider.ts +55 -40
  57. package/src/constants.ts +104 -1
  58. package/src/index.ts +12 -0
  59. package/src/signers/LighterReadOnlyTokenManager.ts +13 -5
  60. package/src/signers/LighterSigner.ts +5 -4
  61. package/src/websocket/LighterWsProvider.ts +5 -5
@@ -1,6 +1,5 @@
1
1
  import {
2
- ExplorerChainId,
3
- explorerTxUrl,
2
+ explorerTxUrlFromBase,
4
3
  getAssetRegistry,
5
4
  getMarketRegistry,
6
5
  getProviders,
@@ -31,6 +30,7 @@ import type {
31
30
  Balance,
32
31
  FillsResponse,
33
32
  LighterAccountConfig,
33
+ LighterProviderKey,
34
34
  Order,
35
35
  OrdersResponse,
36
36
  Position,
@@ -46,6 +46,7 @@ import { projectLighterConfigSettings } from './accountConfig.js'
46
46
  import { getAccountSummary } from './accountSummary.js'
47
47
  import {
48
48
  DEFAULT_API_KEY_INDEX,
49
+ DEFAULT_LIGHTER_EXPLORER_TX_BASE_URL,
49
50
  DEFAULT_LIGHTER_REST_URL,
50
51
  DEFAULT_TRADES_LIMIT,
51
52
  LIGHTER_ALL_MARKETS_WILDCARD,
@@ -177,8 +178,22 @@ const normalizeLighterPublicKey = (key: string): string =>
177
178
  * @public
178
179
  */
179
180
  export interface LighterProviderOptions {
181
+ /**
182
+ * Provider key: the plugin `type`, the `Provider.key` matched against the
183
+ * backend `/providers` response, and the namespace for this instance's market
184
+ * / asset registries and retry policy. Defaults to `'lighter'` (mainnet).
185
+ * Set a distinct key (e.g. `'lighter-rh'`) to register a second Lighter
186
+ * instance on the same client.
187
+ */
188
+ providerKey?: LighterProviderKey
180
189
  /** Lighter REST base URL. Defaults to mainnet. */
181
190
  restUrl?: string
191
+ /**
192
+ * Explorer tx base URL for transfer-activity links (`${base}${txHash}`).
193
+ * Defaults to the mainnet Lighter explorer for the default provider key, and
194
+ * to `undefined` (no transfer links) for any other key unless supplied.
195
+ */
196
+ explorerTxBaseUrl?: string
182
197
  /** Pre-created Lighter read-only bearer. */
183
198
  authToken?: string | (() => string | Promise<string>)
184
199
  /**
@@ -277,7 +292,13 @@ export const lighterProvider = (
277
292
  return boundClient
278
293
  }
279
294
 
295
+ const providerKey = options.providerKey ?? LIGHTER_PROVIDER_KEY
280
296
  const restUrl = options.restUrl ?? DEFAULT_LIGHTER_REST_URL
297
+ const explorerTxBaseUrl =
298
+ options.explorerTxBaseUrl ??
299
+ (providerKey === LIGHTER_PROVIDER_KEY
300
+ ? DEFAULT_LIGHTER_EXPLORER_TX_BASE_URL
301
+ : undefined)
281
302
  const authTokenSource: (() => string | Promise<string>) | undefined =
282
303
  typeof options.authToken === 'function'
283
304
  ? options.authToken
@@ -287,6 +308,7 @@ export const lighterProvider = (
287
308
  const signer = options.signer
288
309
  const keyStore = options.keyStore
289
310
  const readOnlyTokenManager = new LighterReadOnlyTokenManager({
311
+ providerKey,
290
312
  lighterApiUrl: restUrl,
291
313
  ...options.readOnlyTokenOptions,
292
314
  })
@@ -309,7 +331,7 @@ export const lighterProvider = (
309
331
  policy: resolveRetryPolicy(
310
332
  LIGHTER_RETRY_DEFAULTS,
311
333
  client.config.retry,
312
- LIGHTER_PROVIDER_KEY
334
+ providerKey
313
335
  ),
314
336
  fetchImpl: client.config.fetch,
315
337
  })
@@ -644,7 +666,9 @@ export const lighterProvider = (
644
666
  }
645
667
 
646
668
  return {
647
- type: LIGHTER_PROVIDER_KEY,
669
+ type: providerKey,
670
+
671
+ internalSetupActions: [ActionType.SET_REFERRAL],
648
672
 
649
673
  bind(client: PerpsSDKClient): void {
650
674
  boundClient = client
@@ -664,11 +688,8 @@ export const lighterProvider = (
664
688
  resolveAuthToken(opts, params.address),
665
689
  ])
666
690
 
667
- const registry = getMarketRegistry(requireClient(), LIGHTER_PROVIDER_KEY)
668
- const assetRegistry = getAssetRegistry(
669
- requireClient(),
670
- LIGHTER_PROVIDER_KEY
671
- )
691
+ const registry = getMarketRegistry(requireClient(), providerKey)
692
+ const assetRegistry = getAssetRegistry(requireClient(), providerKey)
672
693
  const [
673
694
  { providers },
674
695
  ,
@@ -725,7 +746,7 @@ export const lighterProvider = (
725
746
  )
726
747
 
727
748
  const categories =
728
- providers.find((p) => p.key === LIGHTER_PROVIDER_KEY)?.categories ?? []
749
+ providers.find((p) => p.key === providerKey)?.categories ?? []
729
750
  const perpsCategory = categories.find((c) => c.quoteAsset !== null)
730
751
  const spotCategoryId =
731
752
  categories.find((c) => c.quoteAsset === null)?.id ??
@@ -737,7 +758,7 @@ export const lighterProvider = (
737
758
  // carried by the positions' `marginUsed`.
738
759
  const collateralBalances: Balance[] = [
739
760
  {
740
- categoryId: perpsCategory?.id ?? LIGHTER_PROVIDER_KEY,
761
+ categoryId: perpsCategory?.id ?? providerKey,
741
762
  asset: perpsCategory?.quoteAsset ?? lighterAsset('USDC', 'USDC'),
742
763
  units: account.available_balance,
743
764
  valueUsd: account.available_balance,
@@ -767,7 +788,7 @@ export const lighterProvider = (
767
788
  )
768
789
 
769
790
  const config: LighterAccountConfig = {
770
- provider: LIGHTER_PROVIDER_KEY,
791
+ provider: providerKey,
771
792
  accountIndex: account.index,
772
793
  apiKeyIndex: DEFAULT_API_KEY_INDEX,
773
794
  apiKeyRegistered,
@@ -785,7 +806,7 @@ export const lighterProvider = (
785
806
  }
786
807
 
787
808
  return {
788
- provider: LIGHTER_PROVIDER_KEY,
809
+ provider: providerKey,
789
810
  address: params.address,
790
811
  balances,
791
812
  collateralBalances,
@@ -823,7 +844,7 @@ export const lighterProvider = (
823
844
  opts?: SDKRequestOptions
824
845
  ): Promise<PositionsResponse> {
825
846
  const client = apiClient(opts)
826
- const registry = getMarketRegistry(requireClient(), LIGHTER_PROVIDER_KEY)
847
+ const registry = getMarketRegistry(requireClient(), providerKey)
827
848
  const [account] = await Promise.all([
828
849
  fetchDetailedAccount(client, params.address),
829
850
  registry.sync(),
@@ -838,7 +859,7 @@ export const lighterProvider = (
838
859
  }
839
860
 
840
861
  return {
841
- provider: LIGHTER_PROVIDER_KEY,
862
+ provider: providerKey,
842
863
  positions,
843
864
  pagination: { limit: params.limit ?? positions.length, hasMore: false },
844
865
  }
@@ -857,7 +878,7 @@ export const lighterProvider = (
857
878
  const token = await resolveAuthToken(opts, params.address)
858
879
  if (token === undefined) {
859
880
  return {
860
- provider: LIGHTER_PROVIDER_KEY,
881
+ provider: providerKey,
861
882
  openOrders: [],
862
883
  triggerOrders: [],
863
884
  pagination: { limit: params.limit ?? 0, hasMore: false },
@@ -865,7 +886,7 @@ export const lighterProvider = (
865
886
  }
866
887
 
867
888
  const client = apiClient(opts)
868
- const registry = getMarketRegistry(requireClient(), LIGHTER_PROVIDER_KEY)
889
+ const registry = getMarketRegistry(requireClient(), providerKey)
869
890
  const [account] = await Promise.all([
870
891
  fetchDetailedAccount(client, params.address),
871
892
  registry.sync(),
@@ -891,7 +912,7 @@ export const lighterProvider = (
891
912
 
892
913
  const total = openOrders.length + triggerOrders.length
893
914
  return {
894
- provider: LIGHTER_PROVIDER_KEY,
915
+ provider: providerKey,
895
916
  openOrders,
896
917
  triggerOrders,
897
918
  pagination: { limit: total, hasMore: false },
@@ -913,7 +934,7 @@ export const lighterProvider = (
913
934
  }
914
935
 
915
936
  const client = apiClient(opts)
916
- const registry = getMarketRegistry(requireClient(), LIGHTER_PROVIDER_KEY)
937
+ const registry = getMarketRegistry(requireClient(), providerKey)
917
938
  const [account] = await Promise.all([
918
939
  fetchDetailedAccount(client, params.address),
919
940
  registry.sync(),
@@ -981,14 +1002,14 @@ export const lighterProvider = (
981
1002
  const token = await resolveAuthToken(opts, params.address)
982
1003
  if (token === undefined) {
983
1004
  return {
984
- provider: LIGHTER_PROVIDER_KEY,
1005
+ provider: providerKey,
985
1006
  items: [],
986
1007
  pagination: { limit: params.limit ?? 0, hasMore: false },
987
1008
  }
988
1009
  }
989
1010
 
990
1011
  const client = apiClient(opts)
991
- const registry = getMarketRegistry(requireClient(), LIGHTER_PROVIDER_KEY)
1012
+ const registry = getMarketRegistry(requireClient(), providerKey)
992
1013
  const [account] = await Promise.all([
993
1014
  fetchDetailedAccount(client, params.address),
994
1015
  registry.sync(),
@@ -1017,7 +1038,7 @@ export const lighterProvider = (
1017
1038
  )
1018
1039
 
1019
1040
  return {
1020
- provider: LIGHTER_PROVIDER_KEY,
1041
+ provider: providerKey,
1021
1042
  items,
1022
1043
  pagination: {
1023
1044
  limit: params.limit ?? items.length,
@@ -1034,7 +1055,7 @@ export const lighterProvider = (
1034
1055
  const token = await resolveAuthToken(opts, params.address)
1035
1056
  if (token === undefined) {
1036
1057
  return {
1037
- provider: LIGHTER_PROVIDER_KEY,
1058
+ provider: providerKey,
1038
1059
  items: [],
1039
1060
  pagination: { limit: params.limit ?? 0, hasMore: false },
1040
1061
  }
@@ -1043,14 +1064,8 @@ export const lighterProvider = (
1043
1064
  const inputCursor = decodeActivityCursor(params.cursor)
1044
1065
  const client = apiClient(opts)
1045
1066
  const account = await fetchDetailedAccount(client, params.address)
1046
- const marketRegistry = getMarketRegistry(
1047
- requireClient(),
1048
- LIGHTER_PROVIDER_KEY
1049
- )
1050
- const assetRegistry = getAssetRegistry(
1051
- requireClient(),
1052
- LIGHTER_PROVIDER_KEY
1053
- )
1067
+ const marketRegistry = getMarketRegistry(requireClient(), providerKey)
1068
+ const assetRegistry = getAssetRegistry(requireClient(), providerKey)
1054
1069
  const [history] = await Promise.all([
1055
1070
  retryOnRevoked(opts, params.address, token, (t) =>
1056
1071
  fetchAllHistory(
@@ -1070,7 +1085,7 @@ export const lighterProvider = (
1070
1085
  ...history.deposits.deposits.map(
1071
1086
  (d): ActivityItem => ({
1072
1087
  id: d.id,
1073
- provider: LIGHTER_PROVIDER_KEY,
1088
+ provider: providerKey,
1074
1089
  timestamp: toIsoFromMs(d.timestamp),
1075
1090
  type: ActivityType.DEPOSIT,
1076
1091
  amount: d.amount,
@@ -1082,7 +1097,7 @@ export const lighterProvider = (
1082
1097
  ...history.withdraws.withdraws.map(
1083
1098
  (w): ActivityItem => ({
1084
1099
  id: w.id,
1085
- provider: LIGHTER_PROVIDER_KEY,
1100
+ provider: providerKey,
1086
1101
  timestamp: toIsoFromMs(w.timestamp),
1087
1102
  type: ActivityType.WITHDRAWAL,
1088
1103
  amount: w.amount,
@@ -1095,7 +1110,7 @@ export const lighterProvider = (
1095
1110
  ...history.fundings.position_fundings.map(
1096
1111
  (f): ActivityItem => ({
1097
1112
  id: `funding-${f.funding_id}`,
1098
- provider: LIGHTER_PROVIDER_KEY,
1113
+ provider: providerKey,
1099
1114
  timestamp: toIsoFromSeconds(f.timestamp),
1100
1115
  type: ActivityType.FUNDING,
1101
1116
  market: marketRegistry.require(String(f.market_id)),
@@ -1107,7 +1122,7 @@ export const lighterProvider = (
1107
1122
  ...history.liquidations.liquidations.map(
1108
1123
  (l): ActivityItem => ({
1109
1124
  id: `liquidation-${l.id}`,
1110
- provider: LIGHTER_PROVIDER_KEY,
1125
+ provider: providerKey,
1111
1126
  timestamp: toIsoFromMs(l.executed_at),
1112
1127
  type: ActivityType.LIQUIDATION,
1113
1128
  liquidatedNotionalPosition: '0',
@@ -1128,7 +1143,7 @@ export const lighterProvider = (
1128
1143
  direction === 'OUT' ? t.to_account_index : t.from_account_index
1129
1144
  return {
1130
1145
  id: t.id,
1131
- provider: LIGHTER_PROVIDER_KEY,
1146
+ provider: providerKey,
1132
1147
  timestamp: toIsoFromMs(t.timestamp),
1133
1148
  type: ActivityType.TRANSFER,
1134
1149
  direction,
@@ -1137,7 +1152,7 @@ export const lighterProvider = (
1137
1152
  assetRegistry.get(String(t.asset_id))?.displaySymbol ??
1138
1153
  String(t.asset_id),
1139
1154
  amount: t.amount,
1140
- explorerLink: explorerTxUrl(ExplorerChainId.LIGHTER, t.tx_hash),
1155
+ explorerLink: explorerTxUrlFromBase(explorerTxBaseUrl, t.tx_hash),
1141
1156
  meta: {
1142
1157
  transferType: t.type,
1143
1158
  txHash: t.tx_hash,
@@ -1183,7 +1198,7 @@ export const lighterProvider = (
1183
1198
  const hasMore = responseCursor !== undefined
1184
1199
 
1185
1200
  return {
1186
- provider: LIGHTER_PROVIDER_KEY,
1201
+ provider: providerKey,
1187
1202
  items: emitted,
1188
1203
  pagination: {
1189
1204
  limit,
@@ -1199,7 +1214,7 @@ export const lighterProvider = (
1199
1214
  ): Promise<Quote> {
1200
1215
  return resolveQuote(
1201
1216
  requireClient(),
1202
- LIGHTER_PROVIDER_KEY,
1217
+ providerKey,
1203
1218
  params,
1204
1219
  LIGHTER_BASE_FEE_TIER,
1205
1220
  opts
@@ -1224,7 +1239,7 @@ export const lighterProvider = (
1224
1239
  setup: ProviderAction[],
1225
1240
  options: ProviderAction[]
1226
1241
  ): AccountConfigSetting[] {
1227
- if (config.provider !== LIGHTER_PROVIDER_KEY) {
1242
+ if (config.provider !== providerKey) {
1228
1243
  throw new PerpsError(
1229
1244
  PerpsErrorCode.SDKError,
1230
1245
  `lighterProvider.projectConfig received config for provider ` +
package/src/constants.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { FeeTier } from '@lifi/perps-types'
1
+ import type { FeeTier, LighterProviderKey } from '@lifi/perps-types'
2
2
 
3
3
  /**
4
4
  * Lighter provider key as it appears on `Provider.key` from the backend.
@@ -24,6 +24,109 @@ export const LIGHTER_SPOT_CATEGORY_ID = 'spot'
24
24
  export const DEFAULT_LIGHTER_REST_URL = 'https://mainnet.zklighter.elliot.ai'
25
25
  export const DEFAULT_LIGHTER_WS_URL = 'wss://mainnet.zklighter.elliot.ai/stream'
26
26
 
27
+ /**
28
+ * zkLighter L2 signing chain id fed to {@link LighterSigner} on mainnet.
29
+ *
30
+ * @public
31
+ */
32
+ export const DEFAULT_LIGHTER_SIGNER_CHAIN_ID = 304
33
+
34
+ /**
35
+ * Base URL the mainnet Lighter zkLighter explorer resolves a tx hash against
36
+ * (`${base}${txHash}`).
37
+ *
38
+ * @public
39
+ */
40
+ export const DEFAULT_LIGHTER_EXPLORER_TX_BASE_URL =
41
+ 'https://app.lighter.xyz/explorer/logs/'
42
+
43
+ /**
44
+ * The venue-specific facts that distinguish one Lighter deployment from
45
+ * another. One provider + WS pair is built per instance from these; a client
46
+ * may register several so long as their `providerKey`s differ.
47
+ *
48
+ * @public
49
+ */
50
+ export interface LighterInstanceConfig {
51
+ /** Wire-visible `Provider.key` and the plugin `type`; unique per instance. */
52
+ providerKey: LighterProviderKey
53
+ restUrl: string
54
+ wsUrl: string
55
+ /**
56
+ * zkLighter L2 signing chain id to construct this instance's
57
+ * {@link LighterSigner} with.
58
+ */
59
+ signerChainId: number
60
+ /**
61
+ * Explorer tx base URL for transfer-activity links (`${base}${txHash}`).
62
+ * When omitted, transfer links are not emitted for this instance.
63
+ */
64
+ explorerTxBaseUrl?: string
65
+ }
66
+
67
+ /**
68
+ * The built-in mainnet Lighter instance — the defaults `lighterProvider()` and
69
+ * `lighterWsProvider()` apply when constructed with no instance overrides.
70
+ *
71
+ * @public
72
+ */
73
+ export const LIGHTER_MAINNET_INSTANCE: LighterInstanceConfig = {
74
+ providerKey: LIGHTER_PROVIDER_KEY,
75
+ restUrl: DEFAULT_LIGHTER_REST_URL,
76
+ wsUrl: DEFAULT_LIGHTER_WS_URL,
77
+ signerChainId: DEFAULT_LIGHTER_SIGNER_CHAIN_ID,
78
+ explorerTxBaseUrl: DEFAULT_LIGHTER_EXPLORER_TX_BASE_URL,
79
+ }
80
+
81
+ /**
82
+ * Provider key for the Lighter instance running on Robinhood chain.
83
+ *
84
+ * @public
85
+ */
86
+ export const LIGHTER_RH_PROVIDER_KEY = 'lighter-rh'
87
+
88
+ /** @public */
89
+ export const LIGHTER_RH_REST_URL = 'https://api.rh.lighter.xyz'
90
+ /** @public */
91
+ export const LIGHTER_RH_WS_URL = 'wss://api.rh.lighter.xyz/stream'
92
+
93
+ /**
94
+ * Deployment-supplied facts the RH instance cannot source from public
95
+ * documentation and the caller must confirm.
96
+ *
97
+ * @public
98
+ */
99
+ export interface LighterRhInstanceOverrides {
100
+ /**
101
+ * zkLighter L2 signing chain id for the RH instance. Unverified from public
102
+ * sources — must be the value confirmed against lighter-go / RH support, not
103
+ * mainnet's 304 nor the RH L1 chain id 4663.
104
+ */
105
+ signerChainId: number
106
+ /**
107
+ * RH zkLighter explorer tx base URL. Omit until confirmed; transfer links are
108
+ * then left unset rather than pointed at the mainnet explorer.
109
+ */
110
+ explorerTxBaseUrl?: string
111
+ }
112
+
113
+ /**
114
+ * Build the `lighter-rh` {@link LighterInstanceConfig}. The signing chain id is
115
+ * a required argument because it is not verifiable from public sources — the
116
+ * caller must pass the value confirmed against lighter-go / RH support.
117
+ *
118
+ * @public
119
+ */
120
+ export const lighterRhInstance = (
121
+ overrides: LighterRhInstanceOverrides
122
+ ): LighterInstanceConfig => ({
123
+ providerKey: LIGHTER_RH_PROVIDER_KEY,
124
+ restUrl: LIGHTER_RH_REST_URL,
125
+ wsUrl: LIGHTER_RH_WS_URL,
126
+ signerChainId: overrides.signerChainId,
127
+ explorerTxBaseUrl: overrides.explorerTxBaseUrl,
128
+ })
129
+
27
130
  /** @internal */
28
131
  export const DEFAULT_TRADES_LIMIT = 50
29
132
 
package/src/index.ts CHANGED
@@ -15,11 +15,23 @@
15
15
 
16
16
  export { projectLighterConfigSettings } from './accountConfig.js'
17
17
  export { getAccountSummary } from './accountSummary.js'
18
+ export type {
19
+ LighterInstanceConfig,
20
+ LighterRhInstanceOverrides,
21
+ } from './constants.js'
18
22
  export {
19
23
  DEFAULT_API_KEY_INDEX,
24
+ DEFAULT_LIGHTER_EXPLORER_TX_BASE_URL,
20
25
  DEFAULT_LIGHTER_REST_URL,
26
+ DEFAULT_LIGHTER_SIGNER_CHAIN_ID,
27
+ DEFAULT_LIGHTER_WS_URL,
28
+ LIGHTER_MAINNET_INSTANCE,
21
29
  LIGHTER_PROVIDER_KEY,
30
+ LIGHTER_RH_PROVIDER_KEY,
31
+ LIGHTER_RH_REST_URL,
32
+ LIGHTER_RH_WS_URL,
22
33
  LIGHTER_SPOT_CATEGORY_ID,
34
+ lighterRhInstance,
23
35
  } from './constants.js'
24
36
  export type {
25
37
  LighterPerpsProvider,
@@ -7,12 +7,11 @@ import {
7
7
  import type {
8
8
  ApproveReadOnlyTokenParams,
9
9
  LighterAccountConfig,
10
+ LighterProviderKey,
10
11
  } from '@lifi/perps-types'
11
12
  import { PerpsErrorCode } from '@lifi/perps-types'
12
13
  import type { Address } from 'viem'
13
- import { DEFAULT_LIGHTER_REST_URL } from '../constants.js'
14
-
15
- const STORAGE_PREFIX = 'lifi:perps:lighter:rotoken'
14
+ import { DEFAULT_LIGHTER_REST_URL, LIGHTER_PROVIDER_KEY } from '../constants.js'
16
15
 
17
16
  /**
18
17
  * Default token name persisted alongside Lighter's `tokens/create` row.
@@ -73,6 +72,13 @@ export type LighterTokenFetcher = (params: {
73
72
  /** @public */
74
73
  export interface LighterReadOnlyTokenManagerOptions {
75
74
  storage?: StorageAdapter
75
+ /**
76
+ * Provider instance key. Namespaces persisted tokens so two Lighter
77
+ * instances sharing a storage backend never serve each other's token for a
78
+ * coincident `(address, accountIndex)` pair, and stamps the `provider` of
79
+ * the {@link ApproveReadOnlyTokenResult} config. Defaults to `'lighter'`.
80
+ */
81
+ providerKey?: LighterProviderKey
76
82
  /** Lighter API host. Defaults to {@link DEFAULT_LIGHTER_REST_URL}. */
77
83
  lighterApiUrl?: string
78
84
  /** Override the multipart POST. Defaults to a `fetch`-based implementation. */
@@ -145,6 +151,7 @@ const isLighterReadOnlyToken = (
145
151
  */
146
152
  export class LighterReadOnlyTokenManager {
147
153
  private readonly storage: StorageAdapter
154
+ private readonly providerKey: LighterProviderKey
148
155
  private readonly lighterApiUrl: string
149
156
  private readonly fetcher: LighterTokenFetcher
150
157
  private readonly now: () => number
@@ -152,13 +159,14 @@ export class LighterReadOnlyTokenManager {
152
159
 
153
160
  constructor(options: LighterReadOnlyTokenManagerOptions = {}) {
154
161
  this.storage = options.storage ?? localStorageAdapter
162
+ this.providerKey = options.providerKey ?? LIGHTER_PROVIDER_KEY
155
163
  this.lighterApiUrl = options.lighterApiUrl ?? DEFAULT_LIGHTER_REST_URL
156
164
  this.fetcher = options.fetcher ?? defaultLighterTokenFetcher
157
165
  this.now = options.now ?? (() => Date.now())
158
166
  }
159
167
 
160
168
  private storageKey(address: Address, accountIndex: number): string {
161
- return `${STORAGE_PREFIX}:${address.toLowerCase()}:${accountIndex}`
169
+ return `lifi:perps:${this.providerKey}:rotoken:${address.toLowerCase()}:${accountIndex}`
162
170
  }
163
171
 
164
172
  private isExpired(token: LighterReadOnlyToken): boolean {
@@ -291,7 +299,7 @@ export class LighterReadOnlyTokenManager {
291
299
  return {
292
300
  token,
293
301
  config: {
294
- provider: 'lighter',
302
+ provider: this.providerKey,
295
303
  accountIndex: token.accountIndex,
296
304
  readOnlyTokenApproved: true,
297
305
  readOnlyTokenExpiry: token.expiry,
@@ -1,5 +1,8 @@
1
1
  import { ActionType } from '@lifi/perps-types'
2
- import { DEFAULT_LIGHTER_REST_URL } from '../constants.js'
2
+ import {
3
+ DEFAULT_LIGHTER_REST_URL,
4
+ DEFAULT_LIGHTER_SIGNER_CHAIN_ID,
5
+ } from '../constants.js'
3
6
  import {
4
7
  LT_ASSET_ID_USDC,
5
8
  LT_ROUTE_PERP,
@@ -61,8 +64,6 @@ export interface ApiKeyPair {
61
64
  privateKey: string
62
65
  }
63
66
 
64
- const DEFAULT_CHAIN_ID = 304
65
-
66
67
  // Signing "unset" sentinels mirror lighter-go `types/txtypes/constants.go`.
67
68
  // Passing them yields an empty `L2TxAttributes` — no integrator fees, default
68
69
  // self-trade rules.
@@ -103,7 +104,7 @@ export class LighterSigner {
103
104
 
104
105
  constructor(config: LighterSignerConfig = {}) {
105
106
  this.apiUrl = config.apiUrl ?? DEFAULT_LIGHTER_REST_URL
106
- this.chainId = config.chainId ?? DEFAULT_CHAIN_ID
107
+ this.chainId = config.chainId ?? DEFAULT_LIGHTER_SIGNER_CHAIN_ID
107
108
  this.loaderOptions = {
108
109
  wasmBinaryUrl: config.wasmBinaryUrl,
109
110
  wasmExecJsUrl: config.wasmExecJsUrl,
@@ -185,7 +185,7 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
185
185
 
186
186
  constructor(
187
187
  wsUrl: string = DEFAULT_LIGHTER_WS_URL,
188
- providerKey = 'lighter',
188
+ providerKey: string = LIGHTER_PROVIDER_KEY,
189
189
  options: LighterWsProviderOptions = {},
190
190
  client?: PerpsSDKClient
191
191
  ) {
@@ -199,7 +199,7 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
199
199
  policy: resolveRetryPolicy(
200
200
  LIGHTER_RETRY_DEFAULTS,
201
201
  client?.config.retry,
202
- LIGHTER_PROVIDER_KEY
202
+ providerKey
203
203
  ),
204
204
  fetchImpl: client?.config.fetch,
205
205
  }
@@ -468,19 +468,19 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
468
468
  try {
469
469
  msg = JSON.parse(raw) as LtWsMessage
470
470
  } catch {
471
- wsLog.parseFailure(LIGHTER_PROVIDER_KEY, raw)
471
+ wsLog.parseFailure(this.providerKey, raw)
472
472
  return
473
473
  }
474
474
 
475
475
  if (!isValidLighterFrame(msg)) {
476
- wsLog.parseFailure(LIGHTER_PROVIDER_KEY, raw)
476
+ wsLog.parseFailure(this.providerKey, raw)
477
477
  return
478
478
  }
479
479
 
480
480
  try {
481
481
  this.dispatch(msg)
482
482
  } catch (error) {
483
- wsLog.handlerFailure(LIGHTER_PROVIDER_KEY, error)
483
+ wsLog.handlerFailure(this.providerKey, error)
484
484
  }
485
485
  }
486
486