// High-level wallet account operations shared by the join, recover and login // flows. These compose the low-level primitives (derive / crypto / store) with the // browser-native bus session so the page components stay thin. import { bus } from "../busService"; import type { User } from "../types"; import { decryptJSON, encryptJSON } from "./crypto"; import type { WalletIdentity } from "./derive"; import { getIdentity, putIdentity, type StoredIdentity } from "./store"; // saveAndOpen encrypts the identity under `password`, stores it on this device, and // opens a bus session as that user. Used by join (new identity) and recover // (re-derived identity): both end with a locally-encrypted key plus a live session. // The mnemonic/seed is NOT touched here — only the derived keypair is persisted // (encrypted). The private key is used to open the session IN THE BROWSER and is // never sent to any server (unlike the old gateway model). export async function saveAndOpen( identity: WalletIdentity, handle: string, password: string, remember = false, ): Promise { const enc = await encryptJSON(identity, password); await putIdentity({ handle, signPub: identity.signPub, kexPub: identity.kexPub, enc, createdAt: Date.now(), }); return bus.openSession(identity, handle, remember); } // unlockAndOpen reads this device's stored identity, decrypts the private key with // `password`, and opens a bus session locally. Throws WrongPasswordError on a bad // password (GCM auth failure) and NoLocalIdentityError if the device has none. export async function unlockAndOpen(password: string, remember = false): Promise { const stored = await getIdentity(); if (!stored) throw new NoLocalIdentityError(); const identity = await decryptJSON(stored.enc, password); return bus.openSession(identity, stored.handle, remember); } // localIdentity returns the device's stored identity record (or null), for the // router to decide between the password-unlock screen and the welcome screen, and // to greet the user by handle before unlocking. export async function localIdentity(): Promise { return getIdentity(); } export class NoLocalIdentityError extends Error { constructor() { super("no local identity on this device"); this.name = "NoLocalIdentityError"; } }