@veridex/sdk 1.1.0 → 1.1.1

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 (83) hide show
  1. package/dist/auth/prepareAuth.js +107 -32
  2. package/dist/auth/prepareAuth.js.map +1 -1
  3. package/dist/auth/prepareAuth.mjs +6 -6
  4. package/dist/chains/aptos/index.js.map +1 -1
  5. package/dist/chains/aptos/index.mjs +3 -3
  6. package/dist/chains/avalanche/index.js.map +1 -1
  7. package/dist/chains/avalanche/index.mjs +4 -4
  8. package/dist/chains/evm/index.d.mts +2 -2
  9. package/dist/chains/evm/index.js.map +1 -1
  10. package/dist/chains/evm/index.mjs +3 -3
  11. package/dist/chains/solana/index.js.map +1 -1
  12. package/dist/chains/solana/index.mjs +3 -3
  13. package/dist/chains/stacks/index.d.mts +1 -1
  14. package/dist/chains/stacks/index.js.map +1 -1
  15. package/dist/chains/stacks/index.mjs +3 -3
  16. package/dist/chains/starknet/index.d.mts +1 -1
  17. package/dist/chains/starknet/index.js.map +1 -1
  18. package/dist/chains/starknet/index.mjs +3 -3
  19. package/dist/chains/sui/index.d.mts +1 -1
  20. package/dist/chains/sui/index.js.map +1 -1
  21. package/dist/chains/sui/index.mjs +3 -3
  22. package/dist/{chunk-Q5O3M5LP.mjs → chunk-2TS375ET.mjs} +2 -2
  23. package/dist/{chunk-QT4ZZ4GM.mjs → chunk-5FDOTI5G.mjs} +2 -2
  24. package/dist/{chunk-5T6KPH7A.mjs → chunk-CSU4IV2F.mjs} +2 -2
  25. package/dist/{chunk-YCUJZ6Z7.mjs → chunk-CTYDGO6E.mjs} +63 -6
  26. package/dist/chunk-CTYDGO6E.mjs.map +1 -0
  27. package/dist/{chunk-SXXGTQIR.mjs → chunk-E3SU36C2.mjs} +2 -2
  28. package/dist/{chunk-NUWSMJFJ.mjs → chunk-EFIXFA6V.mjs} +2 -2
  29. package/dist/{chunk-MLXQHIH2.mjs → chunk-GM5DKEHD.mjs} +2 -2
  30. package/dist/{chunk-GWJRKDSA.mjs → chunk-GOWXQPTW.mjs} +3 -3
  31. package/dist/{chunk-OVMMTL6H.mjs → chunk-ICGB3AHI.mjs} +2 -2
  32. package/dist/{chunk-QDO6NQ7P.mjs → chunk-M3GUNREX.mjs} +20 -3
  33. package/dist/{chunk-QDO6NQ7P.mjs.map → chunk-M3GUNREX.mjs.map} +1 -1
  34. package/dist/{chunk-N4A2RMUN.mjs → chunk-PEGOXMBU.mjs} +2 -2
  35. package/dist/{chunk-X7BZMSPQ.mjs → chunk-RD6ZYUVG.mjs} +52 -30
  36. package/dist/chunk-RD6ZYUVG.mjs.map +1 -0
  37. package/dist/{chunk-F3YAGZSW.mjs → chunk-TPEP6XUA.mjs} +2 -2
  38. package/dist/{chunk-M3MM4YMF.mjs → chunk-UPO55SBK.mjs} +2 -2
  39. package/dist/{chunk-USDA5JTN.mjs → chunk-YBN2VC6E.mjs} +2 -2
  40. package/dist/{chunk-PDHZ5X5O.mjs → chunk-YYT3V7CI.mjs} +2 -2
  41. package/dist/constants.d.mts +2 -2
  42. package/dist/constants.js +51 -29
  43. package/dist/constants.js.map +1 -1
  44. package/dist/constants.mjs +1 -1
  45. package/dist/{index-DDalBhAm.d.mts → index-CySMITQ9.d.mts} +9 -6
  46. package/dist/index.d.mts +41 -13
  47. package/dist/index.js +445 -147
  48. package/dist/index.js.map +1 -1
  49. package/dist/index.mjs +327 -127
  50. package/dist/index.mjs.map +1 -1
  51. package/dist/passkey.js +57 -4
  52. package/dist/passkey.js.map +1 -1
  53. package/dist/passkey.mjs +3 -3
  54. package/dist/payload.js.map +1 -1
  55. package/dist/payload.mjs +2 -2
  56. package/dist/portfolio-JA4OTF7Y.mjs +13 -0
  57. package/dist/queries/index.js +49 -27
  58. package/dist/queries/index.js.map +1 -1
  59. package/dist/queries/index.mjs +5 -5
  60. package/dist/{types-B7V5VNbO.d.mts → types-DWx-5jmz.d.mts} +12 -3
  61. package/dist/utils.js +49 -27
  62. package/dist/utils.js.map +1 -1
  63. package/dist/utils.mjs +2 -2
  64. package/dist/wormhole.js.map +1 -1
  65. package/dist/wormhole.mjs +2 -2
  66. package/package.json +1 -1
  67. package/dist/chunk-X7BZMSPQ.mjs.map +0 -1
  68. package/dist/chunk-YCUJZ6Z7.mjs.map +0 -1
  69. package/dist/portfolio-V347KZOL.mjs +0 -13
  70. /package/dist/{chunk-Q5O3M5LP.mjs.map → chunk-2TS375ET.mjs.map} +0 -0
  71. /package/dist/{chunk-QT4ZZ4GM.mjs.map → chunk-5FDOTI5G.mjs.map} +0 -0
  72. /package/dist/{chunk-5T6KPH7A.mjs.map → chunk-CSU4IV2F.mjs.map} +0 -0
  73. /package/dist/{chunk-SXXGTQIR.mjs.map → chunk-E3SU36C2.mjs.map} +0 -0
  74. /package/dist/{chunk-NUWSMJFJ.mjs.map → chunk-EFIXFA6V.mjs.map} +0 -0
  75. /package/dist/{chunk-MLXQHIH2.mjs.map → chunk-GM5DKEHD.mjs.map} +0 -0
  76. /package/dist/{chunk-GWJRKDSA.mjs.map → chunk-GOWXQPTW.mjs.map} +0 -0
  77. /package/dist/{chunk-OVMMTL6H.mjs.map → chunk-ICGB3AHI.mjs.map} +0 -0
  78. /package/dist/{chunk-N4A2RMUN.mjs.map → chunk-PEGOXMBU.mjs.map} +0 -0
  79. /package/dist/{chunk-F3YAGZSW.mjs.map → chunk-TPEP6XUA.mjs.map} +0 -0
  80. /package/dist/{chunk-M3MM4YMF.mjs.map → chunk-UPO55SBK.mjs.map} +0 -0
  81. /package/dist/{chunk-USDA5JTN.mjs.map → chunk-YBN2VC6E.mjs.map} +0 -0
  82. /package/dist/{chunk-PDHZ5X5O.mjs.map → chunk-YYT3V7CI.mjs.map} +0 -0
  83. /package/dist/{portfolio-V347KZOL.mjs.map → portfolio-JA4OTF7Y.mjs.map} +0 -0
package/dist/index.js CHANGED
@@ -90,7 +90,7 @@ var init_constants = __esm({
90
90
  SOLANA_DEVNET: 1,
91
91
  GOERLI: 2,
92
92
  BSC_TESTNET: 4,
93
- POLYGON_MUMBAI: 5,
93
+ POLYGON_AMOY: 10007,
94
94
  AVALANCHE_FUJI: 6,
95
95
  FANTOM_TESTNET: 10,
96
96
  CELO_ALFAJORES: 14,
@@ -152,7 +152,7 @@ var init_constants = __esm({
152
152
  SOLANA_DEVNET: 1,
153
153
  GOERLI: 2,
154
154
  BSC_TESTNET: 4,
155
- POLYGON_MUMBAI: 5,
155
+ POLYGON_AMOY: 10007,
156
156
  AVALANCHE_FUJI: 6,
157
157
  FANTOM_TESTNET: 10,
158
158
  CELO_ALFAJORES: 14,
@@ -173,13 +173,12 @@ var init_constants = __esm({
173
173
  chainId: 84532,
174
174
  wormholeChainId: 10004,
175
175
  rpcUrl: "https://sepolia.base.org",
176
- // Public CORS-friendly RPC
177
176
  explorerUrl: "https://sepolia.basescan.org",
178
177
  isEvm: true,
179
178
  contracts: {
180
- hub: "0x23a39c294891703146c3607e1FEEB5Fe78F7F28d",
181
- vaultFactory: "0x31e8dc9428575334739754Ab2bdB0E8b9Dc707FD",
182
- vaultImplementation: "0xD65E996CD6d5B01689dc54ad30B51f1D88a100f5",
179
+ hub: "0xD5D29b6EaeE6FF4b765e704298a7e48D22607059",
180
+ vaultFactory: "0xb25b73D5FeD5693dcd1Bb78f8e33387B59A022EC",
181
+ vaultImplementation: "0x2CB8397df988c1880d9e5cFfF65bfC22D7D90EE6",
183
182
  wormholeCoreBridge: "0x79A1027a6A159502049F10906D333EC57E95F083",
184
183
  tokenBridge: "0x86F55A04690fd7815A3D802bD587e83eA888B239"
185
184
  }
@@ -192,8 +191,8 @@ var init_constants = __esm({
192
191
  explorerUrl: "https://sepolia.etherscan.io",
193
192
  isEvm: true,
194
193
  contracts: {
195
- vaultFactory: "0x52a6dc19C11b3B53B434Fc7f6D31F8b62ed18F0a",
196
- vaultImplementation: "0xfab72dd1fd3AD79f738B49506f32251B60c95f01",
194
+ vaultFactory: "0x265c10763B4d16AD970bC3d7670c645e37f63AF4",
195
+ vaultImplementation: "0x942426C94652ebC48f4f404928016B95ADb1DA25",
197
196
  wormholeCoreBridge: "0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78",
198
197
  tokenBridge: "0xDB5492265f6038831E89f495670FF909aDe94bd9"
199
198
  }
@@ -206,8 +205,8 @@ var init_constants = __esm({
206
205
  explorerUrl: "https://sepolia-optimism.etherscan.io",
207
206
  isEvm: true,
208
207
  contracts: {
209
- vaultFactory: "0x347feeaBB5655a7a80b56D8D554DA30BE6c28225",
210
- vaultImplementation: "0x26C4FD8fC66150ef5964562F7A69271fB0cd02A4",
208
+ vaultFactory: "0x3c5e4aCdC8Cd53ae5ae603B4c511885191fBb868",
209
+ vaultImplementation: "0xA45dBF322c5A3028687fEEB161603d3BCe02e119",
211
210
  wormholeCoreBridge: "0x31377888146f3253211EFEf5c676D41ECe7D58Fe",
212
211
  tokenBridge: "0x99737Ec4B815d816c49A385943baf0380e75c0Ac"
213
212
  }
@@ -220,24 +219,52 @@ var init_constants = __esm({
220
219
  explorerUrl: "https://sepolia.arbiscan.io",
221
220
  isEvm: true,
222
221
  contracts: {
223
- vaultFactory: "0x708eEE22621A64CDF51d98d3e8D97902D7dF52dD",
224
- vaultImplementation: "0x9f74Dc14A98E59df7AEC5571a2B9E329153dF5Cd",
222
+ vaultFactory: "0xB9C3e6bad3c6f26956be4a4bb5a366376Fd3045D",
223
+ vaultImplementation: "0x8601881b94B68B09b485f407317686103d3CB681",
225
224
  wormholeCoreBridge: "0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35",
226
225
  tokenBridge: "0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e"
227
226
  }
228
227
  },
229
- seiTestnet: {
230
- name: "Sei Atlantic-2",
231
- chainId: 1328,
232
- wormholeChainId: 40,
233
- rpcUrl: "https://evm-rpc-testnet.sei-apis.com",
234
- explorerUrl: "https://seitrace.com/?chain=atlantic-2",
228
+ monadTestnet: {
229
+ name: "Monad Testnet",
230
+ chainId: 10143,
231
+ wormholeChainId: 10048,
232
+ rpcUrl: "https://testnet-rpc.monad.xyz",
233
+ explorerUrl: "https://testnet.monadexplorer.com",
234
+ isEvm: true,
235
+ contracts: {
236
+ vaultFactory: "0xbE9B9c39956448DA75Ac97E5e3dE17e34171660A",
237
+ vaultImplementation: "0x500853DCc54Fd1A707ec9d443032Bb7748f426d3",
238
+ wormholeCoreBridge: "0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd",
239
+ tokenBridge: "0x0000000000000000000000000000000000000000"
240
+ }
241
+ },
242
+ avalancheFuji: {
243
+ name: "Avalanche Fuji",
244
+ chainId: 43113,
245
+ wormholeChainId: 6,
246
+ rpcUrl: "https://api.avax-test.network/ext/bc/C/rpc",
247
+ explorerUrl: "https://testnet.snowtrace.io",
248
+ isEvm: true,
249
+ contracts: {
250
+ vaultFactory: "0x50F2c37584823A6cc293bd0d7647D558d05CA4C1",
251
+ vaultImplementation: "0x53d4D3943d0E524836f0B1955AbB216449F538fF",
252
+ wormholeCoreBridge: "0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C",
253
+ tokenBridge: "0x61E44E506Ca5659E6c0bba9b678586fA2d729756"
254
+ }
255
+ },
256
+ polygonAmoy: {
257
+ name: "Polygon Amoy",
258
+ chainId: 80002,
259
+ wormholeChainId: 10007,
260
+ rpcUrl: "https://rpc-amoy.polygon.technology",
261
+ explorerUrl: "https://amoy.polygonscan.com",
235
262
  isEvm: true,
236
263
  contracts: {
237
264
  vaultFactory: "0x07F608AFf6d63b68029488b726d895c4Bb593038",
238
265
  vaultImplementation: "0xD66153fccFB6731fB6c4944FbD607ba86A76a1f6",
239
- wormholeCoreBridge: "0x0000000000000000000000000000000000000000"
240
- // Mock - not yet deployed
266
+ wormholeCoreBridge: "0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35",
267
+ tokenBridge: "0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e"
241
268
  }
242
269
  },
243
270
  solanaDevnet: {
@@ -274,26 +301,21 @@ var init_constants = __esm({
274
301
  explorerUrl: "https://suiscan.xyz/testnet",
275
302
  isEvm: false,
276
303
  contracts: {
277
- hub: "0x7f6b9a3f9dba7ac6b20d180a9274f525c23a2a9f7e5445218c595c3696c55667",
304
+ hub: "0x1f8f9b79561525275c2de4579a1e5243cfe789656ec666485b7737f4784c1bfc",
278
305
  wormholeCoreBridge: "0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790"
279
306
  }
280
307
  },
281
308
  starknetSepolia: {
282
309
  name: "Starknet Sepolia",
283
310
  chainId: 0,
284
- // Native Starknet chain ID (SN_SEPOLIA = 0x534e5f5345504f4c4941)
285
311
  wormholeChainId: 50001,
286
- // Custom chain ID (50000+ reserved for non-Wormhole chains)
287
- rpcUrl: "https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/tsOnfTBZDKMXcUA26OED-",
312
+ rpcUrl: "https://starknet-sepolia-rpc.publicnode.com",
288
313
  explorerUrl: "https://sepolia.starkscan.co",
289
314
  isEvm: false,
290
315
  contracts: {
291
- // Starknet spoke contract
292
- hub: "0x46139177b8a1d7187cf35fbcddca637882a1d6f50d91f048c59d1322eee9ede",
293
- // Custom bridge contract (NOT Wormhole)
294
- wormholeCoreBridge: "0x700488242f8f03248b2311edddc394f0408a18c36181446eabd265067809c83"
316
+ hub: "0x1c87ca930ad46a5fef167f2d03d6df5b1dd6cdb841955c059edabb0566ff2d6",
317
+ wormholeCoreBridge: "0x30280c19d413eef7515c479186f206498c7f5077e30cb7277ce753d35adab00"
295
318
  },
296
- // Hub chain ID that Starknet bridge validates (Base Sepolia = 10004)
297
319
  hubChainId: 10004
298
320
  }
299
321
  };
@@ -580,6 +602,65 @@ var init_utils = __esm({
580
602
  }
581
603
  });
582
604
 
605
+ // src/core/relayerUrl.ts
606
+ function trimTrailingSlashes(value) {
607
+ return value.trim().replace(/\/+$/, "");
608
+ }
609
+ function normalizeRelayerOrigin(value) {
610
+ const trimmed = trimTrailingSlashes(value);
611
+ if (!trimmed) {
612
+ return "";
613
+ }
614
+ if (trimmed.startsWith("/")) {
615
+ return trimmed.replace(/\/api\/v1$/i, "");
616
+ }
617
+ try {
618
+ const url = new URL(trimmed);
619
+ url.pathname = url.pathname.replace(/\/api\/v1$/i, "").replace(/\/+$/, "");
620
+ return url.toString().replace(/\/+$/, "");
621
+ } catch {
622
+ return trimmed.replace(/\/api\/v1$/i, "");
623
+ }
624
+ }
625
+ function buildRelayerApiUrl(baseUrl, path) {
626
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
627
+ const trimmed = trimTrailingSlashes(baseUrl);
628
+ if (!trimmed) {
629
+ return `${API_ROOT}${normalizedPath}`;
630
+ }
631
+ if (trimmed.startsWith("/")) {
632
+ if (/\/api\/v1$/i.test(trimmed) || /\/api\/auth\/relay$/i.test(trimmed)) {
633
+ return `${trimmed}${normalizedPath}`;
634
+ }
635
+ return `${trimmed}${normalizedPath}`;
636
+ }
637
+ try {
638
+ const url = new URL(trimmed);
639
+ if (/\/api\/v1$/i.test(url.pathname) || /\/api\/auth\/relay$/i.test(url.pathname)) {
640
+ url.pathname = `${url.pathname.replace(/\/+$/, "")}${normalizedPath}`;
641
+ return url.toString();
642
+ }
643
+ if (!url.pathname || url.pathname === "/") {
644
+ url.pathname = `${API_ROOT}${normalizedPath}`;
645
+ return url.toString();
646
+ }
647
+ url.pathname = `${url.pathname.replace(/\/+$/, "")}${normalizedPath}`;
648
+ return url.toString();
649
+ } catch {
650
+ if (/\/api\/v1$/i.test(trimmed) || /\/api\/auth\/relay$/i.test(trimmed)) {
651
+ return `${trimmed}${normalizedPath}`;
652
+ }
653
+ return `${trimmed}${API_ROOT}${normalizedPath}`;
654
+ }
655
+ }
656
+ var API_ROOT;
657
+ var init_relayerUrl = __esm({
658
+ "src/core/relayerUrl.ts"() {
659
+ "use strict";
660
+ API_ROOT = "/api/v1";
661
+ }
662
+ });
663
+
583
664
  // src/core/PasskeyManager.ts
584
665
  function detectRpId(forceLocal) {
585
666
  if (typeof window === "undefined") return "localhost";
@@ -618,6 +699,7 @@ var init_PasskeyManager = __esm({
618
699
  import_browser = require("@simplewebauthn/browser");
619
700
  import_ethers2 = require("ethers");
620
701
  init_utils();
702
+ init_relayerUrl();
621
703
  VERIDEX_RP_ID = "veridex.network";
622
704
  PasskeyManager = class _PasskeyManager {
623
705
  config;
@@ -629,7 +711,7 @@ var init_PasskeyManager = __esm({
629
711
  timeout: config.timeout ?? 6e4,
630
712
  userVerification: config.userVerification ?? "required",
631
713
  authenticatorAttachment: config.authenticatorAttachment ?? "platform",
632
- relayerUrl: config.relayerUrl ?? ""
714
+ relayerUrl: normalizeRelayerOrigin(config.relayerUrl ?? "")
633
715
  };
634
716
  }
635
717
  static isSupported() {
@@ -900,7 +982,7 @@ var init_PasskeyManager = __esm({
900
982
  return false;
901
983
  }
902
984
  try {
903
- const response = await fetch(`${this.config.relayerUrl}/api/v1/credential`, {
985
+ const response = await fetch(buildRelayerApiUrl(this.config.relayerUrl, "/credential"), {
904
986
  method: "POST",
905
987
  headers: { "Content-Type": "application/json" },
906
988
  body: JSON.stringify({
@@ -932,7 +1014,7 @@ var init_PasskeyManager = __esm({
932
1014
  }
933
1015
  try {
934
1016
  const response = await fetch(
935
- `${this.config.relayerUrl}/api/v1/credential/by-id/${encodeURIComponent(credentialId)}`
1017
+ buildRelayerApiUrl(this.config.relayerUrl, `/credential/by-id/${encodeURIComponent(credentialId)}`)
936
1018
  );
937
1019
  if (!response.ok) {
938
1020
  return null;
@@ -971,7 +1053,7 @@ var init_PasskeyManager = __esm({
971
1053
  }
972
1054
  try {
973
1055
  const response = await fetch(
974
- `${this.config.relayerUrl}/api/v1/credential/${encodeURIComponent(keyHash)}`
1056
+ buildRelayerApiUrl(this.config.relayerUrl, `/credential/${encodeURIComponent(keyHash)}`)
975
1057
  );
976
1058
  if (!response.ok) {
977
1059
  return null;
@@ -2228,6 +2310,15 @@ var init_featureFlags = __esm({
2228
2310
  });
2229
2311
 
2230
2312
  // src/presets.ts
2313
+ function configureDefaultRpcUrls(overrides) {
2314
+ for (const key of Object.keys(_rpcOverrides)) {
2315
+ delete _rpcOverrides[key];
2316
+ }
2317
+ Object.assign(_rpcOverrides, overrides);
2318
+ }
2319
+ function getRpcUrlOverride(chain, network) {
2320
+ return _rpcOverrides[chain]?.[network];
2321
+ }
2231
2322
  function getChainConfig(chain, network = "testnet") {
2232
2323
  const preset = CHAIN_PRESETS[chain];
2233
2324
  if (!preset) {
@@ -2235,7 +2326,12 @@ function getChainConfig(chain, network = "testnet") {
2235
2326
  `Unknown chain: "${chain}". Supported chains: ${Object.keys(CHAIN_PRESETS).join(", ")}`
2236
2327
  );
2237
2328
  }
2238
- return preset[network];
2329
+ const config = preset[network];
2330
+ const rpcOverride = getRpcUrlOverride(chain, network);
2331
+ if (rpcOverride) {
2332
+ return { ...config, rpcUrl: rpcOverride };
2333
+ }
2334
+ return config;
2239
2335
  }
2240
2336
  function getChainPreset(chain) {
2241
2337
  const preset = CHAIN_PRESETS[chain];
@@ -2270,7 +2366,7 @@ function getDefaultHub(network = "testnet") {
2270
2366
  const primary = getEffectivePrimaryHub();
2271
2367
  return CHAIN_PRESETS[primary][network];
2272
2368
  }
2273
- var CHAIN_NAMES, CHAIN_PRESETS;
2369
+ var CHAIN_NAMES, CHAIN_PRESETS, _rpcOverrides;
2274
2370
  var init_presets = __esm({
2275
2371
  "src/presets.ts"() {
2276
2372
  "use strict";
@@ -2930,7 +3026,7 @@ var init_presets = __esm({
2930
3026
  chainId: 0,
2931
3027
  wormholeChainId: 50001,
2932
3028
  // Custom bridge (non-Wormhole)
2933
- rpcUrl: "https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/tsOnfTBZDKMXcUA26OED-",
3029
+ rpcUrl: "https://starknet-sepolia-rpc.publicnode.com",
2934
3030
  explorerUrl: "https://sepolia.starkscan.co",
2935
3031
  isEvm: false,
2936
3032
  contracts: {
@@ -3029,6 +3125,7 @@ var init_presets = __esm({
3029
3125
  }
3030
3126
  }
3031
3127
  };
3128
+ _rpcOverrides = {};
3032
3129
  }
3033
3130
  });
3034
3131
 
@@ -4143,6 +4240,7 @@ __export(src_exports, {
4143
4240
  calculatePercentage: () => calculatePercentage,
4144
4241
  computeKeyHash: () => computeKeyHash,
4145
4242
  computeSessionKeyHash: () => computeSessionKeyHash,
4243
+ configureDefaultRpcUrls: () => configureDefaultRpcUrls,
4146
4244
  createAuditEntry: () => createAuditEntry,
4147
4245
  createChainClient: () => createChainClient,
4148
4246
  createChainDetector: () => createChainDetector,
@@ -4213,6 +4311,7 @@ __export(src_exports, {
4213
4311
  getExplorerUrl: () => getExplorerUrl,
4214
4312
  getFeatureFlags: () => getFeatureFlags,
4215
4313
  getHubChains: () => getHubChains,
4314
+ getRpcUrlOverride: () => getRpcUrlOverride,
4216
4315
  getSequenceFromTxReceipt: () => getSequenceFromTxReceipt,
4217
4316
  getStacksContractPrincipal: () => getContractPrincipal,
4218
4317
  getStacksExplorerAddressUrl: () => getStacksExplorerAddressUrl,
@@ -5507,6 +5606,7 @@ var CrossChainManager = class {
5507
5606
  var crossChainManager = new CrossChainManager();
5508
5607
 
5509
5608
  // src/core/RelayerClient.ts
5609
+ init_relayerUrl();
5510
5610
  var DEFAULT_CONFIG2 = {
5511
5611
  apiKey: "",
5512
5612
  timeoutMs: 3e4,
@@ -5516,7 +5616,7 @@ var RelayerClient = class _RelayerClient {
5516
5616
  baseUrl;
5517
5617
  config;
5518
5618
  constructor(config) {
5519
- this.baseUrl = config.baseUrl.replace(/\/+$/, "");
5619
+ this.baseUrl = normalizeRelayerOrigin(config.baseUrl);
5520
5620
  this.config = { ...DEFAULT_CONFIG2, ...config };
5521
5621
  }
5522
5622
  // ========================================================================
@@ -5783,6 +5883,7 @@ var RelayerClient = class _RelayerClient {
5783
5883
  * Make an HTTP request to the relayer
5784
5884
  */
5785
5885
  async fetch(path, options = {}) {
5886
+ const resolvedUrl = path.startsWith("/api/v1/") ? buildRelayerApiUrl(this.baseUrl, path.replace(/^\/api\/v1/, "")) : `${this.baseUrl}${path}`;
5786
5887
  const headers = {
5787
5888
  "Content-Type": "application/json",
5788
5889
  "User-Agent": `@veridex/sdk/${_RelayerClient.SDK_VERSION}`,
@@ -5796,7 +5897,7 @@ var RelayerClient = class _RelayerClient {
5796
5897
  let lastError = null;
5797
5898
  for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
5798
5899
  try {
5799
- const response = await fetch(`${this.baseUrl}${path}`, {
5900
+ const response = await fetch(resolvedUrl, {
5800
5901
  ...options,
5801
5902
  headers,
5802
5903
  signal: controller.signal
@@ -15369,13 +15470,14 @@ function inferBackupEligibility(platform) {
15369
15470
  }
15370
15471
 
15371
15472
  // src/core/CredentialManager.ts
15473
+ init_relayerUrl();
15372
15474
  var DEFAULT_STORAGE_KEY = "veridex_credential_metadata";
15373
15475
  var CredentialManager = class {
15374
15476
  config;
15375
15477
  constructor(config = {}) {
15376
15478
  this.config = {
15377
15479
  storageKey: config.storageKey ?? DEFAULT_STORAGE_KEY,
15378
- relayerUrl: config.relayerUrl ?? ""
15480
+ relayerUrl: normalizeRelayerOrigin(config.relayerUrl ?? "")
15379
15481
  };
15380
15482
  }
15381
15483
  // ========================================================================
@@ -15523,7 +15625,7 @@ var CredentialManager = class {
15523
15625
  const managed = this.getCredential(credentialId);
15524
15626
  if (!managed) return false;
15525
15627
  try {
15526
- const response = await fetch(`${this.config.relayerUrl}/api/v1/credential/metadata`, {
15628
+ const response = await fetch(buildRelayerApiUrl(this.config.relayerUrl, "/credential/metadata"), {
15527
15629
  method: "PUT",
15528
15630
  headers: { "Content-Type": "application/json" },
15529
15631
  body: JSON.stringify({
@@ -15549,7 +15651,10 @@ var CredentialManager = class {
15549
15651
  if (!this.config.relayerUrl) return null;
15550
15652
  try {
15551
15653
  const response = await fetch(
15552
- `${this.config.relayerUrl}/api/v1/credential/metadata?keyHash=${encodeURIComponent(keyHash)}`
15654
+ buildRelayerApiUrl(
15655
+ this.config.relayerUrl,
15656
+ `/credential/metadata?keyHash=${encodeURIComponent(keyHash)}`
15657
+ )
15553
15658
  );
15554
15659
  if (!response.ok) return null;
15555
15660
  const data = await response.json();
@@ -15671,9 +15776,10 @@ var CredentialManager = class {
15671
15776
 
15672
15777
  // src/core/CrossOriginAuth.ts
15673
15778
  init_PasskeyManager();
15779
+ init_relayerUrl();
15674
15780
  init_PasskeyManager();
15675
15781
  var DEFAULT_AUTH_PORTAL_URL = "https://auth.veridex.network";
15676
- var DEFAULT_RELAYER_URL = "https://amused-kameko-veridex-demo-37453117.koyeb.app/api/v1";
15782
+ var DEFAULT_RELAYER_URL = "https://relayer.veridex.network";
15677
15783
  var AUTH_MESSAGE_TYPES = {
15678
15784
  AUTH_REQUEST: "VERIDEX_AUTH_REQUEST",
15679
15785
  AUTH_RESPONSE: "VERIDEX_AUTH_RESPONSE",
@@ -15685,7 +15791,7 @@ var CrossOriginAuth = class {
15685
15791
  this.config = {
15686
15792
  rpId: config.rpId ?? VERIDEX_RP_ID,
15687
15793
  authPortalUrl: config.authPortalUrl ?? DEFAULT_AUTH_PORTAL_URL,
15688
- relayerUrl: config.relayerUrl ?? DEFAULT_RELAYER_URL,
15794
+ relayerUrl: normalizeRelayerOrigin(config.relayerUrl ?? DEFAULT_RELAYER_URL),
15689
15795
  mode: config.mode ?? "popup",
15690
15796
  popupFeatures: config.popupFeatures ?? "width=500,height=600,left=100,top=100",
15691
15797
  timeout: config.timeout ?? 12e4,
@@ -15902,7 +16008,8 @@ var CrossOriginAuth = class {
15902
16008
  return bytes;
15903
16009
  }
15904
16010
  async requestServerSessionChallenge(options) {
15905
- const response = await fetch(`${this.config.relayerUrl}/session/challenge`, {
16011
+ const challengeUrl = buildRelayerApiUrl(this.config.relayerUrl, "/session/challenge");
16012
+ const response = await fetch(challengeUrl, {
15906
16013
  method: "POST",
15907
16014
  headers: { "Content-Type": "application/json" },
15908
16015
  body: JSON.stringify({
@@ -15948,7 +16055,7 @@ var CrossOriginAuth = class {
15948
16055
  if (!session.serverChallengeId) {
15949
16056
  throw new Error("Session must include a relayer-issued serverChallengeId");
15950
16057
  }
15951
- const response = await fetch(`${this.config.relayerUrl}/session/create`, {
16058
+ const response = await fetch(buildRelayerApiUrl(this.config.relayerUrl, "/session/create"), {
15952
16059
  method: "POST",
15953
16060
  headers: { "Content-Type": "application/json" },
15954
16061
  body: JSON.stringify({
@@ -15971,7 +16078,9 @@ var CrossOriginAuth = class {
15971
16078
  * Returns the session details if valid, null if expired/revoked.
15972
16079
  */
15973
16080
  async validateServerSession(sessionId) {
15974
- const response = await fetch(`${this.config.relayerUrl}/session/${encodeURIComponent(sessionId)}`);
16081
+ const response = await fetch(
16082
+ buildRelayerApiUrl(this.config.relayerUrl, `/session/${encodeURIComponent(sessionId)}`)
16083
+ );
15975
16084
  if (!response.ok) {
15976
16085
  return null;
15977
16086
  }
@@ -15985,9 +16094,12 @@ var CrossOriginAuth = class {
15985
16094
  * Revoke a server session token.
15986
16095
  */
15987
16096
  async revokeServerSession(sessionId) {
15988
- const response = await fetch(`${this.config.relayerUrl}/session/${encodeURIComponent(sessionId)}`, {
15989
- method: "DELETE"
15990
- });
16097
+ const response = await fetch(
16098
+ buildRelayerApiUrl(this.config.relayerUrl, `/session/${encodeURIComponent(sessionId)}`),
16099
+ {
16100
+ method: "DELETE"
16101
+ }
16102
+ );
15991
16103
  return response.ok;
15992
16104
  }
15993
16105
  /**
@@ -16547,39 +16659,44 @@ var IndexedDBSessionStorage = class {
16547
16659
  );
16548
16660
  }
16549
16661
  }
16662
+ async decryptSession(stored) {
16663
+ const key = await this.getEncryptionKey();
16664
+ const encryptedPrivateKey = new Uint8Array(stored.encryptedPrivateKey);
16665
+ const privateKey = await decrypt(encryptedPrivateKey, key);
16666
+ return {
16667
+ keyHash: stored.keyHash,
16668
+ publicKey: new Uint8Array(stored.publicKey),
16669
+ privateKey,
16670
+ expiry: stored.expiry,
16671
+ maxValue: BigInt(stored.maxValue),
16672
+ chainScopes: stored.chainScopes ?? [],
16673
+ userKeyHash: stored.userKeyHash
16674
+ };
16675
+ }
16676
+ async pruneExpiredSessions(records) {
16677
+ const now = Date.now();
16678
+ const validRecords = records.filter((record) => record.expiry > now);
16679
+ const expiredRecords = records.filter((record) => record.expiry <= now);
16680
+ if (expiredRecords.length > 0) {
16681
+ await Promise.all(expiredRecords.map((record) => this.remove(record.keyHash)));
16682
+ }
16683
+ return validRecords.sort((left, right) => right.savedAt - left.savedAt);
16684
+ }
16550
16685
  /**
16551
- * Load the active session (decrypts private key)
16686
+ * Load a session (decrypts private key)
16552
16687
  */
16553
- async load() {
16688
+ async load(keyHash) {
16554
16689
  try {
16555
16690
  await this.initialize();
16556
16691
  if (!this.db) {
16557
16692
  throw new Error("Database not initialized");
16558
16693
  }
16559
- const allSessions = await this.getAllSessions();
16560
- if (allSessions.length === 0) {
16561
- return null;
16562
- }
16563
- const now = Date.now();
16564
- const validSessions = allSessions.filter((s) => s.expiry > now).sort((a, b) => b.savedAt - a.savedAt);
16694
+ const sessions = keyHash ? await this.getSessionByKeyHash(keyHash) : await this.getAllSessions();
16695
+ const validSessions = await this.pruneExpiredSessions(sessions);
16565
16696
  if (validSessions.length === 0) {
16566
- await this.clear();
16567
16697
  return null;
16568
16698
  }
16569
- const stored = validSessions[0];
16570
- const key = await this.getEncryptionKey();
16571
- const encryptedPrivateKey = new Uint8Array(stored.encryptedPrivateKey);
16572
- const privateKey = await decrypt(encryptedPrivateKey, key);
16573
- const session = {
16574
- keyHash: stored.keyHash,
16575
- publicKey: new Uint8Array(stored.publicKey),
16576
- privateKey,
16577
- expiry: stored.expiry,
16578
- maxValue: BigInt(stored.maxValue),
16579
- chainScopes: stored.chainScopes,
16580
- userKeyHash: stored.userKeyHash
16581
- };
16582
- return session;
16699
+ return this.decryptSession(validSessions[0]);
16583
16700
  } catch (error) {
16584
16701
  if (error instanceof SessionError) {
16585
16702
  throw error;
@@ -16612,6 +16729,75 @@ var IndexedDBSessionStorage = class {
16612
16729
  };
16613
16730
  });
16614
16731
  }
16732
+ async getSessionByKeyHash(keyHash) {
16733
+ if (!this.db) {
16734
+ return [];
16735
+ }
16736
+ return new Promise((resolve, reject) => {
16737
+ const transaction = this.db.transaction([STORE_NAME], "readonly");
16738
+ const store = transaction.objectStore(STORE_NAME);
16739
+ const request = store.get(keyHash);
16740
+ request.onsuccess = () => {
16741
+ resolve(request.result ? [request.result] : []);
16742
+ };
16743
+ request.onerror = () => {
16744
+ reject(new SessionError(
16745
+ "Failed to get session",
16746
+ "STORAGE_ERROR" /* STORAGE_ERROR */,
16747
+ request.error
16748
+ ));
16749
+ };
16750
+ });
16751
+ }
16752
+ async loadAll() {
16753
+ try {
16754
+ await this.initialize();
16755
+ if (!this.db) {
16756
+ return [];
16757
+ }
16758
+ const records = await this.pruneExpiredSessions(await this.getAllSessions());
16759
+ return Promise.all(records.map((record) => this.decryptSession(record)));
16760
+ } catch (error) {
16761
+ if (error instanceof SessionError) {
16762
+ throw error;
16763
+ }
16764
+ throw new SessionError(
16765
+ "Failed to load sessions",
16766
+ "STORAGE_ERROR" /* STORAGE_ERROR */,
16767
+ error
16768
+ );
16769
+ }
16770
+ }
16771
+ async remove(keyHash) {
16772
+ try {
16773
+ await this.initialize();
16774
+ if (!this.db) {
16775
+ return;
16776
+ }
16777
+ return new Promise((resolve, reject) => {
16778
+ const transaction = this.db.transaction([STORE_NAME], "readwrite");
16779
+ const store = transaction.objectStore(STORE_NAME);
16780
+ const request = store.delete(keyHash);
16781
+ request.onsuccess = () => resolve();
16782
+ request.onerror = () => {
16783
+ reject(new SessionError(
16784
+ "Failed to remove session",
16785
+ "STORAGE_ERROR" /* STORAGE_ERROR */,
16786
+ request.error
16787
+ ));
16788
+ };
16789
+ });
16790
+ } catch (error) {
16791
+ if (error instanceof SessionError) {
16792
+ throw error;
16793
+ }
16794
+ throw new SessionError(
16795
+ "Failed to remove session",
16796
+ "STORAGE_ERROR" /* STORAGE_ERROR */,
16797
+ error
16798
+ );
16799
+ }
16800
+ }
16615
16801
  /**
16616
16802
  * Clear all sessions
16617
16803
  */
@@ -16648,14 +16834,9 @@ var IndexedDBSessionStorage = class {
16648
16834
  /**
16649
16835
  * Check if any session exists
16650
16836
  */
16651
- async exists() {
16837
+ async exists(keyHash) {
16652
16838
  try {
16653
- await this.initialize();
16654
- if (!this.db) {
16655
- return false;
16656
- }
16657
- const sessions = await this.getAllSessions();
16658
- return sessions.length > 0;
16839
+ return await this.load(keyHash) !== null;
16659
16840
  } catch {
16660
16841
  return false;
16661
16842
  }
@@ -16674,7 +16855,8 @@ var STORAGE_KEY_PREFIX = "veridex-session-";
16674
16855
  var LocalStorageSessionStorage = class {
16675
16856
  encryptionKey = null;
16676
16857
  credentialId;
16677
- storageKey;
16858
+ credentialHash;
16859
+ legacyStorageKey;
16678
16860
  /**
16679
16861
  * @param credentialId User's Passkey credential ID (for key derivation)
16680
16862
  */
@@ -16686,7 +16868,60 @@ var LocalStorageSessionStorage = class {
16686
16868
  );
16687
16869
  }
16688
16870
  this.credentialId = credentialId;
16689
- this.storageKey = STORAGE_KEY_PREFIX + import_ethers20.ethers.keccak256(import_ethers20.ethers.toUtf8Bytes(credentialId));
16871
+ this.credentialHash = import_ethers20.ethers.keccak256(import_ethers20.ethers.toUtf8Bytes(credentialId));
16872
+ this.legacyStorageKey = STORAGE_KEY_PREFIX + this.credentialHash;
16873
+ }
16874
+ getSessionStorageKey(keyHash) {
16875
+ return `${STORAGE_KEY_PREFIX}${this.credentialHash}:${keyHash}`;
16876
+ }
16877
+ getSessionStoragePrefix() {
16878
+ return `${STORAGE_KEY_PREFIX}${this.credentialHash}:`;
16879
+ }
16880
+ async deserializeSession(stored) {
16881
+ const key = await this.getEncryptionKey();
16882
+ const encryptedPrivateKey = typeof stored.encryptedPrivateKey === "string" ? import_ethers20.ethers.getBytes(stored.encryptedPrivateKey) : new Uint8Array(stored.encryptedPrivateKey);
16883
+ const privateKey = await decrypt(encryptedPrivateKey, key);
16884
+ return {
16885
+ keyHash: stored.keyHash,
16886
+ publicKey: typeof stored.publicKey === "string" ? import_ethers20.ethers.getBytes(stored.publicKey) : new Uint8Array(stored.publicKey),
16887
+ privateKey,
16888
+ expiry: stored.expiry,
16889
+ maxValue: BigInt(stored.maxValue),
16890
+ chainScopes: stored.chainScopes ?? [],
16891
+ userKeyHash: stored.userKeyHash
16892
+ };
16893
+ }
16894
+ getRawRecords() {
16895
+ const records = [];
16896
+ const prefix = this.getSessionStoragePrefix();
16897
+ for (let index = 0; index < localStorage.length; index++) {
16898
+ const key = localStorage.key(index);
16899
+ if (!key || !key.startsWith(prefix)) {
16900
+ continue;
16901
+ }
16902
+ const value = localStorage.getItem(key);
16903
+ if (!value) {
16904
+ continue;
16905
+ }
16906
+ records.push(JSON.parse(value));
16907
+ }
16908
+ const legacyValue = localStorage.getItem(this.legacyStorageKey);
16909
+ if (legacyValue) {
16910
+ records.push(JSON.parse(legacyValue));
16911
+ }
16912
+ return records;
16913
+ }
16914
+ async getValidRecords() {
16915
+ const now = Date.now();
16916
+ const validRecords = [];
16917
+ for (const record of this.getRawRecords()) {
16918
+ if (record.expiry <= now) {
16919
+ await this.remove(record.keyHash);
16920
+ continue;
16921
+ }
16922
+ validRecords.push(record);
16923
+ }
16924
+ return validRecords.sort((left, right) => right.savedAt - left.savedAt);
16690
16925
  }
16691
16926
  /**
16692
16927
  * Get or derive encryption key
@@ -16715,7 +16950,7 @@ var LocalStorageSessionStorage = class {
16715
16950
  userKeyHash: session.userKeyHash,
16716
16951
  savedAt: Date.now()
16717
16952
  };
16718
- localStorage.setItem(this.storageKey, JSON.stringify(storageObject));
16953
+ localStorage.setItem(this.getSessionStorageKey(session.keyHash), JSON.stringify(storageObject));
16719
16954
  } catch (error) {
16720
16955
  if (error instanceof SessionError) {
16721
16956
  throw error;
@@ -16728,32 +16963,15 @@ var LocalStorageSessionStorage = class {
16728
16963
  }
16729
16964
  }
16730
16965
  /**
16731
- * Load the active session (decrypts private key)
16966
+ * Load a session (decrypts private key)
16732
16967
  */
16733
- async load() {
16968
+ async load(keyHash) {
16734
16969
  try {
16735
- const data = localStorage.getItem(this.storageKey);
16736
- if (!data) {
16970
+ const records = keyHash ? (await this.getValidRecords()).filter((record) => record.keyHash === keyHash) : await this.getValidRecords();
16971
+ if (records.length === 0) {
16737
16972
  return null;
16738
16973
  }
16739
- const stored = JSON.parse(data);
16740
- if (stored.expiry <= Date.now()) {
16741
- await this.clear();
16742
- return null;
16743
- }
16744
- const key = await this.getEncryptionKey();
16745
- const encryptedPrivateKey = import_ethers20.ethers.getBytes(stored.encryptedPrivateKey);
16746
- const privateKey = await decrypt(encryptedPrivateKey, key);
16747
- const session = {
16748
- keyHash: stored.keyHash,
16749
- publicKey: import_ethers20.ethers.getBytes(stored.publicKey),
16750
- privateKey,
16751
- expiry: stored.expiry,
16752
- maxValue: BigInt(stored.maxValue),
16753
- chainScopes: stored.chainScopes,
16754
- userKeyHash: stored.userKeyHash
16755
- };
16756
- return session;
16974
+ return this.deserializeSession(records[0]);
16757
16975
  } catch (error) {
16758
16976
  await this.clear();
16759
16977
  if (error instanceof SessionError) {
@@ -16766,12 +16984,55 @@ var LocalStorageSessionStorage = class {
16766
16984
  );
16767
16985
  }
16768
16986
  }
16987
+ async loadAll() {
16988
+ try {
16989
+ const records = await this.getValidRecords();
16990
+ return Promise.all(records.map((record) => this.deserializeSession(record)));
16991
+ } catch (error) {
16992
+ await this.clear();
16993
+ if (error instanceof SessionError) {
16994
+ throw error;
16995
+ }
16996
+ throw new SessionError(
16997
+ "Failed to load sessions",
16998
+ "STORAGE_ERROR" /* STORAGE_ERROR */,
16999
+ error
17000
+ );
17001
+ }
17002
+ }
17003
+ async remove(keyHash) {
17004
+ try {
17005
+ localStorage.removeItem(this.getSessionStorageKey(keyHash));
17006
+ const legacyValue = localStorage.getItem(this.legacyStorageKey);
17007
+ if (legacyValue) {
17008
+ const legacyRecord = JSON.parse(legacyValue);
17009
+ if (legacyRecord.keyHash === keyHash) {
17010
+ localStorage.removeItem(this.legacyStorageKey);
17011
+ }
17012
+ }
17013
+ } catch (error) {
17014
+ throw new SessionError(
17015
+ "Failed to remove session",
17016
+ "STORAGE_ERROR" /* STORAGE_ERROR */,
17017
+ error
17018
+ );
17019
+ }
17020
+ }
16769
17021
  /**
16770
17022
  * Clear all sessions
16771
17023
  */
16772
17024
  async clear() {
16773
17025
  try {
16774
- localStorage.removeItem(this.storageKey);
17026
+ const keysToRemove = [];
17027
+ const prefix = this.getSessionStoragePrefix();
17028
+ for (let index = 0; index < localStorage.length; index++) {
17029
+ const key = localStorage.key(index);
17030
+ if (key && key.startsWith(prefix)) {
17031
+ keysToRemove.push(key);
17032
+ }
17033
+ }
17034
+ keysToRemove.forEach((key) => localStorage.removeItem(key));
17035
+ localStorage.removeItem(this.legacyStorageKey);
16775
17036
  } catch (error) {
16776
17037
  throw new SessionError(
16777
17038
  "Failed to clear sessions",
@@ -16783,9 +17044,9 @@ var LocalStorageSessionStorage = class {
16783
17044
  /**
16784
17045
  * Check if any session exists
16785
17046
  */
16786
- async exists() {
17047
+ async exists(keyHash) {
16787
17048
  try {
16788
- return localStorage.getItem(this.storageKey) !== null;
17049
+ return await this.load(keyHash) !== null;
16789
17050
  } catch {
16790
17051
  return false;
16791
17052
  }
@@ -16850,6 +17111,14 @@ var SessionManager = class {
16850
17111
  refreshTimer = null;
16851
17112
  eventCallbacks = [];
16852
17113
  debug;
17114
+ resolveConfig(configOverride) {
17115
+ const resolvedConfig = {
17116
+ ...this.config,
17117
+ ...configOverride
17118
+ };
17119
+ validateSessionConfig(resolvedConfig);
17120
+ return resolvedConfig;
17121
+ }
16853
17122
  // ========================================================================
16854
17123
  // Session Lifecycle
16855
17124
  // ========================================================================
@@ -16866,15 +17135,16 @@ var SessionManager = class {
16866
17135
  * @returns Created session key
16867
17136
  * @throws SessionError if registration fails
16868
17137
  */
16869
- async createSession() {
17138
+ async createSession(configOverride) {
16870
17139
  try {
16871
17140
  this.log("Creating new session...");
17141
+ const sessionConfig = this.resolveConfig(configOverride);
16872
17142
  const keyPair = generateSecp256k1KeyPair();
16873
17143
  const keyHash = computeSessionKeyHash(keyPair.publicKey);
16874
17144
  this.log("Generated session key:", keyHash);
16875
17145
  const challenge = import_ethers21.ethers.solidityPacked(
16876
17146
  ["string", "bytes32", "uint256", "uint256"],
16877
- ["registerSession", keyHash, this.config.duration, this.config.maxValue]
17147
+ ["registerSession", keyHash, sessionConfig.duration, sessionConfig.maxValue]
16878
17148
  );
16879
17149
  this.log("Challenge prepared, requesting Passkey signature...");
16880
17150
  const signature = await this.passkeySign(import_ethers21.ethers.getBytes(challenge));
@@ -16884,20 +17154,20 @@ var SessionManager = class {
16884
17154
  publicKeyX: this.credential.publicKeyX,
16885
17155
  publicKeyY: this.credential.publicKeyY,
16886
17156
  sessionKeyHash: keyHash,
16887
- duration: this.config.duration,
16888
- maxValue: this.config.maxValue,
17157
+ duration: sessionConfig.duration,
17158
+ maxValue: sessionConfig.maxValue,
16889
17159
  requireUV: true
16890
17160
  };
16891
17161
  await this.hubClient.registerSession(registerParams);
16892
17162
  this.log("Session registered on Hub");
16893
- const expiry = Date.now() + this.config.duration * 1e3;
17163
+ const expiry = Date.now() + sessionConfig.duration * 1e3;
16894
17164
  this.currentSession = {
16895
17165
  publicKey: keyPair.publicKey,
16896
17166
  privateKey: keyPair.privateKey,
16897
17167
  keyHash,
16898
17168
  expiry,
16899
- maxValue: this.config.maxValue,
16900
- chainScopes: this.config.chainScopes,
17169
+ maxValue: sessionConfig.maxValue,
17170
+ chainScopes: sessionConfig.chainScopes,
16901
17171
  userKeyHash: this.credential.keyHash
16902
17172
  };
16903
17173
  await this.storage.save(this.currentSession);
@@ -16922,12 +17192,15 @@ var SessionManager = class {
16922
17192
  *
16923
17193
  * @returns Loaded session or null if no valid session exists
16924
17194
  */
16925
- async loadSession() {
17195
+ async loadSession(keyHash) {
16926
17196
  try {
16927
- this.log("Loading session from storage...");
16928
- const session = await this.storage.load();
17197
+ this.log("Loading session from storage...", keyHash ?? "latest");
17198
+ const session = await this.storage.load(keyHash);
16929
17199
  if (!session) {
16930
17200
  this.log("No session found in storage");
17201
+ if (!keyHash) {
17202
+ this.currentSession = null;
17203
+ }
16931
17204
  return null;
16932
17205
  }
16933
17206
  if (session.expiry <= Date.now()) {
@@ -16944,27 +17217,43 @@ var SessionManager = class {
16944
17217
  return session;
16945
17218
  } catch (error) {
16946
17219
  this.log("Failed to load session:", error);
16947
- await this.storage.clear();
17220
+ if (!keyHash) {
17221
+ await this.storage.clear();
17222
+ }
16948
17223
  return null;
16949
17224
  }
16950
17225
  }
17226
+ async listSessions() {
17227
+ return this.storage.loadAll();
17228
+ }
17229
+ async selectSession(keyHash) {
17230
+ const session = await this.loadSession(keyHash);
17231
+ if (!session) {
17232
+ throw new SessionError(
17233
+ `Session ${keyHash} not found`,
17234
+ "SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */
17235
+ );
17236
+ }
17237
+ return session;
17238
+ }
16951
17239
  /**
16952
17240
  * Revoke the current session (requires biometric authentication)
16953
17241
  *
16954
17242
  * @throws SessionError if no active session or revocation fails
16955
17243
  */
16956
- async revokeSession() {
16957
- if (!this.currentSession) {
17244
+ async revokeSession(keyHash) {
17245
+ const targetSession = keyHash ? await this.storage.load(keyHash) : this.currentSession;
17246
+ if (!targetSession) {
16958
17247
  throw new SessionError(
16959
- "No active session to revoke",
16960
- "NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
17248
+ keyHash ? `Session ${keyHash} not found` : "No active session to revoke",
17249
+ keyHash ? "SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */ : "NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
16961
17250
  );
16962
17251
  }
16963
17252
  try {
16964
- this.log("Revoking session:", this.currentSession.keyHash);
17253
+ this.log("Revoking session:", targetSession.keyHash);
16965
17254
  const challenge = import_ethers21.ethers.solidityPacked(
16966
17255
  ["string", "bytes32"],
16967
- ["revokeSession", this.currentSession.keyHash]
17256
+ ["revokeSession", targetSession.keyHash]
16968
17257
  );
16969
17258
  const signature = await this.passkeySign(import_ethers21.ethers.getBytes(challenge));
16970
17259
  this.log("Passkey signature obtained, revoking on Hub...");
@@ -16972,18 +17261,24 @@ var SessionManager = class {
16972
17261
  signature,
16973
17262
  publicKeyX: this.credential.publicKeyX,
16974
17263
  publicKeyY: this.credential.publicKeyY,
16975
- sessionKeyHash: this.currentSession.keyHash,
17264
+ sessionKeyHash: targetSession.keyHash,
16976
17265
  requireUV: true
16977
17266
  };
16978
17267
  await this.hubClient.revokeSession(revokeParams);
16979
17268
  this.log("Session revoked on Hub");
16980
- await this.storage.clear();
16981
- if (this.refreshTimer) {
16982
- clearTimeout(this.refreshTimer);
16983
- this.refreshTimer = null;
17269
+ await this.storage.remove(targetSession.keyHash);
17270
+ const revokedKeyHash = targetSession.keyHash;
17271
+ const revokedCurrentSession = this.currentSession?.keyHash === revokedKeyHash;
17272
+ if (revokedCurrentSession) {
17273
+ if (this.refreshTimer) {
17274
+ clearTimeout(this.refreshTimer);
17275
+ this.refreshTimer = null;
17276
+ }
17277
+ this.currentSession = await this.storage.load();
17278
+ if (this.currentSession && this.config.autoRefresh) {
17279
+ this.scheduleRefresh();
17280
+ }
16984
17281
  }
16985
- const revokedKeyHash = this.currentSession.keyHash;
16986
- this.currentSession = null;
16987
17282
  this.emit({ type: "session-revoked", keyHash: revokedKeyHash });
16988
17283
  this.log("Session revoked successfully");
16989
17284
  } catch (error) {
@@ -17061,45 +17356,46 @@ var SessionManager = class {
17061
17356
  * @returns Session signature
17062
17357
  * @throws SessionError if no active session, expired, or value exceeds limit
17063
17358
  */
17064
- async signWithSession(action) {
17065
- if (!this.currentSession) {
17359
+ async signWithSession(action, keyHash) {
17360
+ const session = keyHash ? await this.storage.load(keyHash) : this.currentSession;
17361
+ if (!session) {
17066
17362
  throw new SessionError(
17067
- "No active session available",
17068
- "NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
17363
+ keyHash ? `Session ${keyHash} not found` : "No active session available",
17364
+ keyHash ? "SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */ : "NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
17069
17365
  );
17070
17366
  }
17071
17367
  const now = Date.now();
17072
- if (now >= this.currentSession.expiry) {
17073
- this.emit({ type: "session-expired", keyHash: this.currentSession.keyHash });
17368
+ if (now >= session.expiry) {
17369
+ this.emit({ type: "session-expired", keyHash: session.keyHash });
17074
17370
  throw new SessionError(
17075
17371
  "Session has expired",
17076
17372
  "SESSION_EXPIRED" /* SESSION_EXPIRED */
17077
17373
  );
17078
17374
  }
17079
- if (this.currentSession.maxValue > 0n && action.value > this.currentSession.maxValue) {
17375
+ if (session.maxValue > 0n && action.value > session.maxValue) {
17080
17376
  throw new SessionError(
17081
- `Transaction value (${action.value}) exceeds session limit (${this.currentSession.maxValue})`,
17377
+ `Transaction value (${action.value}) exceeds session limit (${session.maxValue})`,
17082
17378
  "VALUE_EXCEEDS_LIMIT" /* VALUE_EXCEEDS_LIMIT */,
17083
- { value: action.value, limit: this.currentSession.maxValue }
17379
+ { value: action.value, limit: session.maxValue }
17084
17380
  );
17085
17381
  }
17086
- if (this.currentSession.chainScopes.length > 0 && !this.currentSession.chainScopes.includes(action.targetChain)) {
17382
+ if (session.chainScopes.length > 0 && !session.chainScopes.includes(action.targetChain)) {
17087
17383
  throw new SessionError(
17088
17384
  `Chain ${action.targetChain} not in session scope`,
17089
17385
  "CHAIN_NOT_ALLOWED" /* CHAIN_NOT_ALLOWED */,
17090
- { chain: action.targetChain, allowedChains: this.currentSession.chainScopes }
17386
+ { chain: action.targetChain, allowedChains: session.chainScopes }
17091
17387
  );
17092
17388
  }
17093
17389
  this.log("Signing action with session key...");
17094
17390
  const messageHash = hashAction(action);
17095
17391
  const { signature } = signWithSessionKey(
17096
- this.currentSession.privateKey,
17392
+ session.privateKey,
17097
17393
  messageHash
17098
17394
  );
17099
17395
  const sessionSignature = {
17100
17396
  signature,
17101
- sessionKeyHash: this.currentSession.keyHash,
17102
- userKeyHash: this.currentSession.userKeyHash,
17397
+ sessionKeyHash: session.keyHash,
17398
+ userKeyHash: session.userKeyHash,
17103
17399
  timestamp: now,
17104
17400
  nonce: action.nonce
17105
17401
  };
@@ -17112,8 +17408,8 @@ var SessionManager = class {
17112
17408
  * @param action Action parameters
17113
17409
  * @returns Session-signed action ready for submission
17114
17410
  */
17115
- async signAction(action) {
17116
- const signature = await this.signWithSession(action);
17411
+ async signAction(action, keyHash) {
17412
+ const signature = await this.signWithSession(action, keyHash);
17117
17413
  return {
17118
17414
  action,
17119
17415
  signature,
@@ -18097,6 +18393,7 @@ var VALIDATION_REGISTRY_ABI = [
18097
18393
  calculatePercentage,
18098
18394
  computeKeyHash,
18099
18395
  computeSessionKeyHash,
18396
+ configureDefaultRpcUrls,
18100
18397
  createAuditEntry,
18101
18398
  createChainClient,
18102
18399
  createChainDetector,
@@ -18166,6 +18463,7 @@ var VALIDATION_REGISTRY_ABI = [
18166
18463
  getExplorerUrl,
18167
18464
  getFeatureFlags,
18168
18465
  getHubChains,
18466
+ getRpcUrlOverride,
18169
18467
  getSequenceFromTxReceipt,
18170
18468
  getStacksContractPrincipal,
18171
18469
  getStacksExplorerAddressUrl,