@lifi/perps-sdk-provider-lighter 4.0.1 → 5.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 (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 +35 -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 +37 -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 +53 -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,7 @@ export const lighterProvider = (
644
666
  }
645
667
 
646
668
  return {
647
- type: LIGHTER_PROVIDER_KEY,
669
+ type: providerKey,
648
670
 
649
671
  bind(client: PerpsSDKClient): void {
650
672
  boundClient = client
@@ -664,11 +686,8 @@ export const lighterProvider = (
664
686
  resolveAuthToken(opts, params.address),
665
687
  ])
666
688
 
667
- const registry = getMarketRegistry(requireClient(), LIGHTER_PROVIDER_KEY)
668
- const assetRegistry = getAssetRegistry(
669
- requireClient(),
670
- LIGHTER_PROVIDER_KEY
671
- )
689
+ const registry = getMarketRegistry(requireClient(), providerKey)
690
+ const assetRegistry = getAssetRegistry(requireClient(), providerKey)
672
691
  const [
673
692
  { providers },
674
693
  ,
@@ -725,7 +744,7 @@ export const lighterProvider = (
725
744
  )
726
745
 
727
746
  const categories =
728
- providers.find((p) => p.key === LIGHTER_PROVIDER_KEY)?.categories ?? []
747
+ providers.find((p) => p.key === providerKey)?.categories ?? []
729
748
  const perpsCategory = categories.find((c) => c.quoteAsset !== null)
730
749
  const spotCategoryId =
731
750
  categories.find((c) => c.quoteAsset === null)?.id ??
@@ -737,7 +756,7 @@ export const lighterProvider = (
737
756
  // carried by the positions' `marginUsed`.
738
757
  const collateralBalances: Balance[] = [
739
758
  {
740
- categoryId: perpsCategory?.id ?? LIGHTER_PROVIDER_KEY,
759
+ categoryId: perpsCategory?.id ?? providerKey,
741
760
  asset: perpsCategory?.quoteAsset ?? lighterAsset('USDC', 'USDC'),
742
761
  units: account.available_balance,
743
762
  valueUsd: account.available_balance,
@@ -767,7 +786,7 @@ export const lighterProvider = (
767
786
  )
768
787
 
769
788
  const config: LighterAccountConfig = {
770
- provider: LIGHTER_PROVIDER_KEY,
789
+ provider: providerKey,
771
790
  accountIndex: account.index,
772
791
  apiKeyIndex: DEFAULT_API_KEY_INDEX,
773
792
  apiKeyRegistered,
@@ -785,7 +804,7 @@ export const lighterProvider = (
785
804
  }
786
805
 
787
806
  return {
788
- provider: LIGHTER_PROVIDER_KEY,
807
+ provider: providerKey,
789
808
  address: params.address,
790
809
  balances,
791
810
  collateralBalances,
@@ -823,7 +842,7 @@ export const lighterProvider = (
823
842
  opts?: SDKRequestOptions
824
843
  ): Promise<PositionsResponse> {
825
844
  const client = apiClient(opts)
826
- const registry = getMarketRegistry(requireClient(), LIGHTER_PROVIDER_KEY)
845
+ const registry = getMarketRegistry(requireClient(), providerKey)
827
846
  const [account] = await Promise.all([
828
847
  fetchDetailedAccount(client, params.address),
829
848
  registry.sync(),
@@ -838,7 +857,7 @@ export const lighterProvider = (
838
857
  }
839
858
 
840
859
  return {
841
- provider: LIGHTER_PROVIDER_KEY,
860
+ provider: providerKey,
842
861
  positions,
843
862
  pagination: { limit: params.limit ?? positions.length, hasMore: false },
844
863
  }
@@ -857,7 +876,7 @@ export const lighterProvider = (
857
876
  const token = await resolveAuthToken(opts, params.address)
858
877
  if (token === undefined) {
859
878
  return {
860
- provider: LIGHTER_PROVIDER_KEY,
879
+ provider: providerKey,
861
880
  openOrders: [],
862
881
  triggerOrders: [],
863
882
  pagination: { limit: params.limit ?? 0, hasMore: false },
@@ -865,7 +884,7 @@ export const lighterProvider = (
865
884
  }
866
885
 
867
886
  const client = apiClient(opts)
868
- const registry = getMarketRegistry(requireClient(), LIGHTER_PROVIDER_KEY)
887
+ const registry = getMarketRegistry(requireClient(), providerKey)
869
888
  const [account] = await Promise.all([
870
889
  fetchDetailedAccount(client, params.address),
871
890
  registry.sync(),
@@ -891,7 +910,7 @@ export const lighterProvider = (
891
910
 
892
911
  const total = openOrders.length + triggerOrders.length
893
912
  return {
894
- provider: LIGHTER_PROVIDER_KEY,
913
+ provider: providerKey,
895
914
  openOrders,
896
915
  triggerOrders,
897
916
  pagination: { limit: total, hasMore: false },
@@ -913,7 +932,7 @@ export const lighterProvider = (
913
932
  }
914
933
 
915
934
  const client = apiClient(opts)
916
- const registry = getMarketRegistry(requireClient(), LIGHTER_PROVIDER_KEY)
935
+ const registry = getMarketRegistry(requireClient(), providerKey)
917
936
  const [account] = await Promise.all([
918
937
  fetchDetailedAccount(client, params.address),
919
938
  registry.sync(),
@@ -981,14 +1000,14 @@ export const lighterProvider = (
981
1000
  const token = await resolveAuthToken(opts, params.address)
982
1001
  if (token === undefined) {
983
1002
  return {
984
- provider: LIGHTER_PROVIDER_KEY,
1003
+ provider: providerKey,
985
1004
  items: [],
986
1005
  pagination: { limit: params.limit ?? 0, hasMore: false },
987
1006
  }
988
1007
  }
989
1008
 
990
1009
  const client = apiClient(opts)
991
- const registry = getMarketRegistry(requireClient(), LIGHTER_PROVIDER_KEY)
1010
+ const registry = getMarketRegistry(requireClient(), providerKey)
992
1011
  const [account] = await Promise.all([
993
1012
  fetchDetailedAccount(client, params.address),
994
1013
  registry.sync(),
@@ -1017,7 +1036,7 @@ export const lighterProvider = (
1017
1036
  )
1018
1037
 
1019
1038
  return {
1020
- provider: LIGHTER_PROVIDER_KEY,
1039
+ provider: providerKey,
1021
1040
  items,
1022
1041
  pagination: {
1023
1042
  limit: params.limit ?? items.length,
@@ -1034,7 +1053,7 @@ export const lighterProvider = (
1034
1053
  const token = await resolveAuthToken(opts, params.address)
1035
1054
  if (token === undefined) {
1036
1055
  return {
1037
- provider: LIGHTER_PROVIDER_KEY,
1056
+ provider: providerKey,
1038
1057
  items: [],
1039
1058
  pagination: { limit: params.limit ?? 0, hasMore: false },
1040
1059
  }
@@ -1043,14 +1062,8 @@ export const lighterProvider = (
1043
1062
  const inputCursor = decodeActivityCursor(params.cursor)
1044
1063
  const client = apiClient(opts)
1045
1064
  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
- )
1065
+ const marketRegistry = getMarketRegistry(requireClient(), providerKey)
1066
+ const assetRegistry = getAssetRegistry(requireClient(), providerKey)
1054
1067
  const [history] = await Promise.all([
1055
1068
  retryOnRevoked(opts, params.address, token, (t) =>
1056
1069
  fetchAllHistory(
@@ -1070,7 +1083,7 @@ export const lighterProvider = (
1070
1083
  ...history.deposits.deposits.map(
1071
1084
  (d): ActivityItem => ({
1072
1085
  id: d.id,
1073
- provider: LIGHTER_PROVIDER_KEY,
1086
+ provider: providerKey,
1074
1087
  timestamp: toIsoFromMs(d.timestamp),
1075
1088
  type: ActivityType.DEPOSIT,
1076
1089
  amount: d.amount,
@@ -1082,7 +1095,7 @@ export const lighterProvider = (
1082
1095
  ...history.withdraws.withdraws.map(
1083
1096
  (w): ActivityItem => ({
1084
1097
  id: w.id,
1085
- provider: LIGHTER_PROVIDER_KEY,
1098
+ provider: providerKey,
1086
1099
  timestamp: toIsoFromMs(w.timestamp),
1087
1100
  type: ActivityType.WITHDRAWAL,
1088
1101
  amount: w.amount,
@@ -1095,7 +1108,7 @@ export const lighterProvider = (
1095
1108
  ...history.fundings.position_fundings.map(
1096
1109
  (f): ActivityItem => ({
1097
1110
  id: `funding-${f.funding_id}`,
1098
- provider: LIGHTER_PROVIDER_KEY,
1111
+ provider: providerKey,
1099
1112
  timestamp: toIsoFromSeconds(f.timestamp),
1100
1113
  type: ActivityType.FUNDING,
1101
1114
  market: marketRegistry.require(String(f.market_id)),
@@ -1107,7 +1120,7 @@ export const lighterProvider = (
1107
1120
  ...history.liquidations.liquidations.map(
1108
1121
  (l): ActivityItem => ({
1109
1122
  id: `liquidation-${l.id}`,
1110
- provider: LIGHTER_PROVIDER_KEY,
1123
+ provider: providerKey,
1111
1124
  timestamp: toIsoFromMs(l.executed_at),
1112
1125
  type: ActivityType.LIQUIDATION,
1113
1126
  liquidatedNotionalPosition: '0',
@@ -1128,7 +1141,7 @@ export const lighterProvider = (
1128
1141
  direction === 'OUT' ? t.to_account_index : t.from_account_index
1129
1142
  return {
1130
1143
  id: t.id,
1131
- provider: LIGHTER_PROVIDER_KEY,
1144
+ provider: providerKey,
1132
1145
  timestamp: toIsoFromMs(t.timestamp),
1133
1146
  type: ActivityType.TRANSFER,
1134
1147
  direction,
@@ -1137,7 +1150,7 @@ export const lighterProvider = (
1137
1150
  assetRegistry.get(String(t.asset_id))?.displaySymbol ??
1138
1151
  String(t.asset_id),
1139
1152
  amount: t.amount,
1140
- explorerLink: explorerTxUrl(ExplorerChainId.LIGHTER, t.tx_hash),
1153
+ explorerLink: explorerTxUrlFromBase(explorerTxBaseUrl, t.tx_hash),
1141
1154
  meta: {
1142
1155
  transferType: t.type,
1143
1156
  txHash: t.tx_hash,
@@ -1183,7 +1196,7 @@ export const lighterProvider = (
1183
1196
  const hasMore = responseCursor !== undefined
1184
1197
 
1185
1198
  return {
1186
- provider: LIGHTER_PROVIDER_KEY,
1199
+ provider: providerKey,
1187
1200
  items: emitted,
1188
1201
  pagination: {
1189
1202
  limit,
@@ -1199,7 +1212,7 @@ export const lighterProvider = (
1199
1212
  ): Promise<Quote> {
1200
1213
  return resolveQuote(
1201
1214
  requireClient(),
1202
- LIGHTER_PROVIDER_KEY,
1215
+ providerKey,
1203
1216
  params,
1204
1217
  LIGHTER_BASE_FEE_TIER,
1205
1218
  opts
@@ -1224,7 +1237,7 @@ export const lighterProvider = (
1224
1237
  setup: ProviderAction[],
1225
1238
  options: ProviderAction[]
1226
1239
  ): AccountConfigSetting[] {
1227
- if (config.provider !== LIGHTER_PROVIDER_KEY) {
1240
+ if (config.provider !== providerKey) {
1228
1241
  throw new PerpsError(
1229
1242
  PerpsErrorCode.SDKError,
1230
1243
  `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