@veridex/sdk 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.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 +1 -1
- package/dist/chains/starknet/index.js.map +1 -1
- package/dist/chains/starknet/index.mjs +3 -3
- 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-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-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-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 +41 -13
- package/dist/index.js +445 -147
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +327 -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-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-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-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,
|
|
@@ -7182,7 +7190,8 @@ var CrossOriginAuth = class {
|
|
|
7182
7190
|
return bytes;
|
|
7183
7191
|
}
|
|
7184
7192
|
async requestServerSessionChallenge(options) {
|
|
7185
|
-
const
|
|
7193
|
+
const challengeUrl = buildRelayerApiUrl(this.config.relayerUrl, "/session/challenge");
|
|
7194
|
+
const response = await fetch(challengeUrl, {
|
|
7186
7195
|
method: "POST",
|
|
7187
7196
|
headers: { "Content-Type": "application/json" },
|
|
7188
7197
|
body: JSON.stringify({
|
|
@@ -7228,7 +7237,7 @@ var CrossOriginAuth = class {
|
|
|
7228
7237
|
if (!session.serverChallengeId) {
|
|
7229
7238
|
throw new Error("Session must include a relayer-issued serverChallengeId");
|
|
7230
7239
|
}
|
|
7231
|
-
const response = await fetch(
|
|
7240
|
+
const response = await fetch(buildRelayerApiUrl(this.config.relayerUrl, "/session/create"), {
|
|
7232
7241
|
method: "POST",
|
|
7233
7242
|
headers: { "Content-Type": "application/json" },
|
|
7234
7243
|
body: JSON.stringify({
|
|
@@ -7251,7 +7260,9 @@ var CrossOriginAuth = class {
|
|
|
7251
7260
|
* Returns the session details if valid, null if expired/revoked.
|
|
7252
7261
|
*/
|
|
7253
7262
|
async validateServerSession(sessionId) {
|
|
7254
|
-
const response = await fetch(
|
|
7263
|
+
const response = await fetch(
|
|
7264
|
+
buildRelayerApiUrl(this.config.relayerUrl, `/session/${encodeURIComponent(sessionId)}`)
|
|
7265
|
+
);
|
|
7255
7266
|
if (!response.ok) {
|
|
7256
7267
|
return null;
|
|
7257
7268
|
}
|
|
@@ -7265,9 +7276,12 @@ var CrossOriginAuth = class {
|
|
|
7265
7276
|
* Revoke a server session token.
|
|
7266
7277
|
*/
|
|
7267
7278
|
async revokeServerSession(sessionId) {
|
|
7268
|
-
const response = await fetch(
|
|
7269
|
-
|
|
7270
|
-
|
|
7279
|
+
const response = await fetch(
|
|
7280
|
+
buildRelayerApiUrl(this.config.relayerUrl, `/session/${encodeURIComponent(sessionId)}`),
|
|
7281
|
+
{
|
|
7282
|
+
method: "DELETE"
|
|
7283
|
+
}
|
|
7284
|
+
);
|
|
7271
7285
|
return response.ok;
|
|
7272
7286
|
}
|
|
7273
7287
|
/**
|
|
@@ -7824,39 +7838,44 @@ var IndexedDBSessionStorage = class {
|
|
|
7824
7838
|
);
|
|
7825
7839
|
}
|
|
7826
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
|
+
}
|
|
7827
7864
|
/**
|
|
7828
|
-
* Load
|
|
7865
|
+
* Load a session (decrypts private key)
|
|
7829
7866
|
*/
|
|
7830
|
-
async load() {
|
|
7867
|
+
async load(keyHash) {
|
|
7831
7868
|
try {
|
|
7832
7869
|
await this.initialize();
|
|
7833
7870
|
if (!this.db) {
|
|
7834
7871
|
throw new Error("Database not initialized");
|
|
7835
7872
|
}
|
|
7836
|
-
const
|
|
7837
|
-
|
|
7838
|
-
return null;
|
|
7839
|
-
}
|
|
7840
|
-
const now = Date.now();
|
|
7841
|
-
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);
|
|
7842
7875
|
if (validSessions.length === 0) {
|
|
7843
|
-
await this.clear();
|
|
7844
7876
|
return null;
|
|
7845
7877
|
}
|
|
7846
|
-
|
|
7847
|
-
const key = await this.getEncryptionKey();
|
|
7848
|
-
const encryptedPrivateKey = new Uint8Array(stored.encryptedPrivateKey);
|
|
7849
|
-
const privateKey = await decrypt(encryptedPrivateKey, key);
|
|
7850
|
-
const session = {
|
|
7851
|
-
keyHash: stored.keyHash,
|
|
7852
|
-
publicKey: new Uint8Array(stored.publicKey),
|
|
7853
|
-
privateKey,
|
|
7854
|
-
expiry: stored.expiry,
|
|
7855
|
-
maxValue: BigInt(stored.maxValue),
|
|
7856
|
-
chainScopes: stored.chainScopes,
|
|
7857
|
-
userKeyHash: stored.userKeyHash
|
|
7858
|
-
};
|
|
7859
|
-
return session;
|
|
7878
|
+
return this.decryptSession(validSessions[0]);
|
|
7860
7879
|
} catch (error) {
|
|
7861
7880
|
if (error instanceof SessionError) {
|
|
7862
7881
|
throw error;
|
|
@@ -7889,6 +7908,75 @@ var IndexedDBSessionStorage = class {
|
|
|
7889
7908
|
};
|
|
7890
7909
|
});
|
|
7891
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
|
+
}
|
|
7892
7980
|
/**
|
|
7893
7981
|
* Clear all sessions
|
|
7894
7982
|
*/
|
|
@@ -7925,14 +8013,9 @@ var IndexedDBSessionStorage = class {
|
|
|
7925
8013
|
/**
|
|
7926
8014
|
* Check if any session exists
|
|
7927
8015
|
*/
|
|
7928
|
-
async exists() {
|
|
8016
|
+
async exists(keyHash) {
|
|
7929
8017
|
try {
|
|
7930
|
-
await this.
|
|
7931
|
-
if (!this.db) {
|
|
7932
|
-
return false;
|
|
7933
|
-
}
|
|
7934
|
-
const sessions = await this.getAllSessions();
|
|
7935
|
-
return sessions.length > 0;
|
|
8018
|
+
return await this.load(keyHash) !== null;
|
|
7936
8019
|
} catch {
|
|
7937
8020
|
return false;
|
|
7938
8021
|
}
|
|
@@ -7951,7 +8034,8 @@ var STORAGE_KEY_PREFIX = "veridex-session-";
|
|
|
7951
8034
|
var LocalStorageSessionStorage = class {
|
|
7952
8035
|
encryptionKey = null;
|
|
7953
8036
|
credentialId;
|
|
7954
|
-
|
|
8037
|
+
credentialHash;
|
|
8038
|
+
legacyStorageKey;
|
|
7955
8039
|
/**
|
|
7956
8040
|
* @param credentialId User's Passkey credential ID (for key derivation)
|
|
7957
8041
|
*/
|
|
@@ -7963,7 +8047,60 @@ var LocalStorageSessionStorage = class {
|
|
|
7963
8047
|
);
|
|
7964
8048
|
}
|
|
7965
8049
|
this.credentialId = credentialId;
|
|
7966
|
-
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);
|
|
7967
8104
|
}
|
|
7968
8105
|
/**
|
|
7969
8106
|
* Get or derive encryption key
|
|
@@ -7992,7 +8129,7 @@ var LocalStorageSessionStorage = class {
|
|
|
7992
8129
|
userKeyHash: session.userKeyHash,
|
|
7993
8130
|
savedAt: Date.now()
|
|
7994
8131
|
};
|
|
7995
|
-
localStorage.setItem(this.
|
|
8132
|
+
localStorage.setItem(this.getSessionStorageKey(session.keyHash), JSON.stringify(storageObject));
|
|
7996
8133
|
} catch (error) {
|
|
7997
8134
|
if (error instanceof SessionError) {
|
|
7998
8135
|
throw error;
|
|
@@ -8005,32 +8142,15 @@ var LocalStorageSessionStorage = class {
|
|
|
8005
8142
|
}
|
|
8006
8143
|
}
|
|
8007
8144
|
/**
|
|
8008
|
-
* Load
|
|
8145
|
+
* Load a session (decrypts private key)
|
|
8009
8146
|
*/
|
|
8010
|
-
async load() {
|
|
8147
|
+
async load(keyHash) {
|
|
8011
8148
|
try {
|
|
8012
|
-
const
|
|
8013
|
-
if (
|
|
8149
|
+
const records = keyHash ? (await this.getValidRecords()).filter((record) => record.keyHash === keyHash) : await this.getValidRecords();
|
|
8150
|
+
if (records.length === 0) {
|
|
8014
8151
|
return null;
|
|
8015
8152
|
}
|
|
8016
|
-
|
|
8017
|
-
if (stored.expiry <= Date.now()) {
|
|
8018
|
-
await this.clear();
|
|
8019
|
-
return null;
|
|
8020
|
-
}
|
|
8021
|
-
const key = await this.getEncryptionKey();
|
|
8022
|
-
const encryptedPrivateKey = ethers10.getBytes(stored.encryptedPrivateKey);
|
|
8023
|
-
const privateKey = await decrypt(encryptedPrivateKey, key);
|
|
8024
|
-
const session = {
|
|
8025
|
-
keyHash: stored.keyHash,
|
|
8026
|
-
publicKey: ethers10.getBytes(stored.publicKey),
|
|
8027
|
-
privateKey,
|
|
8028
|
-
expiry: stored.expiry,
|
|
8029
|
-
maxValue: BigInt(stored.maxValue),
|
|
8030
|
-
chainScopes: stored.chainScopes,
|
|
8031
|
-
userKeyHash: stored.userKeyHash
|
|
8032
|
-
};
|
|
8033
|
-
return session;
|
|
8153
|
+
return this.deserializeSession(records[0]);
|
|
8034
8154
|
} catch (error) {
|
|
8035
8155
|
await this.clear();
|
|
8036
8156
|
if (error instanceof SessionError) {
|
|
@@ -8043,12 +8163,55 @@ var LocalStorageSessionStorage = class {
|
|
|
8043
8163
|
);
|
|
8044
8164
|
}
|
|
8045
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
|
+
}
|
|
8046
8200
|
/**
|
|
8047
8201
|
* Clear all sessions
|
|
8048
8202
|
*/
|
|
8049
8203
|
async clear() {
|
|
8050
8204
|
try {
|
|
8051
|
-
|
|
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);
|
|
8052
8215
|
} catch (error) {
|
|
8053
8216
|
throw new SessionError(
|
|
8054
8217
|
"Failed to clear sessions",
|
|
@@ -8060,9 +8223,9 @@ var LocalStorageSessionStorage = class {
|
|
|
8060
8223
|
/**
|
|
8061
8224
|
* Check if any session exists
|
|
8062
8225
|
*/
|
|
8063
|
-
async exists() {
|
|
8226
|
+
async exists(keyHash) {
|
|
8064
8227
|
try {
|
|
8065
|
-
return
|
|
8228
|
+
return await this.load(keyHash) !== null;
|
|
8066
8229
|
} catch {
|
|
8067
8230
|
return false;
|
|
8068
8231
|
}
|
|
@@ -8127,6 +8290,14 @@ var SessionManager = class {
|
|
|
8127
8290
|
refreshTimer = null;
|
|
8128
8291
|
eventCallbacks = [];
|
|
8129
8292
|
debug;
|
|
8293
|
+
resolveConfig(configOverride) {
|
|
8294
|
+
const resolvedConfig = {
|
|
8295
|
+
...this.config,
|
|
8296
|
+
...configOverride
|
|
8297
|
+
};
|
|
8298
|
+
validateSessionConfig(resolvedConfig);
|
|
8299
|
+
return resolvedConfig;
|
|
8300
|
+
}
|
|
8130
8301
|
// ========================================================================
|
|
8131
8302
|
// Session Lifecycle
|
|
8132
8303
|
// ========================================================================
|
|
@@ -8143,15 +8314,16 @@ var SessionManager = class {
|
|
|
8143
8314
|
* @returns Created session key
|
|
8144
8315
|
* @throws SessionError if registration fails
|
|
8145
8316
|
*/
|
|
8146
|
-
async createSession() {
|
|
8317
|
+
async createSession(configOverride) {
|
|
8147
8318
|
try {
|
|
8148
8319
|
this.log("Creating new session...");
|
|
8320
|
+
const sessionConfig = this.resolveConfig(configOverride);
|
|
8149
8321
|
const keyPair = generateSecp256k1KeyPair();
|
|
8150
8322
|
const keyHash = computeSessionKeyHash(keyPair.publicKey);
|
|
8151
8323
|
this.log("Generated session key:", keyHash);
|
|
8152
8324
|
const challenge = ethers11.solidityPacked(
|
|
8153
8325
|
["string", "bytes32", "uint256", "uint256"],
|
|
8154
|
-
["registerSession", keyHash,
|
|
8326
|
+
["registerSession", keyHash, sessionConfig.duration, sessionConfig.maxValue]
|
|
8155
8327
|
);
|
|
8156
8328
|
this.log("Challenge prepared, requesting Passkey signature...");
|
|
8157
8329
|
const signature = await this.passkeySign(ethers11.getBytes(challenge));
|
|
@@ -8161,20 +8333,20 @@ var SessionManager = class {
|
|
|
8161
8333
|
publicKeyX: this.credential.publicKeyX,
|
|
8162
8334
|
publicKeyY: this.credential.publicKeyY,
|
|
8163
8335
|
sessionKeyHash: keyHash,
|
|
8164
|
-
duration:
|
|
8165
|
-
maxValue:
|
|
8336
|
+
duration: sessionConfig.duration,
|
|
8337
|
+
maxValue: sessionConfig.maxValue,
|
|
8166
8338
|
requireUV: true
|
|
8167
8339
|
};
|
|
8168
8340
|
await this.hubClient.registerSession(registerParams);
|
|
8169
8341
|
this.log("Session registered on Hub");
|
|
8170
|
-
const expiry = Date.now() +
|
|
8342
|
+
const expiry = Date.now() + sessionConfig.duration * 1e3;
|
|
8171
8343
|
this.currentSession = {
|
|
8172
8344
|
publicKey: keyPair.publicKey,
|
|
8173
8345
|
privateKey: keyPair.privateKey,
|
|
8174
8346
|
keyHash,
|
|
8175
8347
|
expiry,
|
|
8176
|
-
maxValue:
|
|
8177
|
-
chainScopes:
|
|
8348
|
+
maxValue: sessionConfig.maxValue,
|
|
8349
|
+
chainScopes: sessionConfig.chainScopes,
|
|
8178
8350
|
userKeyHash: this.credential.keyHash
|
|
8179
8351
|
};
|
|
8180
8352
|
await this.storage.save(this.currentSession);
|
|
@@ -8199,12 +8371,15 @@ var SessionManager = class {
|
|
|
8199
8371
|
*
|
|
8200
8372
|
* @returns Loaded session or null if no valid session exists
|
|
8201
8373
|
*/
|
|
8202
|
-
async loadSession() {
|
|
8374
|
+
async loadSession(keyHash) {
|
|
8203
8375
|
try {
|
|
8204
|
-
this.log("Loading session from storage...");
|
|
8205
|
-
const session = await this.storage.load();
|
|
8376
|
+
this.log("Loading session from storage...", keyHash ?? "latest");
|
|
8377
|
+
const session = await this.storage.load(keyHash);
|
|
8206
8378
|
if (!session) {
|
|
8207
8379
|
this.log("No session found in storage");
|
|
8380
|
+
if (!keyHash) {
|
|
8381
|
+
this.currentSession = null;
|
|
8382
|
+
}
|
|
8208
8383
|
return null;
|
|
8209
8384
|
}
|
|
8210
8385
|
if (session.expiry <= Date.now()) {
|
|
@@ -8221,27 +8396,43 @@ var SessionManager = class {
|
|
|
8221
8396
|
return session;
|
|
8222
8397
|
} catch (error) {
|
|
8223
8398
|
this.log("Failed to load session:", error);
|
|
8224
|
-
|
|
8399
|
+
if (!keyHash) {
|
|
8400
|
+
await this.storage.clear();
|
|
8401
|
+
}
|
|
8225
8402
|
return null;
|
|
8226
8403
|
}
|
|
8227
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
|
+
}
|
|
8228
8418
|
/**
|
|
8229
8419
|
* Revoke the current session (requires biometric authentication)
|
|
8230
8420
|
*
|
|
8231
8421
|
* @throws SessionError if no active session or revocation fails
|
|
8232
8422
|
*/
|
|
8233
|
-
async revokeSession() {
|
|
8234
|
-
|
|
8423
|
+
async revokeSession(keyHash) {
|
|
8424
|
+
const targetSession = keyHash ? await this.storage.load(keyHash) : this.currentSession;
|
|
8425
|
+
if (!targetSession) {
|
|
8235
8426
|
throw new SessionError(
|
|
8236
|
-
"No active session to revoke",
|
|
8237
|
-
"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 */
|
|
8238
8429
|
);
|
|
8239
8430
|
}
|
|
8240
8431
|
try {
|
|
8241
|
-
this.log("Revoking session:",
|
|
8432
|
+
this.log("Revoking session:", targetSession.keyHash);
|
|
8242
8433
|
const challenge = ethers11.solidityPacked(
|
|
8243
8434
|
["string", "bytes32"],
|
|
8244
|
-
["revokeSession",
|
|
8435
|
+
["revokeSession", targetSession.keyHash]
|
|
8245
8436
|
);
|
|
8246
8437
|
const signature = await this.passkeySign(ethers11.getBytes(challenge));
|
|
8247
8438
|
this.log("Passkey signature obtained, revoking on Hub...");
|
|
@@ -8249,18 +8440,24 @@ var SessionManager = class {
|
|
|
8249
8440
|
signature,
|
|
8250
8441
|
publicKeyX: this.credential.publicKeyX,
|
|
8251
8442
|
publicKeyY: this.credential.publicKeyY,
|
|
8252
|
-
sessionKeyHash:
|
|
8443
|
+
sessionKeyHash: targetSession.keyHash,
|
|
8253
8444
|
requireUV: true
|
|
8254
8445
|
};
|
|
8255
8446
|
await this.hubClient.revokeSession(revokeParams);
|
|
8256
8447
|
this.log("Session revoked on Hub");
|
|
8257
|
-
await this.storage.
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
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
|
+
}
|
|
8261
8460
|
}
|
|
8262
|
-
const revokedKeyHash = this.currentSession.keyHash;
|
|
8263
|
-
this.currentSession = null;
|
|
8264
8461
|
this.emit({ type: "session-revoked", keyHash: revokedKeyHash });
|
|
8265
8462
|
this.log("Session revoked successfully");
|
|
8266
8463
|
} catch (error) {
|
|
@@ -8338,45 +8535,46 @@ var SessionManager = class {
|
|
|
8338
8535
|
* @returns Session signature
|
|
8339
8536
|
* @throws SessionError if no active session, expired, or value exceeds limit
|
|
8340
8537
|
*/
|
|
8341
|
-
async signWithSession(action) {
|
|
8342
|
-
|
|
8538
|
+
async signWithSession(action, keyHash) {
|
|
8539
|
+
const session = keyHash ? await this.storage.load(keyHash) : this.currentSession;
|
|
8540
|
+
if (!session) {
|
|
8343
8541
|
throw new SessionError(
|
|
8344
|
-
"No active session available",
|
|
8345
|
-
"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 */
|
|
8346
8544
|
);
|
|
8347
8545
|
}
|
|
8348
8546
|
const now = Date.now();
|
|
8349
|
-
if (now >=
|
|
8350
|
-
this.emit({ type: "session-expired", keyHash:
|
|
8547
|
+
if (now >= session.expiry) {
|
|
8548
|
+
this.emit({ type: "session-expired", keyHash: session.keyHash });
|
|
8351
8549
|
throw new SessionError(
|
|
8352
8550
|
"Session has expired",
|
|
8353
8551
|
"SESSION_EXPIRED" /* SESSION_EXPIRED */
|
|
8354
8552
|
);
|
|
8355
8553
|
}
|
|
8356
|
-
if (
|
|
8554
|
+
if (session.maxValue > 0n && action.value > session.maxValue) {
|
|
8357
8555
|
throw new SessionError(
|
|
8358
|
-
`Transaction value (${action.value}) exceeds session limit (${
|
|
8556
|
+
`Transaction value (${action.value}) exceeds session limit (${session.maxValue})`,
|
|
8359
8557
|
"VALUE_EXCEEDS_LIMIT" /* VALUE_EXCEEDS_LIMIT */,
|
|
8360
|
-
{ value: action.value, limit:
|
|
8558
|
+
{ value: action.value, limit: session.maxValue }
|
|
8361
8559
|
);
|
|
8362
8560
|
}
|
|
8363
|
-
if (
|
|
8561
|
+
if (session.chainScopes.length > 0 && !session.chainScopes.includes(action.targetChain)) {
|
|
8364
8562
|
throw new SessionError(
|
|
8365
8563
|
`Chain ${action.targetChain} not in session scope`,
|
|
8366
8564
|
"CHAIN_NOT_ALLOWED" /* CHAIN_NOT_ALLOWED */,
|
|
8367
|
-
{ chain: action.targetChain, allowedChains:
|
|
8565
|
+
{ chain: action.targetChain, allowedChains: session.chainScopes }
|
|
8368
8566
|
);
|
|
8369
8567
|
}
|
|
8370
8568
|
this.log("Signing action with session key...");
|
|
8371
8569
|
const messageHash = hashAction(action);
|
|
8372
8570
|
const { signature } = signWithSessionKey(
|
|
8373
|
-
|
|
8571
|
+
session.privateKey,
|
|
8374
8572
|
messageHash
|
|
8375
8573
|
);
|
|
8376
8574
|
const sessionSignature = {
|
|
8377
8575
|
signature,
|
|
8378
|
-
sessionKeyHash:
|
|
8379
|
-
userKeyHash:
|
|
8576
|
+
sessionKeyHash: session.keyHash,
|
|
8577
|
+
userKeyHash: session.userKeyHash,
|
|
8380
8578
|
timestamp: now,
|
|
8381
8579
|
nonce: action.nonce
|
|
8382
8580
|
};
|
|
@@ -8389,8 +8587,8 @@ var SessionManager = class {
|
|
|
8389
8587
|
* @param action Action parameters
|
|
8390
8588
|
* @returns Session-signed action ready for submission
|
|
8391
8589
|
*/
|
|
8392
|
-
async signAction(action) {
|
|
8393
|
-
const signature = await this.signWithSession(action);
|
|
8590
|
+
async signAction(action, keyHash) {
|
|
8591
|
+
const signature = await this.signWithSession(action, keyHash);
|
|
8394
8592
|
return {
|
|
8395
8593
|
action,
|
|
8396
8594
|
signature,
|
|
@@ -9253,6 +9451,7 @@ export {
|
|
|
9253
9451
|
calculatePercentage,
|
|
9254
9452
|
computeKeyHash,
|
|
9255
9453
|
computeSessionKeyHash,
|
|
9454
|
+
configureDefaultRpcUrls,
|
|
9256
9455
|
createAuditEntry,
|
|
9257
9456
|
createChainClient,
|
|
9258
9457
|
createChainDetector,
|
|
@@ -9323,6 +9522,7 @@ export {
|
|
|
9323
9522
|
getExplorerUrl,
|
|
9324
9523
|
getFeatureFlags,
|
|
9325
9524
|
getHubChains,
|
|
9525
|
+
getRpcUrlOverride,
|
|
9326
9526
|
getSequenceFromTxReceipt,
|
|
9327
9527
|
getContractPrincipal as getStacksContractPrincipal,
|
|
9328
9528
|
getStacksExplorerAddressUrl,
|