@veridex/sdk 1.0.1 → 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.
- package/dist/auth/prepareAuth.js +107 -32
- package/dist/auth/prepareAuth.js.map +1 -1
- package/dist/auth/prepareAuth.mjs +6 -6
- package/dist/auth/prepareAuth.mjs.map +1 -1
- package/dist/chains/aptos/index.js.map +1 -1
- package/dist/chains/aptos/index.mjs +3 -3
- package/dist/chains/avalanche/index.js.map +1 -1
- package/dist/chains/avalanche/index.mjs +4 -4
- package/dist/chains/evm/index.d.mts +2 -2
- 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 +2 -3
- package/dist/chains/starknet/index.js +1 -13
- package/dist/chains/starknet/index.js.map +1 -1
- package/dist/chains/starknet/index.mjs +3 -3
- package/dist/chains/sui/index.d.mts +3 -3
- package/dist/chains/sui/index.js +2 -2
- 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-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-PRHNGA4G.mjs → chunk-E3SU36C2.mjs} +4 -4
- package/dist/{chunk-PRHNGA4G.mjs.map → chunk-E3SU36C2.mjs.map} +1 -1
- package/dist/{chunk-NUWSMJFJ.mjs → chunk-EFIXFA6V.mjs} +2 -2
- package/dist/{chunk-EFIURACP.mjs → chunk-GM5DKEHD.mjs} +3 -15
- package/dist/chunk-GM5DKEHD.mjs.map +1 -0
- 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-N4A2RMUN.mjs → chunk-PEGOXMBU.mjs} +2 -2
- 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-USDA5JTN.mjs → chunk-YBN2VC6E.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-CySMITQ9.d.mts} +9 -6
- package/dist/index.d.mts +44 -13
- package/dist/index.js +466 -162
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +345 -127
- 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-DWx-5jmz.d.mts} +12 -3
- 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 +1 -1
- package/dist/chunk-EFIURACP.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-5T6KPH7A.mjs.map → chunk-CSU4IV2F.mjs.map} +0 -0
- /package/dist/{chunk-NUWSMJFJ.mjs.map → chunk-EFIXFA6V.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-N4A2RMUN.mjs.map → chunk-PEGOXMBU.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-USDA5JTN.mjs.map → chunk-YBN2VC6E.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.mjs
CHANGED
|
@@ -1,34 +1,36 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CHAIN_NAMES,
|
|
3
3
|
CHAIN_PRESETS,
|
|
4
|
+
configureDefaultRpcUrls,
|
|
4
5
|
getChainConfig,
|
|
5
6
|
getChainPreset,
|
|
6
7
|
getDefaultHub,
|
|
7
8
|
getEffectivePrimaryHub,
|
|
8
9
|
getFeatureFlags,
|
|
9
10
|
getHubChains,
|
|
11
|
+
getRpcUrlOverride,
|
|
10
12
|
getSupportedChains,
|
|
11
13
|
isChainSupported,
|
|
12
14
|
isHubChain,
|
|
13
15
|
isMultiHubEnabled,
|
|
14
16
|
resetFeatureFlags,
|
|
15
17
|
setFeatureFlags
|
|
16
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-M3GUNREX.mjs";
|
|
17
19
|
import {
|
|
18
20
|
EVMHubClientAdapter
|
|
19
21
|
} from "./chunk-V636MIV3.mjs";
|
|
20
22
|
import {
|
|
21
23
|
SolanaClient
|
|
22
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-2TS375ET.mjs";
|
|
23
25
|
import {
|
|
24
26
|
AptosClient
|
|
25
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-5FDOTI5G.mjs";
|
|
26
28
|
import {
|
|
27
29
|
SuiClient
|
|
28
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-E3SU36C2.mjs";
|
|
29
31
|
import {
|
|
30
32
|
StarknetClient
|
|
31
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-GM5DKEHD.mjs";
|
|
32
34
|
import {
|
|
33
35
|
STACKS_ACTION_TYPES,
|
|
34
36
|
StacksClient,
|
|
@@ -56,13 +58,13 @@ import {
|
|
|
56
58
|
parseContractPrincipal,
|
|
57
59
|
rsToCompactSignature,
|
|
58
60
|
validatePostConditions
|
|
59
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-CSU4IV2F.mjs";
|
|
60
62
|
import {
|
|
61
63
|
AvalancheClient
|
|
62
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-PEGOXMBU.mjs";
|
|
63
65
|
import {
|
|
64
66
|
EVMClient
|
|
65
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-YBN2VC6E.mjs";
|
|
66
68
|
import {
|
|
67
69
|
CONSISTENCY_LEVELS,
|
|
68
70
|
GUARDIAN_CONFIG,
|
|
@@ -85,7 +87,7 @@ import {
|
|
|
85
87
|
supportsRelayer,
|
|
86
88
|
validateEmitter,
|
|
87
89
|
waitForGuardianSignatures
|
|
88
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-UPO55SBK.mjs";
|
|
89
91
|
import {
|
|
90
92
|
buildChallenge,
|
|
91
93
|
buildGaslessChallenge,
|
|
@@ -109,7 +111,7 @@ import {
|
|
|
109
111
|
parseAmount,
|
|
110
112
|
solanaAddressToBytes32,
|
|
111
113
|
trimTo20Bytes
|
|
112
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-TPEP6XUA.mjs";
|
|
113
115
|
import {
|
|
114
116
|
ARBITRUM_SEPOLIA_TOKENS,
|
|
115
117
|
BASE_SEPOLIA_TOKENS,
|
|
@@ -127,13 +129,15 @@ import {
|
|
|
127
129
|
getTokenBySymbol,
|
|
128
130
|
getTokenList,
|
|
129
131
|
isNativeToken
|
|
130
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-YYT3V7CI.mjs";
|
|
131
133
|
import {
|
|
132
134
|
PasskeyManager,
|
|
133
135
|
VERIDEX_RP_ID,
|
|
136
|
+
buildRelayerApiUrl,
|
|
134
137
|
detectRpId,
|
|
138
|
+
normalizeRelayerOrigin,
|
|
135
139
|
supportsRelatedOrigins
|
|
136
|
-
} from "./chunk-
|
|
140
|
+
} from "./chunk-CTYDGO6E.mjs";
|
|
137
141
|
import {
|
|
138
142
|
base64URLDecode,
|
|
139
143
|
base64URLEncode,
|
|
@@ -149,7 +153,7 @@ import {
|
|
|
149
153
|
isValidWormholeChainId,
|
|
150
154
|
parseDERSignature,
|
|
151
155
|
retryWithBackoff
|
|
152
|
-
} from "./chunk-
|
|
156
|
+
} from "./chunk-EFIXFA6V.mjs";
|
|
153
157
|
import {
|
|
154
158
|
ACTION_BRIDGE,
|
|
155
159
|
ACTION_CONFIG,
|
|
@@ -165,7 +169,7 @@ import {
|
|
|
165
169
|
WORMHOLE_API,
|
|
166
170
|
WORMHOLE_CHAIN_IDS,
|
|
167
171
|
WORMHOLE_CHAIN_IDS_FLAT
|
|
168
|
-
} from "./chunk-
|
|
172
|
+
} from "./chunk-RD6ZYUVG.mjs";
|
|
169
173
|
|
|
170
174
|
// src/core/BalanceManager.ts
|
|
171
175
|
import { ethers } from "ethers";
|
|
@@ -1014,7 +1018,7 @@ var RelayerClient = class _RelayerClient {
|
|
|
1014
1018
|
baseUrl;
|
|
1015
1019
|
config;
|
|
1016
1020
|
constructor(config) {
|
|
1017
|
-
this.baseUrl = config.baseUrl
|
|
1021
|
+
this.baseUrl = normalizeRelayerOrigin(config.baseUrl);
|
|
1018
1022
|
this.config = { ...DEFAULT_CONFIG2, ...config };
|
|
1019
1023
|
}
|
|
1020
1024
|
// ========================================================================
|
|
@@ -1281,6 +1285,7 @@ var RelayerClient = class _RelayerClient {
|
|
|
1281
1285
|
* Make an HTTP request to the relayer
|
|
1282
1286
|
*/
|
|
1283
1287
|
async fetch(path, options = {}) {
|
|
1288
|
+
const resolvedUrl = path.startsWith("/api/v1/") ? buildRelayerApiUrl(this.baseUrl, path.replace(/^\/api\/v1/, "")) : `${this.baseUrl}${path}`;
|
|
1284
1289
|
const headers = {
|
|
1285
1290
|
"Content-Type": "application/json",
|
|
1286
1291
|
"User-Agent": `@veridex/sdk/${_RelayerClient.SDK_VERSION}`,
|
|
@@ -1294,7 +1299,7 @@ var RelayerClient = class _RelayerClient {
|
|
|
1294
1299
|
let lastError = null;
|
|
1295
1300
|
for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
|
|
1296
1301
|
try {
|
|
1297
|
-
const response = await fetch(
|
|
1302
|
+
const response = await fetch(resolvedUrl, {
|
|
1298
1303
|
...options,
|
|
1299
1304
|
headers,
|
|
1300
1305
|
signal: controller.signal
|
|
@@ -5300,7 +5305,7 @@ var VeridexSDK = class {
|
|
|
5300
5305
|
const wormholeChainId = chainConfig.wormholeChainId;
|
|
5301
5306
|
const tokenList = getAllTokens(wormholeChainId);
|
|
5302
5307
|
const erc20Tokens = tokenList.filter((t) => !isNativeToken(t.address)).map((t) => t.address);
|
|
5303
|
-
const { queryPortfolio } = await import("./portfolio-
|
|
5308
|
+
const { queryPortfolio } = await import("./portfolio-JA4OTF7Y.mjs");
|
|
5304
5309
|
const result = await queryPortfolio(credential.keyHash, this.queryApiKey, {
|
|
5305
5310
|
network: this.testnet ? "testnet" : "mainnet",
|
|
5306
5311
|
vaultAddresses: { [wormholeChainId]: vaultAddress },
|
|
@@ -5663,7 +5668,7 @@ var VeridexSDK = class {
|
|
|
5663
5668
|
const tokenList = getAllTokens(wormholeChainId);
|
|
5664
5669
|
const erc20Tokens = tokenList.filter((t) => !isNativeToken(t.address)).map((t) => t.address);
|
|
5665
5670
|
const rpcUrl = this.chainRpcUrls?.[wormholeChainId] ?? chainConfig.rpcUrl;
|
|
5666
|
-
const { queryPortfolio } = await import("./portfolio-
|
|
5671
|
+
const { queryPortfolio } = await import("./portfolio-JA4OTF7Y.mjs");
|
|
5667
5672
|
const result = await queryPortfolio(credential.keyHash, this.queryApiKey, {
|
|
5668
5673
|
network: this.testnet ? "testnet" : "mainnet",
|
|
5669
5674
|
vaultAddresses: { [wormholeChainId]: vaultAddress },
|
|
@@ -6657,7 +6662,7 @@ var CredentialManager = class {
|
|
|
6657
6662
|
constructor(config = {}) {
|
|
6658
6663
|
this.config = {
|
|
6659
6664
|
storageKey: config.storageKey ?? DEFAULT_STORAGE_KEY,
|
|
6660
|
-
relayerUrl: config.relayerUrl ?? ""
|
|
6665
|
+
relayerUrl: normalizeRelayerOrigin(config.relayerUrl ?? "")
|
|
6661
6666
|
};
|
|
6662
6667
|
}
|
|
6663
6668
|
// ========================================================================
|
|
@@ -6805,7 +6810,7 @@ var CredentialManager = class {
|
|
|
6805
6810
|
const managed = this.getCredential(credentialId);
|
|
6806
6811
|
if (!managed) return false;
|
|
6807
6812
|
try {
|
|
6808
|
-
const response = await fetch(
|
|
6813
|
+
const response = await fetch(buildRelayerApiUrl(this.config.relayerUrl, "/credential/metadata"), {
|
|
6809
6814
|
method: "PUT",
|
|
6810
6815
|
headers: { "Content-Type": "application/json" },
|
|
6811
6816
|
body: JSON.stringify({
|
|
@@ -6831,7 +6836,10 @@ var CredentialManager = class {
|
|
|
6831
6836
|
if (!this.config.relayerUrl) return null;
|
|
6832
6837
|
try {
|
|
6833
6838
|
const response = await fetch(
|
|
6834
|
-
|
|
6839
|
+
buildRelayerApiUrl(
|
|
6840
|
+
this.config.relayerUrl,
|
|
6841
|
+
`/credential/metadata?keyHash=${encodeURIComponent(keyHash)}`
|
|
6842
|
+
)
|
|
6835
6843
|
);
|
|
6836
6844
|
if (!response.ok) return null;
|
|
6837
6845
|
const data = await response.json();
|
|
@@ -6953,7 +6961,7 @@ var CredentialManager = class {
|
|
|
6953
6961
|
|
|
6954
6962
|
// src/core/CrossOriginAuth.ts
|
|
6955
6963
|
var DEFAULT_AUTH_PORTAL_URL = "https://auth.veridex.network";
|
|
6956
|
-
var DEFAULT_RELAYER_URL = "https://
|
|
6964
|
+
var DEFAULT_RELAYER_URL = "https://relayer.veridex.network";
|
|
6957
6965
|
var AUTH_MESSAGE_TYPES = {
|
|
6958
6966
|
AUTH_REQUEST: "VERIDEX_AUTH_REQUEST",
|
|
6959
6967
|
AUTH_RESPONSE: "VERIDEX_AUTH_RESPONSE",
|
|
@@ -6965,7 +6973,7 @@ var CrossOriginAuth = class {
|
|
|
6965
6973
|
this.config = {
|
|
6966
6974
|
rpId: config.rpId ?? VERIDEX_RP_ID,
|
|
6967
6975
|
authPortalUrl: config.authPortalUrl ?? DEFAULT_AUTH_PORTAL_URL,
|
|
6968
|
-
relayerUrl: config.relayerUrl ?? DEFAULT_RELAYER_URL,
|
|
6976
|
+
relayerUrl: normalizeRelayerOrigin(config.relayerUrl ?? DEFAULT_RELAYER_URL),
|
|
6969
6977
|
mode: config.mode ?? "popup",
|
|
6970
6978
|
popupFeatures: config.popupFeatures ?? "width=500,height=600,left=100,top=100",
|
|
6971
6979
|
timeout: config.timeout ?? 12e4,
|
|
@@ -7061,6 +7069,15 @@ var CrossOriginAuth = class {
|
|
|
7061
7069
|
if (options?.sessionChallenge) {
|
|
7062
7070
|
authUrl.searchParams.set("challenge", options.sessionChallenge);
|
|
7063
7071
|
}
|
|
7072
|
+
if (options?.register) {
|
|
7073
|
+
authUrl.searchParams.set("register", "true");
|
|
7074
|
+
}
|
|
7075
|
+
if (options?.username) {
|
|
7076
|
+
authUrl.searchParams.set("username", options.username);
|
|
7077
|
+
}
|
|
7078
|
+
if (options?.displayName) {
|
|
7079
|
+
authUrl.searchParams.set("display_name", options.displayName);
|
|
7080
|
+
}
|
|
7064
7081
|
const popup = window.open(
|
|
7065
7082
|
authUrl.toString(),
|
|
7066
7083
|
"veridex-auth",
|
|
@@ -7114,6 +7131,15 @@ var CrossOriginAuth = class {
|
|
|
7114
7131
|
if (options?.sessionChallenge) {
|
|
7115
7132
|
authUrl.searchParams.set("challenge", options.sessionChallenge);
|
|
7116
7133
|
}
|
|
7134
|
+
if (options?.register) {
|
|
7135
|
+
authUrl.searchParams.set("register", "true");
|
|
7136
|
+
}
|
|
7137
|
+
if (options?.username) {
|
|
7138
|
+
authUrl.searchParams.set("username", options.username);
|
|
7139
|
+
}
|
|
7140
|
+
if (options?.displayName) {
|
|
7141
|
+
authUrl.searchParams.set("display_name", options.displayName);
|
|
7142
|
+
}
|
|
7117
7143
|
window.location.href = authUrl.toString();
|
|
7118
7144
|
return new Promise(() => {
|
|
7119
7145
|
});
|
|
@@ -7164,7 +7190,8 @@ var CrossOriginAuth = class {
|
|
|
7164
7190
|
return bytes;
|
|
7165
7191
|
}
|
|
7166
7192
|
async requestServerSessionChallenge(options) {
|
|
7167
|
-
const
|
|
7193
|
+
const challengeUrl = buildRelayerApiUrl(this.config.relayerUrl, "/session/challenge");
|
|
7194
|
+
const response = await fetch(challengeUrl, {
|
|
7168
7195
|
method: "POST",
|
|
7169
7196
|
headers: { "Content-Type": "application/json" },
|
|
7170
7197
|
body: JSON.stringify({
|
|
@@ -7210,7 +7237,7 @@ var CrossOriginAuth = class {
|
|
|
7210
7237
|
if (!session.serverChallengeId) {
|
|
7211
7238
|
throw new Error("Session must include a relayer-issued serverChallengeId");
|
|
7212
7239
|
}
|
|
7213
|
-
const response = await fetch(
|
|
7240
|
+
const response = await fetch(buildRelayerApiUrl(this.config.relayerUrl, "/session/create"), {
|
|
7214
7241
|
method: "POST",
|
|
7215
7242
|
headers: { "Content-Type": "application/json" },
|
|
7216
7243
|
body: JSON.stringify({
|
|
@@ -7233,7 +7260,9 @@ var CrossOriginAuth = class {
|
|
|
7233
7260
|
* Returns the session details if valid, null if expired/revoked.
|
|
7234
7261
|
*/
|
|
7235
7262
|
async validateServerSession(sessionId) {
|
|
7236
|
-
const response = await fetch(
|
|
7263
|
+
const response = await fetch(
|
|
7264
|
+
buildRelayerApiUrl(this.config.relayerUrl, `/session/${encodeURIComponent(sessionId)}`)
|
|
7265
|
+
);
|
|
7237
7266
|
if (!response.ok) {
|
|
7238
7267
|
return null;
|
|
7239
7268
|
}
|
|
@@ -7247,9 +7276,12 @@ var CrossOriginAuth = class {
|
|
|
7247
7276
|
* Revoke a server session token.
|
|
7248
7277
|
*/
|
|
7249
7278
|
async revokeServerSession(sessionId) {
|
|
7250
|
-
const response = await fetch(
|
|
7251
|
-
|
|
7252
|
-
|
|
7279
|
+
const response = await fetch(
|
|
7280
|
+
buildRelayerApiUrl(this.config.relayerUrl, `/session/${encodeURIComponent(sessionId)}`),
|
|
7281
|
+
{
|
|
7282
|
+
method: "DELETE"
|
|
7283
|
+
}
|
|
7284
|
+
);
|
|
7253
7285
|
return response.ok;
|
|
7254
7286
|
}
|
|
7255
7287
|
/**
|
|
@@ -7806,39 +7838,44 @@ var IndexedDBSessionStorage = class {
|
|
|
7806
7838
|
);
|
|
7807
7839
|
}
|
|
7808
7840
|
}
|
|
7841
|
+
async decryptSession(stored) {
|
|
7842
|
+
const key = await this.getEncryptionKey();
|
|
7843
|
+
const encryptedPrivateKey = new Uint8Array(stored.encryptedPrivateKey);
|
|
7844
|
+
const privateKey = await decrypt(encryptedPrivateKey, key);
|
|
7845
|
+
return {
|
|
7846
|
+
keyHash: stored.keyHash,
|
|
7847
|
+
publicKey: new Uint8Array(stored.publicKey),
|
|
7848
|
+
privateKey,
|
|
7849
|
+
expiry: stored.expiry,
|
|
7850
|
+
maxValue: BigInt(stored.maxValue),
|
|
7851
|
+
chainScopes: stored.chainScopes ?? [],
|
|
7852
|
+
userKeyHash: stored.userKeyHash
|
|
7853
|
+
};
|
|
7854
|
+
}
|
|
7855
|
+
async pruneExpiredSessions(records) {
|
|
7856
|
+
const now = Date.now();
|
|
7857
|
+
const validRecords = records.filter((record) => record.expiry > now);
|
|
7858
|
+
const expiredRecords = records.filter((record) => record.expiry <= now);
|
|
7859
|
+
if (expiredRecords.length > 0) {
|
|
7860
|
+
await Promise.all(expiredRecords.map((record) => this.remove(record.keyHash)));
|
|
7861
|
+
}
|
|
7862
|
+
return validRecords.sort((left, right) => right.savedAt - left.savedAt);
|
|
7863
|
+
}
|
|
7809
7864
|
/**
|
|
7810
|
-
* Load
|
|
7865
|
+
* Load a session (decrypts private key)
|
|
7811
7866
|
*/
|
|
7812
|
-
async load() {
|
|
7867
|
+
async load(keyHash) {
|
|
7813
7868
|
try {
|
|
7814
7869
|
await this.initialize();
|
|
7815
7870
|
if (!this.db) {
|
|
7816
7871
|
throw new Error("Database not initialized");
|
|
7817
7872
|
}
|
|
7818
|
-
const
|
|
7819
|
-
|
|
7820
|
-
return null;
|
|
7821
|
-
}
|
|
7822
|
-
const now = Date.now();
|
|
7823
|
-
const validSessions = allSessions.filter((s) => s.expiry > now).sort((a, b) => b.savedAt - a.savedAt);
|
|
7873
|
+
const sessions = keyHash ? await this.getSessionByKeyHash(keyHash) : await this.getAllSessions();
|
|
7874
|
+
const validSessions = await this.pruneExpiredSessions(sessions);
|
|
7824
7875
|
if (validSessions.length === 0) {
|
|
7825
|
-
await this.clear();
|
|
7826
7876
|
return null;
|
|
7827
7877
|
}
|
|
7828
|
-
|
|
7829
|
-
const key = await this.getEncryptionKey();
|
|
7830
|
-
const encryptedPrivateKey = new Uint8Array(stored.encryptedPrivateKey);
|
|
7831
|
-
const privateKey = await decrypt(encryptedPrivateKey, key);
|
|
7832
|
-
const session = {
|
|
7833
|
-
keyHash: stored.keyHash,
|
|
7834
|
-
publicKey: new Uint8Array(stored.publicKey),
|
|
7835
|
-
privateKey,
|
|
7836
|
-
expiry: stored.expiry,
|
|
7837
|
-
maxValue: BigInt(stored.maxValue),
|
|
7838
|
-
chainScopes: stored.chainScopes,
|
|
7839
|
-
userKeyHash: stored.userKeyHash
|
|
7840
|
-
};
|
|
7841
|
-
return session;
|
|
7878
|
+
return this.decryptSession(validSessions[0]);
|
|
7842
7879
|
} catch (error) {
|
|
7843
7880
|
if (error instanceof SessionError) {
|
|
7844
7881
|
throw error;
|
|
@@ -7871,6 +7908,75 @@ var IndexedDBSessionStorage = class {
|
|
|
7871
7908
|
};
|
|
7872
7909
|
});
|
|
7873
7910
|
}
|
|
7911
|
+
async getSessionByKeyHash(keyHash) {
|
|
7912
|
+
if (!this.db) {
|
|
7913
|
+
return [];
|
|
7914
|
+
}
|
|
7915
|
+
return new Promise((resolve, reject) => {
|
|
7916
|
+
const transaction = this.db.transaction([STORE_NAME], "readonly");
|
|
7917
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
7918
|
+
const request = store.get(keyHash);
|
|
7919
|
+
request.onsuccess = () => {
|
|
7920
|
+
resolve(request.result ? [request.result] : []);
|
|
7921
|
+
};
|
|
7922
|
+
request.onerror = () => {
|
|
7923
|
+
reject(new SessionError(
|
|
7924
|
+
"Failed to get session",
|
|
7925
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
7926
|
+
request.error
|
|
7927
|
+
));
|
|
7928
|
+
};
|
|
7929
|
+
});
|
|
7930
|
+
}
|
|
7931
|
+
async loadAll() {
|
|
7932
|
+
try {
|
|
7933
|
+
await this.initialize();
|
|
7934
|
+
if (!this.db) {
|
|
7935
|
+
return [];
|
|
7936
|
+
}
|
|
7937
|
+
const records = await this.pruneExpiredSessions(await this.getAllSessions());
|
|
7938
|
+
return Promise.all(records.map((record) => this.decryptSession(record)));
|
|
7939
|
+
} catch (error) {
|
|
7940
|
+
if (error instanceof SessionError) {
|
|
7941
|
+
throw error;
|
|
7942
|
+
}
|
|
7943
|
+
throw new SessionError(
|
|
7944
|
+
"Failed to load sessions",
|
|
7945
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
7946
|
+
error
|
|
7947
|
+
);
|
|
7948
|
+
}
|
|
7949
|
+
}
|
|
7950
|
+
async remove(keyHash) {
|
|
7951
|
+
try {
|
|
7952
|
+
await this.initialize();
|
|
7953
|
+
if (!this.db) {
|
|
7954
|
+
return;
|
|
7955
|
+
}
|
|
7956
|
+
return new Promise((resolve, reject) => {
|
|
7957
|
+
const transaction = this.db.transaction([STORE_NAME], "readwrite");
|
|
7958
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
7959
|
+
const request = store.delete(keyHash);
|
|
7960
|
+
request.onsuccess = () => resolve();
|
|
7961
|
+
request.onerror = () => {
|
|
7962
|
+
reject(new SessionError(
|
|
7963
|
+
"Failed to remove session",
|
|
7964
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
7965
|
+
request.error
|
|
7966
|
+
));
|
|
7967
|
+
};
|
|
7968
|
+
});
|
|
7969
|
+
} catch (error) {
|
|
7970
|
+
if (error instanceof SessionError) {
|
|
7971
|
+
throw error;
|
|
7972
|
+
}
|
|
7973
|
+
throw new SessionError(
|
|
7974
|
+
"Failed to remove session",
|
|
7975
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
7976
|
+
error
|
|
7977
|
+
);
|
|
7978
|
+
}
|
|
7979
|
+
}
|
|
7874
7980
|
/**
|
|
7875
7981
|
* Clear all sessions
|
|
7876
7982
|
*/
|
|
@@ -7907,14 +8013,9 @@ var IndexedDBSessionStorage = class {
|
|
|
7907
8013
|
/**
|
|
7908
8014
|
* Check if any session exists
|
|
7909
8015
|
*/
|
|
7910
|
-
async exists() {
|
|
8016
|
+
async exists(keyHash) {
|
|
7911
8017
|
try {
|
|
7912
|
-
await this.
|
|
7913
|
-
if (!this.db) {
|
|
7914
|
-
return false;
|
|
7915
|
-
}
|
|
7916
|
-
const sessions = await this.getAllSessions();
|
|
7917
|
-
return sessions.length > 0;
|
|
8018
|
+
return await this.load(keyHash) !== null;
|
|
7918
8019
|
} catch {
|
|
7919
8020
|
return false;
|
|
7920
8021
|
}
|
|
@@ -7933,7 +8034,8 @@ var STORAGE_KEY_PREFIX = "veridex-session-";
|
|
|
7933
8034
|
var LocalStorageSessionStorage = class {
|
|
7934
8035
|
encryptionKey = null;
|
|
7935
8036
|
credentialId;
|
|
7936
|
-
|
|
8037
|
+
credentialHash;
|
|
8038
|
+
legacyStorageKey;
|
|
7937
8039
|
/**
|
|
7938
8040
|
* @param credentialId User's Passkey credential ID (for key derivation)
|
|
7939
8041
|
*/
|
|
@@ -7945,7 +8047,60 @@ var LocalStorageSessionStorage = class {
|
|
|
7945
8047
|
);
|
|
7946
8048
|
}
|
|
7947
8049
|
this.credentialId = credentialId;
|
|
7948
|
-
this.
|
|
8050
|
+
this.credentialHash = ethers10.keccak256(ethers10.toUtf8Bytes(credentialId));
|
|
8051
|
+
this.legacyStorageKey = STORAGE_KEY_PREFIX + this.credentialHash;
|
|
8052
|
+
}
|
|
8053
|
+
getSessionStorageKey(keyHash) {
|
|
8054
|
+
return `${STORAGE_KEY_PREFIX}${this.credentialHash}:${keyHash}`;
|
|
8055
|
+
}
|
|
8056
|
+
getSessionStoragePrefix() {
|
|
8057
|
+
return `${STORAGE_KEY_PREFIX}${this.credentialHash}:`;
|
|
8058
|
+
}
|
|
8059
|
+
async deserializeSession(stored) {
|
|
8060
|
+
const key = await this.getEncryptionKey();
|
|
8061
|
+
const encryptedPrivateKey = typeof stored.encryptedPrivateKey === "string" ? ethers10.getBytes(stored.encryptedPrivateKey) : new Uint8Array(stored.encryptedPrivateKey);
|
|
8062
|
+
const privateKey = await decrypt(encryptedPrivateKey, key);
|
|
8063
|
+
return {
|
|
8064
|
+
keyHash: stored.keyHash,
|
|
8065
|
+
publicKey: typeof stored.publicKey === "string" ? ethers10.getBytes(stored.publicKey) : new Uint8Array(stored.publicKey),
|
|
8066
|
+
privateKey,
|
|
8067
|
+
expiry: stored.expiry,
|
|
8068
|
+
maxValue: BigInt(stored.maxValue),
|
|
8069
|
+
chainScopes: stored.chainScopes ?? [],
|
|
8070
|
+
userKeyHash: stored.userKeyHash
|
|
8071
|
+
};
|
|
8072
|
+
}
|
|
8073
|
+
getRawRecords() {
|
|
8074
|
+
const records = [];
|
|
8075
|
+
const prefix = this.getSessionStoragePrefix();
|
|
8076
|
+
for (let index = 0; index < localStorage.length; index++) {
|
|
8077
|
+
const key = localStorage.key(index);
|
|
8078
|
+
if (!key || !key.startsWith(prefix)) {
|
|
8079
|
+
continue;
|
|
8080
|
+
}
|
|
8081
|
+
const value = localStorage.getItem(key);
|
|
8082
|
+
if (!value) {
|
|
8083
|
+
continue;
|
|
8084
|
+
}
|
|
8085
|
+
records.push(JSON.parse(value));
|
|
8086
|
+
}
|
|
8087
|
+
const legacyValue = localStorage.getItem(this.legacyStorageKey);
|
|
8088
|
+
if (legacyValue) {
|
|
8089
|
+
records.push(JSON.parse(legacyValue));
|
|
8090
|
+
}
|
|
8091
|
+
return records;
|
|
8092
|
+
}
|
|
8093
|
+
async getValidRecords() {
|
|
8094
|
+
const now = Date.now();
|
|
8095
|
+
const validRecords = [];
|
|
8096
|
+
for (const record of this.getRawRecords()) {
|
|
8097
|
+
if (record.expiry <= now) {
|
|
8098
|
+
await this.remove(record.keyHash);
|
|
8099
|
+
continue;
|
|
8100
|
+
}
|
|
8101
|
+
validRecords.push(record);
|
|
8102
|
+
}
|
|
8103
|
+
return validRecords.sort((left, right) => right.savedAt - left.savedAt);
|
|
7949
8104
|
}
|
|
7950
8105
|
/**
|
|
7951
8106
|
* Get or derive encryption key
|
|
@@ -7974,7 +8129,7 @@ var LocalStorageSessionStorage = class {
|
|
|
7974
8129
|
userKeyHash: session.userKeyHash,
|
|
7975
8130
|
savedAt: Date.now()
|
|
7976
8131
|
};
|
|
7977
|
-
localStorage.setItem(this.
|
|
8132
|
+
localStorage.setItem(this.getSessionStorageKey(session.keyHash), JSON.stringify(storageObject));
|
|
7978
8133
|
} catch (error) {
|
|
7979
8134
|
if (error instanceof SessionError) {
|
|
7980
8135
|
throw error;
|
|
@@ -7987,32 +8142,15 @@ var LocalStorageSessionStorage = class {
|
|
|
7987
8142
|
}
|
|
7988
8143
|
}
|
|
7989
8144
|
/**
|
|
7990
|
-
* Load
|
|
8145
|
+
* Load a session (decrypts private key)
|
|
7991
8146
|
*/
|
|
7992
|
-
async load() {
|
|
8147
|
+
async load(keyHash) {
|
|
7993
8148
|
try {
|
|
7994
|
-
const
|
|
7995
|
-
if (
|
|
7996
|
-
return null;
|
|
7997
|
-
}
|
|
7998
|
-
const stored = JSON.parse(data);
|
|
7999
|
-
if (stored.expiry <= Date.now()) {
|
|
8000
|
-
await this.clear();
|
|
8149
|
+
const records = keyHash ? (await this.getValidRecords()).filter((record) => record.keyHash === keyHash) : await this.getValidRecords();
|
|
8150
|
+
if (records.length === 0) {
|
|
8001
8151
|
return null;
|
|
8002
8152
|
}
|
|
8003
|
-
|
|
8004
|
-
const encryptedPrivateKey = ethers10.getBytes(stored.encryptedPrivateKey);
|
|
8005
|
-
const privateKey = await decrypt(encryptedPrivateKey, key);
|
|
8006
|
-
const session = {
|
|
8007
|
-
keyHash: stored.keyHash,
|
|
8008
|
-
publicKey: ethers10.getBytes(stored.publicKey),
|
|
8009
|
-
privateKey,
|
|
8010
|
-
expiry: stored.expiry,
|
|
8011
|
-
maxValue: BigInt(stored.maxValue),
|
|
8012
|
-
chainScopes: stored.chainScopes,
|
|
8013
|
-
userKeyHash: stored.userKeyHash
|
|
8014
|
-
};
|
|
8015
|
-
return session;
|
|
8153
|
+
return this.deserializeSession(records[0]);
|
|
8016
8154
|
} catch (error) {
|
|
8017
8155
|
await this.clear();
|
|
8018
8156
|
if (error instanceof SessionError) {
|
|
@@ -8025,12 +8163,55 @@ var LocalStorageSessionStorage = class {
|
|
|
8025
8163
|
);
|
|
8026
8164
|
}
|
|
8027
8165
|
}
|
|
8166
|
+
async loadAll() {
|
|
8167
|
+
try {
|
|
8168
|
+
const records = await this.getValidRecords();
|
|
8169
|
+
return Promise.all(records.map((record) => this.deserializeSession(record)));
|
|
8170
|
+
} catch (error) {
|
|
8171
|
+
await this.clear();
|
|
8172
|
+
if (error instanceof SessionError) {
|
|
8173
|
+
throw error;
|
|
8174
|
+
}
|
|
8175
|
+
throw new SessionError(
|
|
8176
|
+
"Failed to load sessions",
|
|
8177
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
8178
|
+
error
|
|
8179
|
+
);
|
|
8180
|
+
}
|
|
8181
|
+
}
|
|
8182
|
+
async remove(keyHash) {
|
|
8183
|
+
try {
|
|
8184
|
+
localStorage.removeItem(this.getSessionStorageKey(keyHash));
|
|
8185
|
+
const legacyValue = localStorage.getItem(this.legacyStorageKey);
|
|
8186
|
+
if (legacyValue) {
|
|
8187
|
+
const legacyRecord = JSON.parse(legacyValue);
|
|
8188
|
+
if (legacyRecord.keyHash === keyHash) {
|
|
8189
|
+
localStorage.removeItem(this.legacyStorageKey);
|
|
8190
|
+
}
|
|
8191
|
+
}
|
|
8192
|
+
} catch (error) {
|
|
8193
|
+
throw new SessionError(
|
|
8194
|
+
"Failed to remove session",
|
|
8195
|
+
"STORAGE_ERROR" /* STORAGE_ERROR */,
|
|
8196
|
+
error
|
|
8197
|
+
);
|
|
8198
|
+
}
|
|
8199
|
+
}
|
|
8028
8200
|
/**
|
|
8029
8201
|
* Clear all sessions
|
|
8030
8202
|
*/
|
|
8031
8203
|
async clear() {
|
|
8032
8204
|
try {
|
|
8033
|
-
|
|
8205
|
+
const keysToRemove = [];
|
|
8206
|
+
const prefix = this.getSessionStoragePrefix();
|
|
8207
|
+
for (let index = 0; index < localStorage.length; index++) {
|
|
8208
|
+
const key = localStorage.key(index);
|
|
8209
|
+
if (key && key.startsWith(prefix)) {
|
|
8210
|
+
keysToRemove.push(key);
|
|
8211
|
+
}
|
|
8212
|
+
}
|
|
8213
|
+
keysToRemove.forEach((key) => localStorage.removeItem(key));
|
|
8214
|
+
localStorage.removeItem(this.legacyStorageKey);
|
|
8034
8215
|
} catch (error) {
|
|
8035
8216
|
throw new SessionError(
|
|
8036
8217
|
"Failed to clear sessions",
|
|
@@ -8042,9 +8223,9 @@ var LocalStorageSessionStorage = class {
|
|
|
8042
8223
|
/**
|
|
8043
8224
|
* Check if any session exists
|
|
8044
8225
|
*/
|
|
8045
|
-
async exists() {
|
|
8226
|
+
async exists(keyHash) {
|
|
8046
8227
|
try {
|
|
8047
|
-
return
|
|
8228
|
+
return await this.load(keyHash) !== null;
|
|
8048
8229
|
} catch {
|
|
8049
8230
|
return false;
|
|
8050
8231
|
}
|
|
@@ -8109,6 +8290,14 @@ var SessionManager = class {
|
|
|
8109
8290
|
refreshTimer = null;
|
|
8110
8291
|
eventCallbacks = [];
|
|
8111
8292
|
debug;
|
|
8293
|
+
resolveConfig(configOverride) {
|
|
8294
|
+
const resolvedConfig = {
|
|
8295
|
+
...this.config,
|
|
8296
|
+
...configOverride
|
|
8297
|
+
};
|
|
8298
|
+
validateSessionConfig(resolvedConfig);
|
|
8299
|
+
return resolvedConfig;
|
|
8300
|
+
}
|
|
8112
8301
|
// ========================================================================
|
|
8113
8302
|
// Session Lifecycle
|
|
8114
8303
|
// ========================================================================
|
|
@@ -8125,15 +8314,16 @@ var SessionManager = class {
|
|
|
8125
8314
|
* @returns Created session key
|
|
8126
8315
|
* @throws SessionError if registration fails
|
|
8127
8316
|
*/
|
|
8128
|
-
async createSession() {
|
|
8317
|
+
async createSession(configOverride) {
|
|
8129
8318
|
try {
|
|
8130
8319
|
this.log("Creating new session...");
|
|
8320
|
+
const sessionConfig = this.resolveConfig(configOverride);
|
|
8131
8321
|
const keyPair = generateSecp256k1KeyPair();
|
|
8132
8322
|
const keyHash = computeSessionKeyHash(keyPair.publicKey);
|
|
8133
8323
|
this.log("Generated session key:", keyHash);
|
|
8134
8324
|
const challenge = ethers11.solidityPacked(
|
|
8135
8325
|
["string", "bytes32", "uint256", "uint256"],
|
|
8136
|
-
["registerSession", keyHash,
|
|
8326
|
+
["registerSession", keyHash, sessionConfig.duration, sessionConfig.maxValue]
|
|
8137
8327
|
);
|
|
8138
8328
|
this.log("Challenge prepared, requesting Passkey signature...");
|
|
8139
8329
|
const signature = await this.passkeySign(ethers11.getBytes(challenge));
|
|
@@ -8143,20 +8333,20 @@ var SessionManager = class {
|
|
|
8143
8333
|
publicKeyX: this.credential.publicKeyX,
|
|
8144
8334
|
publicKeyY: this.credential.publicKeyY,
|
|
8145
8335
|
sessionKeyHash: keyHash,
|
|
8146
|
-
duration:
|
|
8147
|
-
maxValue:
|
|
8336
|
+
duration: sessionConfig.duration,
|
|
8337
|
+
maxValue: sessionConfig.maxValue,
|
|
8148
8338
|
requireUV: true
|
|
8149
8339
|
};
|
|
8150
8340
|
await this.hubClient.registerSession(registerParams);
|
|
8151
8341
|
this.log("Session registered on Hub");
|
|
8152
|
-
const expiry = Date.now() +
|
|
8342
|
+
const expiry = Date.now() + sessionConfig.duration * 1e3;
|
|
8153
8343
|
this.currentSession = {
|
|
8154
8344
|
publicKey: keyPair.publicKey,
|
|
8155
8345
|
privateKey: keyPair.privateKey,
|
|
8156
8346
|
keyHash,
|
|
8157
8347
|
expiry,
|
|
8158
|
-
maxValue:
|
|
8159
|
-
chainScopes:
|
|
8348
|
+
maxValue: sessionConfig.maxValue,
|
|
8349
|
+
chainScopes: sessionConfig.chainScopes,
|
|
8160
8350
|
userKeyHash: this.credential.keyHash
|
|
8161
8351
|
};
|
|
8162
8352
|
await this.storage.save(this.currentSession);
|
|
@@ -8181,12 +8371,15 @@ var SessionManager = class {
|
|
|
8181
8371
|
*
|
|
8182
8372
|
* @returns Loaded session or null if no valid session exists
|
|
8183
8373
|
*/
|
|
8184
|
-
async loadSession() {
|
|
8374
|
+
async loadSession(keyHash) {
|
|
8185
8375
|
try {
|
|
8186
|
-
this.log("Loading session from storage...");
|
|
8187
|
-
const session = await this.storage.load();
|
|
8376
|
+
this.log("Loading session from storage...", keyHash ?? "latest");
|
|
8377
|
+
const session = await this.storage.load(keyHash);
|
|
8188
8378
|
if (!session) {
|
|
8189
8379
|
this.log("No session found in storage");
|
|
8380
|
+
if (!keyHash) {
|
|
8381
|
+
this.currentSession = null;
|
|
8382
|
+
}
|
|
8190
8383
|
return null;
|
|
8191
8384
|
}
|
|
8192
8385
|
if (session.expiry <= Date.now()) {
|
|
@@ -8203,27 +8396,43 @@ var SessionManager = class {
|
|
|
8203
8396
|
return session;
|
|
8204
8397
|
} catch (error) {
|
|
8205
8398
|
this.log("Failed to load session:", error);
|
|
8206
|
-
|
|
8399
|
+
if (!keyHash) {
|
|
8400
|
+
await this.storage.clear();
|
|
8401
|
+
}
|
|
8207
8402
|
return null;
|
|
8208
8403
|
}
|
|
8209
8404
|
}
|
|
8405
|
+
async listSessions() {
|
|
8406
|
+
return this.storage.loadAll();
|
|
8407
|
+
}
|
|
8408
|
+
async selectSession(keyHash) {
|
|
8409
|
+
const session = await this.loadSession(keyHash);
|
|
8410
|
+
if (!session) {
|
|
8411
|
+
throw new SessionError(
|
|
8412
|
+
`Session ${keyHash} not found`,
|
|
8413
|
+
"SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */
|
|
8414
|
+
);
|
|
8415
|
+
}
|
|
8416
|
+
return session;
|
|
8417
|
+
}
|
|
8210
8418
|
/**
|
|
8211
8419
|
* Revoke the current session (requires biometric authentication)
|
|
8212
8420
|
*
|
|
8213
8421
|
* @throws SessionError if no active session or revocation fails
|
|
8214
8422
|
*/
|
|
8215
|
-
async revokeSession() {
|
|
8216
|
-
|
|
8423
|
+
async revokeSession(keyHash) {
|
|
8424
|
+
const targetSession = keyHash ? await this.storage.load(keyHash) : this.currentSession;
|
|
8425
|
+
if (!targetSession) {
|
|
8217
8426
|
throw new SessionError(
|
|
8218
|
-
"No active session to revoke",
|
|
8219
|
-
"NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
|
|
8427
|
+
keyHash ? `Session ${keyHash} not found` : "No active session to revoke",
|
|
8428
|
+
keyHash ? "SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */ : "NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
|
|
8220
8429
|
);
|
|
8221
8430
|
}
|
|
8222
8431
|
try {
|
|
8223
|
-
this.log("Revoking session:",
|
|
8432
|
+
this.log("Revoking session:", targetSession.keyHash);
|
|
8224
8433
|
const challenge = ethers11.solidityPacked(
|
|
8225
8434
|
["string", "bytes32"],
|
|
8226
|
-
["revokeSession",
|
|
8435
|
+
["revokeSession", targetSession.keyHash]
|
|
8227
8436
|
);
|
|
8228
8437
|
const signature = await this.passkeySign(ethers11.getBytes(challenge));
|
|
8229
8438
|
this.log("Passkey signature obtained, revoking on Hub...");
|
|
@@ -8231,18 +8440,24 @@ var SessionManager = class {
|
|
|
8231
8440
|
signature,
|
|
8232
8441
|
publicKeyX: this.credential.publicKeyX,
|
|
8233
8442
|
publicKeyY: this.credential.publicKeyY,
|
|
8234
|
-
sessionKeyHash:
|
|
8443
|
+
sessionKeyHash: targetSession.keyHash,
|
|
8235
8444
|
requireUV: true
|
|
8236
8445
|
};
|
|
8237
8446
|
await this.hubClient.revokeSession(revokeParams);
|
|
8238
8447
|
this.log("Session revoked on Hub");
|
|
8239
|
-
await this.storage.
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8448
|
+
await this.storage.remove(targetSession.keyHash);
|
|
8449
|
+
const revokedKeyHash = targetSession.keyHash;
|
|
8450
|
+
const revokedCurrentSession = this.currentSession?.keyHash === revokedKeyHash;
|
|
8451
|
+
if (revokedCurrentSession) {
|
|
8452
|
+
if (this.refreshTimer) {
|
|
8453
|
+
clearTimeout(this.refreshTimer);
|
|
8454
|
+
this.refreshTimer = null;
|
|
8455
|
+
}
|
|
8456
|
+
this.currentSession = await this.storage.load();
|
|
8457
|
+
if (this.currentSession && this.config.autoRefresh) {
|
|
8458
|
+
this.scheduleRefresh();
|
|
8459
|
+
}
|
|
8243
8460
|
}
|
|
8244
|
-
const revokedKeyHash = this.currentSession.keyHash;
|
|
8245
|
-
this.currentSession = null;
|
|
8246
8461
|
this.emit({ type: "session-revoked", keyHash: revokedKeyHash });
|
|
8247
8462
|
this.log("Session revoked successfully");
|
|
8248
8463
|
} catch (error) {
|
|
@@ -8320,45 +8535,46 @@ var SessionManager = class {
|
|
|
8320
8535
|
* @returns Session signature
|
|
8321
8536
|
* @throws SessionError if no active session, expired, or value exceeds limit
|
|
8322
8537
|
*/
|
|
8323
|
-
async signWithSession(action) {
|
|
8324
|
-
|
|
8538
|
+
async signWithSession(action, keyHash) {
|
|
8539
|
+
const session = keyHash ? await this.storage.load(keyHash) : this.currentSession;
|
|
8540
|
+
if (!session) {
|
|
8325
8541
|
throw new SessionError(
|
|
8326
|
-
"No active session available",
|
|
8327
|
-
"NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
|
|
8542
|
+
keyHash ? `Session ${keyHash} not found` : "No active session available",
|
|
8543
|
+
keyHash ? "SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */ : "NO_ACTIVE_SESSION" /* NO_ACTIVE_SESSION */
|
|
8328
8544
|
);
|
|
8329
8545
|
}
|
|
8330
8546
|
const now = Date.now();
|
|
8331
|
-
if (now >=
|
|
8332
|
-
this.emit({ type: "session-expired", keyHash:
|
|
8547
|
+
if (now >= session.expiry) {
|
|
8548
|
+
this.emit({ type: "session-expired", keyHash: session.keyHash });
|
|
8333
8549
|
throw new SessionError(
|
|
8334
8550
|
"Session has expired",
|
|
8335
8551
|
"SESSION_EXPIRED" /* SESSION_EXPIRED */
|
|
8336
8552
|
);
|
|
8337
8553
|
}
|
|
8338
|
-
if (
|
|
8554
|
+
if (session.maxValue > 0n && action.value > session.maxValue) {
|
|
8339
8555
|
throw new SessionError(
|
|
8340
|
-
`Transaction value (${action.value}) exceeds session limit (${
|
|
8556
|
+
`Transaction value (${action.value}) exceeds session limit (${session.maxValue})`,
|
|
8341
8557
|
"VALUE_EXCEEDS_LIMIT" /* VALUE_EXCEEDS_LIMIT */,
|
|
8342
|
-
{ value: action.value, limit:
|
|
8558
|
+
{ value: action.value, limit: session.maxValue }
|
|
8343
8559
|
);
|
|
8344
8560
|
}
|
|
8345
|
-
if (
|
|
8561
|
+
if (session.chainScopes.length > 0 && !session.chainScopes.includes(action.targetChain)) {
|
|
8346
8562
|
throw new SessionError(
|
|
8347
8563
|
`Chain ${action.targetChain} not in session scope`,
|
|
8348
8564
|
"CHAIN_NOT_ALLOWED" /* CHAIN_NOT_ALLOWED */,
|
|
8349
|
-
{ chain: action.targetChain, allowedChains:
|
|
8565
|
+
{ chain: action.targetChain, allowedChains: session.chainScopes }
|
|
8350
8566
|
);
|
|
8351
8567
|
}
|
|
8352
8568
|
this.log("Signing action with session key...");
|
|
8353
8569
|
const messageHash = hashAction(action);
|
|
8354
8570
|
const { signature } = signWithSessionKey(
|
|
8355
|
-
|
|
8571
|
+
session.privateKey,
|
|
8356
8572
|
messageHash
|
|
8357
8573
|
);
|
|
8358
8574
|
const sessionSignature = {
|
|
8359
8575
|
signature,
|
|
8360
|
-
sessionKeyHash:
|
|
8361
|
-
userKeyHash:
|
|
8576
|
+
sessionKeyHash: session.keyHash,
|
|
8577
|
+
userKeyHash: session.userKeyHash,
|
|
8362
8578
|
timestamp: now,
|
|
8363
8579
|
nonce: action.nonce
|
|
8364
8580
|
};
|
|
@@ -8371,8 +8587,8 @@ var SessionManager = class {
|
|
|
8371
8587
|
* @param action Action parameters
|
|
8372
8588
|
* @returns Session-signed action ready for submission
|
|
8373
8589
|
*/
|
|
8374
|
-
async signAction(action) {
|
|
8375
|
-
const signature = await this.signWithSession(action);
|
|
8590
|
+
async signAction(action, keyHash) {
|
|
8591
|
+
const signature = await this.signWithSession(action, keyHash);
|
|
8376
8592
|
return {
|
|
8377
8593
|
action,
|
|
8378
8594
|
signature,
|
|
@@ -9235,6 +9451,7 @@ export {
|
|
|
9235
9451
|
calculatePercentage,
|
|
9236
9452
|
computeKeyHash,
|
|
9237
9453
|
computeSessionKeyHash,
|
|
9454
|
+
configureDefaultRpcUrls,
|
|
9238
9455
|
createAuditEntry,
|
|
9239
9456
|
createChainClient,
|
|
9240
9457
|
createChainDetector,
|
|
@@ -9305,6 +9522,7 @@ export {
|
|
|
9305
9522
|
getExplorerUrl,
|
|
9306
9523
|
getFeatureFlags,
|
|
9307
9524
|
getHubChains,
|
|
9525
|
+
getRpcUrlOverride,
|
|
9308
9526
|
getSequenceFromTxReceipt,
|
|
9309
9527
|
getContractPrincipal as getStacksContractPrincipal,
|
|
9310
9528
|
getStacksExplorerAddressUrl,
|