@vaultkeepr/smart-account 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.mts +194 -95
- package/dist/index.d.ts +194 -95
- package/dist/index.js +333 -281
- package/dist/index.mjs +325 -273
- package/package.json +12 -6
- package/src/index.ts +16 -14
package/dist/index.js
CHANGED
|
@@ -20,12 +20,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
23
|
+
KEYED_MIGRATION_ENABLED: () => KEYED_MIGRATION_ENABLED,
|
|
24
|
+
PASSAGE_ENABLED: () => PASSAGE_ENABLED,
|
|
25
|
+
canWritePointer: () => canWritePointer,
|
|
24
26
|
clearIdentity: () => clearIdentity,
|
|
25
27
|
clearSmartAccountCache: () => clearSmartAccountCache,
|
|
26
28
|
computeSmartAccountAddress: () => computeSmartAccountAddress,
|
|
29
|
+
createPassageIO: () => createPassageIO,
|
|
27
30
|
createVaultSmartAccount: () => createVaultSmartAccount,
|
|
28
|
-
|
|
31
|
+
deriveIdentity: () => deriveIdentity,
|
|
29
32
|
formatSecretKeyForDisplay: () => formatSecretKeyForDisplay,
|
|
30
33
|
generateSecretKey: () => generateSecretKey,
|
|
31
34
|
getCachedSmartAccountAddress: () => getCachedSmartAccountAddress,
|
|
@@ -35,24 +38,24 @@ __export(index_exports, {
|
|
|
35
38
|
getIdentityOwner: () => getIdentityOwner,
|
|
36
39
|
getIdentitySmartAccount: () => getIdentitySmartAccount,
|
|
37
40
|
getIdentitySnapshot: () => getIdentitySnapshot,
|
|
38
|
-
getOnChainSyncStatus: () => getOnChainSyncStatus,
|
|
39
41
|
getOwnerFromPassword: () => getOwnerFromPassword,
|
|
40
42
|
getPimlicoApiKey: () => getPimlicoApiKey,
|
|
41
43
|
getTargetChain: () => getTargetChain,
|
|
44
|
+
identityState: () => identityState,
|
|
42
45
|
initIdentityFromPassword: () => initIdentityFromPassword,
|
|
43
46
|
initIdentityFromSigner: () => initIdentityFromSigner,
|
|
44
|
-
isCidRegistryConfigured: () => isCidRegistryConfigured,
|
|
45
47
|
isIdentityConnected: () => isIdentityConnected,
|
|
46
48
|
isSmartAccountConfigured: () => isSmartAccountConfigured,
|
|
47
49
|
isValidSecretKey: () => isValidSecretKey,
|
|
50
|
+
migrateKeyedPointer: () => migrateKeyedPointer,
|
|
48
51
|
parseSecretKeyInput: () => parseSecretKeyInput,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
scheduleCidOnChainSync: () => scheduleCidOnChainSync,
|
|
52
|
+
readPassageState: () => readPassageState,
|
|
53
|
+
runPassage: () => runPassage,
|
|
54
|
+
runPassageWith: () => runPassageWith,
|
|
53
55
|
signMessageWithIdentity: () => signMessageWithIdentity,
|
|
54
56
|
subscribeIdentity: () => subscribeIdentity,
|
|
55
|
-
useIdentity: () => useIdentity
|
|
57
|
+
useIdentity: () => useIdentity,
|
|
58
|
+
verifyAAAuth: () => verifyAAAuth
|
|
56
59
|
});
|
|
57
60
|
module.exports = __toCommonJS(index_exports);
|
|
58
61
|
|
|
@@ -214,248 +217,95 @@ function clearSmartAccountCache() {
|
|
|
214
217
|
_cachedKey = null;
|
|
215
218
|
}
|
|
216
219
|
|
|
217
|
-
// src/
|
|
218
|
-
var import_core = require("@vaultkeepr/core");
|
|
219
|
-
async function getOwnerFromPassword(password, secretKey) {
|
|
220
|
-
return (0, import_core.getHiddenWalletFromPassword)(password, secretKey);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// src/cidRegistry.ts
|
|
220
|
+
// src/deriveIdentity.ts
|
|
224
221
|
var import_viem2 = require("viem");
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
{
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
outputs: []
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
name: "deleteCid",
|
|
236
|
-
type: "function",
|
|
237
|
-
stateMutability: "nonpayable",
|
|
238
|
-
inputs: [],
|
|
239
|
-
outputs: []
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
name: "getCid",
|
|
243
|
-
type: "function",
|
|
244
|
-
stateMutability: "view",
|
|
245
|
-
inputs: [{ name: "account", type: "address" }],
|
|
246
|
-
outputs: [{ name: "", type: "string" }]
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
name: "hasCid",
|
|
250
|
-
type: "function",
|
|
251
|
-
stateMutability: "view",
|
|
252
|
-
inputs: [{ name: "account", type: "address" }],
|
|
253
|
-
outputs: [{ name: "", type: "bool" }]
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
name: "getUpdatedAt",
|
|
257
|
-
type: "function",
|
|
258
|
-
stateMutability: "view",
|
|
259
|
-
inputs: [{ name: "account", type: "address" }],
|
|
260
|
-
outputs: [{ name: "", type: "uint256" }]
|
|
261
|
-
},
|
|
262
|
-
{
|
|
263
|
-
name: "nextAllowedUpdate",
|
|
264
|
-
type: "function",
|
|
265
|
-
stateMutability: "view",
|
|
266
|
-
inputs: [{ name: "account", type: "address" }],
|
|
267
|
-
outputs: [{ name: "", type: "uint256" }]
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
name: "cooldownSeconds",
|
|
271
|
-
type: "function",
|
|
272
|
-
stateMutability: "view",
|
|
273
|
-
inputs: [],
|
|
274
|
-
outputs: [{ name: "", type: "uint256" }]
|
|
275
|
-
}
|
|
276
|
-
];
|
|
277
|
-
function getCidRegistryAddress() {
|
|
278
|
-
let addr = "";
|
|
279
|
-
try {
|
|
280
|
-
addr = process.env.CID_REGISTRY_ADDRESS || "";
|
|
281
|
-
} catch {
|
|
282
|
-
}
|
|
283
|
-
if (addr) return addr;
|
|
284
|
-
try {
|
|
285
|
-
addr = process.env.NEXT_PUBLIC_CID_REGISTRY_ADDRESS || "";
|
|
286
|
-
} catch {
|
|
287
|
-
}
|
|
288
|
-
if (addr) return addr;
|
|
289
|
-
try {
|
|
290
|
-
addr = process.env.EXPO_PUBLIC_CID_REGISTRY_ADDRESS || "";
|
|
291
|
-
} catch {
|
|
292
|
-
}
|
|
293
|
-
if (addr) return addr;
|
|
294
|
-
return "0x0000000000000000000000000000000000000000";
|
|
222
|
+
async function deriveIdentity(ownerAccount, mode) {
|
|
223
|
+
const aaAddress = await computeSmartAccountAddress(ownerAccount);
|
|
224
|
+
return {
|
|
225
|
+
ownerAddress: ownerAccount.address,
|
|
226
|
+
aaAddress,
|
|
227
|
+
mode
|
|
228
|
+
};
|
|
295
229
|
}
|
|
296
|
-
|
|
297
|
-
|
|
230
|
+
var MAX_SKEW_MS = 5 * 6e4;
|
|
231
|
+
var UNSIGNABLE_OWNER = "verifyAAAuth: owner stub cannot sign";
|
|
232
|
+
function addressOnlyAccount(address) {
|
|
233
|
+
return {
|
|
234
|
+
address,
|
|
235
|
+
type: "local",
|
|
236
|
+
publicKey: "0x",
|
|
237
|
+
source: "custom",
|
|
238
|
+
signMessage: async () => {
|
|
239
|
+
throw new Error(UNSIGNABLE_OWNER);
|
|
240
|
+
},
|
|
241
|
+
signTypedData: async () => {
|
|
242
|
+
throw new Error(UNSIGNABLE_OWNER);
|
|
243
|
+
},
|
|
244
|
+
signTransaction: async () => {
|
|
245
|
+
throw new Error(UNSIGNABLE_OWNER);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
298
248
|
}
|
|
299
|
-
async function
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
249
|
+
async function verifyAAAuth(params) {
|
|
250
|
+
const rejected = {
|
|
251
|
+
ok: false,
|
|
252
|
+
ownerAddress: import_viem2.zeroAddress,
|
|
253
|
+
aaAddress: import_viem2.zeroAddress
|
|
254
|
+
};
|
|
306
255
|
try {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
256
|
+
if (!Number.isFinite(params.timestamp) || Math.abs(Date.now() - params.timestamp) > MAX_SKEW_MS) {
|
|
257
|
+
return rejected;
|
|
258
|
+
}
|
|
259
|
+
const signature = params.signature;
|
|
260
|
+
let ownerAddress;
|
|
261
|
+
if (params.claimedOwner) {
|
|
262
|
+
ownerAddress = (0, import_viem2.getAddress)(params.claimedOwner);
|
|
263
|
+
const publicClient = (0, import_viem2.createPublicClient)({
|
|
264
|
+
chain: TARGET_CHAIN,
|
|
265
|
+
transport: (0, import_viem2.http)()
|
|
266
|
+
});
|
|
267
|
+
const valid = await publicClient.verifyMessage({
|
|
268
|
+
address: ownerAddress,
|
|
269
|
+
message: params.message,
|
|
270
|
+
signature
|
|
271
|
+
});
|
|
272
|
+
if (!valid) {
|
|
273
|
+
return {
|
|
274
|
+
ok: false,
|
|
275
|
+
ownerAddress,
|
|
276
|
+
aaAddress: params.claimedAA ? (0, import_viem2.getAddress)(params.claimedAA) : import_viem2.zeroAddress
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
ownerAddress = await (0, import_viem2.recoverMessageAddress)({
|
|
281
|
+
message: params.message,
|
|
282
|
+
signature
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
const claimedAA = params.claimedAA ? (0, import_viem2.getAddress)(params.claimedAA) : null;
|
|
286
|
+
const aaAddress = await computeSmartAccountAddress(
|
|
287
|
+
addressOnlyAccount(ownerAddress)
|
|
329
288
|
);
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
return
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
async function readCidOnChain(smartAccountAddress) {
|
|
337
|
-
if (!isCidRegistryConfigured()) return null;
|
|
338
|
-
try {
|
|
339
|
-
const publicClient = (0, import_viem2.createPublicClient)({
|
|
340
|
-
chain: TARGET_CHAIN,
|
|
341
|
-
transport: (0, import_viem2.http)()
|
|
342
|
-
});
|
|
343
|
-
const cid = await publicClient.readContract({
|
|
344
|
-
address: getCidRegistryAddress(),
|
|
345
|
-
abi: CID_REGISTRY_ABI,
|
|
346
|
-
functionName: "getCid",
|
|
347
|
-
args: [smartAccountAddress]
|
|
348
|
-
});
|
|
349
|
-
return cid && cid.length > 0 ? cid : null;
|
|
350
|
-
} catch (error) {
|
|
351
|
-
import_logger2.logger.error("[CidRegistry] Erreur lecture:", error instanceof Error ? error.message : error);
|
|
352
|
-
return null;
|
|
289
|
+
if (claimedAA && !(0, import_viem2.isAddressEqual)(claimedAA, aaAddress)) {
|
|
290
|
+
return { ok: false, ownerAddress, aaAddress };
|
|
291
|
+
}
|
|
292
|
+
return { ok: true, ownerAddress, aaAddress };
|
|
293
|
+
} catch {
|
|
294
|
+
return rejected;
|
|
353
295
|
}
|
|
354
296
|
}
|
|
355
297
|
|
|
356
|
-
// src/
|
|
357
|
-
var
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
var _debounceTimer = null;
|
|
362
|
-
var _lastPublishedCid = null;
|
|
363
|
-
var _lastPublishTime = 0;
|
|
364
|
-
var _isPublishing = false;
|
|
365
|
-
function scheduleCidOnChainSync(smartAccount, cid, debounceMs = DEFAULT_DEBOUNCE_MS) {
|
|
366
|
-
if (!isCidRegistryConfigured()) return;
|
|
367
|
-
if (cid === _lastPublishedCid) {
|
|
368
|
-
import_logger3.logger.debug("[OnChainSync] CID identique, skip");
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
const sa = smartAccount ?? _pendingSmartAccount;
|
|
372
|
-
if (!sa) {
|
|
373
|
-
import_logger3.logger.warn("[OnChainSync] Pas de Smart Account disponible, skip");
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
_pendingCid = cid;
|
|
377
|
-
_pendingSmartAccount = sa;
|
|
378
|
-
if (_debounceTimer) {
|
|
379
|
-
clearTimeout(_debounceTimer);
|
|
380
|
-
}
|
|
381
|
-
_debounceTimer = setTimeout(() => {
|
|
382
|
-
_executeSync();
|
|
383
|
-
}, debounceMs);
|
|
384
|
-
import_logger3.logger.debug(
|
|
385
|
-
`[OnChainSync] CID planifi\xE9 dans ${(debounceMs / 1e3).toFixed(0)}s : ${cid.slice(0, 20)}...`
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
async function flushCidOnChainSync() {
|
|
389
|
-
import_logger3.logger.debug(
|
|
390
|
-
"[OnChainSync] flush demand\xE9 \u2014 pending:",
|
|
391
|
-
_pendingCid?.slice(0, 20),
|
|
392
|
-
"SA:",
|
|
393
|
-
!!_pendingSmartAccount
|
|
394
|
-
);
|
|
395
|
-
if (!_pendingCid || !_pendingSmartAccount) {
|
|
396
|
-
import_logger3.logger.debug("[OnChainSync] Rien \xE0 flush");
|
|
397
|
-
return true;
|
|
398
|
-
}
|
|
399
|
-
if (_debounceTimer) {
|
|
400
|
-
clearTimeout(_debounceTimer);
|
|
401
|
-
_debounceTimer = null;
|
|
402
|
-
}
|
|
403
|
-
import_logger3.logger.debug("[OnChainSync] Flush imm\xE9diat...");
|
|
404
|
-
return _executeSync();
|
|
405
|
-
}
|
|
406
|
-
function getOnChainSyncStatus() {
|
|
407
|
-
return {
|
|
408
|
-
hasPending: _pendingCid !== null && _pendingCid !== _lastPublishedCid,
|
|
409
|
-
pendingCid: _pendingCid,
|
|
410
|
-
lastPublishedCid: _lastPublishedCid,
|
|
411
|
-
lastPublishTime: _lastPublishTime,
|
|
412
|
-
isPublishing: _isPublishing
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
function resetOnChainSync() {
|
|
416
|
-
if (_debounceTimer) {
|
|
417
|
-
clearTimeout(_debounceTimer);
|
|
418
|
-
_debounceTimer = null;
|
|
419
|
-
}
|
|
420
|
-
_pendingCid = null;
|
|
421
|
-
_pendingSmartAccount = null;
|
|
422
|
-
_lastPublishedCid = null;
|
|
423
|
-
_lastPublishTime = 0;
|
|
424
|
-
_isPublishing = false;
|
|
425
|
-
}
|
|
426
|
-
async function _executeSync() {
|
|
427
|
-
if (!_pendingCid || !_pendingSmartAccount || _isPublishing) return false;
|
|
428
|
-
if (_pendingCid === _lastPublishedCid) {
|
|
429
|
-
_pendingCid = null;
|
|
430
|
-
return true;
|
|
431
|
-
}
|
|
432
|
-
_isPublishing = true;
|
|
433
|
-
const cid = _pendingCid;
|
|
434
|
-
const sa = _pendingSmartAccount;
|
|
435
|
-
try {
|
|
436
|
-
import_logger3.logger.debug(`[OnChainSync] Publication on-chain: ${cid.slice(0, 20)}...`);
|
|
437
|
-
const txHash = await publishCidOnChain(sa, cid);
|
|
438
|
-
if (txHash) {
|
|
439
|
-
_lastPublishedCid = cid;
|
|
440
|
-
_lastPublishTime = Date.now();
|
|
441
|
-
_pendingCid = null;
|
|
442
|
-
import_logger3.logger.debug(
|
|
443
|
-
`[OnChainSync] \u2705 CID publi\xE9 on-chain : ${cid.slice(0, 20)}...`
|
|
444
|
-
);
|
|
445
|
-
return true;
|
|
446
|
-
}
|
|
447
|
-
import_logger3.logger.warn("[OnChainSync] Publication \xE9chou\xE9e (null txHash)");
|
|
448
|
-
return false;
|
|
449
|
-
} catch (error) {
|
|
450
|
-
import_logger3.logger.error("[OnChainSync] Erreur publication:", error instanceof Error ? error.message : error);
|
|
451
|
-
return false;
|
|
452
|
-
} finally {
|
|
453
|
-
_isPublishing = false;
|
|
298
|
+
// src/owner.ts
|
|
299
|
+
var import_core = require("@vaultkeepr/core");
|
|
300
|
+
async function getOwnerFromPassword(password, secretKey) {
|
|
301
|
+
if (secretKey) {
|
|
302
|
+
return (0, import_core.getHiddenWalletFromSecretKey)(secretKey);
|
|
454
303
|
}
|
|
304
|
+
return (0, import_core.getHiddenWalletFromPassword)(password);
|
|
455
305
|
}
|
|
456
306
|
|
|
457
307
|
// src/identity.ts
|
|
458
|
-
var
|
|
308
|
+
var import_logger2 = require("@vaultkeepr/logger");
|
|
459
309
|
var _state = {
|
|
460
310
|
owner: null,
|
|
461
311
|
smartAccount: null,
|
|
@@ -481,7 +331,15 @@ async function initIdentityFromPassword(password, secretKey) {
|
|
|
481
331
|
mode: "password"
|
|
482
332
|
});
|
|
483
333
|
} catch (e) {
|
|
484
|
-
|
|
334
|
+
import_logger2.logger.warn("[Identity] SA init failed (non-blocking):", e.message);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
let aaAddress = sa?.address ?? null;
|
|
338
|
+
if (!aaAddress && isSmartAccountConfigured()) {
|
|
339
|
+
try {
|
|
340
|
+
aaAddress = await computeSmartAccountAddress(owner);
|
|
341
|
+
} catch (e) {
|
|
342
|
+
import_logger2.logger.warn("[Identity] AA derivation failed (non-blocking):", e.message);
|
|
485
343
|
}
|
|
486
344
|
}
|
|
487
345
|
_state = {
|
|
@@ -491,12 +349,13 @@ async function initIdentityFromPassword(password, secretKey) {
|
|
|
491
349
|
initialized: true
|
|
492
350
|
};
|
|
493
351
|
_notify();
|
|
494
|
-
|
|
495
|
-
`[Identity] Connect\xE9 (password) \u2014 adresse: ${(0,
|
|
352
|
+
import_logger2.logger.debug(
|
|
353
|
+
`[Identity] Connect\xE9 (password) \u2014 adresse: ${(0, import_logger2.redactAddress)(owner.address)}` + (sa ? ` | SA: ${(0, import_logger2.redactAddress)(sa.address)}` : "") + (secretKey ? ` | SK: \u2713` : " | no secretKey")
|
|
496
354
|
);
|
|
497
355
|
return {
|
|
498
356
|
address: owner.address,
|
|
499
|
-
smartAccountAddress: sa?.address ?? null
|
|
357
|
+
smartAccountAddress: sa?.address ?? null,
|
|
358
|
+
aaAddress
|
|
500
359
|
};
|
|
501
360
|
}
|
|
502
361
|
async function initIdentityFromSigner(signer, mode = "passkey") {
|
|
@@ -505,7 +364,15 @@ async function initIdentityFromSigner(signer, mode = "passkey") {
|
|
|
505
364
|
try {
|
|
506
365
|
sa = await createVaultSmartAccount({ ownerAccount: signer, mode });
|
|
507
366
|
} catch (e) {
|
|
508
|
-
|
|
367
|
+
import_logger2.logger.warn("[Identity] SA init failed (non-blocking):", e.message);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
let aaAddress = sa?.address ?? null;
|
|
371
|
+
if (!aaAddress && isSmartAccountConfigured()) {
|
|
372
|
+
try {
|
|
373
|
+
aaAddress = await computeSmartAccountAddress(signer);
|
|
374
|
+
} catch (e) {
|
|
375
|
+
import_logger2.logger.warn("[Identity] AA derivation failed (non-blocking):", e.message);
|
|
509
376
|
}
|
|
510
377
|
}
|
|
511
378
|
_state = {
|
|
@@ -515,12 +382,13 @@ async function initIdentityFromSigner(signer, mode = "passkey") {
|
|
|
515
382
|
initialized: true
|
|
516
383
|
};
|
|
517
384
|
_notify();
|
|
518
|
-
|
|
385
|
+
import_logger2.logger.info(
|
|
519
386
|
`[Identity] Connected (${mode}) \u2014 address: ${signer.address}` + (sa ? ` | SA: ${sa.address}` : "")
|
|
520
387
|
);
|
|
521
388
|
return {
|
|
522
389
|
address: signer.address,
|
|
523
|
-
smartAccountAddress: sa?.address ?? null
|
|
390
|
+
smartAccountAddress: sa?.address ?? null,
|
|
391
|
+
aaAddress
|
|
524
392
|
};
|
|
525
393
|
}
|
|
526
394
|
function clearIdentity() {
|
|
@@ -532,7 +400,7 @@ function clearIdentity() {
|
|
|
532
400
|
};
|
|
533
401
|
clearSmartAccountCache();
|
|
534
402
|
_notify();
|
|
535
|
-
|
|
403
|
+
import_logger2.logger.info("[Identity] Disconnected");
|
|
536
404
|
}
|
|
537
405
|
function getIdentityAddress() {
|
|
538
406
|
return _state.owner?.address ?? null;
|
|
@@ -591,24 +459,10 @@ function useIdentity() {
|
|
|
591
459
|
const disconnect = (0, import_react.useCallback)(() => {
|
|
592
460
|
clearIdentity();
|
|
593
461
|
}, []);
|
|
594
|
-
const
|
|
595
|
-
(cid) => {
|
|
596
|
-
const sa = getIdentitySmartAccount();
|
|
597
|
-
if (!sa) return;
|
|
598
|
-
scheduleCidOnChainSync(sa, cid);
|
|
599
|
-
},
|
|
600
|
-
[]
|
|
601
|
-
);
|
|
602
|
-
const cleanupOnLock = (0, import_react.useCallback)(async () => {
|
|
603
|
-
await flushCidOnChainSync().catch(() => {
|
|
604
|
-
});
|
|
462
|
+
const cleanupOnLock = (0, import_react.useCallback)(() => {
|
|
605
463
|
clearSmartAccountCache();
|
|
606
|
-
resetOnChainSync();
|
|
607
464
|
clearIdentity();
|
|
608
|
-
|
|
609
|
-
const flushOnChainSync = (0, import_react.useCallback)(async () => {
|
|
610
|
-
await flushCidOnChainSync().catch(() => {
|
|
611
|
-
});
|
|
465
|
+
return Promise.resolve();
|
|
612
466
|
}, []);
|
|
613
467
|
return {
|
|
614
468
|
address: state.owner?.address ?? null,
|
|
@@ -617,9 +471,7 @@ function useIdentity() {
|
|
|
617
471
|
smartAccountAddress: state.smartAccount?.address ?? null,
|
|
618
472
|
signMessage,
|
|
619
473
|
disconnect,
|
|
620
|
-
|
|
621
|
-
cleanupOnLock,
|
|
622
|
-
flushOnChainSync
|
|
474
|
+
cleanupOnLock
|
|
623
475
|
};
|
|
624
476
|
}
|
|
625
477
|
|
|
@@ -627,13 +479,12 @@ function useIdentity() {
|
|
|
627
479
|
var import_viem3 = require("viem");
|
|
628
480
|
function generateSecretKey() {
|
|
629
481
|
const bytes = new Uint8Array(32);
|
|
630
|
-
if (typeof globalThis.crypto?.getRandomValues
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
bytes[i] = Math.floor(Math.random() * 256);
|
|
635
|
-
}
|
|
482
|
+
if (typeof globalThis.crypto?.getRandomValues !== "function") {
|
|
483
|
+
throw new Error(
|
|
484
|
+
"[SmartAccount] CSPRNG indisponible: crypto.getRandomValues est requis pour generer une cle secrete. Un fallback Math.random produirait une cle devinable (CWE-338), refuse."
|
|
485
|
+
);
|
|
636
486
|
}
|
|
487
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
637
488
|
return (0, import_viem3.bytesToHex)(bytes).slice(2);
|
|
638
489
|
}
|
|
639
490
|
function isValidSecretKey(key) {
|
|
@@ -646,14 +497,215 @@ function formatSecretKeyForDisplay(key) {
|
|
|
646
497
|
function parseSecretKeyInput(input) {
|
|
647
498
|
return input.replace(/[-\s]/g, "").toLowerCase();
|
|
648
499
|
}
|
|
500
|
+
|
|
501
|
+
// src/keyPassage.ts
|
|
502
|
+
function identityState(input) {
|
|
503
|
+
if (input.hasSecretKey) return { kind: "ready" };
|
|
504
|
+
if (input.pointer === "moved") return { kind: "pair_required" };
|
|
505
|
+
if (input.pointer === "active") return { kind: "pass_to_key" };
|
|
506
|
+
return { kind: "join_or_create" };
|
|
507
|
+
}
|
|
508
|
+
function canWritePointer(state) {
|
|
509
|
+
return state.kind === "ready" || state.kind === "pass_to_key";
|
|
510
|
+
}
|
|
511
|
+
function sameAddress(a, b) {
|
|
512
|
+
return a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
513
|
+
}
|
|
514
|
+
async function runPassage(io, opts) {
|
|
515
|
+
if (opts.hasSecretKey) return { status: "already_keyed" };
|
|
516
|
+
const legacy = await io.readLegacyPointer();
|
|
517
|
+
if (legacy.moved) {
|
|
518
|
+
const pending = await io.peekPendingKey();
|
|
519
|
+
if (pending && legacy.movedTo && sameAddress(await io.smartAccountOf(pending), legacy.movedTo)) {
|
|
520
|
+
await io.activatePendingKey();
|
|
521
|
+
return { status: "moved", smartAccount: legacy.movedTo };
|
|
522
|
+
}
|
|
523
|
+
if (pending) await io.discardPendingKey();
|
|
524
|
+
return { status: "already_moved" };
|
|
525
|
+
}
|
|
526
|
+
if (!legacy.cid) return { status: "nothing_to_pass" };
|
|
527
|
+
const secretKey = await io.getOrCreatePendingKey();
|
|
528
|
+
const smartAccount = await io.smartAccountOf(secretKey);
|
|
529
|
+
await io.writeSmartAccountPointer(smartAccount, legacy.cid);
|
|
530
|
+
await io.markLegacyMoved(smartAccount);
|
|
531
|
+
await io.activatePendingKey();
|
|
532
|
+
return { status: "moved", smartAccount };
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// src/passageClient.ts
|
|
536
|
+
var PASSAGE_ENABLED = false;
|
|
537
|
+
var DELEGATION_TTL_SECONDS = 300;
|
|
538
|
+
async function postJson(env, path, body) {
|
|
539
|
+
const res = await env.fetch(`${env.apiBase}${path}`, {
|
|
540
|
+
method: "POST",
|
|
541
|
+
headers: { "Content-Type": "application/json" },
|
|
542
|
+
body: JSON.stringify(body)
|
|
543
|
+
});
|
|
544
|
+
if (!res.ok) throw new Error(`passage ${path} failed (${res.status})`);
|
|
545
|
+
return res.json();
|
|
546
|
+
}
|
|
547
|
+
function createPassageIO(env) {
|
|
548
|
+
const legacyAddress = env.legacyAddress.toLowerCase();
|
|
549
|
+
const delegation2 = async (sign) => {
|
|
550
|
+
const sessionId = env.newSessionId();
|
|
551
|
+
const expiryTimestamp = Math.floor(env.now() / 1e3) + DELEGATION_TTL_SECONDS;
|
|
552
|
+
const delegationSignature = await sign(env.formatDelegation(sessionId, expiryTimestamp));
|
|
553
|
+
return { sessionId, expiryTimestamp, delegationSignature };
|
|
554
|
+
};
|
|
555
|
+
return {
|
|
556
|
+
async readLegacyPointer() {
|
|
557
|
+
const d = await delegation2((m) => env.signLegacy(m));
|
|
558
|
+
const query = [
|
|
559
|
+
`wallet=${encodeURIComponent(legacyAddress)}`,
|
|
560
|
+
`delegationSignature=${encodeURIComponent(d.delegationSignature)}`,
|
|
561
|
+
`sessionId=${encodeURIComponent(d.sessionId)}`,
|
|
562
|
+
`expiryTimestamp=${d.expiryTimestamp}`
|
|
563
|
+
].join("&");
|
|
564
|
+
const res = await env.fetch(`${env.apiBase}/api/vault-cid?${query}`);
|
|
565
|
+
if (!res.ok) throw new Error(`passage read failed (${res.status})`);
|
|
566
|
+
const json = await res.json();
|
|
567
|
+
return { cid: json.cid ?? null, moved: !!json.moved, movedTo: json.movedTo ?? void 0 };
|
|
568
|
+
},
|
|
569
|
+
peekPendingKey: () => env.pending.read(),
|
|
570
|
+
async getOrCreatePendingKey() {
|
|
571
|
+
const existing = await env.pending.read();
|
|
572
|
+
if (existing) return existing;
|
|
573
|
+
const secretKey = env.newSecretKey();
|
|
574
|
+
await env.pending.write(secretKey);
|
|
575
|
+
return secretKey;
|
|
576
|
+
},
|
|
577
|
+
smartAccountOf: (secretKey) => env.smartAccountOf(secretKey),
|
|
578
|
+
async writeSmartAccountPointer(smartAccount, cid) {
|
|
579
|
+
const pendingKey = await env.pending.read();
|
|
580
|
+
if (!pendingKey) throw new Error("passage: no pending key");
|
|
581
|
+
const d = await delegation2((m) => env.signWithKey(pendingKey, m));
|
|
582
|
+
await postJson(env, "/api/vault-cid", {
|
|
583
|
+
walletAddress: smartAccount,
|
|
584
|
+
cid,
|
|
585
|
+
delegationSignature: d.delegationSignature,
|
|
586
|
+
sessionId: d.sessionId,
|
|
587
|
+
expiryTimestamp: d.expiryTimestamp
|
|
588
|
+
});
|
|
589
|
+
},
|
|
590
|
+
async markLegacyMoved(smartAccount) {
|
|
591
|
+
const d = await delegation2((m) => env.signLegacy(m));
|
|
592
|
+
await postJson(env, "/api/vault-cid/move", {
|
|
593
|
+
walletAddress: legacyAddress,
|
|
594
|
+
targetSmartAccount: smartAccount,
|
|
595
|
+
delegationSignature: d.delegationSignature,
|
|
596
|
+
sessionId: d.sessionId,
|
|
597
|
+
expiryTimestamp: d.expiryTimestamp
|
|
598
|
+
});
|
|
599
|
+
},
|
|
600
|
+
async activatePendingKey() {
|
|
601
|
+
const pendingKey = await env.pending.read();
|
|
602
|
+
if (!pendingKey) throw new Error("passage: no pending key");
|
|
603
|
+
await env.activate(pendingKey);
|
|
604
|
+
await env.pending.clear();
|
|
605
|
+
},
|
|
606
|
+
discardPendingKey: () => env.pending.clear()
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
async function readPassageState(env, hasSecretKey) {
|
|
610
|
+
const legacy = await createPassageIO(env).readLegacyPointer();
|
|
611
|
+
const pointer = legacy.moved ? "moved" : legacy.cid ? "active" : "none";
|
|
612
|
+
return identityState({ hasSecretKey, pointer });
|
|
613
|
+
}
|
|
614
|
+
function runPassageWith(env, hasSecretKey) {
|
|
615
|
+
return runPassage(createPassageIO(env), { hasSecretKey });
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// src/keyedMigration.ts
|
|
619
|
+
var KEYED_MIGRATION_ENABLED = false;
|
|
620
|
+
var DELEGATION_TTL_SECONDS2 = 300;
|
|
621
|
+
async function delegation(env) {
|
|
622
|
+
const sessionId = env.newSessionId();
|
|
623
|
+
const expiryTimestamp = Math.floor(env.now() / 1e3) + DELEGATION_TTL_SECONDS2;
|
|
624
|
+
const delegationSignature = await env.signWithKey(env.formatDelegation(sessionId, expiryTimestamp));
|
|
625
|
+
return { sessionId, expiryTimestamp, delegationSignature };
|
|
626
|
+
}
|
|
627
|
+
async function readPointer(env, wallet) {
|
|
628
|
+
const d = await delegation(env);
|
|
629
|
+
const query = [
|
|
630
|
+
`wallet=${encodeURIComponent(wallet)}`,
|
|
631
|
+
`delegationSignature=${encodeURIComponent(d.delegationSignature)}`,
|
|
632
|
+
`sessionId=${encodeURIComponent(d.sessionId)}`,
|
|
633
|
+
`expiryTimestamp=${d.expiryTimestamp}`
|
|
634
|
+
].join("&");
|
|
635
|
+
const res = await env.fetch(`${env.apiBase}/api/vault-cid?${query}`);
|
|
636
|
+
if (!res.ok) throw new Error(`keyed migration: read failed (${res.status})`);
|
|
637
|
+
const json = await res.json();
|
|
638
|
+
return { cid: json.cid ?? null, moved: !!json.moved, movedTo: json.movedTo ?? void 0 };
|
|
639
|
+
}
|
|
640
|
+
async function copyPointer(env, smartAccount, cid) {
|
|
641
|
+
const d = await delegation(env);
|
|
642
|
+
const res = await env.fetch(`${env.apiBase}/api/vault-cid`, {
|
|
643
|
+
method: "POST",
|
|
644
|
+
headers: { "Content-Type": "application/json" },
|
|
645
|
+
body: JSON.stringify({
|
|
646
|
+
walletAddress: smartAccount,
|
|
647
|
+
cid,
|
|
648
|
+
delegationSignature: d.delegationSignature,
|
|
649
|
+
sessionId: d.sessionId,
|
|
650
|
+
expiryTimestamp: d.expiryTimestamp
|
|
651
|
+
})
|
|
652
|
+
});
|
|
653
|
+
if (!res.ok) throw new Error(`keyed migration: SA copy failed (${res.status})`);
|
|
654
|
+
}
|
|
655
|
+
async function markMoved(env, owner, smartAccount) {
|
|
656
|
+
const d = await delegation(env);
|
|
657
|
+
const res = await env.fetch(`${env.apiBase}/api/vault-cid/move`, {
|
|
658
|
+
method: "POST",
|
|
659
|
+
headers: { "Content-Type": "application/json" },
|
|
660
|
+
body: JSON.stringify({
|
|
661
|
+
walletAddress: owner,
|
|
662
|
+
targetSmartAccount: smartAccount,
|
|
663
|
+
delegationSignature: d.delegationSignature,
|
|
664
|
+
sessionId: d.sessionId,
|
|
665
|
+
expiryTimestamp: d.expiryTimestamp
|
|
666
|
+
})
|
|
667
|
+
});
|
|
668
|
+
if (!res.ok) throw new Error(`keyed migration: move failed (${res.status})`);
|
|
669
|
+
}
|
|
670
|
+
async function reconcileAfterMove(env, owner, smartAccount) {
|
|
671
|
+
const frozen = await readPointer(env, owner);
|
|
672
|
+
if (!frozen.cid) throw new Error("keyed migration: legacy pointer empty after the move");
|
|
673
|
+
const copied = await readPointer(env, smartAccount);
|
|
674
|
+
if (copied.cid === frozen.cid) return;
|
|
675
|
+
await copyPointer(env, smartAccount, frozen.cid);
|
|
676
|
+
const check = await readPointer(env, smartAccount);
|
|
677
|
+
if (check.cid !== frozen.cid) throw new Error("keyed migration: SA copy differs after the move");
|
|
678
|
+
}
|
|
679
|
+
async function migrateKeyedPointer(env) {
|
|
680
|
+
const owner = env.ownerAddress.toLowerCase();
|
|
681
|
+
const smartAccount = env.smartAccount.toLowerCase();
|
|
682
|
+
const legacy = await readPointer(env, owner);
|
|
683
|
+
if (legacy.moved) {
|
|
684
|
+
if ((legacy.movedTo ?? "").toLowerCase() !== smartAccount) {
|
|
685
|
+
throw new Error("keyed migration: legacy pointer moved to another smart account");
|
|
686
|
+
}
|
|
687
|
+
await reconcileAfterMove(env, owner, smartAccount);
|
|
688
|
+
return "already_moved";
|
|
689
|
+
}
|
|
690
|
+
if (!legacy.cid) return "no_pointer";
|
|
691
|
+
const target = await readPointer(env, smartAccount);
|
|
692
|
+
if (target.cid !== null && target.cid !== legacy.cid) return "conflict";
|
|
693
|
+
if (target.cid === null) await copyPointer(env, smartAccount, legacy.cid);
|
|
694
|
+
await markMoved(env, owner, smartAccount);
|
|
695
|
+
await reconcileAfterMove(env, owner, smartAccount);
|
|
696
|
+
return "moved";
|
|
697
|
+
}
|
|
649
698
|
// Annotate the CommonJS export names for ESM import in node:
|
|
650
699
|
0 && (module.exports = {
|
|
651
|
-
|
|
700
|
+
KEYED_MIGRATION_ENABLED,
|
|
701
|
+
PASSAGE_ENABLED,
|
|
702
|
+
canWritePointer,
|
|
652
703
|
clearIdentity,
|
|
653
704
|
clearSmartAccountCache,
|
|
654
705
|
computeSmartAccountAddress,
|
|
706
|
+
createPassageIO,
|
|
655
707
|
createVaultSmartAccount,
|
|
656
|
-
|
|
708
|
+
deriveIdentity,
|
|
657
709
|
formatSecretKeyForDisplay,
|
|
658
710
|
generateSecretKey,
|
|
659
711
|
getCachedSmartAccountAddress,
|
|
@@ -663,22 +715,22 @@ function parseSecretKeyInput(input) {
|
|
|
663
715
|
getIdentityOwner,
|
|
664
716
|
getIdentitySmartAccount,
|
|
665
717
|
getIdentitySnapshot,
|
|
666
|
-
getOnChainSyncStatus,
|
|
667
718
|
getOwnerFromPassword,
|
|
668
719
|
getPimlicoApiKey,
|
|
669
720
|
getTargetChain,
|
|
721
|
+
identityState,
|
|
670
722
|
initIdentityFromPassword,
|
|
671
723
|
initIdentityFromSigner,
|
|
672
|
-
isCidRegistryConfigured,
|
|
673
724
|
isIdentityConnected,
|
|
674
725
|
isSmartAccountConfigured,
|
|
675
726
|
isValidSecretKey,
|
|
727
|
+
migrateKeyedPointer,
|
|
676
728
|
parseSecretKeyInput,
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
scheduleCidOnChainSync,
|
|
729
|
+
readPassageState,
|
|
730
|
+
runPassage,
|
|
731
|
+
runPassageWith,
|
|
681
732
|
signMessageWithIdentity,
|
|
682
733
|
subscribeIdentity,
|
|
683
|
-
useIdentity
|
|
734
|
+
useIdentity,
|
|
735
|
+
verifyAAAuth
|
|
684
736
|
});
|