@veridex/sdk 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{EVMClient-DtqvdfUP.d.mts → EVMClient-Bmy9czkE.d.mts} +2 -0
- package/dist/auth/prepareAuth.js +107 -32
- package/dist/auth/prepareAuth.js.map +1 -1
- package/dist/auth/prepareAuth.mjs +6 -6
- package/dist/chains/aptos/index.js.map +1 -1
- package/dist/chains/aptos/index.mjs +3 -3
- package/dist/chains/avalanche/index.d.mts +1 -1
- package/dist/chains/avalanche/index.js +59 -11
- package/dist/chains/avalanche/index.js.map +1 -1
- package/dist/chains/avalanche/index.mjs +4 -4
- package/dist/chains/evm/index.d.mts +3 -3
- package/dist/chains/evm/index.js +59 -11
- package/dist/chains/evm/index.js.map +1 -1
- package/dist/chains/evm/index.mjs +3 -3
- package/dist/chains/solana/index.js.map +1 -1
- package/dist/chains/solana/index.mjs +3 -3
- package/dist/chains/stacks/index.d.mts +1 -1
- package/dist/chains/stacks/index.js.map +1 -1
- package/dist/chains/stacks/index.mjs +3 -3
- package/dist/chains/starknet/index.d.mts +1 -1
- package/dist/chains/starknet/index.js.map +1 -1
- package/dist/chains/starknet/index.mjs +3 -3
- package/dist/chains/stellar/index.d.mts +312 -0
- package/dist/chains/stellar/index.js +300 -0
- package/dist/chains/stellar/index.js.map +1 -0
- package/dist/chains/stellar/index.mjs +260 -0
- package/dist/chains/stellar/index.mjs.map +1 -0
- package/dist/chains/sui/index.d.mts +1 -1
- package/dist/chains/sui/index.js.map +1 -1
- package/dist/chains/sui/index.mjs +3 -3
- package/dist/{chunk-Q5O3M5LP.mjs → chunk-2TS375ET.mjs} +2 -2
- package/dist/{chunk-QT4ZZ4GM.mjs → chunk-5FDOTI5G.mjs} +2 -2
- package/dist/{chunk-N4A2RMUN.mjs → chunk-AFHWA4CZ.mjs} +2 -2
- package/dist/{chunk-5T6KPH7A.mjs → chunk-CSU4IV2F.mjs} +2 -2
- package/dist/{chunk-YCUJZ6Z7.mjs → chunk-CTYDGO6E.mjs} +63 -6
- package/dist/chunk-CTYDGO6E.mjs.map +1 -0
- package/dist/{chunk-USDA5JTN.mjs → chunk-DZUNCSI5.mjs} +61 -13
- package/dist/chunk-DZUNCSI5.mjs.map +1 -0
- package/dist/{chunk-SXXGTQIR.mjs → chunk-E3SU36C2.mjs} +2 -2
- package/dist/{chunk-NUWSMJFJ.mjs → chunk-EFIXFA6V.mjs} +2 -2
- package/dist/{chunk-MLXQHIH2.mjs → chunk-GM5DKEHD.mjs} +2 -2
- package/dist/{chunk-GWJRKDSA.mjs → chunk-GOWXQPTW.mjs} +3 -3
- package/dist/{chunk-OVMMTL6H.mjs → chunk-ICGB3AHI.mjs} +2 -2
- package/dist/{chunk-QDO6NQ7P.mjs → chunk-M3GUNREX.mjs} +20 -3
- package/dist/{chunk-QDO6NQ7P.mjs.map → chunk-M3GUNREX.mjs.map} +1 -1
- package/dist/{chunk-X7BZMSPQ.mjs → chunk-RD6ZYUVG.mjs} +52 -30
- package/dist/chunk-RD6ZYUVG.mjs.map +1 -0
- package/dist/{chunk-F3YAGZSW.mjs → chunk-TPEP6XUA.mjs} +2 -2
- package/dist/{chunk-M3MM4YMF.mjs → chunk-UPO55SBK.mjs} +2 -2
- package/dist/{chunk-PDHZ5X5O.mjs → chunk-YYT3V7CI.mjs} +2 -2
- package/dist/constants.d.mts +2 -2
- package/dist/constants.js +51 -29
- package/dist/constants.js.map +1 -1
- package/dist/constants.mjs +1 -1
- package/dist/{index-DDalBhAm.d.mts → index-CKKUV4J7.d.mts} +10 -7
- package/dist/index.d.mts +43 -14
- package/dist/index.js +512 -159
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +335 -128
- package/dist/index.mjs.map +1 -1
- package/dist/passkey.js +57 -4
- package/dist/passkey.js.map +1 -1
- package/dist/passkey.mjs +3 -3
- package/dist/payload.js.map +1 -1
- package/dist/payload.mjs +2 -2
- package/dist/portfolio-JA4OTF7Y.mjs +13 -0
- package/dist/queries/index.js +49 -27
- package/dist/queries/index.js.map +1 -1
- package/dist/queries/index.mjs +5 -5
- package/dist/{types-B7V5VNbO.d.mts → types-C564CfsE.d.mts} +33 -4
- package/dist/utils.js +49 -27
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +2 -2
- package/dist/wormhole.js.map +1 -1
- package/dist/wormhole.mjs +2 -2
- package/package.json +8 -1
- package/dist/chunk-USDA5JTN.mjs.map +0 -1
- package/dist/chunk-X7BZMSPQ.mjs.map +0 -1
- package/dist/chunk-YCUJZ6Z7.mjs.map +0 -1
- package/dist/portfolio-V347KZOL.mjs +0 -13
- /package/dist/{chunk-Q5O3M5LP.mjs.map → chunk-2TS375ET.mjs.map} +0 -0
- /package/dist/{chunk-QT4ZZ4GM.mjs.map → chunk-5FDOTI5G.mjs.map} +0 -0
- /package/dist/{chunk-N4A2RMUN.mjs.map → chunk-AFHWA4CZ.mjs.map} +0 -0
- /package/dist/{chunk-5T6KPH7A.mjs.map → chunk-CSU4IV2F.mjs.map} +0 -0
- /package/dist/{chunk-SXXGTQIR.mjs.map → chunk-E3SU36C2.mjs.map} +0 -0
- /package/dist/{chunk-NUWSMJFJ.mjs.map → chunk-EFIXFA6V.mjs.map} +0 -0
- /package/dist/{chunk-MLXQHIH2.mjs.map → chunk-GM5DKEHD.mjs.map} +0 -0
- /package/dist/{chunk-GWJRKDSA.mjs.map → chunk-GOWXQPTW.mjs.map} +0 -0
- /package/dist/{chunk-OVMMTL6H.mjs.map → chunk-ICGB3AHI.mjs.map} +0 -0
- /package/dist/{chunk-F3YAGZSW.mjs.map → chunk-TPEP6XUA.mjs.map} +0 -0
- /package/dist/{chunk-M3MM4YMF.mjs.map → chunk-UPO55SBK.mjs.map} +0 -0
- /package/dist/{chunk-PDHZ5X5O.mjs.map → chunk-YYT3V7CI.mjs.map} +0 -0
- /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
|
-
|
|
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
|
-
|
|
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: "
|
|
181
|
-
vaultFactory: "
|
|
182
|
-
vaultImplementation: "
|
|
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: "
|
|
196
|
-
vaultImplementation: "
|
|
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: "
|
|
210
|
-
vaultImplementation: "
|
|
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: "
|
|
224
|
-
vaultImplementation: "
|
|
222
|
+
vaultFactory: "0xB9C3e6bad3c6f26956be4a4bb5a366376Fd3045D",
|
|
223
|
+
vaultImplementation: "0x8601881b94B68B09b485f407317686103d3CB681",
|
|
225
224
|
wormholeCoreBridge: "0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35",
|
|
226
225
|
tokenBridge: "0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e"
|
|
227
226
|
}
|
|
228
227
|
},
|
|
229
|
-
|
|
230
|
-
name: "
|
|
231
|
-
chainId:
|
|
232
|
-
wormholeChainId:
|
|
233
|
-
rpcUrl: "https://
|
|
234
|
-
explorerUrl: "https://
|
|
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: "
|
|
240
|
-
|
|
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: "
|
|
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
|
-
|
|
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
|
-
|
|
292
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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(
|
|
5900
|
+
const response = await fetch(resolvedUrl, {
|
|
5800
5901
|
...options,
|
|
5801
5902
|
headers,
|
|
5802
5903
|
signal: controller.signal
|
|
@@ -12654,7 +12755,9 @@ var ERC20_ABI2 = [
|
|
|
12654
12755
|
var HUB_ABI2 = [
|
|
12655
12756
|
"function dispatch(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) signature, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) payable returns (uint64 sequence)",
|
|
12656
12757
|
"function userNonces(bytes32 userKeyHash) view returns (uint256)",
|
|
12657
|
-
|
|
12758
|
+
// Hub exposes the Wormhole core bridge address; message fee is read from the
|
|
12759
|
+
// bridge directly (getMessageFee() was removed from the Hub).
|
|
12760
|
+
"function wormhole() view returns (address)",
|
|
12658
12761
|
"function getVaultAddress(bytes32 userKeyHash) view returns (address)",
|
|
12659
12762
|
"function vaultExists(bytes32 userKeyHash) view returns (bool)",
|
|
12660
12763
|
"function createVault(bytes32 userKeyHash) returns (address)",
|
|
@@ -12711,6 +12814,8 @@ var EVMClient = class {
|
|
|
12711
12814
|
hubContract;
|
|
12712
12815
|
factoryContract = null;
|
|
12713
12816
|
cachedImplementation = null;
|
|
12817
|
+
cachedWormholeAddress = null;
|
|
12818
|
+
cachedMessageFee = null;
|
|
12714
12819
|
constructor(config) {
|
|
12715
12820
|
this.config = {
|
|
12716
12821
|
name: config.name ?? `EVM Chain ${config.chainId}`,
|
|
@@ -12883,8 +12988,24 @@ var EVMClient = class {
|
|
|
12883
12988
|
return Number(count);
|
|
12884
12989
|
}
|
|
12885
12990
|
async getMessageFee() {
|
|
12886
|
-
const
|
|
12887
|
-
|
|
12991
|
+
const now = Date.now();
|
|
12992
|
+
if (this.cachedMessageFee && this.cachedMessageFee.expiresAt > now) {
|
|
12993
|
+
return this.cachedMessageFee.value;
|
|
12994
|
+
}
|
|
12995
|
+
let wormholeAddress = this.config.contracts.wormholeCoreBridge ?? this.cachedWormholeAddress;
|
|
12996
|
+
if (!wormholeAddress) {
|
|
12997
|
+
wormholeAddress = await this.hubContract.wormhole();
|
|
12998
|
+
this.cachedWormholeAddress = wormholeAddress;
|
|
12999
|
+
}
|
|
13000
|
+
const wormhole = new import_ethers16.ethers.Contract(
|
|
13001
|
+
wormholeAddress,
|
|
13002
|
+
["function messageFee() view returns (uint256)"],
|
|
13003
|
+
this.provider
|
|
13004
|
+
);
|
|
13005
|
+
const fee = await wormhole.messageFee();
|
|
13006
|
+
const value = BigInt(fee.toString());
|
|
13007
|
+
this.cachedMessageFee = { value, expiresAt: now + 3e4 };
|
|
13008
|
+
return value;
|
|
12888
13009
|
}
|
|
12889
13010
|
async buildTransferPayload(params) {
|
|
12890
13011
|
return encodeTransferAction(
|
|
@@ -12983,13 +13104,41 @@ var EVMClient = class {
|
|
|
12983
13104
|
actionPayload,
|
|
12984
13105
|
nonce: Number(nonce)
|
|
12985
13106
|
};
|
|
12986
|
-
const
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
13107
|
+
const MAX_ATTEMPTS = 3;
|
|
13108
|
+
const baseDelayMs = 1e3;
|
|
13109
|
+
const sleep5 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
13110
|
+
let response;
|
|
13111
|
+
let lastError;
|
|
13112
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
13113
|
+
try {
|
|
13114
|
+
response = await fetch(`${relayerUrl}/api/v1/submit`, {
|
|
13115
|
+
method: "POST",
|
|
13116
|
+
headers: {
|
|
13117
|
+
"Content-Type": "application/json"
|
|
13118
|
+
},
|
|
13119
|
+
body: JSON.stringify(request)
|
|
13120
|
+
});
|
|
13121
|
+
const retryable = response.status >= 500 || response.status === 408 || response.status === 429;
|
|
13122
|
+
if (!retryable) {
|
|
13123
|
+
break;
|
|
13124
|
+
}
|
|
13125
|
+
if (attempt === MAX_ATTEMPTS) break;
|
|
13126
|
+
const retryAfter = response.headers.get("retry-after");
|
|
13127
|
+
const explicitDelay = retryAfter ? parseInt(retryAfter, 10) * 1e3 : 0;
|
|
13128
|
+
const backoff = explicitDelay > 0 ? explicitDelay : baseDelayMs * 2 ** (attempt - 1) + Math.floor(Math.random() * 200);
|
|
13129
|
+
await sleep5(backoff);
|
|
13130
|
+
} catch (err) {
|
|
13131
|
+
lastError = err;
|
|
13132
|
+
if (attempt === MAX_ATTEMPTS) break;
|
|
13133
|
+
const backoff = baseDelayMs * 2 ** (attempt - 1) + Math.floor(Math.random() * 200);
|
|
13134
|
+
await sleep5(backoff);
|
|
13135
|
+
}
|
|
13136
|
+
}
|
|
13137
|
+
if (!response) {
|
|
13138
|
+
throw new Error(
|
|
13139
|
+
`Relayer submission failed after ${MAX_ATTEMPTS} attempts: ${lastError instanceof Error ? lastError.message : String(lastError)}`
|
|
13140
|
+
);
|
|
13141
|
+
}
|
|
12993
13142
|
if (!response.ok) {
|
|
12994
13143
|
const error = await response.json().catch(() => ({ error: response.statusText }));
|
|
12995
13144
|
throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);
|
|
@@ -13820,7 +13969,7 @@ var EVMClient = class {
|
|
|
13820
13969
|
async executeTransactionProposal(proposalId, signer) {
|
|
13821
13970
|
const s = signer;
|
|
13822
13971
|
const hub = this.hubContract.connect(s);
|
|
13823
|
-
const fee = await this.
|
|
13972
|
+
const fee = await this.getMessageFee();
|
|
13824
13973
|
const tx = await hub.executeTransactionProposal(proposalId, { value: fee });
|
|
13825
13974
|
const receipt = await tx.wait();
|
|
13826
13975
|
const sequence = this._extractSequenceFromReceipt(receipt);
|
|
@@ -15369,13 +15518,14 @@ function inferBackupEligibility(platform) {
|
|
|
15369
15518
|
}
|
|
15370
15519
|
|
|
15371
15520
|
// src/core/CredentialManager.ts
|
|
15521
|
+
init_relayerUrl();
|
|
15372
15522
|
var DEFAULT_STORAGE_KEY = "veridex_credential_metadata";
|
|
15373
15523
|
var CredentialManager = class {
|
|
15374
15524
|
config;
|
|
15375
15525
|
constructor(config = {}) {
|
|
15376
15526
|
this.config = {
|
|
15377
15527
|
storageKey: config.storageKey ?? DEFAULT_STORAGE_KEY,
|
|
15378
|
-
relayerUrl: config.relayerUrl ?? ""
|
|
15528
|
+
relayerUrl: normalizeRelayerOrigin(config.relayerUrl ?? "")
|
|
15379
15529
|
};
|
|
15380
15530
|
}
|
|
15381
15531
|
// ========================================================================
|
|
@@ -15523,7 +15673,7 @@ var CredentialManager = class {
|
|
|
15523
15673
|
const managed = this.getCredential(credentialId);
|
|
15524
15674
|
if (!managed) return false;
|
|
15525
15675
|
try {
|
|
15526
|
-
const response = await fetch(
|
|
15676
|
+
const response = await fetch(buildRelayerApiUrl(this.config.relayerUrl, "/credential/metadata"), {
|
|
15527
15677
|
method: "PUT",
|
|
15528
15678
|
headers: { "Content-Type": "application/json" },
|
|
15529
15679
|
body: JSON.stringify({
|
|
@@ -15549,7 +15699,10 @@ var CredentialManager = class {
|
|
|
15549
15699
|
if (!this.config.relayerUrl) return null;
|
|
15550
15700
|
try {
|
|
15551
15701
|
const response = await fetch(
|
|
15552
|
-
|
|
15702
|
+
buildRelayerApiUrl(
|
|
15703
|
+
this.config.relayerUrl,
|
|
15704
|
+
`/credential/metadata?keyHash=${encodeURIComponent(keyHash)}`
|
|
15705
|
+
)
|
|
15553
15706
|
);
|
|
15554
15707
|
if (!response.ok) return null;
|
|
15555
15708
|
const data = await response.json();
|
|
@@ -15671,9 +15824,10 @@ var CredentialManager = class {
|
|
|
15671
15824
|
|
|
15672
15825
|
// src/core/CrossOriginAuth.ts
|
|
15673
15826
|
init_PasskeyManager();
|
|
15827
|
+
init_relayerUrl();
|
|
15674
15828
|
init_PasskeyManager();
|
|
15675
15829
|
var DEFAULT_AUTH_PORTAL_URL = "https://auth.veridex.network";
|
|
15676
|
-
var DEFAULT_RELAYER_URL = "https://
|
|
15830
|
+
var DEFAULT_RELAYER_URL = "https://relayer.veridex.network";
|
|
15677
15831
|
var AUTH_MESSAGE_TYPES = {
|
|
15678
15832
|
AUTH_REQUEST: "VERIDEX_AUTH_REQUEST",
|
|
15679
15833
|
AUTH_RESPONSE: "VERIDEX_AUTH_RESPONSE",
|
|
@@ -15685,7 +15839,7 @@ var CrossOriginAuth = class {
|
|
|
15685
15839
|
this.config = {
|
|
15686
15840
|
rpId: config.rpId ?? VERIDEX_RP_ID,
|
|
15687
15841
|
authPortalUrl: config.authPortalUrl ?? DEFAULT_AUTH_PORTAL_URL,
|
|
15688
|
-
relayerUrl: config.relayerUrl ?? DEFAULT_RELAYER_URL,
|
|
15842
|
+
relayerUrl: normalizeRelayerOrigin(config.relayerUrl ?? DEFAULT_RELAYER_URL),
|
|
15689
15843
|
mode: config.mode ?? "popup",
|
|
15690
15844
|
popupFeatures: config.popupFeatures ?? "width=500,height=600,left=100,top=100",
|
|
15691
15845
|
timeout: config.timeout ?? 12e4,
|
|
@@ -15902,7 +16056,8 @@ var CrossOriginAuth = class {
|
|
|
15902
16056
|
return bytes;
|
|
15903
16057
|
}
|
|
15904
16058
|
async requestServerSessionChallenge(options) {
|
|
15905
|
-
const
|
|
16059
|
+
const challengeUrl = buildRelayerApiUrl(this.config.relayerUrl, "/session/challenge");
|
|
16060
|
+
const response = await fetch(challengeUrl, {
|
|
15906
16061
|
method: "POST",
|
|
15907
16062
|
headers: { "Content-Type": "application/json" },
|
|
15908
16063
|
body: JSON.stringify({
|
|
@@ -15948,7 +16103,7 @@ var CrossOriginAuth = class {
|
|
|
15948
16103
|
if (!session.serverChallengeId) {
|
|
15949
16104
|
throw new Error("Session must include a relayer-issued serverChallengeId");
|
|
15950
16105
|
}
|
|
15951
|
-
const response = await fetch(
|
|
16106
|
+
const response = await fetch(buildRelayerApiUrl(this.config.relayerUrl, "/session/create"), {
|
|
15952
16107
|
method: "POST",
|
|
15953
16108
|
headers: { "Content-Type": "application/json" },
|
|
15954
16109
|
body: JSON.stringify({
|
|
@@ -15971,7 +16126,9 @@ var CrossOriginAuth = class {
|
|
|
15971
16126
|
* Returns the session details if valid, null if expired/revoked.
|
|
15972
16127
|
*/
|
|
15973
16128
|
async validateServerSession(sessionId) {
|
|
15974
|
-
const response = await fetch(
|
|
16129
|
+
const response = await fetch(
|
|
16130
|
+
buildRelayerApiUrl(this.config.relayerUrl, `/session/${encodeURIComponent(sessionId)}`)
|
|
16131
|
+
);
|
|
15975
16132
|
if (!response.ok) {
|
|
15976
16133
|
return null;
|
|
15977
16134
|
}
|
|
@@ -15985,9 +16142,12 @@ var CrossOriginAuth = class {
|
|
|
15985
16142
|
* Revoke a server session token.
|
|
15986
16143
|
*/
|
|
15987
16144
|
async revokeServerSession(sessionId) {
|
|
15988
|
-
const response = await fetch(
|
|
15989
|
-
|
|
15990
|
-
|
|
16145
|
+
const response = await fetch(
|
|
16146
|
+
buildRelayerApiUrl(this.config.relayerUrl, `/session/${encodeURIComponent(sessionId)}`),
|
|
16147
|
+
{
|
|
16148
|
+
method: "DELETE"
|
|
16149
|
+
}
|
|
16150
|
+
);
|
|
15991
16151
|
return response.ok;
|
|
15992
16152
|
}
|
|
15993
16153
|
/**
|
|
@@ -16439,6 +16599,12 @@ function validateSessionConfig(config) {
|
|
|
16439
16599
|
"INVALID_CONFIG" /* INVALID_CONFIG */
|
|
16440
16600
|
);
|
|
16441
16601
|
}
|
|
16602
|
+
if (config.maxValue === 0n && config.allowUnboundedMaxValue !== true) {
|
|
16603
|
+
throw new SessionError(
|
|
16604
|
+
'Session maxValue=0 means "no per-tx limit" \u2014 the vault daily cap is then the only bound. This is a foot-gun: a compromised session key can drain the vault up to that cap. Pass a non-zero maxValue, or set allowUnboundedMaxValue:true if you have verified the vault daily cap and accept the residual risk.',
|
|
16605
|
+
"INVALID_CONFIG" /* INVALID_CONFIG */
|
|
16606
|
+
);
|
|
16607
|
+
}
|
|
16442
16608
|
}
|
|
16443
16609
|
|
|
16444
16610
|
// src/sessions/storage.ts
|
|
@@ -16547,39 +16713,44 @@ var IndexedDBSessionStorage = class {
|
|
|
16547
16713
|
);
|
|
16548
16714
|
}
|
|
16549
16715
|
}
|
|
16716
|
+
async decryptSession(stored) {
|
|
16717
|
+
const key = await this.getEncryptionKey();
|
|
16718
|
+
const encryptedPrivateKey = new Uint8Array(stored.encryptedPrivateKey);
|
|
16719
|
+
const privateKey = await decrypt(encryptedPrivateKey, key);
|
|
16720
|
+
return {
|
|
16721
|
+
keyHash: stored.keyHash,
|
|
16722
|
+
publicKey: new Uint8Array(stored.publicKey),
|
|
16723
|
+
privateKey,
|
|
16724
|
+
expiry: stored.expiry,
|
|
16725
|
+
maxValue: BigInt(stored.maxValue),
|
|
16726
|
+
chainScopes: stored.chainScopes ?? [],
|
|
16727
|
+
userKeyHash: stored.userKeyHash
|
|
16728
|
+
};
|
|
16729
|
+
}
|
|
16730
|
+
async pruneExpiredSessions(records) {
|
|
16731
|
+
const now = Date.now();
|
|
16732
|
+
const validRecords = records.filter((record) => record.expiry > now);
|
|
16733
|
+
const expiredRecords = records.filter((record) => record.expiry <= now);
|
|
16734
|
+
if (expiredRecords.length > 0) {
|
|
16735
|
+
await Promise.all(expiredRecords.map((record) => this.remove(record.keyHash)));
|
|
16736
|
+
}
|
|
16737
|
+
return validRecords.sort((left, right) => right.savedAt - left.savedAt);
|
|
16738
|
+
}
|
|
16550
16739
|
/**
|
|
16551
|
-
* Load
|
|
16740
|
+
* Load a session (decrypts private key)
|
|
16552
16741
|
*/
|
|
16553
|
-
async load() {
|
|
16742
|
+
async load(keyHash) {
|
|
16554
16743
|
try {
|
|
16555
16744
|
await this.initialize();
|
|
16556
16745
|
if (!this.db) {
|
|
16557
16746
|
throw new Error("Database not initialized");
|
|
16558
16747
|
}
|
|
16559
|
-
const
|
|
16560
|
-
|
|
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);
|
|
16748
|
+
const sessions = keyHash ? await this.getSessionByKeyHash(keyHash) : await this.getAllSessions();
|
|
16749
|
+
const validSessions = await this.pruneExpiredSessions(sessions);
|
|
16565
16750
|
if (validSessions.length === 0) {
|
|
16566
|
-
await this.clear();
|
|
16567
16751
|
return null;
|
|
16568
16752
|
}
|
|
16569
|
-
|
|
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;
|
|
16753
|
+
return this.decryptSession(validSessions[0]);
|
|
16583
16754
|
} catch (error) {
|
|
16584
16755
|
if (error instanceof SessionError) {
|
|
16585
16756
|
throw error;
|
|
@@ -16612,6 +16783,75 @@ var IndexedDBSessionStorage = class {
|
|
|
16612
16783
|
};
|
|
16613
16784
|
});
|
|
16614
16785
|
}
|
|
16786
|
+
async getSessionByKeyHash(keyHash) {
|
|
16787
|
+
if (!this.db) {
|
|
16788
|
+
return [];
|
|
16789
|
+
}
|
|
16790
|
+
return new Promise((resolve, reject) => {
|
|
16791
|
+
const transaction = this.db.transaction([STORE_NAME], "readonly");
|
|
16792
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
16793
|
+
const request = store.get(keyHash);
|
|
16794
|
+
request.onsuccess = () => {
|
|
16795
|
+
resolve(request.result ? [request.result] : []);
|
|
16796
|
+
};
|
|
16797
|
+
request.onerror = () => {
|
|
16798
|
+
reject(new SessionError(
|
|
16799
|
+
"Failed to get session",
|
|
16800
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
16801
|
+
request.error
|
|
16802
|
+
));
|
|
16803
|
+
};
|
|
16804
|
+
});
|
|
16805
|
+
}
|
|
16806
|
+
async loadAll() {
|
|
16807
|
+
try {
|
|
16808
|
+
await this.initialize();
|
|
16809
|
+
if (!this.db) {
|
|
16810
|
+
return [];
|
|
16811
|
+
}
|
|
16812
|
+
const records = await this.pruneExpiredSessions(await this.getAllSessions());
|
|
16813
|
+
return Promise.all(records.map((record) => this.decryptSession(record)));
|
|
16814
|
+
} catch (error) {
|
|
16815
|
+
if (error instanceof SessionError) {
|
|
16816
|
+
throw error;
|
|
16817
|
+
}
|
|
16818
|
+
throw new SessionError(
|
|
16819
|
+
"Failed to load sessions",
|
|
16820
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
16821
|
+
error
|
|
16822
|
+
);
|
|
16823
|
+
}
|
|
16824
|
+
}
|
|
16825
|
+
async remove(keyHash) {
|
|
16826
|
+
try {
|
|
16827
|
+
await this.initialize();
|
|
16828
|
+
if (!this.db) {
|
|
16829
|
+
return;
|
|
16830
|
+
}
|
|
16831
|
+
return new Promise((resolve, reject) => {
|
|
16832
|
+
const transaction = this.db.transaction([STORE_NAME], "readwrite");
|
|
16833
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
16834
|
+
const request = store.delete(keyHash);
|
|
16835
|
+
request.onsuccess = () => resolve();
|
|
16836
|
+
request.onerror = () => {
|
|
16837
|
+
reject(new SessionError(
|
|
16838
|
+
"Failed to remove session",
|
|
16839
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
16840
|
+
request.error
|
|
16841
|
+
));
|
|
16842
|
+
};
|
|
16843
|
+
});
|
|
16844
|
+
} catch (error) {
|
|
16845
|
+
if (error instanceof SessionError) {
|
|
16846
|
+
throw error;
|
|
16847
|
+
}
|
|
16848
|
+
throw new SessionError(
|
|
16849
|
+
"Failed to remove session",
|
|
16850
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
16851
|
+
error
|
|
16852
|
+
);
|
|
16853
|
+
}
|
|
16854
|
+
}
|
|
16615
16855
|
/**
|
|
16616
16856
|
* Clear all sessions
|
|
16617
16857
|
*/
|
|
@@ -16648,14 +16888,9 @@ var IndexedDBSessionStorage = class {
|
|
|
16648
16888
|
/**
|
|
16649
16889
|
* Check if any session exists
|
|
16650
16890
|
*/
|
|
16651
|
-
async exists() {
|
|
16891
|
+
async exists(keyHash) {
|
|
16652
16892
|
try {
|
|
16653
|
-
await this.
|
|
16654
|
-
if (!this.db) {
|
|
16655
|
-
return false;
|
|
16656
|
-
}
|
|
16657
|
-
const sessions = await this.getAllSessions();
|
|
16658
|
-
return sessions.length > 0;
|
|
16893
|
+
return await this.load(keyHash) !== null;
|
|
16659
16894
|
} catch {
|
|
16660
16895
|
return false;
|
|
16661
16896
|
}
|
|
@@ -16674,7 +16909,8 @@ var STORAGE_KEY_PREFIX = "veridex-session-";
|
|
|
16674
16909
|
var LocalStorageSessionStorage = class {
|
|
16675
16910
|
encryptionKey = null;
|
|
16676
16911
|
credentialId;
|
|
16677
|
-
|
|
16912
|
+
credentialHash;
|
|
16913
|
+
legacyStorageKey;
|
|
16678
16914
|
/**
|
|
16679
16915
|
* @param credentialId User's Passkey credential ID (for key derivation)
|
|
16680
16916
|
*/
|
|
@@ -16686,7 +16922,60 @@ var LocalStorageSessionStorage = class {
|
|
|
16686
16922
|
);
|
|
16687
16923
|
}
|
|
16688
16924
|
this.credentialId = credentialId;
|
|
16689
|
-
this.
|
|
16925
|
+
this.credentialHash = import_ethers20.ethers.keccak256(import_ethers20.ethers.toUtf8Bytes(credentialId));
|
|
16926
|
+
this.legacyStorageKey = STORAGE_KEY_PREFIX + this.credentialHash;
|
|
16927
|
+
}
|
|
16928
|
+
getSessionStorageKey(keyHash) {
|
|
16929
|
+
return `${STORAGE_KEY_PREFIX}${this.credentialHash}:${keyHash}`;
|
|
16930
|
+
}
|
|
16931
|
+
getSessionStoragePrefix() {
|
|
16932
|
+
return `${STORAGE_KEY_PREFIX}${this.credentialHash}:`;
|
|
16933
|
+
}
|
|
16934
|
+
async deserializeSession(stored) {
|
|
16935
|
+
const key = await this.getEncryptionKey();
|
|
16936
|
+
const encryptedPrivateKey = typeof stored.encryptedPrivateKey === "string" ? import_ethers20.ethers.getBytes(stored.encryptedPrivateKey) : new Uint8Array(stored.encryptedPrivateKey);
|
|
16937
|
+
const privateKey = await decrypt(encryptedPrivateKey, key);
|
|
16938
|
+
return {
|
|
16939
|
+
keyHash: stored.keyHash,
|
|
16940
|
+
publicKey: typeof stored.publicKey === "string" ? import_ethers20.ethers.getBytes(stored.publicKey) : new Uint8Array(stored.publicKey),
|
|
16941
|
+
privateKey,
|
|
16942
|
+
expiry: stored.expiry,
|
|
16943
|
+
maxValue: BigInt(stored.maxValue),
|
|
16944
|
+
chainScopes: stored.chainScopes ?? [],
|
|
16945
|
+
userKeyHash: stored.userKeyHash
|
|
16946
|
+
};
|
|
16947
|
+
}
|
|
16948
|
+
getRawRecords() {
|
|
16949
|
+
const records = [];
|
|
16950
|
+
const prefix = this.getSessionStoragePrefix();
|
|
16951
|
+
for (let index = 0; index < localStorage.length; index++) {
|
|
16952
|
+
const key = localStorage.key(index);
|
|
16953
|
+
if (!key || !key.startsWith(prefix)) {
|
|
16954
|
+
continue;
|
|
16955
|
+
}
|
|
16956
|
+
const value = localStorage.getItem(key);
|
|
16957
|
+
if (!value) {
|
|
16958
|
+
continue;
|
|
16959
|
+
}
|
|
16960
|
+
records.push(JSON.parse(value));
|
|
16961
|
+
}
|
|
16962
|
+
const legacyValue = localStorage.getItem(this.legacyStorageKey);
|
|
16963
|
+
if (legacyValue) {
|
|
16964
|
+
records.push(JSON.parse(legacyValue));
|
|
16965
|
+
}
|
|
16966
|
+
return records;
|
|
16967
|
+
}
|
|
16968
|
+
async getValidRecords() {
|
|
16969
|
+
const now = Date.now();
|
|
16970
|
+
const validRecords = [];
|
|
16971
|
+
for (const record of this.getRawRecords()) {
|
|
16972
|
+
if (record.expiry <= now) {
|
|
16973
|
+
await this.remove(record.keyHash);
|
|
16974
|
+
continue;
|
|
16975
|
+
}
|
|
16976
|
+
validRecords.push(record);
|
|
16977
|
+
}
|
|
16978
|
+
return validRecords.sort((left, right) => right.savedAt - left.savedAt);
|
|
16690
16979
|
}
|
|
16691
16980
|
/**
|
|
16692
16981
|
* Get or derive encryption key
|
|
@@ -16715,7 +17004,7 @@ var LocalStorageSessionStorage = class {
|
|
|
16715
17004
|
userKeyHash: session.userKeyHash,
|
|
16716
17005
|
savedAt: Date.now()
|
|
16717
17006
|
};
|
|
16718
|
-
localStorage.setItem(this.
|
|
17007
|
+
localStorage.setItem(this.getSessionStorageKey(session.keyHash), JSON.stringify(storageObject));
|
|
16719
17008
|
} catch (error) {
|
|
16720
17009
|
if (error instanceof SessionError) {
|
|
16721
17010
|
throw error;
|
|
@@ -16728,32 +17017,15 @@ var LocalStorageSessionStorage = class {
|
|
|
16728
17017
|
}
|
|
16729
17018
|
}
|
|
16730
17019
|
/**
|
|
16731
|
-
* Load
|
|
17020
|
+
* Load a session (decrypts private key)
|
|
16732
17021
|
*/
|
|
16733
|
-
async load() {
|
|
17022
|
+
async load(keyHash) {
|
|
16734
17023
|
try {
|
|
16735
|
-
const
|
|
16736
|
-
if (
|
|
16737
|
-
return null;
|
|
16738
|
-
}
|
|
16739
|
-
const stored = JSON.parse(data);
|
|
16740
|
-
if (stored.expiry <= Date.now()) {
|
|
16741
|
-
await this.clear();
|
|
17024
|
+
const records = keyHash ? (await this.getValidRecords()).filter((record) => record.keyHash === keyHash) : await this.getValidRecords();
|
|
17025
|
+
if (records.length === 0) {
|
|
16742
17026
|
return null;
|
|
16743
17027
|
}
|
|
16744
|
-
|
|
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;
|
|
17028
|
+
return this.deserializeSession(records[0]);
|
|
16757
17029
|
} catch (error) {
|
|
16758
17030
|
await this.clear();
|
|
16759
17031
|
if (error instanceof SessionError) {
|
|
@@ -16766,12 +17038,55 @@ var LocalStorageSessionStorage = class {
|
|
|
16766
17038
|
);
|
|
16767
17039
|
}
|
|
16768
17040
|
}
|
|
17041
|
+
async loadAll() {
|
|
17042
|
+
try {
|
|
17043
|
+
const records = await this.getValidRecords();
|
|
17044
|
+
return Promise.all(records.map((record) => this.deserializeSession(record)));
|
|
17045
|
+
} catch (error) {
|
|
17046
|
+
await this.clear();
|
|
17047
|
+
if (error instanceof SessionError) {
|
|
17048
|
+
throw error;
|
|
17049
|
+
}
|
|
17050
|
+
throw new SessionError(
|
|
17051
|
+
"Failed to load sessions",
|
|
17052
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
17053
|
+
error
|
|
17054
|
+
);
|
|
17055
|
+
}
|
|
17056
|
+
}
|
|
17057
|
+
async remove(keyHash) {
|
|
17058
|
+
try {
|
|
17059
|
+
localStorage.removeItem(this.getSessionStorageKey(keyHash));
|
|
17060
|
+
const legacyValue = localStorage.getItem(this.legacyStorageKey);
|
|
17061
|
+
if (legacyValue) {
|
|
17062
|
+
const legacyRecord = JSON.parse(legacyValue);
|
|
17063
|
+
if (legacyRecord.keyHash === keyHash) {
|
|
17064
|
+
localStorage.removeItem(this.legacyStorageKey);
|
|
17065
|
+
}
|
|
17066
|
+
}
|
|
17067
|
+
} catch (error) {
|
|
17068
|
+
throw new SessionError(
|
|
17069
|
+
"Failed to remove session",
|
|
17070
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
17071
|
+
error
|
|
17072
|
+
);
|
|
17073
|
+
}
|
|
17074
|
+
}
|
|
16769
17075
|
/**
|
|
16770
17076
|
* Clear all sessions
|
|
16771
17077
|
*/
|
|
16772
17078
|
async clear() {
|
|
16773
17079
|
try {
|
|
16774
|
-
|
|
17080
|
+
const keysToRemove = [];
|
|
17081
|
+
const prefix = this.getSessionStoragePrefix();
|
|
17082
|
+
for (let index = 0; index < localStorage.length; index++) {
|
|
17083
|
+
const key = localStorage.key(index);
|
|
17084
|
+
if (key && key.startsWith(prefix)) {
|
|
17085
|
+
keysToRemove.push(key);
|
|
17086
|
+
}
|
|
17087
|
+
}
|
|
17088
|
+
keysToRemove.forEach((key) => localStorage.removeItem(key));
|
|
17089
|
+
localStorage.removeItem(this.legacyStorageKey);
|
|
16775
17090
|
} catch (error) {
|
|
16776
17091
|
throw new SessionError(
|
|
16777
17092
|
"Failed to clear sessions",
|
|
@@ -16783,9 +17098,9 @@ var LocalStorageSessionStorage = class {
|
|
|
16783
17098
|
/**
|
|
16784
17099
|
* Check if any session exists
|
|
16785
17100
|
*/
|
|
16786
|
-
async exists() {
|
|
17101
|
+
async exists(keyHash) {
|
|
16787
17102
|
try {
|
|
16788
|
-
return
|
|
17103
|
+
return await this.load(keyHash) !== null;
|
|
16789
17104
|
} catch {
|
|
16790
17105
|
return false;
|
|
16791
17106
|
}
|
|
@@ -16835,7 +17150,8 @@ var SessionManager = class {
|
|
|
16835
17150
|
maxValue: config.maxValue ?? 0n,
|
|
16836
17151
|
autoRefresh: config.autoRefresh ?? true,
|
|
16837
17152
|
refreshBuffer: config.refreshBuffer ?? DEFAULT_REFRESH_BUFFER,
|
|
16838
|
-
chainScopes: config.chainScopes ?? []
|
|
17153
|
+
chainScopes: config.chainScopes ?? [],
|
|
17154
|
+
allowUnboundedMaxValue: config.allowUnboundedMaxValue ?? false
|
|
16839
17155
|
};
|
|
16840
17156
|
validateSessionConfig(this.config);
|
|
16841
17157
|
this.debug = managerConfig?.debug ?? false;
|
|
@@ -16850,6 +17166,14 @@ var SessionManager = class {
|
|
|
16850
17166
|
refreshTimer = null;
|
|
16851
17167
|
eventCallbacks = [];
|
|
16852
17168
|
debug;
|
|
17169
|
+
resolveConfig(configOverride) {
|
|
17170
|
+
const resolvedConfig = {
|
|
17171
|
+
...this.config,
|
|
17172
|
+
...configOverride
|
|
17173
|
+
};
|
|
17174
|
+
validateSessionConfig(resolvedConfig);
|
|
17175
|
+
return resolvedConfig;
|
|
17176
|
+
}
|
|
16853
17177
|
// ========================================================================
|
|
16854
17178
|
// Session Lifecycle
|
|
16855
17179
|
// ========================================================================
|
|
@@ -16866,15 +17190,16 @@ var SessionManager = class {
|
|
|
16866
17190
|
* @returns Created session key
|
|
16867
17191
|
* @throws SessionError if registration fails
|
|
16868
17192
|
*/
|
|
16869
|
-
async createSession() {
|
|
17193
|
+
async createSession(configOverride) {
|
|
16870
17194
|
try {
|
|
16871
17195
|
this.log("Creating new session...");
|
|
17196
|
+
const sessionConfig = this.resolveConfig(configOverride);
|
|
16872
17197
|
const keyPair = generateSecp256k1KeyPair();
|
|
16873
17198
|
const keyHash = computeSessionKeyHash(keyPair.publicKey);
|
|
16874
17199
|
this.log("Generated session key:", keyHash);
|
|
16875
17200
|
const challenge = import_ethers21.ethers.solidityPacked(
|
|
16876
17201
|
["string", "bytes32", "uint256", "uint256"],
|
|
16877
|
-
["registerSession", keyHash,
|
|
17202
|
+
["registerSession", keyHash, sessionConfig.duration, sessionConfig.maxValue]
|
|
16878
17203
|
);
|
|
16879
17204
|
this.log("Challenge prepared, requesting Passkey signature...");
|
|
16880
17205
|
const signature = await this.passkeySign(import_ethers21.ethers.getBytes(challenge));
|
|
@@ -16884,20 +17209,20 @@ var SessionManager = class {
|
|
|
16884
17209
|
publicKeyX: this.credential.publicKeyX,
|
|
16885
17210
|
publicKeyY: this.credential.publicKeyY,
|
|
16886
17211
|
sessionKeyHash: keyHash,
|
|
16887
|
-
duration:
|
|
16888
|
-
maxValue:
|
|
17212
|
+
duration: sessionConfig.duration,
|
|
17213
|
+
maxValue: sessionConfig.maxValue,
|
|
16889
17214
|
requireUV: true
|
|
16890
17215
|
};
|
|
16891
17216
|
await this.hubClient.registerSession(registerParams);
|
|
16892
17217
|
this.log("Session registered on Hub");
|
|
16893
|
-
const expiry = Date.now() +
|
|
17218
|
+
const expiry = Date.now() + sessionConfig.duration * 1e3;
|
|
16894
17219
|
this.currentSession = {
|
|
16895
17220
|
publicKey: keyPair.publicKey,
|
|
16896
17221
|
privateKey: keyPair.privateKey,
|
|
16897
17222
|
keyHash,
|
|
16898
17223
|
expiry,
|
|
16899
|
-
maxValue:
|
|
16900
|
-
chainScopes:
|
|
17224
|
+
maxValue: sessionConfig.maxValue,
|
|
17225
|
+
chainScopes: sessionConfig.chainScopes,
|
|
16901
17226
|
userKeyHash: this.credential.keyHash
|
|
16902
17227
|
};
|
|
16903
17228
|
await this.storage.save(this.currentSession);
|
|
@@ -16922,12 +17247,15 @@ var SessionManager = class {
|
|
|
16922
17247
|
*
|
|
16923
17248
|
* @returns Loaded session or null if no valid session exists
|
|
16924
17249
|
*/
|
|
16925
|
-
async loadSession() {
|
|
17250
|
+
async loadSession(keyHash) {
|
|
16926
17251
|
try {
|
|
16927
|
-
this.log("Loading session from storage...");
|
|
16928
|
-
const session = await this.storage.load();
|
|
17252
|
+
this.log("Loading session from storage...", keyHash ?? "latest");
|
|
17253
|
+
const session = await this.storage.load(keyHash);
|
|
16929
17254
|
if (!session) {
|
|
16930
17255
|
this.log("No session found in storage");
|
|
17256
|
+
if (!keyHash) {
|
|
17257
|
+
this.currentSession = null;
|
|
17258
|
+
}
|
|
16931
17259
|
return null;
|
|
16932
17260
|
}
|
|
16933
17261
|
if (session.expiry <= Date.now()) {
|
|
@@ -16944,27 +17272,43 @@ var SessionManager = class {
|
|
|
16944
17272
|
return session;
|
|
16945
17273
|
} catch (error) {
|
|
16946
17274
|
this.log("Failed to load session:", error);
|
|
16947
|
-
|
|
17275
|
+
if (!keyHash) {
|
|
17276
|
+
await this.storage.clear();
|
|
17277
|
+
}
|
|
16948
17278
|
return null;
|
|
16949
17279
|
}
|
|
16950
17280
|
}
|
|
17281
|
+
async listSessions() {
|
|
17282
|
+
return this.storage.loadAll();
|
|
17283
|
+
}
|
|
17284
|
+
async selectSession(keyHash) {
|
|
17285
|
+
const session = await this.loadSession(keyHash);
|
|
17286
|
+
if (!session) {
|
|
17287
|
+
throw new SessionError(
|
|
17288
|
+
`Session ${keyHash} not found`,
|
|
17289
|
+
"SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */
|
|
17290
|
+
);
|
|
17291
|
+
}
|
|
17292
|
+
return session;
|
|
17293
|
+
}
|
|
16951
17294
|
/**
|
|
16952
17295
|
* Revoke the current session (requires biometric authentication)
|
|
16953
17296
|
*
|
|
16954
17297
|
* @throws SessionError if no active session or revocation fails
|
|
16955
17298
|
*/
|
|
16956
|
-
async revokeSession() {
|
|
16957
|
-
|
|
17299
|
+
async revokeSession(keyHash) {
|
|
17300
|
+
const targetSession = keyHash ? await this.storage.load(keyHash) : this.currentSession;
|
|
17301
|
+
if (!targetSession) {
|
|
16958
17302
|
throw new SessionError(
|
|
16959
|
-
"No active session to revoke",
|
|
16960
|
-
"NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
|
|
17303
|
+
keyHash ? `Session ${keyHash} not found` : "No active session to revoke",
|
|
17304
|
+
keyHash ? "SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */ : "NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
|
|
16961
17305
|
);
|
|
16962
17306
|
}
|
|
16963
17307
|
try {
|
|
16964
|
-
this.log("Revoking session:",
|
|
17308
|
+
this.log("Revoking session:", targetSession.keyHash);
|
|
16965
17309
|
const challenge = import_ethers21.ethers.solidityPacked(
|
|
16966
17310
|
["string", "bytes32"],
|
|
16967
|
-
["revokeSession",
|
|
17311
|
+
["revokeSession", targetSession.keyHash]
|
|
16968
17312
|
);
|
|
16969
17313
|
const signature = await this.passkeySign(import_ethers21.ethers.getBytes(challenge));
|
|
16970
17314
|
this.log("Passkey signature obtained, revoking on Hub...");
|
|
@@ -16972,18 +17316,24 @@ var SessionManager = class {
|
|
|
16972
17316
|
signature,
|
|
16973
17317
|
publicKeyX: this.credential.publicKeyX,
|
|
16974
17318
|
publicKeyY: this.credential.publicKeyY,
|
|
16975
|
-
sessionKeyHash:
|
|
17319
|
+
sessionKeyHash: targetSession.keyHash,
|
|
16976
17320
|
requireUV: true
|
|
16977
17321
|
};
|
|
16978
17322
|
await this.hubClient.revokeSession(revokeParams);
|
|
16979
17323
|
this.log("Session revoked on Hub");
|
|
16980
|
-
await this.storage.
|
|
16981
|
-
|
|
16982
|
-
|
|
16983
|
-
|
|
17324
|
+
await this.storage.remove(targetSession.keyHash);
|
|
17325
|
+
const revokedKeyHash = targetSession.keyHash;
|
|
17326
|
+
const revokedCurrentSession = this.currentSession?.keyHash === revokedKeyHash;
|
|
17327
|
+
if (revokedCurrentSession) {
|
|
17328
|
+
if (this.refreshTimer) {
|
|
17329
|
+
clearTimeout(this.refreshTimer);
|
|
17330
|
+
this.refreshTimer = null;
|
|
17331
|
+
}
|
|
17332
|
+
this.currentSession = await this.storage.load();
|
|
17333
|
+
if (this.currentSession && this.config.autoRefresh) {
|
|
17334
|
+
this.scheduleRefresh();
|
|
17335
|
+
}
|
|
16984
17336
|
}
|
|
16985
|
-
const revokedKeyHash = this.currentSession.keyHash;
|
|
16986
|
-
this.currentSession = null;
|
|
16987
17337
|
this.emit({ type: "session-revoked", keyHash: revokedKeyHash });
|
|
16988
17338
|
this.log("Session revoked successfully");
|
|
16989
17339
|
} catch (error) {
|
|
@@ -17061,45 +17411,46 @@ var SessionManager = class {
|
|
|
17061
17411
|
* @returns Session signature
|
|
17062
17412
|
* @throws SessionError if no active session, expired, or value exceeds limit
|
|
17063
17413
|
*/
|
|
17064
|
-
async signWithSession(action) {
|
|
17065
|
-
|
|
17414
|
+
async signWithSession(action, keyHash) {
|
|
17415
|
+
const session = keyHash ? await this.storage.load(keyHash) : this.currentSession;
|
|
17416
|
+
if (!session) {
|
|
17066
17417
|
throw new SessionError(
|
|
17067
|
-
"No active session available",
|
|
17068
|
-
"NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
|
|
17418
|
+
keyHash ? `Session ${keyHash} not found` : "No active session available",
|
|
17419
|
+
keyHash ? "SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */ : "NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
|
|
17069
17420
|
);
|
|
17070
17421
|
}
|
|
17071
17422
|
const now = Date.now();
|
|
17072
|
-
if (now >=
|
|
17073
|
-
this.emit({ type: "session-expired", keyHash:
|
|
17423
|
+
if (now >= session.expiry) {
|
|
17424
|
+
this.emit({ type: "session-expired", keyHash: session.keyHash });
|
|
17074
17425
|
throw new SessionError(
|
|
17075
17426
|
"Session has expired",
|
|
17076
17427
|
"SESSION_EXPIRED" /* SESSION_EXPIRED */
|
|
17077
17428
|
);
|
|
17078
17429
|
}
|
|
17079
|
-
if (
|
|
17430
|
+
if (session.maxValue > 0n && action.value > session.maxValue) {
|
|
17080
17431
|
throw new SessionError(
|
|
17081
|
-
`Transaction value (${action.value}) exceeds session limit (${
|
|
17432
|
+
`Transaction value (${action.value}) exceeds session limit (${session.maxValue})`,
|
|
17082
17433
|
"VALUE_EXCEEDS_LIMIT" /* VALUE_EXCEEDS_LIMIT */,
|
|
17083
|
-
{ value: action.value, limit:
|
|
17434
|
+
{ value: action.value, limit: session.maxValue }
|
|
17084
17435
|
);
|
|
17085
17436
|
}
|
|
17086
|
-
if (
|
|
17437
|
+
if (session.chainScopes.length > 0 && !session.chainScopes.includes(action.targetChain)) {
|
|
17087
17438
|
throw new SessionError(
|
|
17088
17439
|
`Chain ${action.targetChain} not in session scope`,
|
|
17089
17440
|
"CHAIN_NOT_ALLOWED" /* CHAIN_NOT_ALLOWED */,
|
|
17090
|
-
{ chain: action.targetChain, allowedChains:
|
|
17441
|
+
{ chain: action.targetChain, allowedChains: session.chainScopes }
|
|
17091
17442
|
);
|
|
17092
17443
|
}
|
|
17093
17444
|
this.log("Signing action with session key...");
|
|
17094
17445
|
const messageHash = hashAction(action);
|
|
17095
17446
|
const { signature } = signWithSessionKey(
|
|
17096
|
-
|
|
17447
|
+
session.privateKey,
|
|
17097
17448
|
messageHash
|
|
17098
17449
|
);
|
|
17099
17450
|
const sessionSignature = {
|
|
17100
17451
|
signature,
|
|
17101
|
-
sessionKeyHash:
|
|
17102
|
-
userKeyHash:
|
|
17452
|
+
sessionKeyHash: session.keyHash,
|
|
17453
|
+
userKeyHash: session.userKeyHash,
|
|
17103
17454
|
timestamp: now,
|
|
17104
17455
|
nonce: action.nonce
|
|
17105
17456
|
};
|
|
@@ -17112,8 +17463,8 @@ var SessionManager = class {
|
|
|
17112
17463
|
* @param action Action parameters
|
|
17113
17464
|
* @returns Session-signed action ready for submission
|
|
17114
17465
|
*/
|
|
17115
|
-
async signAction(action) {
|
|
17116
|
-
const signature = await this.signWithSession(action);
|
|
17466
|
+
async signAction(action, keyHash) {
|
|
17467
|
+
const signature = await this.signWithSession(action, keyHash);
|
|
17117
17468
|
return {
|
|
17118
17469
|
action,
|
|
17119
17470
|
signature,
|
|
@@ -18097,6 +18448,7 @@ var VALIDATION_REGISTRY_ABI = [
|
|
|
18097
18448
|
calculatePercentage,
|
|
18098
18449
|
computeKeyHash,
|
|
18099
18450
|
computeSessionKeyHash,
|
|
18451
|
+
configureDefaultRpcUrls,
|
|
18100
18452
|
createAuditEntry,
|
|
18101
18453
|
createChainClient,
|
|
18102
18454
|
createChainDetector,
|
|
@@ -18166,6 +18518,7 @@ var VALIDATION_REGISTRY_ABI = [
|
|
|
18166
18518
|
getExplorerUrl,
|
|
18167
18519
|
getFeatureFlags,
|
|
18168
18520
|
getHubChains,
|
|
18521
|
+
getRpcUrlOverride,
|
|
18169
18522
|
getSequenceFromTxReceipt,
|
|
18170
18523
|
getStacksContractPrincipal,
|
|
18171
18524
|
getStacksExplorerAddressUrl,
|