@kingdomchain/wallet-client 0.6.2 → 0.6.3

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/index.d.ts CHANGED
@@ -413,6 +413,18 @@ interface VaultStorageOptions {
413
413
  /** When set, vault is stored under this account-scoped key instead of {@link VAULT_LEGACY_KEY}. */
414
414
  scopeId?: string;
415
415
  }
416
+ /**
417
+ * Encrypted, expiring session-unlock cache (see {@link file://./sessionCache.ts}).
418
+ * The `key` is a non-extractable AES-GCM {@link CryptoKey} stored directly in
419
+ * IndexedDB via structured clone — its raw bytes can never be read back out by
420
+ * any JavaScript. `ciphertext`/`iv` are base64; `expiresAt` is epoch millis.
421
+ */
422
+ interface EmbeddedWalletSessionCacheRecord {
423
+ key: CryptoKey;
424
+ iv: string;
425
+ ciphertext: string;
426
+ expiresAt: number;
427
+ }
416
428
  interface PasscodeLockoutRecord {
417
429
  failedAttempts: number;
418
430
  lockoutTier: number;
@@ -425,6 +437,42 @@ declare function clearVaultFromIndexedDb(options?: VaultStorageOptions): Promise
425
437
  declare function loadPasscodeLockoutRecord(publicAddress: string): Promise<PasscodeLockoutRecord | null>;
426
438
  declare function savePasscodeLockoutRecord(publicAddress: string, record: PasscodeLockoutRecord): Promise<void>;
427
439
  declare function clearPasscodeLockoutRecord(publicAddress: string): Promise<void>;
440
+ declare function saveSessionCacheRecord(record: EmbeddedWalletSessionCacheRecord, options?: VaultStorageOptions): Promise<void>;
441
+ declare function loadSessionCacheRecord(options?: VaultStorageOptions): Promise<EmbeddedWalletSessionCacheRecord | null>;
442
+ declare function clearSessionCacheRecord(options?: VaultStorageOptions): Promise<void>;
443
+
444
+ /**
445
+ * How long a passcode/passkey unlock stays valid across page reloads and new
446
+ * tabs (same browser, same device) before the unlock form is required again.
447
+ *
448
+ * Phase 1 session-persistent unlock: 12 hours of wall-clock time from the last
449
+ * unlock. Deliberately bounded — not "until tab closes" (too strict, reintroduces
450
+ * daily friction) and not "forever" (that is phase 2's job, backed by WebAuthn).
451
+ * Tune here; it is intentionally the single source of truth for the window.
452
+ */
453
+ declare const EMBEDDED_WALLET_SESSION_TTL_MS: number;
454
+ interface CacheUnlockedSessionOptions extends VaultStorageOptions {
455
+ /** Decrypted vault material needed to rebuild the signer without the passcode. */
456
+ plaintext: EmbeddedWalletPlaintext;
457
+ /** Override the default session window (mainly for tests). */
458
+ ttlMs?: number;
459
+ }
460
+ /**
461
+ * Encrypt the just-decrypted session material under a fresh non-extractable key
462
+ * and persist it (with an expiry) so a reload or new tab can restore the signer
463
+ * without re-prompting for the passcode. Best-effort: callers should not fail an
464
+ * unlock if this throws.
465
+ */
466
+ declare function cacheUnlockedSession(options: CacheUnlockedSessionOptions): Promise<void>;
467
+ /**
468
+ * Restore the decrypted session material from the cache for a scope, or return
469
+ * `null` when there is nothing valid cached. "No session" is a normal, expected
470
+ * state — this never throws for it. An expired or undecryptable record is wiped
471
+ * and treated as `null`.
472
+ */
473
+ declare function restoreCachedSessionPlaintext(options?: VaultStorageOptions): Promise<EmbeddedWalletPlaintext | null>;
474
+ /** Wipe the cached session key + ciphertext for a scope. */
475
+ declare function clearUnlockedSession(options?: VaultStorageOptions): Promise<void>;
428
476
 
429
477
  /** Consecutive wrong passcodes before lockout triggers. */
430
478
  declare const PASSCODE_LOCKOUT_FAILURE_THRESHOLD = 5;
@@ -582,7 +630,20 @@ declare function enableEmbeddedPasskeyUnlock(options: EnableEmbeddedPasskeyUnloc
582
630
  }>;
583
631
  /** Unlock existing vault with passcode (default) or passkey (opt-in upgrade path). */
584
632
  declare function unlockEmbeddedWallet(options?: UnlockEmbeddedWalletOptions): Promise<EmbeddedWalletSession>;
585
- /** Clear in-memory signer. */
633
+ /**
634
+ * Silently restore a still-valid unlock cached by a previous {@link unlockEmbeddedWallet}
635
+ * (this page load, a prior one, or another tab in the same browser), without the
636
+ * passcode. Returns the same session shape {@link unlockEmbeddedWallet} returns,
637
+ * or `null` when nothing valid is cached — "no session" is a normal state and is
638
+ * never thrown. The vault encryption/passcode mechanism is untouched; this only
639
+ * reads a parallel, expiring session cache.
640
+ */
641
+ declare function tryRestoreUnlockedSession(options?: EmbeddedWalletScopeOptions): Promise<EmbeddedWalletSession | null>;
642
+ /**
643
+ * Clear the in-memory signer and wipe the persistent session cache for the
644
+ * active scope. Wiring the cache clear here guarantees an explicit lock/logout
645
+ * never leaves a silent-unlock path alive.
646
+ */
586
647
  declare function lockEmbeddedWallet(): void;
587
648
  declare function getEmbeddedWalletSession(): EmbeddedWalletSession | null;
588
649
  /** Offline signer for CosmJS; enforces backup gate before signing. */
@@ -743,4 +804,4 @@ interface MessageFns<T> {
743
804
  fromPartial(object: DeepPartial<T>): T;
744
805
  }
745
806
 
746
- export { ATTESTATION_TYPE_CITIZENSHIP_APPLICATION, ATTESTATION_TYPE_RECOVERY, type AcknowledgeEmbeddedBackupOptions, ApplicationStatus, type AttestationPayloadInput, BECH32_PREFIX, type BankBalanceResponse, type BroadcastConfirmOptions, type BroadcastConfirmResult, type BrowserWalletApi, CHAIN_COIN_TYPE, type ChainCurrency, type ChainInfo, CitizenTxError, type CitizenTxErrorCode, type ClearEmbeddedWalletOptions, type CosmostationWindowApi, type CreateEmbeddedWalletOptions, DEFAULT_CHAIN_ID, DEFAULT_REST_URL, DEFAULT_RPC_URL, EMBEDDED_WALLET_KDF_PBKDF2, EMBEDDED_WALLET_KDF_PIN, EMBEDDED_WALLET_KDF_PRF, EMBEDDED_WALLET_KEY_DIRECT_ENTROPY, EMBEDDED_WALLET_KEY_HD_DERIVED, EMBEDDED_WALLET_PASSCODE_MAX_LENGTH, EMBEDDED_WALLET_PASSCODE_MIN_LENGTH, EMBEDDED_WALLET_PASSKEY_PBKDF2_ITERATIONS, EMBEDDED_WALLET_PIN_PBKDF2_ITERATIONS, EMBEDDED_WALLET_RECOVERY_PHRASE_DIRECT_ENTROPY_WARNING, EMBEDDED_WALLET_RECOVERY_PHRASE_GENERAL_WARNING, EMBEDDED_WALLET_VAULT_VERSION, type EmbeddedWalletBackupFileV1, EmbeddedWalletBackupRequiredError, EmbeddedWalletDecryptError, type EmbeddedWalletKdf, type EmbeddedWalletKeyType, EmbeddedWalletLockoutError, type EmbeddedWalletPlaintext, type EmbeddedWalletRecoveryPhraseReveal, type EmbeddedWalletRecoveryPhraseWarning, type EmbeddedWalletScopeOptions, type EmbeddedWalletSession, EmbeddedWalletVaultError, type EmbeddedWalletVaultV1, EmbeddedWalletWeakPasscodeError, type EnableEmbeddedPasskeyUnlockOptions, type EncryptWalletOptions, type FeeGrantAllowancesResponse, FinalizedReward, type ImportEmbeddedBackupOptions, InvalidChainConfigError, type MigrateLegacyEmbeddedWalletOptions, MsgClaimReward, MsgSubmitApplication, MsgSubmitRecoveryAttestation, PASSCODE_LOCKOUT_FAILURE_THRESHOLD, PASSCODE_LOCKOUT_INITIAL_MS, PASSCODE_LOCKOUT_MAX_MS, type PasscodeBlockReason, type PasscodeLockoutRecord, type PasscodeStrengthLabel, type PasscodeStrengthResult, type PasskeyAssertionResult, type PasskeyRegistrationResult, type RecoverEmbeddedWalletOptions, RecoveryAttestationStatus, RestQueryError, type RevealEmbeddedRecoveryPhraseOptions, RpcConnectionError, type SubmitApplicationParams, UKDR_DECIMALS, UKDR_DISPLAY_DENOM, UKDR_MINIMAL_DENOM, type UnclaimedRewardsResponse, type UnlockEmbeddedWalletOptions, VAULT_LEGACY_KEY, type VaultStorageOptions, WALLETCONNECT_COSMOS_METHODS, WALLETCONNECT_COSMOS_NAMESPACE, WEBAUTHN_RP_NAME, WalletAccountError, type WalletConnectChainConfig, type WalletConnectConnectResult, type WalletConnectMetadata, WalletConnectNotInitializedError, WalletConnectSessionError, WalletConnectSigningError, WalletConnectionError, WalletConnectionRejectedError, WalletNotInstalledError, type WebAuthnPrfCapabilities, WebAuthnUnavailableError, WebAuthnUserCancelledError, acknowledgeEmbeddedBackup, addressFromHdMnemonic, addressFromPrivateKey, assertPasscodeAllowedForCreation, assertPasscodeUnlockAllowed, assertPasskey, assertValidPasscode, assertValidRecoveryMnemonic, assertVaultPermitsTransaction, attestationSignPayload, broadcastAndConfirmTx, buildClaimRewardMsg, buildKingdomChainInfo, buildRequiredCosmosNamespaces, buildSendUkdrMsg, buildSubmitApplicationMsg, citizenTxErrorMessage, clearEmbeddedWallet, clearPasscodeLockoutRecord, clearVaultFromIndexedDb, computePasscodeLockoutDurationMs, connectCosmostation, connectKeplr, connectLeap, connectWalletConnect, createBrowserSigningClient, createEmbeddedWallet, createHdDerivedPlaintext, createKingdomChainRegistry, createPasskeyMaterialFromAssertion, createPbkdf2Salt, createWalletConnectOfflineSigner, decodeCredentialId, decodeDirectEntropyMnemonic, decryptWalletPayload, defaultEmbeddedHdPath, defaultUkdrTxFee, deriveKekFromPasscode, deriveKekFromPbkdf2, deriveKekFromPrf, derivePrivateKeyFromHdMnemonic, detectRecoveryMnemonicKeyType, detectWebAuthnPrfCapabilities, disconnectWalletConnect, downloadEmbeddedBackupFile, embeddedPlaintextToSigner, enableEmbeddedPasskeyUnlock, encodeCredentialId, encodeDirectEntropyMnemonic, encryptWalletPayload, evaluatePasscodeStrength, exportEncryptedBackup, fetchFeeGrantGranter, fetchUkdrBalance, fetchUnclaimedFinalizedRewards, formatUkdrAsKdr, getCosmostationKeplrApi, getEmbeddedOfflineSigner, getEmbeddedWalletSession, getPasscodeLockoutState, hasEmbeddedWallet, hasLegacyEmbeddedWallet, hasMixedCharacterClasses, importEmbeddedBackup, initWalletConnectClient, isCosmostationAvailable, isKeplrAvailable, isLeapAvailable, loadPasscodeLockoutRecord, loadVaultFromIndexedDb, lockEmbeddedWallet, markVaultBackupAcknowledged, migrateLegacyEmbeddedWallet, normalizePasscode, normalizeRecoveryMnemonic, parseEncryptedBackup, parseKdrToUkdr, parseWalletConnectAccount, plaintextFromRecoveryMnemonic, providerSeedFromHex, publicKeyFromPrivateSeed, readPrfOutput, recordPasscodeUnlockFailure, recordPasscodeUnlockSuccess, recoverEmbeddedWalletFromMnemonic, recoveryMnemonicAddress, recoveryMnemonicFromPlaintext, registerPasskey, resolvePlaintextKeyType, resolveVaultStorageKey, restoreWalletConnectSession, revealEmbeddedRecoveryPhrase, savePasscodeLockoutRecord, saveVaultToIndexedDb, selectEmbeddedWalletKdf, serializeBackupFile, signAttestationPayload, signCitizenshipAttestation, suggestAndConnect, toWalletConnectCosmosChainId, ukdrCoin, unlockEmbeddedWallet, validateChainConfig, vaultUsesPasscodeUnlock, vaultUsesPasskeyUnlock };
807
+ export { ATTESTATION_TYPE_CITIZENSHIP_APPLICATION, ATTESTATION_TYPE_RECOVERY, type AcknowledgeEmbeddedBackupOptions, ApplicationStatus, type AttestationPayloadInput, BECH32_PREFIX, type BankBalanceResponse, type BroadcastConfirmOptions, type BroadcastConfirmResult, type BrowserWalletApi, CHAIN_COIN_TYPE, type CacheUnlockedSessionOptions, type ChainCurrency, type ChainInfo, CitizenTxError, type CitizenTxErrorCode, type ClearEmbeddedWalletOptions, type CosmostationWindowApi, type CreateEmbeddedWalletOptions, DEFAULT_CHAIN_ID, DEFAULT_REST_URL, DEFAULT_RPC_URL, EMBEDDED_WALLET_KDF_PBKDF2, EMBEDDED_WALLET_KDF_PIN, EMBEDDED_WALLET_KDF_PRF, EMBEDDED_WALLET_KEY_DIRECT_ENTROPY, EMBEDDED_WALLET_KEY_HD_DERIVED, EMBEDDED_WALLET_PASSCODE_MAX_LENGTH, EMBEDDED_WALLET_PASSCODE_MIN_LENGTH, EMBEDDED_WALLET_PASSKEY_PBKDF2_ITERATIONS, EMBEDDED_WALLET_PIN_PBKDF2_ITERATIONS, EMBEDDED_WALLET_RECOVERY_PHRASE_DIRECT_ENTROPY_WARNING, EMBEDDED_WALLET_RECOVERY_PHRASE_GENERAL_WARNING, EMBEDDED_WALLET_SESSION_TTL_MS, EMBEDDED_WALLET_VAULT_VERSION, type EmbeddedWalletBackupFileV1, EmbeddedWalletBackupRequiredError, EmbeddedWalletDecryptError, type EmbeddedWalletKdf, type EmbeddedWalletKeyType, EmbeddedWalletLockoutError, type EmbeddedWalletPlaintext, type EmbeddedWalletRecoveryPhraseReveal, type EmbeddedWalletRecoveryPhraseWarning, type EmbeddedWalletScopeOptions, type EmbeddedWalletSession, type EmbeddedWalletSessionCacheRecord, EmbeddedWalletVaultError, type EmbeddedWalletVaultV1, EmbeddedWalletWeakPasscodeError, type EnableEmbeddedPasskeyUnlockOptions, type EncryptWalletOptions, type FeeGrantAllowancesResponse, FinalizedReward, type ImportEmbeddedBackupOptions, InvalidChainConfigError, type MigrateLegacyEmbeddedWalletOptions, MsgClaimReward, MsgSubmitApplication, MsgSubmitRecoveryAttestation, PASSCODE_LOCKOUT_FAILURE_THRESHOLD, PASSCODE_LOCKOUT_INITIAL_MS, PASSCODE_LOCKOUT_MAX_MS, type PasscodeBlockReason, type PasscodeLockoutRecord, type PasscodeStrengthLabel, type PasscodeStrengthResult, type PasskeyAssertionResult, type PasskeyRegistrationResult, type RecoverEmbeddedWalletOptions, RecoveryAttestationStatus, RestQueryError, type RevealEmbeddedRecoveryPhraseOptions, RpcConnectionError, type SubmitApplicationParams, UKDR_DECIMALS, UKDR_DISPLAY_DENOM, UKDR_MINIMAL_DENOM, type UnclaimedRewardsResponse, type UnlockEmbeddedWalletOptions, VAULT_LEGACY_KEY, type VaultStorageOptions, WALLETCONNECT_COSMOS_METHODS, WALLETCONNECT_COSMOS_NAMESPACE, WEBAUTHN_RP_NAME, WalletAccountError, type WalletConnectChainConfig, type WalletConnectConnectResult, type WalletConnectMetadata, WalletConnectNotInitializedError, WalletConnectSessionError, WalletConnectSigningError, WalletConnectionError, WalletConnectionRejectedError, WalletNotInstalledError, type WebAuthnPrfCapabilities, WebAuthnUnavailableError, WebAuthnUserCancelledError, acknowledgeEmbeddedBackup, addressFromHdMnemonic, addressFromPrivateKey, assertPasscodeAllowedForCreation, assertPasscodeUnlockAllowed, assertPasskey, assertValidPasscode, assertValidRecoveryMnemonic, assertVaultPermitsTransaction, attestationSignPayload, broadcastAndConfirmTx, buildClaimRewardMsg, buildKingdomChainInfo, buildRequiredCosmosNamespaces, buildSendUkdrMsg, buildSubmitApplicationMsg, cacheUnlockedSession, citizenTxErrorMessage, clearEmbeddedWallet, clearPasscodeLockoutRecord, clearSessionCacheRecord, clearUnlockedSession, clearVaultFromIndexedDb, computePasscodeLockoutDurationMs, connectCosmostation, connectKeplr, connectLeap, connectWalletConnect, createBrowserSigningClient, createEmbeddedWallet, createHdDerivedPlaintext, createKingdomChainRegistry, createPasskeyMaterialFromAssertion, createPbkdf2Salt, createWalletConnectOfflineSigner, decodeCredentialId, decodeDirectEntropyMnemonic, decryptWalletPayload, defaultEmbeddedHdPath, defaultUkdrTxFee, deriveKekFromPasscode, deriveKekFromPbkdf2, deriveKekFromPrf, derivePrivateKeyFromHdMnemonic, detectRecoveryMnemonicKeyType, detectWebAuthnPrfCapabilities, disconnectWalletConnect, downloadEmbeddedBackupFile, embeddedPlaintextToSigner, enableEmbeddedPasskeyUnlock, encodeCredentialId, encodeDirectEntropyMnemonic, encryptWalletPayload, evaluatePasscodeStrength, exportEncryptedBackup, fetchFeeGrantGranter, fetchUkdrBalance, fetchUnclaimedFinalizedRewards, formatUkdrAsKdr, getCosmostationKeplrApi, getEmbeddedOfflineSigner, getEmbeddedWalletSession, getPasscodeLockoutState, hasEmbeddedWallet, hasLegacyEmbeddedWallet, hasMixedCharacterClasses, importEmbeddedBackup, initWalletConnectClient, isCosmostationAvailable, isKeplrAvailable, isLeapAvailable, loadPasscodeLockoutRecord, loadSessionCacheRecord, loadVaultFromIndexedDb, lockEmbeddedWallet, markVaultBackupAcknowledged, migrateLegacyEmbeddedWallet, normalizePasscode, normalizeRecoveryMnemonic, parseEncryptedBackup, parseKdrToUkdr, parseWalletConnectAccount, plaintextFromRecoveryMnemonic, providerSeedFromHex, publicKeyFromPrivateSeed, readPrfOutput, recordPasscodeUnlockFailure, recordPasscodeUnlockSuccess, recoverEmbeddedWalletFromMnemonic, recoveryMnemonicAddress, recoveryMnemonicFromPlaintext, registerPasskey, resolvePlaintextKeyType, resolveVaultStorageKey, restoreCachedSessionPlaintext, restoreWalletConnectSession, revealEmbeddedRecoveryPhrase, savePasscodeLockoutRecord, saveSessionCacheRecord, saveVaultToIndexedDb, selectEmbeddedWalletKdf, serializeBackupFile, signAttestationPayload, signCitizenshipAttestation, suggestAndConnect, toWalletConnectCosmosChainId, tryRestoreUnlockedSession, ukdrCoin, unlockEmbeddedWallet, validateChainConfig, vaultUsesPasscodeUnlock, vaultUsesPasskeyUnlock };
package/dist/index.js CHANGED
@@ -2519,9 +2519,10 @@ function decodeCredentialId(encoded) {
2519
2519
 
2520
2520
  // src/embeddedWallet/storage.ts
2521
2521
  var DB_NAME = "kingdom-os-wallet";
2522
- var DB_VERSION = 2;
2522
+ var DB_VERSION = 3;
2523
2523
  var VAULT_STORE_NAME = "vault";
2524
2524
  var LOCKOUT_STORE_NAME = "passcode-lockout";
2525
+ var SESSION_STORE_NAME = "session-cache";
2525
2526
  var VAULT_LEGACY_KEY = "primary";
2526
2527
  function resolveVaultStorageKey(scopeId) {
2527
2528
  const trimmed = scopeId?.trim();
@@ -2539,6 +2540,9 @@ function openDb() {
2539
2540
  if (!db.objectStoreNames.contains(LOCKOUT_STORE_NAME)) {
2540
2541
  db.createObjectStore(LOCKOUT_STORE_NAME);
2541
2542
  }
2543
+ if (!db.objectStoreNames.contains(SESSION_STORE_NAME)) {
2544
+ db.createObjectStore(SESSION_STORE_NAME);
2545
+ }
2542
2546
  };
2543
2547
  request.onsuccess = () => resolve(request.result);
2544
2548
  });
@@ -2613,6 +2617,115 @@ async function clearPasscodeLockoutRecord(publicAddress) {
2613
2617
  });
2614
2618
  db.close();
2615
2619
  }
2620
+ async function saveSessionCacheRecord(record, options = {}) {
2621
+ const key = resolveVaultStorageKey(options.scopeId);
2622
+ const db = await openDb();
2623
+ await new Promise((resolve, reject) => {
2624
+ const tx = db.transaction(SESSION_STORE_NAME, "readwrite");
2625
+ tx.objectStore(SESSION_STORE_NAME).put(record, key);
2626
+ tx.oncomplete = () => resolve();
2627
+ tx.onerror = () => reject(tx.error ?? new Error("IndexedDB write failed"));
2628
+ });
2629
+ db.close();
2630
+ }
2631
+ async function loadSessionCacheRecord(options = {}) {
2632
+ const key = resolveVaultStorageKey(options.scopeId);
2633
+ const db = await openDb();
2634
+ const record = await new Promise((resolve, reject) => {
2635
+ const tx = db.transaction(SESSION_STORE_NAME, "readonly");
2636
+ const request = tx.objectStore(SESSION_STORE_NAME).get(key);
2637
+ request.onsuccess = () => resolve(request.result ?? null);
2638
+ request.onerror = () => reject(request.error ?? new Error("IndexedDB read failed"));
2639
+ });
2640
+ db.close();
2641
+ return record;
2642
+ }
2643
+ async function clearSessionCacheRecord(options = {}) {
2644
+ const key = resolveVaultStorageKey(options.scopeId);
2645
+ const db = await openDb();
2646
+ await new Promise((resolve, reject) => {
2647
+ const tx = db.transaction(SESSION_STORE_NAME, "readwrite");
2648
+ tx.objectStore(SESSION_STORE_NAME).delete(key);
2649
+ tx.oncomplete = () => resolve();
2650
+ tx.onerror = () => reject(tx.error ?? new Error("IndexedDB delete failed"));
2651
+ });
2652
+ db.close();
2653
+ }
2654
+ var EMBEDDED_WALLET_SESSION_TTL_MS = 12 * 60 * 60 * 1e3;
2655
+ var AES_GCM_IV_BYTES2 = 12;
2656
+ function serializeSessionPlaintext(plaintext) {
2657
+ const wire = {
2658
+ privateKey: toBase64(plaintext.privateKey),
2659
+ hdPath: plaintext.hdPath,
2660
+ createdAt: plaintext.createdAt,
2661
+ keyType: plaintext.keyType ?? EMBEDDED_WALLET_KEY_DIRECT_ENTROPY
2662
+ };
2663
+ if (plaintext.mnemonic) {
2664
+ wire.mnemonic = plaintext.mnemonic;
2665
+ }
2666
+ return new TextEncoder().encode(JSON.stringify(wire));
2667
+ }
2668
+ function deserializeSessionPlaintext(bytes) {
2669
+ const wire = JSON.parse(new TextDecoder().decode(bytes));
2670
+ const plaintext = {
2671
+ privateKey: fromBase64(wire.privateKey),
2672
+ hdPath: wire.hdPath,
2673
+ createdAt: wire.createdAt,
2674
+ keyType: wire.keyType ?? EMBEDDED_WALLET_KEY_DIRECT_ENTROPY
2675
+ };
2676
+ if (wire.mnemonic) {
2677
+ plaintext.mnemonic = wire.mnemonic;
2678
+ }
2679
+ return plaintext;
2680
+ }
2681
+ async function generateNonExtractableSessionKey() {
2682
+ return crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, false, [
2683
+ "encrypt",
2684
+ "decrypt"
2685
+ ]);
2686
+ }
2687
+ async function cacheUnlockedSession(options) {
2688
+ const { plaintext, ttlMs, ...storageOptions } = options;
2689
+ const key = await generateNonExtractableSessionKey();
2690
+ const iv = crypto.getRandomValues(new Uint8Array(AES_GCM_IV_BYTES2));
2691
+ const material = serializeSessionPlaintext(plaintext);
2692
+ const ciphertext = await crypto.subtle.encrypt(
2693
+ { name: "AES-GCM", iv },
2694
+ key,
2695
+ new Uint8Array(material)
2696
+ );
2697
+ const record = {
2698
+ key,
2699
+ iv: toBase64(iv),
2700
+ ciphertext: toBase64(new Uint8Array(ciphertext)),
2701
+ expiresAt: Date.now() + (ttlMs ?? EMBEDDED_WALLET_SESSION_TTL_MS)
2702
+ };
2703
+ await saveSessionCacheRecord(record, storageOptions);
2704
+ }
2705
+ async function restoreCachedSessionPlaintext(options = {}) {
2706
+ const record = await loadSessionCacheRecord(options);
2707
+ if (!record) {
2708
+ return null;
2709
+ }
2710
+ if (typeof record.expiresAt !== "number" || Date.now() >= record.expiresAt) {
2711
+ await clearSessionCacheRecord(options).catch(() => void 0);
2712
+ return null;
2713
+ }
2714
+ try {
2715
+ const plaintextBytes = await crypto.subtle.decrypt(
2716
+ { name: "AES-GCM", iv: new Uint8Array(fromBase64(record.iv)) },
2717
+ record.key,
2718
+ new Uint8Array(fromBase64(record.ciphertext))
2719
+ );
2720
+ return deserializeSessionPlaintext(new Uint8Array(plaintextBytes));
2721
+ } catch {
2722
+ await clearSessionCacheRecord(options).catch(() => void 0);
2723
+ return null;
2724
+ }
2725
+ }
2726
+ async function clearUnlockedSession(options = {}) {
2727
+ await clearSessionCacheRecord(options);
2728
+ }
2616
2729
 
2617
2730
  // src/embeddedWallet/lockout.ts
2618
2731
  var PASSCODE_LOCKOUT_FAILURE_THRESHOLD = 5;
@@ -2905,24 +3018,25 @@ async function encryptPlaintextWithPasskeyRegistration(plaintext, registration,
2905
3018
  return { address: account.address, vault };
2906
3019
  }
2907
3020
  async function unlockVaultToSession(vault, options = {}) {
3021
+ const scopeId = scopeFromOptions(options);
3022
+ let plaintext;
2908
3023
  if (vaultUsesPasscodeUnlock(vault)) {
2909
- const plaintext2 = await decryptVaultWithPasscodeProtected(vault, options.passcode);
2910
- const signer2 = await embeddedPlaintextToSigner(plaintext2);
2911
- const [account2] = await signer2.getAccounts();
2912
- const session2 = { address: account2.address, vault, signer: signer2 };
2913
- activeSession = session2;
2914
- activeScopeId = scopeFromOptions(options);
2915
- return session2;
2916
- }
2917
- const credentialId = decodeCredentialId(vault.credentialId);
2918
- const prfSalt = vault.prfSalt ? decodeCredentialId(vault.prfSalt) : void 0;
2919
- const assertion = await assertPasskey({ credentialId, rpId: void 0, prfSalt });
2920
- const plaintext = await decryptVaultWithUnlockMaterial(vault, void 0, assertion);
3024
+ plaintext = await decryptVaultWithPasscodeProtected(vault, options.passcode);
3025
+ } else {
3026
+ const credentialId = decodeCredentialId(vault.credentialId);
3027
+ const prfSalt = vault.prfSalt ? decodeCredentialId(vault.prfSalt) : void 0;
3028
+ const assertion = await assertPasskey({ credentialId, rpId: void 0, prfSalt });
3029
+ plaintext = await decryptVaultWithUnlockMaterial(vault, void 0, assertion);
3030
+ }
2921
3031
  const signer = await embeddedPlaintextToSigner(plaintext);
2922
3032
  const [account] = await signer.getAccounts();
2923
3033
  const session = { address: account.address, vault, signer };
2924
3034
  activeSession = session;
2925
- activeScopeId = scopeFromOptions(options);
3035
+ activeScopeId = scopeId;
3036
+ try {
3037
+ await cacheUnlockedSession({ scopeId, plaintext });
3038
+ } catch {
3039
+ }
2926
3040
  return session;
2927
3041
  }
2928
3042
  async function hasEmbeddedWallet(options = {}) {
@@ -3084,9 +3198,33 @@ async function unlockEmbeddedWallet(options = {}) {
3084
3198
  }
3085
3199
  return unlockVaultToSession(vault, options);
3086
3200
  }
3201
+ async function tryRestoreUnlockedSession(options = {}) {
3202
+ const scopeId = scopeFromOptions(options) ?? activeScopeId;
3203
+ const plaintext = await restoreCachedSessionPlaintext({ scopeId });
3204
+ if (!plaintext) {
3205
+ return null;
3206
+ }
3207
+ const vault = await loadVaultForScope(scopeId);
3208
+ if (!vault) {
3209
+ await clearUnlockedSession({ scopeId }).catch(() => void 0);
3210
+ return null;
3211
+ }
3212
+ const signer = await embeddedPlaintextToSigner(plaintext);
3213
+ const [account] = await signer.getAccounts();
3214
+ if (account.address !== vault.publicAddress) {
3215
+ await clearUnlockedSession({ scopeId }).catch(() => void 0);
3216
+ return null;
3217
+ }
3218
+ const session = { address: account.address, vault, signer };
3219
+ activeSession = session;
3220
+ activeScopeId = scopeId;
3221
+ return session;
3222
+ }
3087
3223
  function lockEmbeddedWallet() {
3224
+ const scopeId = activeScopeId;
3088
3225
  activeSession = null;
3089
3226
  activeScopeId = void 0;
3227
+ void clearUnlockedSession({ scopeId }).catch(() => void 0);
3090
3228
  }
3091
3229
  function getEmbeddedWalletSession() {
3092
3230
  return activeSession;
@@ -3141,6 +3279,7 @@ async function importEmbeddedBackup(json, options = {}) {
3141
3279
  async function clearEmbeddedWallet(options = {}) {
3142
3280
  const scopeId = scopeFromOptions(options) ?? activeScopeId;
3143
3281
  lockEmbeddedWallet();
3282
+ await clearUnlockedSession({ scopeId });
3144
3283
  await clearVaultFromIndexedDb({ scopeId });
3145
3284
  }
3146
3285
 
@@ -3423,6 +3562,6 @@ function sleep(ms) {
3423
3562
  return new Promise((resolve) => setTimeout(resolve, ms));
3424
3563
  }
3425
3564
 
3426
- export { ATTESTATION_TYPE_CITIZENSHIP_APPLICATION, ATTESTATION_TYPE_RECOVERY, ApplicationStatus, BECH32_PREFIX, CHAIN_COIN_TYPE, CitizenTxError, DEFAULT_CHAIN_ID, DEFAULT_REST_URL, DEFAULT_RPC_URL, EMBEDDED_WALLET_KDF_PBKDF2, EMBEDDED_WALLET_KDF_PIN, EMBEDDED_WALLET_KDF_PRF, EMBEDDED_WALLET_KEY_DIRECT_ENTROPY, EMBEDDED_WALLET_KEY_HD_DERIVED, EMBEDDED_WALLET_PASSCODE_MAX_LENGTH, EMBEDDED_WALLET_PASSCODE_MIN_LENGTH, EMBEDDED_WALLET_PASSKEY_PBKDF2_ITERATIONS, EMBEDDED_WALLET_PIN_PBKDF2_ITERATIONS, EMBEDDED_WALLET_RECOVERY_PHRASE_DIRECT_ENTROPY_WARNING, EMBEDDED_WALLET_RECOVERY_PHRASE_GENERAL_WARNING, EMBEDDED_WALLET_VAULT_VERSION, EmbeddedWalletBackupRequiredError, EmbeddedWalletDecryptError, EmbeddedWalletLockoutError, EmbeddedWalletVaultError, EmbeddedWalletWeakPasscodeError, InvalidChainConfigError, MsgClaimReward, MsgSubmitApplication, MsgSubmitRecoveryAttestation, PASSCODE_LOCKOUT_FAILURE_THRESHOLD, PASSCODE_LOCKOUT_INITIAL_MS, PASSCODE_LOCKOUT_MAX_MS, RecoveryAttestationStatus, RestQueryError, RpcConnectionError, UKDR_DECIMALS, UKDR_DISPLAY_DENOM, UKDR_MINIMAL_DENOM, VAULT_LEGACY_KEY, WALLETCONNECT_COSMOS_METHODS, WALLETCONNECT_COSMOS_NAMESPACE, WEBAUTHN_RP_NAME, WalletAccountError, WalletConnectNotInitializedError, WalletConnectSessionError, WalletConnectSigningError, WalletConnectionError, WalletConnectionRejectedError, WalletNotInstalledError, WebAuthnUnavailableError, WebAuthnUserCancelledError, acknowledgeEmbeddedBackup, addressFromHdMnemonic, addressFromPrivateKey, assertPasscodeAllowedForCreation, assertPasscodeUnlockAllowed, assertPasskey, assertValidPasscode, assertValidRecoveryMnemonic, assertVaultPermitsTransaction, attestationSignPayload, broadcastAndConfirmTx, buildClaimRewardMsg, buildKingdomChainInfo, buildRequiredCosmosNamespaces, buildSendUkdrMsg, buildSubmitApplicationMsg, citizenTxErrorMessage, clearEmbeddedWallet, clearPasscodeLockoutRecord, clearVaultFromIndexedDb, computePasscodeLockoutDurationMs, connectCosmostation, connectKeplr, connectLeap, connectWalletConnect, createBrowserSigningClient, createEmbeddedWallet, createHdDerivedPlaintext, createKingdomChainRegistry, createPasskeyMaterialFromAssertion, createPbkdf2Salt, createWalletConnectOfflineSigner, decodeCredentialId, decodeDirectEntropyMnemonic, decryptWalletPayload, defaultEmbeddedHdPath, defaultUkdrTxFee, deriveKekFromPasscode, deriveKekFromPbkdf2, deriveKekFromPrf, derivePrivateKeyFromHdMnemonic, detectRecoveryMnemonicKeyType, detectWebAuthnPrfCapabilities, disconnectWalletConnect, downloadEmbeddedBackupFile, embeddedPlaintextToSigner, enableEmbeddedPasskeyUnlock, encodeCredentialId, encodeDirectEntropyMnemonic, encryptWalletPayload, evaluatePasscodeStrength, exportEncryptedBackup, fetchFeeGrantGranter, fetchUkdrBalance, fetchUnclaimedFinalizedRewards, formatUkdrAsKdr, getCosmostationKeplrApi, getEmbeddedOfflineSigner, getEmbeddedWalletSession, getPasscodeLockoutState, hasEmbeddedWallet, hasLegacyEmbeddedWallet, hasMixedCharacterClasses, importEmbeddedBackup, initWalletConnectClient, isCosmostationAvailable, isKeplrAvailable, isLeapAvailable, loadPasscodeLockoutRecord, loadVaultFromIndexedDb, lockEmbeddedWallet, markVaultBackupAcknowledged, migrateLegacyEmbeddedWallet, normalizePasscode, normalizeRecoveryMnemonic, parseEncryptedBackup, parseKdrToUkdr, parseWalletConnectAccount, plaintextFromRecoveryMnemonic, providerSeedFromHex, publicKeyFromPrivateSeed, readPrfOutput, recordPasscodeUnlockFailure, recordPasscodeUnlockSuccess, recoverEmbeddedWalletFromMnemonic, recoveryMnemonicAddress, recoveryMnemonicFromPlaintext, registerPasskey, resolvePlaintextKeyType, resolveVaultStorageKey, restoreWalletConnectSession, revealEmbeddedRecoveryPhrase, savePasscodeLockoutRecord, saveVaultToIndexedDb, selectEmbeddedWalletKdf, serializeBackupFile, signAttestationPayload, signCitizenshipAttestation, suggestAndConnect, toWalletConnectCosmosChainId, ukdrCoin, unlockEmbeddedWallet, validateChainConfig, vaultUsesPasscodeUnlock, vaultUsesPasskeyUnlock };
3565
+ export { ATTESTATION_TYPE_CITIZENSHIP_APPLICATION, ATTESTATION_TYPE_RECOVERY, ApplicationStatus, BECH32_PREFIX, CHAIN_COIN_TYPE, CitizenTxError, DEFAULT_CHAIN_ID, DEFAULT_REST_URL, DEFAULT_RPC_URL, EMBEDDED_WALLET_KDF_PBKDF2, EMBEDDED_WALLET_KDF_PIN, EMBEDDED_WALLET_KDF_PRF, EMBEDDED_WALLET_KEY_DIRECT_ENTROPY, EMBEDDED_WALLET_KEY_HD_DERIVED, EMBEDDED_WALLET_PASSCODE_MAX_LENGTH, EMBEDDED_WALLET_PASSCODE_MIN_LENGTH, EMBEDDED_WALLET_PASSKEY_PBKDF2_ITERATIONS, EMBEDDED_WALLET_PIN_PBKDF2_ITERATIONS, EMBEDDED_WALLET_RECOVERY_PHRASE_DIRECT_ENTROPY_WARNING, EMBEDDED_WALLET_RECOVERY_PHRASE_GENERAL_WARNING, EMBEDDED_WALLET_SESSION_TTL_MS, EMBEDDED_WALLET_VAULT_VERSION, EmbeddedWalletBackupRequiredError, EmbeddedWalletDecryptError, EmbeddedWalletLockoutError, EmbeddedWalletVaultError, EmbeddedWalletWeakPasscodeError, InvalidChainConfigError, MsgClaimReward, MsgSubmitApplication, MsgSubmitRecoveryAttestation, PASSCODE_LOCKOUT_FAILURE_THRESHOLD, PASSCODE_LOCKOUT_INITIAL_MS, PASSCODE_LOCKOUT_MAX_MS, RecoveryAttestationStatus, RestQueryError, RpcConnectionError, UKDR_DECIMALS, UKDR_DISPLAY_DENOM, UKDR_MINIMAL_DENOM, VAULT_LEGACY_KEY, WALLETCONNECT_COSMOS_METHODS, WALLETCONNECT_COSMOS_NAMESPACE, WEBAUTHN_RP_NAME, WalletAccountError, WalletConnectNotInitializedError, WalletConnectSessionError, WalletConnectSigningError, WalletConnectionError, WalletConnectionRejectedError, WalletNotInstalledError, WebAuthnUnavailableError, WebAuthnUserCancelledError, acknowledgeEmbeddedBackup, addressFromHdMnemonic, addressFromPrivateKey, assertPasscodeAllowedForCreation, assertPasscodeUnlockAllowed, assertPasskey, assertValidPasscode, assertValidRecoveryMnemonic, assertVaultPermitsTransaction, attestationSignPayload, broadcastAndConfirmTx, buildClaimRewardMsg, buildKingdomChainInfo, buildRequiredCosmosNamespaces, buildSendUkdrMsg, buildSubmitApplicationMsg, cacheUnlockedSession, citizenTxErrorMessage, clearEmbeddedWallet, clearPasscodeLockoutRecord, clearSessionCacheRecord, clearUnlockedSession, clearVaultFromIndexedDb, computePasscodeLockoutDurationMs, connectCosmostation, connectKeplr, connectLeap, connectWalletConnect, createBrowserSigningClient, createEmbeddedWallet, createHdDerivedPlaintext, createKingdomChainRegistry, createPasskeyMaterialFromAssertion, createPbkdf2Salt, createWalletConnectOfflineSigner, decodeCredentialId, decodeDirectEntropyMnemonic, decryptWalletPayload, defaultEmbeddedHdPath, defaultUkdrTxFee, deriveKekFromPasscode, deriveKekFromPbkdf2, deriveKekFromPrf, derivePrivateKeyFromHdMnemonic, detectRecoveryMnemonicKeyType, detectWebAuthnPrfCapabilities, disconnectWalletConnect, downloadEmbeddedBackupFile, embeddedPlaintextToSigner, enableEmbeddedPasskeyUnlock, encodeCredentialId, encodeDirectEntropyMnemonic, encryptWalletPayload, evaluatePasscodeStrength, exportEncryptedBackup, fetchFeeGrantGranter, fetchUkdrBalance, fetchUnclaimedFinalizedRewards, formatUkdrAsKdr, getCosmostationKeplrApi, getEmbeddedOfflineSigner, getEmbeddedWalletSession, getPasscodeLockoutState, hasEmbeddedWallet, hasLegacyEmbeddedWallet, hasMixedCharacterClasses, importEmbeddedBackup, initWalletConnectClient, isCosmostationAvailable, isKeplrAvailable, isLeapAvailable, loadPasscodeLockoutRecord, loadSessionCacheRecord, loadVaultFromIndexedDb, lockEmbeddedWallet, markVaultBackupAcknowledged, migrateLegacyEmbeddedWallet, normalizePasscode, normalizeRecoveryMnemonic, parseEncryptedBackup, parseKdrToUkdr, parseWalletConnectAccount, plaintextFromRecoveryMnemonic, providerSeedFromHex, publicKeyFromPrivateSeed, readPrfOutput, recordPasscodeUnlockFailure, recordPasscodeUnlockSuccess, recoverEmbeddedWalletFromMnemonic, recoveryMnemonicAddress, recoveryMnemonicFromPlaintext, registerPasskey, resolvePlaintextKeyType, resolveVaultStorageKey, restoreCachedSessionPlaintext, restoreWalletConnectSession, revealEmbeddedRecoveryPhrase, savePasscodeLockoutRecord, saveSessionCacheRecord, saveVaultToIndexedDb, selectEmbeddedWalletKdf, serializeBackupFile, signAttestationPayload, signCitizenshipAttestation, suggestAndConnect, toWalletConnectCosmosChainId, tryRestoreUnlockedSession, ukdrCoin, unlockEmbeddedWallet, validateChainConfig, vaultUsesPasscodeUnlock, vaultUsesPasskeyUnlock };
3427
3566
  //# sourceMappingURL=index.js.map
3428
3567
  //# sourceMappingURL=index.js.map