@waaskey/sdk 0.3.2 → 0.4.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/analytics/analytics.ts","../src/analytics/http-sink.ts","../src/errors.ts","../src/auth.ts","../src/balances/evm-provider.ts","../src/balances/format.ts","../src/balances/balances.ts","../src/broadcast.ts","../src/http.ts","../src/members.ts","../src/onramp.ts","../src/storage/crypto.ts","../src/recovery.ts","../src/chains.ts","../src/internal.ts","../src/reshare.ts","../src/custody.ts","../src/eddsa-share.ts","../src/enc-keys.ts","../src/session-sign.ts","../src/share-blob.ts","../src/passkey/assertion.ts","../src/wallet.ts","../src/wallets.ts","../src/client.ts","../src/mpc/wasm-core.ts","../src/mpc/load-wasm.ts","../src/mpc/prime-pool.ts","../src/storage/indexeddb-store.ts","../src/storage/encrypted-share-store.ts","../src/storage/memory-store.ts","../src/passkey/prf.ts"],"names":["x25519","bytesToBase64","base64ToBytes"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AnalyticsEvent, AnalyticsEventType, AnalyticsSink } from './types';\n\n/**\n * Emits lifecycle events to a {@link AnalyticsSink}; a no-op when analytics is disabled (no sink).\n * Fire-and-forget and exception-safe — analytics must NEVER break or slow a wallet operation.\n */\nexport class Analytics {\n constructor(private readonly sink?: AnalyticsSink) {}\n\n track(type: AnalyticsEventType, props: Omit<AnalyticsEvent, 'type' | 'timestamp'> = {}): void {\n if (!this.sink) return;\n try {\n this.sink.track({ type, timestamp: new Date().toISOString(), ...props });\n } catch {\n // Swallow — a broken analytics sink must not surface to the caller.\n }\n }\n}\n","import type { HttpClient } from '../http';\nimport type { AnalyticsEvent, AnalyticsSink } from './types';\n\n/** Default sink: POST events to the Waaskey API, fire-and-forget — delivery failures are swallowed. */\nexport class HttpAnalyticsSink implements AnalyticsSink {\n constructor(private readonly http: HttpClient) {}\n\n track(event: AnalyticsEvent): void {\n void this.http.request<unknown>('POST', '/v1/analytics/events', event).catch(() => undefined);\n }\n}\n","/**\n * Structured error model for the SDK.\n *\n * Every failure surfaces as a {@link WaaskeyError} carrying a typed {@link WaaskeyErrorCode}\n * — never a bare string — so callers can branch on `error.code` instead of matching\n * message text. Transport/HTTP failures map the API's error envelope\n * (`{ statusCode, message, error }`) to a code; orchestration failures (device keygen,\n * missing share, cancellation) use the SDK-side codes.\n */\n\nexport type WaaskeyErrorCode =\n // Transport / HTTP (mapped from the API response status).\n | 'unauthorized' // 401 — missing/invalid API key\n | 'forbidden' // 403 — key scope or policy denied the action\n | 'not_found' // 404 — resource (e.g. wallet) does not exist for this tenant\n | 'validation' // 400 — request failed validation\n | 'conflict' // 409 — e.g. signing a wallet that is not active\n | 'rate_limited' // 429 — throttled\n | 'server_error' // 5xx — upstream/server failure\n | 'network' // fetch threw (offline, DNS, CORS, …)\n // SDK orchestration (client-side).\n | 'unsupported_chain' // no signing curve / chain provider for the requested chain\n | 'provider_error' // a chain RPC provider call failed (balances)\n | 'device_core_required' // create needs a configured MpcCore + ShareStore\n | 'keygen_failed' // the device half of the keygen ceremony failed\n | 'sign_failed' // the device half of an n-party (member-bound) sign ceremony failed\n | 'reshare_failed' // the device half of a reshare completion (assemble / aux ceremony) failed\n | 'reshare_pubkey_mismatch' // the completed reshared share reproduced a DIFFERENT public key — aborted (funds-safety)\n | 'share_not_found' // no stored device share for the wallet (or no registered user_backup backup)\n | 'recovery_failed' // could not decrypt the recovery share (wrong recovery code?)\n | 'invalid_recovery_code' // the recovery code could not open the sealed user_backup backup (device-loss recover-sign, #351/#78)\n | 'backup_failed' // the user_backup share was keygen'd + sealed locally but its server-side registration failed — retry with wallets.retryBackup(walletId)\n | 'wallet_activation_timeout' // keygen did not finish (wallet stayed PENDING)\n | 'sign_ceremony_timeout' // the t-of-n quorum did not fix (or select this member) before the timeout\n | 'unauthenticated' // no end-user session — call auth.email.verify(...) first\n | 'firebase_not_enabled' // 412 — embedded Firebase sign-in is not enabled for this tenant\n | 'mfa_required' // 401 — a 2FA member's Firebase token did not pass a second factor\n | 'no_member' // 401 — no org member exists for the Firebase identity (never self-provisioned)\n | 'unsupported' // a capability isn't available in this runtime (e.g. passkeys without @simplewebauthn/browser)\n | 'aborted' // cancelled via an AbortSignal\n | 'unknown';\n\nexport interface WaaskeyErrorOptions {\n /** HTTP status, when the error originates from an API response. */\n status?: number;\n /** Raw error payload from the API (or other context), for debugging. */\n details?: unknown;\n /** The underlying error that triggered this one. */\n cause?: unknown;\n}\n\n/** The single error type thrown by the SDK. */\nexport class WaaskeyError extends Error {\n readonly code: WaaskeyErrorCode;\n readonly status?: number;\n readonly details?: unknown;\n\n constructor(message: string, code: WaaskeyErrorCode, options: WaaskeyErrorOptions = {}) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = 'WaaskeyError';\n this.code = code;\n this.status = options.status;\n this.details = options.details;\n }\n}\n\nconst STATUS_CODES: Record<number, WaaskeyErrorCode> = {\n 400: 'validation',\n 401: 'unauthorized',\n 403: 'forbidden',\n 404: 'not_found',\n 409: 'conflict',\n 429: 'rate_limited',\n};\n\n/** Map an API error response (status + parsed body) to a typed {@link WaaskeyError}. */\nexport function errorFromResponse(status: number, body: unknown): WaaskeyError {\n const code: WaaskeyErrorCode = STATUS_CODES[status] ?? (status >= 500 ? 'server_error' : 'unknown');\n return new WaaskeyError(messageFromBody(body, status), code, { status, details: body });\n}\n\n/** The API envelope is `{ statusCode, message, error }`; `message` may be a string or string[] (validation). */\nfunction messageFromBody(body: unknown, status: number): string {\n if (body && typeof body === 'object') {\n const { message, error } = body as { message?: unknown; error?: unknown };\n if (Array.isArray(message)) return message.filter((m): m is string => typeof m === 'string').join('; ');\n if (typeof message === 'string' && message) return message;\n if (typeof error === 'string' && error) return error;\n }\n return `Request failed with status ${status}`;\n}\n","import { WaaskeyError } from './errors';\nimport type { HttpClient } from './http';\nimport type { EmailStartResult, EmbeddedSession, EndUser } from './types';\n\n/**\n * Embedded end-user authentication (#6) — Privy-style login that maps an end-user to a\n * non-custodial wallet, distinct from the dashboard member auth. The developer's API key\n * authorizes the flow; a successful login yields an end-user **session token** the SDK\n * holds and sends on end-user-scoped calls.\n *\n * Methods (email-OTP, phone-OTP, …) live behind the same `auth` surface and all establish\n * the same session; social / passkey are added the same way.\n */\nexport class Auth {\n private current?: EmbeddedSession;\n\n constructor(private readonly http: HttpClient) {}\n\n /** Email one-time-code login. */\n readonly email = {\n /** Send a login code to `email`. */\n start: (email: string, signal?: AbortSignal): Promise<EmailStartResult> => this.http.request<EmailStartResult>('POST', '/v1/embedded/auth/email/start', { email }, signal),\n /** Verify the code; on success the end-user is provisioned and the session is established. */\n verify: (email: string, code: string, signal?: AbortSignal): Promise<EmbeddedSession> => this.establish('/v1/embedded/auth/email/verify', { email, code }, signal),\n };\n\n /** Phone one-time-code (SMS) login. `phone` is E.164, e.g. `+14155550123`. */\n readonly phone = {\n /** Send a login code to `phone`. */\n start: (phone: string, signal?: AbortSignal): Promise<EmailStartResult> => this.http.request<EmailStartResult>('POST', '/v1/embedded/auth/phone/start', { phone }, signal),\n /** Verify the code; on success the end-user is provisioned and the session is established. */\n verify: (phone: string, code: string, signal?: AbortSignal): Promise<EmbeddedSession> => this.establish('/v1/embedded/auth/phone/verify', { phone, code }, signal),\n };\n\n /** Social / federated-provider login. */\n readonly social = {\n /**\n * Exchange a Google ID token (obtained on the client via Google Identity Services) for a\n * session. Requires the tenant's Google client id to be configured server-side.\n */\n google: (idToken: string, signal?: AbortSignal): Promise<EmbeddedSession> => this.establish('/v1/embedded/auth/social/google', { idToken }, signal),\n /**\n * Exchange a Firebase ID token (obtained on the client via the Firebase Auth SDK) for a session\n * — the Firebase analogue of {@link social.google}. Requires the tenant to have opted into\n * embedded Firebase sign-in (`firebaseAuthEnabled`); when it hasn't, the API replies 412 and the\n * SDK surfaces a typed `firebase_not_enabled` {@link WaaskeyError}.\n */\n firebase: (idToken: string, signal?: AbortSignal): Promise<EmbeddedSession> =>\n this.establish('/v1/embedded/auth/firebase', { idToken }, signal).catch((error: unknown) => {\n if (error instanceof WaaskeyError && error.status === 412) {\n throw new WaaskeyError('Firebase sign-in is not enabled for this tenant.', 'firebase_not_enabled', { status: 412, cause: error, details: error.details });\n }\n throw error;\n }),\n };\n\n /**\n * Passkey (WebAuthn) login. `register` adds a passkey to the **currently logged-in** end-user;\n * `login` is usernameless (a passkey assertion resolves the user and establishes a session).\n *\n * The browser ceremony uses `@simplewebauthn/browser` (an optional peer dependency, loaded on\n * demand). Pass a `ceremony` to override it — e.g. on React Native with a native authenticator.\n */\n readonly passkey = {\n /** Add a passkey to the logged-in end-user. Requires an active session. */\n register: async (ceremony?: PasskeyCeremony): Promise<void> => {\n const token = this.requireToken();\n const options = await this.http.request<unknown>('POST', '/v1/embedded/auth/passkey/register/options', undefined, undefined, token);\n const response = await (ceremony ?? (await defaultCeremony())).create(options);\n await this.http.request<void>('POST', '/v1/embedded/auth/passkey/register/verify', { response }, undefined, token);\n },\n /** Usernameless passkey login — establishes the session on success. */\n login: async (ceremony?: PasskeyCeremony): Promise<EmbeddedSession> => {\n const { challengeId, options } = await this.http.request<PasskeyLoginOptions>('POST', '/v1/embedded/auth/passkey/login/options', {});\n const response = await (ceremony ?? (await defaultCeremony())).get(options);\n return this.establish('/v1/embedded/auth/passkey/login/verify', { challengeId, response } as unknown as Record<string, string>);\n },\n };\n\n /** The active session, or `undefined` when not logged in. */\n get session(): EmbeddedSession | undefined {\n return this.current;\n }\n\n /** The end-user session token, or `undefined` when not logged in. */\n get token(): string | undefined {\n return this.current?.token;\n }\n\n /** Whether an end-user is currently logged in. */\n get isAuthenticated(): boolean {\n return this.current !== undefined;\n }\n\n /** The logged-in end-user (re-fetched from the session token). Rejects if not logged in. */\n async me(signal?: AbortSignal): Promise<EndUser> {\n return this.http.request<EndUser>('GET', '/v1/embedded/auth/me', undefined, signal, this.requireToken());\n }\n\n /** Restore a session from a previously stored token (e.g. across reloads). */\n restore(session: EmbeddedSession): void {\n this.current = session;\n }\n\n /** Clear the session (sign out). */\n logout(): void {\n this.current = undefined;\n }\n\n /** POST a verify request, store the resulting session, and return it. */\n private async establish(path: string, body: Record<string, unknown>, signal?: AbortSignal): Promise<EmbeddedSession> {\n const session = await this.http.request<EmbeddedSession>('POST', path, body, signal);\n this.current = session;\n return session;\n }\n\n private requireToken(): string {\n if (!this.current) throw new WaaskeyError('Not authenticated — verify a login code first.', 'unauthenticated');\n return this.current.token;\n }\n}\n\n/** WebAuthn options + the id under which the server tracked the login challenge. */\ninterface PasskeyLoginOptions {\n challengeId: string;\n options: unknown;\n}\n\n/**\n * The browser WebAuthn ceremony. Defaults to `@simplewebauthn/browser`; override for non-DOM\n * runtimes (e.g. a React Native native-passkey module). `create` runs registration\n * (navigator.credentials.create), `get` runs authentication (navigator.credentials.get).\n */\nexport interface PasskeyCeremony {\n create(options: unknown): Promise<unknown>;\n get(options: unknown): Promise<unknown>;\n}\n\n/** Lazily load `@simplewebauthn/browser` and adapt it to {@link PasskeyCeremony}. */\nasync function defaultCeremony(): Promise<PasskeyCeremony> {\n let mod: typeof import('@simplewebauthn/browser');\n try {\n mod = await import('@simplewebauthn/browser');\n } catch {\n throw new WaaskeyError('Passkeys need \"@simplewebauthn/browser\" installed, or pass a custom ceremony.', 'unsupported');\n }\n return {\n create: (options) => mod.startRegistration({ optionsJSON: options as Parameters<typeof mod.startRegistration>[0]['optionsJSON'] }),\n get: (options) => mod.startAuthentication({ optionsJSON: options as Parameters<typeof mod.startAuthentication>[0]['optionsJSON'] }),\n };\n}\n","import { WaaskeyError } from '../errors';\nimport type { ChainProvider } from './types';\n\n// ERC-20 function selectors.\nconst SELECTOR_BALANCE_OF = '0x70a08231'; // balanceOf(address)\nconst SELECTOR_DECIMALS = '0x313ce567'; // decimals()\n\n/**\n * {@link ChainProvider} backed by an EVM JSON-RPC endpoint (`eth_getBalance`,\n * `eth_call`). Reads are dApp-style and need no backend. A custom `fetch` can be\n * injected (non-browser runtimes / tests).\n */\nexport class EvmRpcProvider implements ChainProvider {\n private readonly fetchImpl: typeof fetch;\n\n constructor(\n private readonly rpcUrl: string,\n fetchImpl?: typeof fetch,\n ) {\n const resolved = fetchImpl ?? globalThis.fetch;\n if (!resolved) throw new WaaskeyError('No fetch implementation for the EVM provider.', 'provider_error');\n this.fetchImpl = resolved.bind(globalThis);\n }\n\n async getNativeBalance(address: string): Promise<bigint> {\n return this.toBigInt(await this.call('eth_getBalance', [address, 'latest']));\n }\n\n async getTokenBalance(token: string, owner: string): Promise<bigint> {\n const data = SELECTOR_BALANCE_OF + padAddress(owner);\n return this.toBigInt(await this.call('eth_call', [{ to: token, data }, 'latest']));\n }\n\n async getTokenDecimals(token: string): Promise<number> {\n const result = await this.call('eth_call', [{ to: token, data: SELECTOR_DECIMALS }, 'latest']);\n return result === '0x' || result === undefined ? 18 : Number(this.toBigInt(result));\n }\n\n private async call(method: string, params: unknown[]): Promise<string | undefined> {\n let res: Response;\n try {\n res = await this.fetchImpl(this.rpcUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),\n });\n } catch (cause) {\n throw new WaaskeyError(`Chain RPC request failed (${method}).`, 'provider_error', { cause });\n }\n if (!res.ok) throw new WaaskeyError(`Chain RPC returned ${res.status} (${method}).`, 'provider_error', { status: res.status });\n\n const json = (await res.json().catch(() => ({}))) as { result?: string; error?: { message?: string } };\n if (json.error) throw new WaaskeyError(`Chain RPC error (${method}): ${json.error.message ?? 'unknown'}.`, 'provider_error', { details: json.error });\n return json.result;\n }\n\n private toBigInt(hex: string | undefined): bigint {\n return hex && hex !== '0x' ? BigInt(hex) : 0n;\n }\n}\n\n/** 20-byte address → 32-byte left-padded hex (no `0x`), for ABI encoding. */\nfunction padAddress(address: string): string {\n return address.replace(/^0x/i, '').toLowerCase().padStart(64, '0');\n}\n","/** Render a base-unit integer as a decimal string (e.g. `formatUnits(1500000n, 6)` → `\"1.5\"`). No float. */\nexport function formatUnits(raw: bigint, decimals: number): string {\n if (decimals === 0) return raw.toString();\n const negative = raw < 0n;\n const value = negative ? -raw : raw;\n const base = 10n ** BigInt(decimals);\n const whole = value / base;\n const fraction = (value % base).toString().padStart(decimals, '0').replace(/0+$/, '');\n const text = fraction ? `${whole}.${fraction}` : `${whole}`;\n return negative ? `-${text}` : text;\n}\n","import { WaaskeyError } from '../errors';\nimport { EvmRpcProvider } from './evm-provider';\nimport { formatUnits } from './format';\nimport type { Chain } from '../types';\nimport type { Balance, ChainConfig, ChainProvider, TokenBalanceOptions } from './types';\n\ninterface NativeAsset {\n symbol: string;\n decimals: number;\n}\n\n/** Native asset (gas token) metadata per chain, for formatting native balances. */\nconst NATIVE_ASSETS: Record<Chain, NativeAsset> = {\n ethereum: { symbol: 'ETH', decimals: 18 },\n polygon: { symbol: 'POL', decimals: 18 },\n arbitrum: { symbol: 'ETH', decimals: 18 },\n base: { symbol: 'ETH', decimals: 18 },\n optimism: { symbol: 'ETH', decimals: 18 },\n bitcoin: { symbol: 'BTC', decimals: 8 },\n solana: { symbol: 'SOL', decimals: 9 },\n};\n\n/** EVM chains with a built-in public JSON-RPC default (overridable via config). */\nconst DEFAULT_EVM_RPC: Partial<Record<Chain, string>> = {\n ethereum: 'https://eth.llamarpc.com',\n polygon: 'https://polygon-rpc.com',\n arbitrum: 'https://arb1.arbitrum.io/rpc',\n base: 'https://mainnet.base.org',\n optimism: 'https://mainnet.optimism.io',\n};\n\nconst isEvm = (chain: Chain): boolean => chain in DEFAULT_EVM_RPC;\n\n/**\n * Reads balances directly from a chain provider (never the backend). EVM chains work\n * out of the box via a default public RPC; override per chain with `chains` (an RPC\n * URL or a custom {@link ChainProvider}), and supply a provider for non-EVM chains.\n */\nexport class Balances {\n private readonly providers = new Map<Chain, ChainProvider>();\n\n constructor(\n private readonly config: Partial<Record<Chain, ChainConfig>> = {},\n private readonly fetchImpl?: typeof fetch,\n ) {}\n\n /** Native (gas-token) balance of an address on a chain. */\n async getBalance(chain: Chain, address: string): Promise<Balance> {\n const { symbol, decimals } = NATIVE_ASSETS[chain];\n const raw = await this.provider(chain).getNativeBalance(address);\n return { raw, decimals, symbol, formatted: formatUnits(raw, decimals) };\n }\n\n /** Token balance of `owner` for `token` on a chain (ERC-20 on EVM). */\n async getTokenBalance(chain: Chain, token: string, owner: string, options: TokenBalanceOptions = {}): Promise<Balance> {\n const provider = this.provider(chain);\n const raw = await provider.getTokenBalance(token, owner);\n const decimals = options.decimals ?? (provider.getTokenDecimals ? await provider.getTokenDecimals(token) : 18);\n return { raw, decimals, symbol: options.symbol, formatted: formatUnits(raw, decimals) };\n }\n\n /** Resolve (and cache) the provider for a chain: custom → configured RPC → default EVM RPC. */\n private provider(chain: Chain): ChainProvider {\n const cached = this.providers.get(chain);\n if (cached) return cached;\n\n const cfg = this.config[chain];\n let provider: ChainProvider | undefined = cfg?.provider;\n if (!provider) {\n const rpcUrl = cfg?.rpcUrl ?? DEFAULT_EVM_RPC[chain];\n if (rpcUrl && isEvm(chain)) provider = new EvmRpcProvider(rpcUrl, this.fetchImpl);\n }\n if (!provider) {\n throw new WaaskeyError(`No chain provider configured for \"${chain}\". Pass chains: { ${chain}: { rpcUrl } } or a custom provider.`, 'unsupported_chain');\n }\n this.providers.set(chain, provider);\n return provider;\n }\n}\n","import { WaaskeyError } from './errors';\nimport type { BroadcastOptions, BroadcastResult } from './types';\n\n/**\n * **Optional** client-side broadcast helper.\n *\n * WaaS is a **signing service**, not a broadcaster: `wallet.send(...)` returns the\n * signed raw transaction (`signedTx`) and WaaS never submits it. Broadcasting,\n * nonce/mempool handling and status-tracking are the integrator's concern — that\n * is what non-custodial means. This helper is a thin convenience so you can submit\n * a signed tx from **your own** node/provider; it is deliberately best-effort:\n * one JSON-RPC call, **no status polling and no retries**. For production you will\n * usually broadcast (and track) with your own infra.\n *\n * Today it submits an EVM raw transaction via `eth_sendRawTransaction`. The node's\n * returned hash is passed through as {@link BroadcastResult.txHash}.\n */\nexport async function broadcast(signedTx: string, options: BroadcastOptions): Promise<BroadcastResult> {\n if (!signedTx) throw new WaaskeyError('`signedTx` is required to broadcast.', 'validation');\n if (!options?.rpcUrl) throw new WaaskeyError('`rpcUrl` is required — broadcast from your own node/provider.', 'validation');\n\n const fetchImpl = (options.fetch ?? globalThis.fetch)?.bind(globalThis);\n if (!fetchImpl) throw new WaaskeyError('No fetch implementation for broadcast — pass `fetch`.', 'provider_error');\n\n const rawTx = signedTx.startsWith('0x') ? signedTx : `0x${signedTx}`;\n\n let res: Response;\n try {\n res = await fetchImpl(options.rpcUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_sendRawTransaction', params: [rawTx] }),\n signal: options.signal,\n });\n } catch (cause) {\n if (options.signal?.aborted) throw new WaaskeyError('Broadcast aborted.', 'aborted', { cause });\n throw new WaaskeyError('Broadcast request failed.', 'provider_error', { cause });\n }\n if (!res.ok) throw new WaaskeyError(`Broadcast RPC returned ${res.status}.`, 'provider_error', { status: res.status });\n\n const json = (await res.json().catch(() => ({}))) as { result?: string; error?: { message?: string } };\n if (json.error) throw new WaaskeyError(`Broadcast rejected by the node: ${json.error.message ?? 'unknown'}.`, 'provider_error', { details: json.error });\n if (!json.result) throw new WaaskeyError('Broadcast returned no transaction hash.', 'provider_error');\n\n return { txHash: json.result };\n}\n","import { errorFromResponse, WaaskeyError } from './errors';\n\n/** Thin typed HTTP client over fetch — the single place requests are issued. */\nexport class HttpClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof fetch;\n private memberAccessToken?: () => string | undefined;\n\n constructor(apiKey: string, baseUrl: string, fetchImpl?: typeof fetch) {\n this.apiKey = apiKey;\n this.baseUrl = assertSecureBaseUrl(baseUrl).replace(/\\/$/, '');\n const resolved = fetchImpl ?? globalThis.fetch;\n if (!resolved) {\n throw new Error('No fetch implementation available — pass `fetch` in WaaskeyOptions.');\n }\n this.fetchImpl = resolved.bind(globalThis);\n }\n\n /**\n * Wire a provider of the held org-member access token (from {@link Members}). When it returns a\n * token, {@link requestAsMember} authenticates member calls with `Authorization: Bearer <token>`\n * rather than the ambient dashboard cookie. Injected by the client (not imported) so `Members` and\n * `HttpClient` don't form an import cycle.\n */\n useMemberAccessToken(provider: () => string | undefined): void {\n this.memberAccessToken = provider;\n }\n\n async request<T>(method: string, path: string, body?: unknown, signal?: AbortSignal, bearer?: string): Promise<T> {\n // `bearer` overrides the API key for end-user-scoped calls (embedded session token).\n return this.send<T>(method, path, { authorization: `Bearer ${bearer ?? this.apiKey}`, 'content-type': 'application/json' }, body, signal);\n }\n\n /**\n * `@Public` request: NO `Authorization` header and NO cookie. Used by the org-member Firebase\n * login exchange (`POST /v1/auth/firebase`), which authenticates from the Firebase ID token in the\n * body alone and returns the member bearer tokens in its response.\n */\n async requestPublic<T>(method: string, path: string, body?: unknown, signal?: AbortSignal): Promise<T> {\n return this.send<T>(method, path, { 'content-type': 'application/json' }, body, signal);\n }\n\n /**\n * Member-session request (#349). Authenticates as the org member in one of two ways, transparent\n * to the caller ({@link Wallets.joinCeremony} / {@link Wallets.joinSignCeremony}):\n *\n * - **Held bearer session** (a {@link memberAccessToken} provider returns a token — e.g. after\n * {@link Members.loginWithFirebase}): sends `Authorization: Bearer <accessToken>`. The backend's\n * `ApiKeyAuthGuard` recognises a non-API-key bearer and falls through to the member-session\n * resolver, so a headless (non-browser) consumer authenticates without a cookie.\n * - **No held session** (the browser dashboard path): sends NO `Authorization` header and\n * `credentials: 'include'`, relying on the caller's own same-site httpOnly member cookie. The\n * guard only falls back to the cookie resolver when the header is absent entirely, so it is\n * omitted here.\n *\n * Never used by the tenant-apiKey ({@link request}) or embedded-end-user paths.\n */\n async requestAsMember<T>(method: string, path: string, body?: unknown, signal?: AbortSignal): Promise<T> {\n const token = this.memberAccessToken?.();\n if (token) {\n return this.send<T>(method, path, { authorization: `Bearer ${token}`, 'content-type': 'application/json' }, body, signal);\n }\n return this.send<T>(method, path, { 'content-type': 'application/json' }, body, signal, 'include');\n }\n\n private async send<T>(method: string, path: string, headers: Record<string, string>, body: unknown, signal?: AbortSignal, credentials?: RequestCredentials): Promise<T> {\n let res: Response;\n try {\n res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n signal,\n ...(credentials === undefined ? {} : { credentials }),\n });\n } catch (cause) {\n if (signal?.aborted) throw new WaaskeyError('Request aborted.', 'aborted', { cause });\n throw new WaaskeyError('Network request failed.', 'network', { cause });\n }\n\n if (!res.ok) {\n const detail = await res.json().catch(() => ({}) as unknown);\n throw errorFromResponse(res.status, detail);\n }\n\n // Some endpoints (e.g. passkey register/verify) reply 200/204 with no body.\n const text = await res.text();\n return (text ? JSON.parse(text) : undefined) as T;\n }\n}\n\n/**\n * Enforce TLS on the API base URL (issue #41): the API key / bearer travels in the\n * `Authorization` header, so a plaintext `http://` origin would leak it. Only\n * `https://` is allowed, with `http://` permitted solely for loopback (local dev).\n */\nfunction assertSecureBaseUrl(baseUrl: string): string {\n let url: URL;\n try {\n url = new URL(baseUrl);\n } catch (cause) {\n throw new WaaskeyError(`Invalid API baseUrl \"${baseUrl}\" — expected an absolute URL.`, 'validation', { cause });\n }\n const isLoopback = url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.hostname === '[::1]' || url.hostname === '::1';\n if (url.protocol === 'https:') return baseUrl;\n if (url.protocol === 'http:' && isLoopback) return baseUrl;\n throw new WaaskeyError(`Insecure API baseUrl \"${baseUrl}\" — the API key would be sent in cleartext. Use https:// (http:// is allowed only for localhost).`, 'validation');\n}\n","import { WaaskeyError } from './errors';\nimport type { HttpClient } from './http';\nimport type { FirebaseAuthRequest, Member, MemberSession } from './types';\n\n/**\n * Org-member (dashboard \"plane B\") authentication — a bearer member login for a NON-browser\n * consumer (a Node app, or the browser extension via the SDK) that cannot carry the ambient\n * same-site dashboard session cookie the browser console relies on.\n *\n * {@link loginWithFirebase} exchanges a Firebase ID token at the `@Public` `POST /v1/auth/firebase`\n * (no API key, no cookie) for a member session `{ accessToken, refreshToken, member }`, which the\n * client HOLDS. Once held, member-scoped calls ({@link Wallets.joinCeremony} /\n * {@link Wallets.joinSignCeremony}, which go through {@link HttpClient.requestAsMember}) send\n * `Authorization: Bearer <accessToken>` rather than relying on the cookie — so a headless consumer\n * can drive the member-bound ceremonies.\n *\n * **Refresh is out of scope for now:** the SDK holds `refreshToken` but does not yet auto-refresh.\n * Once the access token expires a member call surfaces a 401 (`unauthorized`) error; a future\n * revision will exchange the refresh token at `/v1/auth/refresh` from here.\n */\nexport class Members {\n private held?: MemberSession;\n\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Exchange a Firebase ID token for an org-member session and hold it.\n *\n * The token must belong to an ALREADY-INVITED member — Firebase never self-provisions a member, so\n * an unknown email is rejected (`no_member`). A member with 2FA enrolled must present a Firebase\n * token that itself passed a second factor, or the login is refused (`mfa_required`).\n *\n * @throws {WaaskeyError} `no_member` — no org member exists for the token's Firebase identity (401).\n * @throws {WaaskeyError} `mfa_required` — the member needs a second factor the token didn't carry (401).\n */\n async loginWithFirebase(idToken: string, signal?: AbortSignal): Promise<MemberSession> {\n const body: FirebaseAuthRequest = { idToken };\n let session: MemberSession;\n try {\n session = await this.http.requestPublic<MemberSession>('POST', '/v1/auth/firebase', body, signal);\n } catch (error) {\n throw mapFirebaseMemberError(error);\n }\n this.held = session;\n return session;\n }\n\n /** The current member, or `undefined` when not logged in. */\n get member(): Member | undefined {\n return this.held?.member;\n }\n\n /** The held member session (access + refresh tokens + member), or `undefined` when not logged in. */\n get session(): MemberSession | undefined {\n return this.held;\n }\n\n /** The held member access token — the value the client wires into {@link HttpClient.requestAsMember}. */\n get accessToken(): string | undefined {\n return this.held?.accessToken;\n }\n\n /** Whether an org member is currently logged in over a held bearer session. */\n get isAuthenticated(): boolean {\n return this.held !== undefined;\n }\n\n /** Restore a previously stored member session (e.g. across process restarts). */\n restore(session: MemberSession): void {\n this.held = session;\n }\n\n /** Clear the held member session (sign out); member calls fall back to the cookie path afterwards. */\n memberSignOut(): void {\n this.held = undefined;\n }\n}\n\n/**\n * The member Firebase login rejects with 401 for BOTH \"no member for this email\" and \"second factor\n * required\" (and a handful of other link failures). Re-map the two the caller must branch on to\n * specific codes by the backend message; leave every other error unchanged (so an invalid/unverified\n * token stays a plain `unauthorized`).\n */\nfunction mapFirebaseMemberError(error: unknown): unknown {\n if (error instanceof WaaskeyError && error.status === 401) {\n const message = error.message.toLowerCase();\n if (message.includes('multi-factor') || message.includes('second factor')) {\n return new WaaskeyError(error.message, 'mfa_required', { status: 401, cause: error, details: error.details });\n }\n if (message.includes('no member account')) {\n return new WaaskeyError(error.message, 'no_member', { status: 401, cause: error, details: error.details });\n }\n }\n return error;\n}\n","import type { HttpClient } from './http';\nimport type { OnrampWidgetParams, OnrampWidgetUrl } from './types';\n\n/**\n * The `onramp` resource — fund an embedded wallet with fiat (card/bank) via a provider\n * (e.g. Transak). The SDK returns a provider widget URL to open; the purchase settles on\n * chain to the wallet address and the on-chain balance reflects it once the provider delivers.\n */\nexport class Onramp {\n constructor(private readonly http: HttpClient) {}\n\n /** Get a provider widget URL to buy `cryptoCurrency` on `chainId` for `walletAddress`. */\n widgetUrl(params: OnrampWidgetParams, signal?: AbortSignal): Promise<OnrampWidgetUrl> {\n return this.http.request<OnrampWidgetUrl>('POST', '/onramp/widget-url', params, signal);\n }\n}\n","/**\n * WebCrypto sealing primitives for the device share store.\n *\n * The encryption key is **derived** from a user/device secret via PBKDF2 (never\n * embedded in the bundle) with a per-store random salt, and shares are sealed with\n * AES-256-GCM (authenticated) using a fresh random IV per record. Runs on the\n * WebCrypto `SubtleCrypto` available in browsers and Node ≥ 22.\n */\n\nconst PBKDF2_ITERATIONS = 210_000;\nconst PBKDF2_HASH = 'SHA-256';\nconst SALT_BYTES = 16;\nconst IV_BYTES = 12;\nconst AES_KEY_BITS = 256;\n\nfunction subtle(): SubtleCrypto {\n const c = globalThis.crypto;\n if (!c?.subtle) {\n throw new Error('WebCrypto (crypto.subtle) is unavailable — a secure context (https/localhost) or Node ≥ 22 is required for share storage.');\n }\n return c.subtle;\n}\n\n/** Cryptographically-random bytes. */\nexport function randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n}\n\n/**\n * Lowercase-hex SHA-256 of a UTF-8 string.\n *\n * Used to derive the recovery **credential hash** (Contract A): the client hashes\n * the recovery code and sends only the hash, so the server never receives the\n * sealing secret and therefore can never unseal the backup ciphertext it stores.\n */\nexport async function sha256Hex(input: string): Promise<string> {\n const digest = await subtle().digest('SHA-256', new TextEncoder().encode(input) as BufferSource);\n return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nexport function freshSalt(): Uint8Array {\n return randomBytes(SALT_BYTES);\n}\n\n/** Derive a non-extractable AES-GCM key from a secret + salt (PBKDF2-HMAC-SHA256). */\nexport async function deriveKey(secret: string, salt: Uint8Array): Promise<CryptoKey> {\n const s = subtle();\n const baseKey = await s.importKey('raw', new TextEncoder().encode(secret), 'PBKDF2', false, ['deriveKey']);\n return s.deriveKey({ name: 'PBKDF2', salt: salt as BufferSource, iterations: PBKDF2_ITERATIONS, hash: PBKDF2_HASH }, baseKey, { name: 'AES-GCM', length: AES_KEY_BITS }, false, [\n 'encrypt',\n 'decrypt',\n ]);\n}\n\n/** Seal `plaintext` into a self-describing `<iv>.<ciphertext>` base64 record. */\nexport async function seal(key: CryptoKey, plaintext: string): Promise<string> {\n const iv = randomBytes(IV_BYTES);\n const data = new TextEncoder().encode(plaintext);\n const ct = await subtle().encrypt({ name: 'AES-GCM', iv: iv as BufferSource }, key, data);\n return `${bytesToBase64(iv)}.${bytesToBase64(new Uint8Array(ct))}`;\n}\n\n/** Open a `<iv>.<ciphertext>` record produced by {@link seal}. Throws if the secret is wrong or the data is tampered. */\nexport async function open(key: CryptoKey, record: string): Promise<string> {\n const dot = record.indexOf('.');\n if (dot <= 0) throw new Error('Malformed encrypted share record.');\n const iv = base64ToBytes(record.slice(0, dot));\n const ct = base64ToBytes(record.slice(dot + 1));\n try {\n const plain = await subtle().decrypt({ name: 'AES-GCM', iv: iv as BufferSource }, key, ct as BufferSource);\n return new TextDecoder().decode(plain);\n } catch {\n throw new Error('Failed to decrypt share — wrong secret or corrupted data.');\n }\n}\n\n/**\n * Self-contained password sealing: derive a key from `password` with a fresh random\n * salt and seal `plaintext`, embedding the salt so the blob can be opened anywhere\n * with only the password. Format: `<salt>.<iv>.<ciphertext>` (base64). Used for the\n * recovery share, which carries no external salt store (unlike {@link seal}).\n */\nexport async function sealWithPassword(password: string, plaintext: string): Promise<string> {\n const salt = freshSalt();\n const key = await deriveKey(password, salt);\n return `${bytesToBase64(salt)}.${await seal(key, plaintext)}`;\n}\n\n/** Open a `<salt>.<iv>.<ciphertext>` blob produced by {@link sealWithPassword}. Throws on a wrong password / tamper. */\nexport async function openWithPassword(password: string, record: string): Promise<string> {\n const dot = record.indexOf('.');\n if (dot <= 0) throw new Error('Malformed password-sealed record.');\n const salt = base64ToBytes(record.slice(0, dot));\n const key = await deriveKey(password, salt);\n return open(key, record.slice(dot + 1));\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\nfunction base64ToBytes(base64: string): Uint8Array {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n","import { WaaskeyError } from './errors';\nimport { openWithPassword, randomBytes, sealWithPassword, sha256Hex } from './storage/crypto';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { ShareStore } from './storage';\nimport type {\n FactorEnrollment,\n FactorVerification,\n RecoverParams,\n RecoverWalletResponse,\n RecoveryChallengeResponse,\n RecoveryRetrieveResponse,\n RecoveryShareInfo,\n RegisterRecoveryParams,\n} from './types';\n\nconst MIN_FACTORS = 3;\n\n/** Dependencies the {@link Recovery} resource needs. */\nexport interface RecoveryDeps {\n shareStore?: ShareStore;\n /** Optional analytics emitter for the wallet.recovered event. */\n analytics?: Analytics;\n}\n\n/**\n * Multi-factor wallet recovery.\n *\n * The recovery share is encrypted **client-side** with the user's recovery code\n * (the server stores only the opaque ciphertext) and its release is gated behind\n * ≥3 factors (recovery code + TOTP + email OTP). Device-loss recovery verifies the\n * factors, has the server rotate the key shares (invalidating the lost device\n * share), then decrypts the backup and restores it on the new device.\n */\nexport class Recovery {\n constructor(\n private readonly http: HttpClient,\n private readonly deps: RecoveryDeps = {},\n ) {}\n\n /**\n * Back up a wallet's device share: encrypt it with the recovery code and enrol the\n * factors. Returns the (possibly generated) recovery code — show it to the user\n * once; it is the only key to the backup and is never recoverable from the server.\n */\n async register(walletId: string, params: RegisterRecoveryParams, options: { signal?: AbortSignal } = {}): Promise<{ recoveryCode: string; share: RecoveryShareInfo }> {\n return registerRecoveryShare(this.http, walletId, params, options.signal);\n }\n\n /** The registered recovery factors for a wallet (no secrets). */\n getInfo(walletId: string, options: { signal?: AbortSignal } = {}): Promise<RecoveryShareInfo> {\n return this.http.request<RecoveryShareInfo>('GET', `/v1/wallets/${walletId}/recovery/info`, undefined, options.signal);\n }\n\n /** Start a recovery session — returns the challengeId + the factors the user must verify. */\n challenge(walletId: string, options: { signal?: AbortSignal } = {}): Promise<RecoveryChallengeResponse> {\n return this.http.request<RecoveryChallengeResponse>('POST', `/v1/wallets/${walletId}/recovery/challenge`, undefined, options.signal);\n }\n\n /**\n * Device-loss recovery: verify factors, have the server rotate the key shares,\n * then decrypt the backup with the recovery code and restore it to the share store\n * (when one is configured). Returns when the share is restored.\n */\n async recover(walletId: string, params: RecoverParams, options: { signal?: AbortSignal } = {}): Promise<{ share: string; refreshedAt: string }> {\n const res = await this.http.request<RecoverWalletResponse>(\n 'POST',\n `/v1/wallets/${walletId}/recovery/recover`,\n { challengeId: params.challengeId, verifications: await hashRecoveryFactors(params.verifications) },\n options.signal,\n );\n const share = await this.decrypt(res.ciphertext, params.recoveryCode);\n await this.deps.shareStore?.put(walletId, share);\n this.deps.analytics?.track('wallet.recovered', { walletId });\n return { share, refreshedAt: res.refreshedAt };\n }\n\n /**\n * Verify factors and decrypt the backed-up share **without** rotating keys — for a\n * read-only restore. Use {@link recover} for true device-loss (which re-keys).\n *\n * NOTE (issue #41, LOW): because this path does not rotate the (possibly lost) device\n * share, the server `/verify` endpoint must enforce that **all ≥3 factors** were\n * satisfied before releasing the ciphertext; prefer {@link recover} (always-rotate) for\n * device-loss so a leaked backup can't be replayed against a still-valid old share.\n */\n async retrieveShare(walletId: string, params: RecoverParams, options: { signal?: AbortSignal } = {}): Promise<string> {\n const ciphertext = await fetchRecoveryCiphertext(this.http, walletId, params, options.signal);\n return this.decrypt(ciphertext, params.recoveryCode);\n }\n\n private async decrypt(ciphertext: string, recoveryCode: string): Promise<string> {\n try {\n return await openWithPassword(recoveryCode, ciphertext);\n } catch (cause) {\n throw new WaaskeyError('Could not decrypt the recovery share — wrong recovery code?', 'recovery_failed', { cause });\n }\n }\n}\n\n/**\n * The exact `POST /v1/wallets/:id/recovery/register` request body — the sealed share ciphertext plus the\n * enrolled factors. Split out from the seal step ({@link buildRecoveryRegistration}) and the POST\n * ({@link postRecoveryRegistration}) so a caller can persist it as a durable retry buffer BEFORE the\n * network call: it is opaque without the recovery code (which never leaves the device), so caching a\n * copy locally is safe. Used by the non-custodial `create` flow to make the user_backup backup\n * crash/network-safe (the sealed share is not lost if registration throws).\n */\nexport interface RecoveryRegisterPayload {\n ciphertext: string;\n factors: FactorEnrollment[];\n}\n\n/**\n * Seal a NAMED key share with a recovery code and build the register payload — WITHOUT the network call.\n * Contract A: the raw recovery code NEVER leaves the device (the share is sealed with it client-side via\n * `sealWithPassword`, and only the code's SHA-256 is enrolled), so the server holds an undecryptable blob\n * and can never reconstruct the key. Returns the effective recovery code (caller-supplied, or generated)\n * + the {@link RecoveryRegisterPayload} ready to POST (or to persist as a retry buffer, then POST).\n */\nexport async function buildRecoveryRegistration(params: RegisterRecoveryParams): Promise<{ recoveryCode: string; payload: RecoveryRegisterPayload }> {\n const recoveryCode = params.recoveryCode ?? generateRecoveryCode();\n const ciphertext = await sealWithPassword(recoveryCode, params.share);\n\n // Contract A: never transmit the sealing secret. Enrol a SHA-256 of the code so the\n // server (which holds share-2 + this ciphertext) can never derive the code to unseal.\n // The hash travels in the SAME `credential` field every factor uses — that is the field\n // the API's FactorEnrollmentDto declares, and its validation pipe (whitelist +\n // forbidNonWhitelisted) rejects the request outright under any other name (#91).\n const factors: FactorEnrollment[] = [\n { type: 'recovery_code', credential: await sha256Hex(recoveryCode) },\n { type: 'totp', credential: params.totpSecret },\n { type: 'email_otp', credential: params.email },\n ...(params.extraFactors ?? []),\n ];\n if (factors.length < MIN_FACTORS) {\n throw new WaaskeyError(`Recovery requires at least ${MIN_FACTORS} factors.`, 'validation');\n }\n return { recoveryCode, payload: { ciphertext, factors } };\n}\n\n/** POST an already-built {@link RecoveryRegisterPayload} to the recovery-register endpoint. */\nexport function postRecoveryRegistration(http: HttpClient, walletId: string, payload: RecoveryRegisterPayload, signal?: AbortSignal): Promise<RecoveryShareInfo> {\n return http.request<RecoveryShareInfo>('POST', `/v1/wallets/${walletId}/recovery/register`, payload, signal);\n}\n\n/**\n * Verify the recovery factors and fetch the sealed share ciphertext (`POST /v1/wallets/:id/recovery/verify`),\n * WITHOUT decrypting it — the retrieval half of {@link Recovery.retrieveShare}, split out so a caller that\n * decrypts with its OWN error contract can reuse the gate. Contract A: the `recovery_code` factor is proven\n * with its SHA-256 (via {@link hashRecoveryFactors}), never the plaintext code. The returned ciphertext is\n * opaque to the server; only the recovery code opens it. Reused by the non-custodial device-loss recover-sign\n * ({@link Wallets.recoverSign}, #351/#78) to restore the client-held `user_backup` share.\n */\nexport async function fetchRecoveryCiphertext(http: HttpClient, walletId: string, params: RecoverParams, signal?: AbortSignal): Promise<string> {\n const res = await http.request<RecoveryRetrieveResponse>(\n 'POST',\n `/v1/wallets/${walletId}/recovery/verify`,\n { challengeId: params.challengeId, verifications: await hashRecoveryFactors(params.verifications) },\n signal,\n );\n return res.ciphertext;\n}\n\n/**\n * Seal a NAMED key share with a recovery code and register the resulting ciphertext + enrolled factors\n * server-side (`POST /v1/wallets/:id/recovery/register`) in one shot. The single source of truth for the\n * recovery backup mechanism, reused by two callers:\n *\n * - {@link Recovery.register} — back up the **device** share after keygen (recovery code generated if omitted);\n * - the non-custodial `create` flow ({@link Wallets.create}, #351/#78) — back up the client-held\n * **user_backup** share inline at keygen (which additionally persists a local retry buffer first, so a\n * failed register never loses the share).\n *\n * Returns the effective recovery code + the registered share metadata.\n */\nexport async function registerRecoveryShare(\n http: HttpClient,\n walletId: string,\n params: RegisterRecoveryParams,\n signal?: AbortSignal,\n): Promise<{ recoveryCode: string; share: RecoveryShareInfo }> {\n const { recoveryCode, payload } = await buildRecoveryRegistration(params);\n const share = await postRecoveryRegistration(http, walletId, payload, signal);\n return { recoveryCode, share };\n}\n\n/**\n * Contract A: replace a `recovery_code` proof's plaintext `token` with its SHA-256\n * before it leaves the device, so the server verifies possession against the stored\n * hash and never sees the code. The hash stays in the SAME `token` field — that is the\n * field the API's FactorVerificationDto declares, and its validation pipe rejects any\n * other property name (#91). Other factors pass through untouched.\n *\n * A `recovery_code` proof with no `token` (only reachable from untyped JS) is passed through as-is\n * rather than hashed: `sha256Hex(undefined)` would digest the literal string and turn a precise\n * \"token should not be empty\" 400 into an opaque 401 at the factor gate.\n */\nasync function hashRecoveryFactors(verifications: FactorVerification[]): Promise<FactorVerification[]> {\n return Promise.all(verifications.map(async (v) => (v.type === 'recovery_code' && typeof v.token === 'string' ? { type: v.type, token: await sha256Hex(v.token) } : v)));\n}\n\n/** A high-entropy (128-bit) recovery code, grouped for readability — e.g. `7F3A-9C21-...`. */\nexport function generateRecoveryCode(): string {\n const alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // Crockford-ish base32 (no I/O/0/1)\n const bytes = randomBytes(20);\n let out = '';\n for (let i = 0; i < bytes.length; i++) {\n out += alphabet[bytes[i]! % alphabet.length];\n if ((i + 1) % 4 === 0 && i + 1 < bytes.length) out += '-';\n }\n return out;\n}\n","import { WaaskeyError } from './errors';\nimport type { MpcCurve } from './mpc';\nimport type { Chain, WalletCurve } from './types';\n\n/** Maps a chain to the threshold-signing curve its wallet uses. `null` = not creatable yet. */\nconst CHAIN_CURVES: Record<Chain, WalletCurve | null> = {\n ethereum: 'secp256k1',\n polygon: 'secp256k1',\n arbitrum: 'secp256k1',\n base: 'secp256k1',\n optimism: 'secp256k1',\n bitcoin: 'secp256k1',\n // Solana signs with threshold EdDSA (ed25519 / FROST, #110): the device co-signs 2-party with the\n // server `server` party over the relay (keygenEddsa / signEddsa), distinct from the cggmp24 path.\n solana: 'ed25519',\n};\n\n/** The signing curve for a chain, or a typed `unsupported_chain` error if not supported yet. */\nexport function curveForChain(chain: Chain): WalletCurve {\n const curve = CHAIN_CURVES[chain];\n if (!curve) {\n throw new WaaskeyError(`Chain \"${chain}\" is not supported yet.`, 'unsupported_chain');\n }\n return curve;\n}\n\n/**\n * Narrow a {@link WalletCurve} to the cggmp24 {@link MpcCurve} the curve-based device core runs\n * (`secp256k1`). `ed25519` (FROST) is curveless and drives the separate\n * `runEddsaKeygen` / `runEddsaSign` path, so it is refused here — the guard keeps a cggmp24-only flow\n * (member keygen/sign, reshare, prime prewarm) from ever mis-running an ed25519 wallet.\n */\nexport function toMpcCurve(curve: WalletCurve): MpcCurve {\n if (curve === 'ed25519') {\n throw new WaaskeyError('ed25519 (FROST) wallets do not use the cggmp24 curve-based MPC path.', 'unsupported');\n }\n return curve;\n}\n","import { WaaskeyError } from './errors';\n\n/** Throw a typed `aborted` error if the signal is already aborted. */\nexport function throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw new WaaskeyError('Operation aborted.', 'aborted');\n}\n\n/** Resolve after `ms`, or reject with a typed `aborted` error if the signal fires first. */\nexport function delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new WaaskeyError('Operation aborted.', 'aborted'));\n return;\n }\n const handle: { timer?: ReturnType<typeof setTimeout> } = {};\n const onAbort = (): void => {\n if (handle.timer) clearTimeout(handle.timer);\n reject(new WaaskeyError('Operation aborted.', 'aborted'));\n };\n handle.timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","import { toMpcCurve } from './chains';\nimport { WaaskeyError } from './errors';\nimport { throwIfAborted } from './internal';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { DeviceCompleteReshareResult, MpcCore } from './mpc';\nimport type { ShareStore } from './storage';\nimport type { ReshareCompletionParams, ReshareCompletionResult, WalletData } from './types';\n\n/** Dependencies the {@link Reshare} resource needs for the device-side completion ceremony. */\nexport interface ReshareDeps {\n mpc?: MpcCore;\n shareStore?: ShareStore;\n /** Optional analytics emitter for the wallet.reshared event. */\n analytics?: Analytics;\n}\n\n/**\n * Device-side completion of a **device-retaining** reshare (#318 phase 2b).\n *\n * A backend reshare that keeps a USER_DEVICE holder commits a NEW epoch whose shares are CORE-ONLY\n * (no aux) — the wallet is `reshareAuxPending` and cannot sign until the aux material is generated\n * over the new committee. The platform signer drives its server + recovery parties of that aux\n * ceremony; the DEVICE must join it or the ceremony can't complete. This resource is the device's\n * half: it assembles its NEW-epoch bare core locally from the reshare's {@link DeviceReshareMaterial},\n * runs the `<sessionId>/reshare-aux` aux ceremony over the relay alongside the platform parties, and\n * seals the resulting COMPLETE share on the device under the new epoch.\n *\n * The device is never left worse off: nothing is stored until the completed share's public key is\n * verified equal to the wallet's (unchanged across a reshare — the funds-safety invariant), and the\n * OLD-epoch share is kept intact, so an interrupted completion can simply be retried.\n */\nexport class Reshare {\n constructor(\n private readonly http: HttpClient,\n private readonly deps: ReshareDeps = {},\n ) {}\n\n /**\n * Complete this device's share for a device-retaining reshare and make the wallet signable on the\n * device under the new epoch.\n *\n * 1. Fetch the wallet to learn its (unchanged) public key — the invariant the completion is checked\n * against, taken from the server's truth rather than the caller.\n * 2. Assemble the NEW-epoch bare core locally from {@link ReshareCompletionParams.material} (no relay).\n * 3. Run the aux-completion ceremony over the relay ({@link ReshareCompletionParams.ceremony}),\n * alongside the platform server + recovery parties, to obtain the COMPLETE signable share.\n * 4. Verify the completed share's public key equals the wallet's (fail closed on any mismatch).\n * 5. Seal + persist the completed share under `(walletId, keyEpoch)`, keeping the old-epoch share.\n *\n * Requires `mpc` (built with the reshare capability) + `shareStore`. Idempotent/recoverable: safe to\n * retry, since nothing is overwritten until the new share is assembled, verified, and stored.\n */\n async complete(walletId: string, params: ReshareCompletionParams, options: { signal?: AbortSignal } = {}): Promise<ReshareCompletionResult> {\n const { mpc, shareStore } = this.deps;\n if (!mpc || !shareStore) {\n throw new WaaskeyError('Completing a reshare requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n if (!mpc.runReshareAssemble || !mpc.runCompleteReshare) {\n throw new WaaskeyError('The configured MPC core does not support reshare — use a client-wasm built with the `reshare` feature.', 'unsupported');\n }\n\n const { material, ceremony, keyEpoch } = params;\n const { signal } = options;\n throwIfAborted(signal);\n\n // The wallet's public key is UNCHANGED across a reshare; take it from the server as the invariant.\n const wallet = await this.http.request<WalletData>('GET', `/v1/wallets/${walletId}`, undefined, signal);\n if (!wallet.publicKey) {\n throw new WaaskeyError('The wallet has no public key yet — it must be an ACTIVE reshared wallet to complete on device.', 'reshare_failed', { details: { walletId } });\n }\n\n throwIfAborted(signal);\n let completed: DeviceCompleteReshareResult;\n try {\n // Stage 1 — assemble the NEW-epoch bare core locally (pure, no relay).\n const assembled = await mpc.runReshareAssemble({\n curve: toMpcCurve(material.curve),\n newPosition: material.newPosition,\n newPreimages: material.newPreimages,\n newThreshold: material.newThreshold,\n wallet: material.wallet,\n commitments: material.commitments,\n subShares: material.subShares,\n });\n // Fail fast BEFORE the relay ceremony if assemble already reproduced a different key.\n assertPublicKey(assembled.sharedPublicKey, wallet.publicKey, walletId);\n\n throwIfAborted(signal);\n // Stage 2 — aux-completion over the new committee (relay), yielding the complete signable share.\n completed = await mpc.runCompleteReshare({\n curve: toMpcCurve(material.curve),\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n role: ceremony.role,\n peerRole: ceremony.peerRole,\n partyIndex: ceremony.partyIndex,\n peerPartyIndex: ceremony.peerPartyIndex,\n parties: ceremony.parties,\n relayToken: ceremony.relayToken,\n core: assembled.core,\n pregeneratedPrimes: params.pregeneratedPrimes,\n });\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The device reshare-completion ceremony failed.', 'reshare_failed', { cause });\n }\n\n // Funds-safety invariant: the completed share MUST reproduce the wallet's public key. Verify\n // before adopting it — a mismatch means the reshare is corrupt; store nothing (old share intact).\n assertPublicKey(completed.sharedPublicKey, wallet.publicKey, walletId);\n\n // Seal + persist under the NEW epoch, keeping the old-epoch share until cutover is confirmed\n // (mirrors the backend's epoch-keyed `(walletId, keyEpoch)` model). Sealed exactly like keygen.\n await shareStore.put(epochShareKey(walletId, keyEpoch), serializeCompletedShare(completed));\n this.deps.analytics?.track('wallet.reshared', { walletId, curve: material.curve });\n\n return { walletId, keyEpoch, sharedPublicKey: completed.sharedPublicKey };\n }\n}\n\n/**\n * Compose the epoch-keyed device-share storage key `(walletId, keyEpoch)`, mirroring the backend's\n * epoch-keyed share model (#295). Epoch 1 (a fresh keygen) keeps the bare `walletId` key for\n * back-compat with existing stored shares; later epochs (reshares) use a distinct suffixed key, so a\n * completed reshare never overwrites the old-epoch share until cutover is confirmed.\n */\nexport function epochShareKey(walletId: string, keyEpoch: number): string {\n return keyEpoch <= 1 ? walletId : `${walletId}@epoch-${keyEpoch}`;\n}\n\n/** Fail closed unless the assembled/completed share reproduces the wallet's (unchanged) public key. */\nfunction assertPublicKey(actual: string, expected: string, walletId: string): void {\n if (actual !== expected) {\n throw new WaaskeyError('The reshared share reproduced a DIFFERENT public key than the wallet — aborting (device share not stored).', 'reshare_pubkey_mismatch', {\n details: { walletId, expected, actual },\n });\n }\n}\n\n/** The on-device record persisted per completed reshare — the same sealed shape a keygen share uses. */\nfunction serializeCompletedShare(completed: DeviceCompleteReshareResult): string {\n return JSON.stringify({ keyShare: completed.keyShare, sharedPublicKey: completed.sharedPublicKey });\n}\n","import { WaaskeyError } from './errors';\nimport type { CreateWalletParams, CustodyKind, CustodyType, WalletData } from './types';\n\nconst CUSTODY_KINDS: ReadonlySet<CustodyKind> = new Set<CustodyKind>(['user_device', 'user_backup', 'platform_signer', 'platform_recovery', 'external_party']);\nconst CUSTODY_TYPES: ReadonlySet<CustodyType> = new Set<CustodyType>(['embedded', 'shared', 'self_custody']);\n\n/**\n * Whether a wallet is **non-custodial** — the platform alone cannot produce a\n * signature because the shares it holds do not meet the threshold\n * (`platformShareCount < threshold`, i.e. custody type `shared` or `self_custody`).\n *\n * This mirrors the server-attested invariant `platformShares < t ⟺ non-custodial`,\n * so an app can display the custody guarantee straight off the returned wallet.\n */\nexport function isNonCustodial(wallet: Pick<WalletData, 'platformShareCount' | 'threshold'>): boolean {\n return wallet.platformShareCount < wallet.threshold;\n}\n\n/**\n * Validate a create-wallet custody policy client-side, before the request — clear\n * errors instead of a round-trip to a 400. A no-op when no policy is supplied\n * (the default embedded 2-of-3 topology).\n *\n * The rules mirror the backend contract: `parties` (when supplied) are ≥2 distinct,\n * non-empty roles that define `n`; `threshold` is an integer in `[2, n]`; and\n * `custodyKinds` has exactly one known kind per party.\n */\nexport function validateCustodyPolicy(params: Pick<CreateWalletParams, 'threshold' | 'parties' | 'custodyKinds' | 'custodyType'>): void {\n const { threshold, parties, custodyKinds, custodyType } = params;\n if (threshold === undefined && parties === undefined && custodyKinds === undefined && custodyType === undefined) return;\n\n if (parties !== undefined) {\n if (!Array.isArray(parties) || parties.length < 2) {\n throw new WaaskeyError('`parties` must list at least 2 party roles.', 'validation');\n }\n if (parties.some((role) => typeof role !== 'string' || role.trim() === '')) {\n throw new WaaskeyError('`parties` roles must be non-empty strings.', 'validation');\n }\n if (new Set(parties).size !== parties.length) {\n throw new WaaskeyError('`parties` roles must be distinct.', 'validation');\n }\n }\n\n if (threshold !== undefined) {\n if (!Number.isInteger(threshold) || threshold < 2) {\n throw new WaaskeyError('`threshold` must be an integer of at least 2.', 'validation');\n }\n if (parties !== undefined && threshold > parties.length) {\n throw new WaaskeyError('`threshold` cannot exceed the number of parties.', 'validation');\n }\n }\n\n if (custodyKinds !== undefined) {\n if (parties === undefined) {\n throw new WaaskeyError('`custodyKinds` requires `parties` — they are parallel arrays.', 'validation');\n }\n if (custodyKinds.length !== parties.length) {\n throw new WaaskeyError('`custodyKinds` must have exactly one entry per party (same length as `parties`).', 'validation');\n }\n const unknown = custodyKinds.find((kind) => !CUSTODY_KINDS.has(kind));\n if (unknown !== undefined) {\n throw new WaaskeyError(`\\`custodyKinds\\` contains an unknown custody kind: ${String(unknown)}.`, 'validation');\n }\n }\n\n if (custodyType !== undefined && !CUSTODY_TYPES.has(custodyType)) {\n throw new WaaskeyError(`\\`custodyType\\` is not a valid custody type: ${String(custodyType)}.`, 'validation');\n }\n}\n","import { WaaskeyError } from './errors';\nimport type { EddsaKeygenResult } from './mpc';\n\n/**\n * On-device storage codec for an ed25519 (FROST) wallet's device share — the FROST `keyPackage`\n * (secret) + the group `publicKeyPackage`. Kept DISTINCT from the cggmp24 `{ keyShare, auxInfo,\n * sharedPublicKey }` blob (see `wallets.ts` `serializeShare`): the two share shapes never mix. This\n * leaf module is imported by both the keygen (persist, in `wallets.ts`) and the sign (read, in\n * `wallet.ts`) paths, so neither file forms an import cycle with the other.\n */\n\n/** Seal-input for the device's ed25519 share: the two FROST packages, as the `signEddsa` path reads them back. */\nexport function serializeEddsaShare(keygen: EddsaKeygenResult): string {\n return JSON.stringify({ keyPackage: keygen.keyPackage, publicKeyPackage: keygen.publicKeyPackage });\n}\n\n/** Inverse of {@link serializeEddsaShare}: parse a stored blob back into the FROST packages `signEddsa` needs. */\nexport function deserializeEddsaShare(blob: string): { keyPackage: unknown; publicKeyPackage: unknown } {\n let parsed: { keyPackage?: unknown; publicKeyPackage?: unknown };\n try {\n parsed = JSON.parse(blob) as { keyPackage?: unknown; publicKeyPackage?: unknown };\n } catch (cause) {\n throw new WaaskeyError('Stored ed25519 device share is corrupt — it is not valid JSON.', 'share_not_found', { cause });\n }\n if (parsed.keyPackage === undefined || parsed.publicKeyPackage === undefined) {\n throw new WaaskeyError('Stored ed25519 device share is malformed — it is missing its FROST key/public-key package.', 'share_not_found', {\n details: { keys: Object.keys(parsed) },\n });\n }\n return { keyPackage: parsed.keyPackage, publicKeyPackage: parsed.publicKeyPackage };\n}\n","import { x25519 } from '@noble/curves/ed25519.js';\nimport { WaaskeyError } from './errors';\nimport type { ShareStore } from './storage';\n\n/**\n * The device's long-lived X25519 encryption keypair for FROST ed25519 (FROST) keygen (#114).\n *\n * FROST DKG round-2 sends each party a secret share sealed to the recipient's X25519 key (libsodium\n * `crypto_box`), so no share ever crosses the relay in the clear. The device therefore needs its OWN\n * encryption keypair: the PUBLIC key is advertised on wallet create (`deviceEncPubkey`) and echoed back\n * to every party in the ceremony's `encPubkeys` roster; the SECRET key opens the round-2 packages sealed\n * to this device. It is device-private and long-lived — the SAME keypair is reused for later reshare aux\n * ceremonies — so it is generated + sealed ONCE into the (encrypted) {@link ShareStore} and reused after.\n *\n * The raw 32-byte X25519 keys are compatible with waas-core's `crypto_box` (`PublicKey`/`SecretKey::from_bytes`).\n */\n\n/** Reserved {@link ShareStore} key the device encryption keypair is sealed under — never a wallet id. */\nconst DEVICE_ENC_STORE_KEY = '__waaskey_device_enc_v1__';\n\n/** The device's X25519 encryption keypair (hex), sealed in the {@link ShareStore}. */\nexport interface DeviceEncKeypair {\n /** X25519 secret key, 32-byte lowercase hex. SECRET — never logged, never sent to the server. */\n secretHex: string;\n /** X25519 public key, 32-byte lowercase hex (non-zero) — the `deviceEncPubkey` supplied on create. */\n publicHex: string;\n}\n\n/**\n * Get-or-create the device's long-lived X25519 encryption keypair (#114). Reuses the keypair already\n * sealed in `shareStore` when present (so it stays stable across wallets and across reshares); otherwise\n * generates a fresh one, verifies its public key is non-zero, and seals it once. The secret never leaves\n * the device and is never logged.\n */\nexport async function getOrCreateDeviceEncKeypair(shareStore: ShareStore): Promise<DeviceEncKeypair> {\n const existing = await shareStore.get(DEVICE_ENC_STORE_KEY);\n if (existing !== null) return parseDeviceEncKeypair(existing);\n const keypair = generateDeviceEncKeypair();\n await shareStore.put(DEVICE_ENC_STORE_KEY, JSON.stringify(keypair));\n return keypair;\n}\n\n/** Generate a fresh X25519 encryption keypair, refusing an all-zero (invalid) public key. */\nfunction generateDeviceEncKeypair(): DeviceEncKeypair {\n const secret = x25519.utils.randomSecretKey();\n const publicKey = x25519.getPublicKey(secret);\n if (isAllZero(publicKey)) {\n throw new WaaskeyError('Generated an all-zero X25519 encryption public key — refusing to seal keygen packages to it.', 'keygen_failed');\n }\n return { secretHex: bytesToHex(secret), publicHex: bytesToHex(publicKey) };\n}\n\n/** Inverse of the seal in {@link getOrCreateDeviceEncKeypair}: parse + validate a stored keypair blob. */\nfunction parseDeviceEncKeypair(blob: string): DeviceEncKeypair {\n let parsed: { secretHex?: unknown; publicHex?: unknown };\n try {\n parsed = JSON.parse(blob) as { secretHex?: unknown; publicHex?: unknown };\n } catch (cause) {\n throw new WaaskeyError('Stored device encryption keypair is corrupt — it is not valid JSON.', 'keygen_failed', { cause });\n }\n if (!isHex32(parsed.secretHex) || !isHex32(parsed.publicHex)) {\n throw new WaaskeyError('Stored device encryption keypair is malformed — expected 32-byte (64 hex) secret + public keys.', 'keygen_failed', {\n details: { keys: Object.keys(parsed) },\n });\n }\n return { secretHex: parsed.secretHex, publicHex: parsed.publicHex };\n}\n\n/** Is `v` a 32-byte (64 hex char) hex string? */\nfunction isHex32(v: unknown): v is string {\n return typeof v === 'string' && /^[0-9a-fA-F]{64}$/.test(v);\n}\n\n/** Are all bytes zero? An all-zero X25519 public key is a low-order (invalid) point. */\nfunction isAllZero(bytes: Uint8Array): boolean {\n return bytes.every((byte) => byte === 0);\n}\n\n/** Lowercase-hex encode raw bytes (no external hex-codec dependency). */\nfunction bytesToHex(bytes: Uint8Array): string {\n let hex = '';\n for (const byte of bytes) hex += byte.toString(16).padStart(2, '0');\n return hex;\n}\n","import { toMpcCurve } from './chains';\nimport { WaaskeyError } from './errors';\nimport type { DeviceSignParams } from './mpc';\nimport type { SignSessionResponse, WalletCurve } from './types';\n\n/**\n * The relay coordination a device party needs to run its half of a started ceremony, normalized from\n * whichever backend descriptor started it — the sign session (which names this party + its peer) or\n * the send session (which names the whole quorum roster). Both reduce to: where the relay is, who is\n * in the quorum (in `participants` order), and which slot this device holds.\n */\nexport interface DeviceCeremony {\n curve: WalletCurve;\n /** Relay websocket URL every party connects to. */\n relayUrl: string;\n /** Ceremony id shared by every party; derives the execution ids. */\n sessionId: string;\n /** The quorum's relay roles, in `participants` order (`roles[i]` ↔ `participants[i]`). */\n roles: string[];\n /** The quorum's keygen indices, in protocol order. */\n participants: number[];\n /** This device's own 0-based slot into {@link roles} / {@link participants}. */\n signerPosition: number;\n /** Short-lived relay token (JWT) this device presents to join as `roles[signerPosition]`. */\n relayToken?: string;\n}\n\n/**\n * Map a started ceremony onto the {@link DeviceSignParams} the device party runs. This is the single\n * place that translation happens — the raw `sign`, the device-co-signed `send` and recover-sign all\n * share it, so they cannot drift on how a quorum is addressed.\n *\n * Only the 2-party shape is handled: cggmp24's plain `sign` transport addresses exactly one peer, so a\n * larger quorum needs the roster-routed member path (see waas-core#131) and is refused here rather\n * than silently mis-routed.\n *\n * `partyIndex`/`peerPartyIndex` are quorum POSITIONS, not keygen indices — the keygen indices ride in\n * `participants` (e.g. a `{server, user_backup}` recover-sign runs at positions 0/1 over participants\n * `[1, 2]`).\n */\nexport function toDeviceSignParams(ceremony: DeviceCeremony, share: string, digest: string): DeviceSignParams {\n const { roles, participants, signerPosition } = ceremony;\n if (participants.length !== 2 || roles.length !== 2 || signerPosition < 0 || signerPosition > 1) {\n throw new WaaskeyError(\n `Unexpected sign descriptor: the quorum must be exactly 2 parties with signerPosition in {0, 1} (got ${participants.length} participants, ${roles.length} roles, signerPosition ${signerPosition}).`,\n 'sign_failed',\n { details: { roles, participants, signerPosition } },\n );\n }\n const peerPosition = 1 - signerPosition;\n return {\n curve: toMpcCurve(ceremony.curve),\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n role: roles[signerPosition]!,\n peerRole: roles[peerPosition]!,\n partyIndex: signerPosition,\n peerPartyIndex: peerPosition,\n relayToken: ceremony.relayToken,\n share,\n participants,\n signerPosition,\n digest,\n };\n}\n\n/**\n * Map a backend **sign-session** descriptor onto the device party's params.\n *\n * The descriptor is authoritative: the backend derives the quorum from the wallet's own party list and\n * issues the relay token bound to `{sessionId, role}`, so the client must NOT re-derive indices or join\n * unauthenticated. It names only this party and its peer (never a roster), so the pair is ordered by\n * `signerPosition` before it reaches {@link toDeviceSignParams}.\n */\nexport function toSessionSignParams(session: SignSessionResponse, share: string, digest: string): DeviceSignParams {\n return toDeviceSignParams(\n {\n curve: session.curve,\n relayUrl: session.relayUrl,\n sessionId: session.sessionId,\n roles: sessionRoles(session),\n participants: session.participants,\n signerPosition: session.signerPosition,\n relayToken: session.relayToken,\n },\n share,\n digest,\n );\n}\n\n/**\n * The 2-party roster a sign-session descriptor names: this party's `role` sits at its `signerPosition`,\n * `peerRole` takes the other slot. (A larger quorum carries no roster on that descriptor — the caller\n * supplies the wallet's own party slice instead.)\n */\nexport function sessionRoles(session: Pick<SignSessionResponse, 'role' | 'peerRole' | 'signerPosition'>): string[] {\n return session.signerPosition === 0 ? [session.role, session.peerRole] : [session.peerRole, session.role];\n}\n","import { WaaskeyError } from './errors';\nimport type { DeviceKeygenResult } from './mpc';\n\n/**\n * The on-device storage blob persisted per wallet — the device key share plus the data sign\n * needs. `relayUrl` (when known, i.e. for shares persisted at keygen) lets a later\n * device-present sign rejoin the SAME relay the ceremony used without any extra round-trip\n * (waas-core#131 follow-up: the sign quorum includes the device, so it must co-sign).\n */\nexport function serializeShare(keygen: DeviceKeygenResult, relayUrl?: string): string {\n return JSON.stringify({\n keyShare: keygen.keyShare,\n auxInfo: keygen.auxInfo,\n sharedPublicKey: keygen.sharedPublicKey,\n ...(relayUrl === undefined ? {} : { relayUrl }),\n });\n}\n\n/**\n * Inverse of {@link serializeShare}: parse a persisted storage blob back into its parts — the bare\n * KeyShare (its JSON string, the crypto material the MPC core signs with), the wallet's shared\n * public key, and the keygen relay URL when the blob recorded one. This is the ONE place that knows\n * the on-device storage shape, so the MPC layer only ever receives the KeyShare, never the wrapper.\n */\nexport function deserializeShare(blob: string): { keyShare: string; sharedPublicKey?: string; relayUrl?: string } {\n let parsed: { keyShare?: unknown; sharedPublicKey?: unknown; relayUrl?: unknown };\n try {\n parsed = JSON.parse(blob) as { keyShare?: unknown; sharedPublicKey?: unknown; relayUrl?: unknown };\n } catch (cause) {\n throw new WaaskeyError('Stored device share is corrupt — it is not valid JSON.', 'share_not_found', { cause });\n }\n if (typeof parsed.keyShare !== 'string') {\n throw new WaaskeyError('Stored device share is malformed — it is missing its KeyShare.', 'share_not_found', { details: { keys: Object.keys(parsed) } });\n }\n return {\n keyShare: parsed.keyShare,\n sharedPublicKey: typeof parsed.sharedPublicKey === 'string' ? parsed.sharedPublicKey : undefined,\n relayUrl: typeof parsed.relayUrl === 'string' ? parsed.relayUrl : undefined,\n };\n}\n","/**\n * Passkey step-up signing assertion (Pattern B).\n *\n * The backend accepts an optional `passkeyAssertion` (`AuthenticationResponseJSON`)\n * on sign/send/recover DTOs and verifies it server-side. This module runs the\n * WebAuthn assertion over a **server-issued one-time challenge** and returns the\n * typed `AuthenticationResponseJSON` ready to be included in the POST body.\n *\n * ### Challenge (issue #39 — replay-safe)\n * The challenge is a random nonce the **server** mints (via a step-up challenge\n * endpoint), NOT a value derived from the request payload. `Wallet.sign`/`send`\n * fetch it, run the assertion over it, and echo its `challengeId` on the request;\n * the server verifies the assertion against the stored challenge and **burns** it,\n * so a captured assertion cannot be replayed for a later identical payload.\n *\n * ### Wiring in Wallet\n * ```ts\n * // In wallet.sign() (handled by Wallet.resolveStepUp):\n * const { challengeId, challenge } = await http.request('POST', '/v1/wallets/${id}/stepup/challenge', { operation: 'sign' });\n * const assertion = await getSigningAssertion(challenge, { credentialId });\n * await http.request('POST', '/v1/wallets/${id}/sign', { message, passkeyAssertion: assertion, passkeyChallengeId: challengeId });\n *\n * // Caller opts in:\n * await wallet.sign(digest, { requirePasskey: true });\n * ```\n */\n\nimport { WaaskeyError } from '../errors';\nimport type { AuthenticationResponseJSON, PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';\n\n// ─── Capability detection ─────────────────────────────────────────────────────\n\n/**\n * Returns `true` if the current runtime has WebAuthn available — i.e. the SDK\n * can attempt a passkey assertion. Use this as a fast pre-flight before calling\n * `getSigningAssertion()` when you want to show/hide a \"sign with passkey\" button.\n */\nexport function isPasskeyAssertionSupported(): boolean {\n return typeof globalThis.navigator !== 'undefined' && typeof (globalThis.navigator as { credentials?: unknown }).credentials !== 'undefined';\n}\n\n// ─── SigningAssertionCeremony (override for non-browser / tests) ──────────────\n\n/**\n * Override the WebAuthn `credentials.get` call. Useful for React Native (native\n * passkey module) or unit tests (mock the assertion response).\n */\nexport interface SigningAssertionCeremony {\n get(options: PublicKeyCredentialRequestOptionsJSON): Promise<AuthenticationResponseJSON>;\n}\n\n/** @internal Default ceremony backed by @simplewebauthn/browser. */\nasync function defaultAssertionCeremony(): Promise<SigningAssertionCeremony> {\n let mod: typeof import('@simplewebauthn/browser');\n try {\n mod = await import('@simplewebauthn/browser');\n } catch {\n throw new WaaskeyError('Passkey step-up requires \"@simplewebauthn/browser\" installed, or pass a custom ceremony.', 'unsupported');\n }\n return {\n get: (options) => mod.startAuthentication({ optionsJSON: options }),\n };\n}\n\n// ─── getSigningAssertion ──────────────────────────────────────────────────────\n\n/** Options for `getSigningAssertion()`. */\nexport interface SigningAssertionOptions {\n /**\n * Restrict the assertion to a specific credential. Pass the `credentialId`\n * that was enrolled (e.g. from `PasskeyPrfSecretProvider.enroll()`). When\n * omitted the browser presents all resident credentials for the RP.\n */\n credentialId?: string;\n /**\n * Fully qualified domain name of the relying party. Defaults to the current\n * origin's hostname in the browser.\n */\n rpId?: string;\n /**\n * Custom ceremony implementation (for React Native or tests).\n */\n ceremony?: SigningAssertionCeremony;\n}\n\n/**\n * Run a WebAuthn assertion over a **server-issued one-time `challenge`** and return\n * the typed `AuthenticationResponseJSON` to attach as `passkeyAssertion` in the\n * request body.\n *\n * @param challenge — the base64url one-time challenge nonce from the server's\n * step-up challenge endpoint ({@link StepUpChallengeResponse.challenge}). It is\n * passed to the authenticator verbatim; the server verifies the assertion against\n * the stored challenge and burns it, so the assertion cannot be replayed.\n * @param options — optional ceremony override and credential hint.\n *\n * @throws `WaaskeyError('unsupported')` when WebAuthn is not available in this runtime.\n * @throws `WaaskeyError('aborted')` when the user cancels the authenticator prompt.\n */\nexport async function getSigningAssertion(challenge: string, options: SigningAssertionOptions = {}): Promise<AuthenticationResponseJSON> {\n // Skip the availability check when a custom ceremony is supplied — the caller\n // is responsible for the platform (e.g. React Native native passkey, or tests).\n if (options.ceremony === undefined && !isPasskeyAssertionSupported()) {\n throw new WaaskeyError('Passkey step-up is not available in this runtime (no WebAuthn API).', 'unsupported');\n }\n\n const ceremony = options.ceremony ?? (await defaultAssertionCeremony());\n\n const rpId = options.rpId ?? (typeof location === 'undefined' ? undefined : location.hostname);\n\n const requestOptions: PublicKeyCredentialRequestOptionsJSON = {\n challenge,\n userVerification: 'required',\n ...(rpId ? { rpId } : {}),\n ...(options.credentialId ? { allowCredentials: [{ id: options.credentialId, type: 'public-key' }] } : {}),\n };\n\n try {\n return await ceremony.get(requestOptions);\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n const msg = cause instanceof Error ? cause.message : String(cause);\n if (/cancel|abort|not allowed|user gesture/i.test(msg)) {\n throw new WaaskeyError('Passkey authentication was cancelled by the user.', 'aborted', { cause });\n }\n throw new WaaskeyError('Passkey step-up assertion failed.', 'unsupported', { cause });\n }\n}\n","import { toMpcCurve } from './chains';\nimport { isNonCustodial } from './custody';\nimport { deserializeEddsaShare } from './eddsa-share';\nimport { WaaskeyError } from './errors';\nimport { throwIfAborted } from './internal';\nimport { getSigningAssertion } from './passkey/assertion';\nimport { sessionRoles, toDeviceSignParams } from './session-sign';\nimport { deserializeShare } from './share-blob';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { MpcCore } from './mpc';\nimport type { DeviceCeremony } from './session-sign';\nimport type { ShareStore } from './storage';\nimport type {\n CustodyKind,\n CustodyType,\n EddsaAssembleRequest,\n Page,\n PageQuery,\n SendOptions,\n SendParams,\n SendResult,\n Signature,\n SignMessageResponse,\n SignOptions,\n SendSessionResponse,\n SignSessionResponse,\n StepUpChallengeResponse,\n StepUpOperation,\n WalletCurve,\n WalletData,\n WalletStatus,\n} from './types';\n\n/** Device-party dependencies a {@link Wallet} needs to co-sign an ed25519 (FROST) transaction locally. */\nexport interface WalletDeviceDeps {\n mpc?: MpcCore;\n shareStore?: ShareStore;\n}\n\n/** The relay role of the user's own party — the one this SDK can run. Mirrors the backend's `DEVICE_ROLE`. */\nconst DEVICE_ROLE = 'device';\n\n/**\n * A handle to a single wallet. Returned by `waaskey.wallets.create(...)` /\n * `waaskey.wallets.get(...)`.\n */\nexport class Wallet {\n /** Waaskey wallet id, e.g. `wlt_…`. */\n readonly id: string;\n /** The full wallet record as returned by the API. */\n readonly data: WalletData;\n\n constructor(\n private readonly http: HttpClient,\n data: WalletData,\n private readonly analytics?: Analytics,\n /** Device core + share store, threaded from {@link Wallets}, so an ed25519 wallet can co-sign locally. */\n private readonly device: WalletDeviceDeps = {},\n ) {\n this.id = data.id;\n this.data = data;\n }\n\n /** On-chain address (set once keygen completes). */\n get address(): string | undefined {\n return this.data.address;\n }\n\n /** Lifecycle state (`pending` until keygen completes, then `active`). */\n get status(): WalletStatus {\n return this.data.status;\n }\n\n /** Signing curve of the wallet. */\n get curve(): WalletCurve {\n return this.data.curve;\n }\n\n /** Signing threshold `t` of the wallet's `t`-of-`n` MPC key. */\n get threshold(): number {\n return this.data.threshold;\n }\n\n /** Ordered party roles of the wallet's keygen topology, length `n`. */\n get parties(): string[] {\n return this.data.parties;\n }\n\n /** Per-party custody kind, parallel to {@link parties}. */\n get custodyKinds(): CustodyKind[] {\n return this.data.custodyKinds;\n }\n\n /** How many of the wallet's shares the platform itself holds. */\n get platformShareCount(): number {\n return this.data.platformShareCount;\n }\n\n /**\n * The wallet's custody attestation (`embedded` / `shared` / `self_custody`) — display\n * it to prove the custody guarantee to the end-user (see {@link isNonCustodial}).\n */\n get custodyType(): CustodyType {\n return this.data.custodyType;\n }\n\n /**\n * Whether this wallet is **non-custodial** — the platform's shares alone do not meet\n * the threshold (`platformShareCount < threshold`, i.e. custody type `shared` or\n * `self_custody`), so WaaS cannot sign without the user/external party.\n */\n get isNonCustodial(): boolean {\n return isNonCustodial(this.data);\n }\n\n /**\n * Sign a 32-byte message digest with this wallet's key (2-of-3 threshold MPC).\n *\n * `digest` is a 32-byte hash as hex (the `0x` prefix is optional) — e.g. the\n * keccak-256 of an EVM transaction. Hashing a higher-level message/transaction\n * into a digest is the caller's (or a chain helper's) responsibility.\n *\n * **Passkey step-up (Pattern B / issue #21, #39):** pass `{ requirePasskey: true }` to run a\n * WebAuthn assertion before signing. The SDK fetches a **server-issued one-time challenge**,\n * prompts the user's authenticator over it, and attaches `passkeyAssertion` + its\n * `passkeyChallengeId` to the POST body; the backend verifies both the MPC signature and the\n * assertion, then burns the challenge (so it cannot be replayed). Alternatively supply a\n * pre-built assertion via `options.passkeyAssertion` (with its `options.passkeyChallengeId`).\n */\n async sign(digest: string, options: SignOptions = {}): Promise<string> {\n const message = normalizeDigest(digest);\n const quorum = this.signQuorum();\n const devicePosition = quorum?.indexOf(DEVICE_ROLE) ?? -1;\n\n // Platform-only quorum (custodial wallets): the server holds enough shares to sign alone, so the\n // one blocking POST is both correct and cheapest. Unknown topology falls here too — the server decides.\n if (devicePosition < 0) {\n const body: Record<string, unknown> = { message };\n await this.attachStepUp(body, 'sign', options);\n const res = await this.http.request<SignMessageResponse>('POST', `/v1/wallets/${this.id}/sign`, body, options.signal);\n this.analytics?.track('wallet.signed', { walletId: this.id, curve: this.data.curve });\n return res.signature;\n }\n\n // Device-present quorum: START the ceremony and let it run on the RELAY, off the request path.\n // The blocking `POST /sign` cannot serve this shape — it holds the HTTP request open for the\n // whole ceremony, which a proxy cuts (Cloudflare drops a proxied request idle ~100s) — and it\n // makes the client guess the routing. The session descriptor is authoritative instead: the\n // backend derives the quorum from the wallet's own party list and mints the relay token bound\n // to `{sessionId, role}`, which an unauthenticated device join would otherwise be refused.\n const { mpc, keyShare } = await this.loadDeviceParty(quorum!, 'signing');\n\n const startBody: Record<string, unknown> = { digest: message };\n await this.attachStepUp(startBody, 'sign', options);\n const session = await this.http.request<SignSessionResponse>('POST', `/v1/wallets/${this.id}/sign-session`, startBody, options.signal);\n\n // cggmp24's interactive sign hands the completed signature to BOTH parties, so the device's own\n // result IS the signature — there is nothing left to fetch or assemble server-side.\n const { signature } = await this.runDeviceSign(mpc, this.toSignCeremony(session, quorum!), keyShare, message);\n this.analytics?.track('wallet.signed', { walletId: this.id, curve: this.data.curve });\n return signature;\n }\n\n /**\n * The roles that will actually sign — the first `threshold` of the wallet's party list (#292),\n * mirroring the signer's own derivation. `undefined` when the topology is unknown (a legacy\n * wallet record), which callers treat as \"let the server decide\".\n */\n private signQuorum(): string[] | undefined {\n if (this.data.curve === 'ed25519') return undefined; // FROST signs through the send-session flow\n const roles = this.data.parties;\n const { threshold } = this.data;\n if (!Array.isArray(roles) || typeof threshold !== 'number') return undefined;\n return roles.slice(0, threshold);\n }\n\n /**\n * Everything this device needs to join a ceremony, resolved BEFORE one is started (#89): the MPC\n * core, the routed-sign capability a >2-party quorum needs, and the stored key share.\n *\n * Each failure is a typed error thrown straight to the caller, and the ordering is the point: a\n * device that cannot co-sign must never leave the platform party waiting on the relay for a\n * counterpart that will never arrive. That wait ends at the party-runner timeout (~210s) and\n * reaches the caller as an opaque 5xx — minutes after a knowable, local cause.\n */\n private async loadDeviceParty(quorum: string[], action: 'signing' | 'sending'): Promise<{ mpc: MpcCore; keyShare: string }> {\n const { mpc, shareStore } = this.device;\n if (!mpc || !shareStore) {\n throw new WaaskeyError(\n `This wallet's signing quorum [${quorum.join(', ')}] includes the device, so ${action} requires the device MPC core and share store — pass \\`mpc\\` and \\`shareStore\\` to \\`new Waaskey(...)\\`.`,\n 'device_core_required',\n );\n }\n // Hoisted out of the ceremony itself: a core without the routed export can never run a >2-party\n // quorum, and learning that only AFTER the platform party is on the relay is the #89 failure.\n if (quorum.length > 2 && !mpc.runMemberSign) {\n throw new WaaskeyError(`This wallet's sign quorum has ${quorum.length} parties, which needs an MPC core with routed (member-ceremony) sign support.`, 'unsupported');\n }\n const blob = await shareStore.get(this.id);\n if (!blob) {\n throw new WaaskeyError(`No stored device share for wallet ${this.id} — this device cannot join the signing quorum.`, 'share_not_found');\n }\n const { keyShare } = deserializeShare(blob);\n return { mpc, keyShare };\n }\n\n /**\n * Normalize a sign-session descriptor into the shared {@link DeviceCeremony}. The 2-party roster\n * comes from the descriptor's own `role`/`peerRole` (authoritative — the relay token is bound to\n * that role); a larger quorum carries no server-sent roster, so the wallet's own party slice — the\n * same slice the signer derives — supplies it.\n */\n private toSignCeremony(session: SignSessionResponse, quorum: string[]): DeviceCeremony {\n return {\n curve: session.curve,\n relayUrl: session.relayUrl,\n sessionId: session.sessionId,\n roles: session.participants.length === 2 ? sessionRoles(session) : quorum,\n participants: session.participants,\n signerPosition: session.signerPosition,\n relayToken: session.relayToken,\n };\n }\n\n /**\n * Run this device's half of a started ceremony. A 2-party quorum uses the plain single-peer\n * transport; anything larger MUST be roster-routed, or the transport attributes every inbound\n * message to the one configured peer and the protocol aborts on the third party's first message\n * (waas-core#131).\n */\n private runDeviceSign(mpc: MpcCore, ceremony: DeviceCeremony, keyShare: string, digest: string): Promise<{ signature: string }> {\n if (ceremony.participants.length === 2) {\n return mpc.runSign(toDeviceSignParams(ceremony, keyShare, digest));\n }\n // Normally unreachable — `loadDeviceParty` refuses a >2-party quorum without the routed export\n // before anything starts. It still guards here, because the STARTED ceremony's size is the\n // server's word and could exceed the quorum the wallet record described.\n if (!mpc.runMemberSign) {\n throw new WaaskeyError(\n `This wallet's sign quorum has ${ceremony.participants.length} parties, which needs an MPC core with routed (member-ceremony) sign support.`,\n 'unsupported',\n );\n }\n return mpc.runMemberSign({\n curve: toMpcCurve(ceremony.curve),\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n relayToken: ceremony.relayToken,\n roles: ceremony.roles,\n share: keyShare,\n participants: ceremony.participants,\n signerPosition: ceremony.signerPosition,\n digest,\n });\n }\n\n /**\n * Send a transaction from this wallet. The platform builds the chain-specific transaction\n * and co-signs it with the 2-of-3 MPC quorum, returning the **signed raw transaction**.\n * `value` is in the chain's base unit (wei) as a numeric string.\n *\n * **WaaS is sign-only — it never broadcasts.** The result's {@link SendResult.signedTx} is\n * the signed raw tx the *client* submits to its own node/provider (see\n * {@link Waaskey.broadcast} or your own submitter); {@link SendResult.txHash} is a\n * deterministic offline id for reference, not proof of broadcast.\n *\n * **Passkey step-up (Pattern B / issue #21, #39):** pass `{ requirePasskey: true }` to run a\n * WebAuthn assertion before sending, over a server-issued one-time challenge (verified + burned\n * server-side). Alternatively supply a pre-built assertion via `options.passkeyAssertion`.\n */\n async send(params: SendParams, options: SendOptions = {}): Promise<SendResult> {\n // An ed25519 (FROST) wallet is always device-co-signed — the platform cannot sign alone.\n if (this.data.curve === 'ed25519') {\n return this.sendEd25519(params, options);\n }\n // A secp wallet whose signing quorum holds the device is co-signed the same way: only the\n // platform can build the transaction (the client has no chain adapter to derive its digest),\n // so the ceremony must be split across three short requests rather than one held-open POST.\n const quorum = this.signQuorum();\n if ((quorum?.indexOf(DEVICE_ROLE) ?? -1) >= 0) {\n return this.sendWithDevice(params, options, quorum!);\n }\n // Platform-only quorum (custodial): the server signs alone — one request, no client party.\n const body: Record<string, unknown> = { ...params };\n await this.attachStepUp(body, 'send', options);\n const res = await this.http.request<SendResult>('POST', `/v1/wallets/${this.id}/send`, body, options.signal);\n this.analytics?.track('wallet.sent', { walletId: this.id, chain: params.chainId });\n return res;\n }\n\n /**\n * Device-co-signed send for a secp wallet — the cggmp24 counterpart of {@link sendEd25519}:\n *\n * 1. **START** (`POST …/send-session`): the platform runs the transfer gates, builds the unsigned\n * tx, puts its own party on the relay in the background, and returns the 32-byte digest plus\n * the relay coordination. It does NOT wait for the ceremony.\n * 2. **CO-SIGN**: this device runs its half over the relay with its stored share; cggmp24 hands\n * the completed signature to both parties.\n * 3. **ASSEMBLE** (`POST …/send-session/:txId/assemble`): the platform verifies the signature\n * (recovers to the wallet key AND equals its own party's) and embeds it into the wire tx.\n *\n * Every device-side precondition is resolved BEFORE the START (see {@link loadDeviceParty}), so a\n * device that cannot co-sign costs nothing: no tx is built and no platform party is left waiting.\n *\n * **A co-sign that fails after a successful START rejects with its typed error.** START is not the\n * commit point — it yields an *unsigned* tx and a pending session, and nothing broadcastable exists\n * until ASSEMBLE returns a `signedTx` — so there is no result to salvage by swallowing the failure,\n * and no fallback to `POST /send` (the platform cannot reach the threshold on this wallet alone, so\n * a retry there would only hang). The backend expires the abandoned session and fails the tx row.\n */\n private async sendWithDevice(params: SendParams, options: SendOptions, quorum: string[]): Promise<SendResult> {\n const { signal } = options;\n const { mpc, keyShare } = await this.loadDeviceParty(quorum, 'sending');\n throwIfAborted(signal);\n\n const startBody: Record<string, unknown> = { ...params };\n await this.attachStepUp(startBody, 'send', options);\n throwIfAborted(signal);\n const session = await this.http.request<SendSessionResponse>('POST', `/v1/wallets/${this.id}/send-session`, startBody, signal);\n const digest = sendPayload(session, 'digest');\n\n throwIfAborted(signal);\n const { signature } = await this.runDeviceSign(mpc, toSendCeremony(session), keyShare, digest);\n throwIfAborted(signal);\n const assemble: EddsaAssembleRequest = { signature };\n const res = await this.http.request<SendResult>('POST', `/v1/wallets/${this.id}/send-session/${session.txId}/assemble`, assemble, signal);\n this.analytics?.track('wallet.sent', { walletId: this.id, chain: params.chainId });\n return res;\n }\n\n /**\n * Device-co-signed send for an ed25519 (FROST) wallet (#110) — the browser holds the device FROST\n * share and co-signs 2-party with the backend `server` party over the relay:\n *\n * 1. **START** (`POST …/send-session`): the backend builds the unsigned tx (chain adapter), starts\n * its server FROST party on the relay in the background, and returns the raw `message` bytes to\n * sign + the relay coordination ({@link SendSessionResponse}).\n * 2. **CO-SIGN**: the device runs `signEddsa` over the relay with its stored `{keyPackage,\n * publicKeyPackage}` share; the two parties aggregate the RFC 8032 signature (returned locally).\n * 3. **ASSEMBLE** (`POST …/send-session/:txId/assemble`): the backend embeds the aggregated\n * signature into the wire tx (chain adapter) and returns the signed raw tx + offline `txHash`.\n *\n * WaaS stays sign-only: the returned {@link SendResult.signedTx} is what the client broadcasts.\n */\n private async sendEd25519(params: SendParams, options: SendOptions): Promise<SendResult> {\n const { mpc, shareStore } = this.device;\n if (!mpc || !shareStore) {\n throw new WaaskeyError(\n 'Signing an ed25519 transaction requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.',\n 'device_core_required',\n );\n }\n if (!mpc.runEddsaSign) {\n throw new WaaskeyError(\n 'The configured MPC core does not support ed25519 (FROST) signing — use a client-wasm build with the ed25519 (keygenEddsa/signEddsa) exports.',\n 'unsupported',\n );\n }\n const { signal } = options;\n throwIfAborted(signal);\n\n // Load this device's FROST share (persisted by the ed25519 keygen), keyed by wallet id.\n const blob = await shareStore.get(this.id);\n if (!blob) {\n throw new WaaskeyError(`No stored device share for wallet \"${this.id}\" — this device never completed the ed25519 keygen.`, 'share_not_found', {\n details: { walletId: this.id },\n });\n }\n const { keyPackage, publicKeyPackage } = deserializeEddsaShare(blob);\n\n // PHASE 1 — START. Passkey step-up (server-issued one-time challenge) rides the START body, exactly\n // as it does on the secp send; the backend verifies + burns it before its server party joins.\n const startBody: Record<string, unknown> = { ...params };\n await this.attachStepUp(startBody, 'send', options);\n throwIfAborted(signal);\n const session = await this.http.request<SendSessionResponse>('POST', `/v1/wallets/${this.id}/send-session`, startBody, signal);\n const message = sendPayload(session, 'message');\n\n // PHASE 2 — CO-SIGN over the relay. The device holds the FROST share; the server co-signs concurrently.\n throwIfAborted(signal);\n let signature: string;\n try {\n ({ signature } = await mpc.runEddsaSign({\n relayUrl: session.relayUrl,\n sessionId: session.sessionId,\n roles: session.roles,\n partyIndex: session.signerPosition,\n keyPackage,\n publicKeyPackage,\n participants: session.participants,\n message,\n relayToken: session.relayToken,\n }));\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The device ed25519 sign ceremony failed.', 'sign_failed', { cause });\n }\n\n // PHASE 3 — ASSEMBLE the wire tx from the aggregated signature.\n throwIfAborted(signal);\n const assemble: EddsaAssembleRequest = { signature };\n const res = await this.http.request<SendResult>('POST', `/v1/wallets/${this.id}/send-session/${session.txId}/assemble`, assemble, signal);\n this.analytics?.track('wallet.sent', { walletId: this.id, chain: params.chainId });\n return res;\n }\n\n /**\n * Attach a passkey step-up assertion to `body` when the caller requests one (issue #39).\n *\n * The challenge is a **server-issued one-time nonce**, never derived from the request\n * payload: the SDK fetches it from the step-up challenge endpoint, runs the WebAuthn\n * assertion over it, and echoes its `challengeId` so the server can verify and burn it —\n * making a captured assertion non-replayable. A pre-built `passkeyAssertion` (with its\n * `passkeyChallengeId`) is attached as-is and takes precedence over `requirePasskey`.\n */\n private attachStepUp(body: Record<string, unknown>, operation: StepUpOperation, options: SignOptions | SendOptions): Promise<void> {\n return attachPasskeyStepUp(this.http, this.id, body, operation, options);\n }\n\n /**\n * List this wallet's **signing activity**, newest first (paginated) — the unified audit\n * trail of what this key signed (raw signs and send/sweep signed txs, #289). A send/sweep\n * record carries the `signedTx` the client broadcasts.\n */\n async signatures(query: PageQuery = {}, options: SendOptions = {}): Promise<Page<Signature>> {\n const qs = new URLSearchParams();\n if (query.page !== undefined) qs.set('page', String(query.page));\n if (query.limit !== undefined) qs.set('limit', String(query.limit));\n const suffix = qs.toString() ? `?${qs}` : '';\n return this.http.request<Page<Signature>>('GET', `/v1/wallets/${this.id}/signatures${suffix}`, undefined, options.signal);\n }\n}\n\n/**\n * Attach a passkey step-up assertion to a sign/send request `body` when the caller requests one\n * (issue #39) — the standalone form of {@link Wallet}'s step-up, so other sign flows on a walletId\n * (e.g. {@link Wallets.recoverSign}, #351/#78) thread the SAME replay-safe challenge without\n * duplicating it. A pre-built `passkeyAssertion` (with its `passkeyChallengeId`) is attached as-is and\n * takes precedence over `requirePasskey`; otherwise, when `requirePasskey`, the SDK fetches a\n * server-issued one-time challenge, runs the WebAuthn assertion over it, and echoes its `challengeId`\n * so the server can verify and burn it. No-op when neither is set.\n */\nexport async function attachPasskeyStepUp(\n http: HttpClient,\n walletId: string,\n body: Record<string, unknown>,\n operation: StepUpOperation,\n options: SignOptions | SendOptions,\n): Promise<void> {\n if (options.passkeyAssertion !== undefined) {\n body['passkeyAssertion'] = options.passkeyAssertion;\n if (options.passkeyChallengeId !== undefined) body['passkeyChallengeId'] = options.passkeyChallengeId;\n return;\n }\n if (!options.requirePasskey) return;\n\n const { challengeId, challenge } = await http.request<StepUpChallengeResponse>('POST', `/v1/wallets/${walletId}/stepup/challenge`, { operation }, options.signal);\n body['passkeyAssertion'] = await getSigningAssertion(challenge, { credentialId: options.passkeyCredentialId });\n body['passkeyChallengeId'] = challengeId;\n}\n\n/**\n * Normalize a send descriptor into the shared {@link DeviceCeremony}. The send session names the whole\n * quorum (`roles` parallel to `participants`), so nothing has to be re-derived client-side.\n */\nfunction toSendCeremony(session: SendSessionResponse): DeviceCeremony {\n return {\n curve: session.curve,\n relayUrl: session.relayUrl,\n sessionId: session.sessionId,\n roles: session.roles,\n participants: session.participants,\n signerPosition: session.signerPosition,\n relayToken: session.relayToken,\n };\n}\n\n/**\n * The payload this curve's device party signs, taken off the send descriptor — the tx `digest` for\n * secp256k1 (cggmp24 signs a hash), the raw `message` bytes for ed25519 (FROST signs the message).\n * Exactly one is populated per curve, so a missing one means the descriptor does not match the wallet\n * being signed for; failing here keeps the device from joining a ceremony over undefined bytes.\n *\n * `details` carries only the ids — never the descriptor itself, which holds the short-lived\n * `relayToken` an app would then ship to its error reporter.\n */\nfunction sendPayload(session: SendSessionResponse, field: 'digest' | 'message'): string {\n const payload = session[field];\n if (!payload) {\n throw new WaaskeyError(`The send session did not return the \\`${field}\\` this wallet's curve (${session.curve}) signs.`, 'sign_failed', {\n details: { txId: session.txId, curve: session.curve },\n });\n }\n return payload;\n}\n\n/** Strip an optional `0x` and validate the digest is exactly 32 bytes of hex. */\nexport function normalizeDigest(digest: string): string {\n const hex = digest.startsWith('0x') || digest.startsWith('0X') ? digest.slice(2) : digest;\n if (!/^[0-9a-fA-F]{64}$/.test(hex)) {\n throw new WaaskeyError('`digest` must be a 32-byte hex string (64 hex chars, optional 0x prefix).', 'validation');\n }\n return hex;\n}\n","import { curveForChain, toMpcCurve } from './chains';\nimport { validateCustodyPolicy } from './custody';\nimport { serializeEddsaShare } from './eddsa-share';\nimport { getOrCreateDeviceEncKeypair, type DeviceEncKeypair } from './enc-keys';\nimport { WaaskeyError } from './errors';\nimport { delay, throwIfAborted } from './internal';\nimport { buildRecoveryRegistration, fetchRecoveryCiphertext, postRecoveryRegistration, type RecoveryRegisterPayload } from './recovery';\nimport { toSessionSignParams } from './session-sign';\nimport { serializeShare, deserializeShare } from './share-blob';\nimport { openWithPassword } from './storage/crypto';\nimport { attachPasskeyStepUp, normalizeDigest, Wallet } from './wallet';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { DeviceKeygenParams, DeviceKeygenResult, DeviceSignResult, EddsaKeygenResult, MpcCore, MpcCurve, PrimePool } from './mpc';\nimport type { ShareStore } from './storage';\nimport type {\n CreateMemberWalletParams,\n CreateWalletOptions,\n CreateWalletParams,\n CreateWalletResponse,\n JoinCeremonyOptions,\n JoinSignCeremonyOptions,\n MemberCeremony,\n MemberCeremonyJoinResponse,\n MemberSignCeremony,\n Page,\n PageQuery,\n RecoverSignParams,\n RecoveryFactor,\n RecoveryShareInfo,\n SigningRequestResponse,\n SignOptions,\n SignRequestsQuery,\n SignSessionResponse,\n WalletBackupParams,\n WalletCeremony,\n WalletData,\n WalletShareholder,\n} from './types';\n\n/** Bounded retry for the user_backup backup registration — transient failures only, short backoff. */\nconst BACKUP_REGISTER_ATTEMPTS = 3;\nconst BACKUP_REGISTER_BACKOFF_MS = 200;\n\n/**\n * The client-held second-user party role in the non-custodial default roster `[device, server, user_backup]`\n * (#351/#78). The ONE device runs it as a SECOND keygen party alongside `device` (the platform signer\n * drives only `server`), and its share is the non-custodial backup — sealed + registered, never platform-held.\n */\nconst USER_BACKUP_ROLE = 'user_backup';\n\nconst DEFAULT_ACTIVATION_TIMEOUT_MS = 60_000;\nconst DEFAULT_POLL_INTERVAL_MS = 1_000;\n\n/** Dependencies a {@link Wallets} resource needs for the non-custodial ceremony. */\nexport interface WalletsDeps {\n mpc?: MpcCore;\n shareStore?: ShareStore;\n /** Optional pool of pre-generated primes; when present, keygen claims one instead of generating inline. */\n primePool?: PrimePool;\n /** Optional analytics emitter for wallet lifecycle events. */\n analytics?: Analytics;\n}\n\n/**\n * The `wallets` resource: create and load wallets, plus the approver actions\n * ({@link Wallets.approveSignRequest}/{@link Wallets.declineSignRequest}) and the approver\n * queue listing ({@link Wallets.listSignRequests}/{@link Wallets.listPendingApprovals}) on\n * their async signing requests (#229, #309, #329).\n */\nexport class Wallets {\n constructor(\n private readonly http: HttpClient,\n private readonly deps: WalletsDeps = {},\n ) {}\n\n /**\n * Create a new MPC wallet on the given chain. The keygen is a `t`-of-`n` ceremony:\n *\n * 1. ask the API to start a wallet + the server party (returns the ceremony params),\n * 2. run the **device** half of keygen locally (in WASM) against the relay,\n * 3. seal + persist the device share (it never leaves the device),\n * 4. wait until the wallet is ACTIVE (server party finished) and return it.\n *\n * By default (no custody policy) this is the embedded **2-of-3** topology. Supply an\n * explicit `{ threshold, parties, custodyKinds }` and/or a requested `custodyType` to\n * change the topology / custody posture — the SDK validates it client-side (see\n * {@link validateCustodyPolicy}) and the backend enforces the attested invariant. The\n * device runs whatever `t`-of-`n` the returned ceremony describes (its `parties` /\n * `threshold`), so the ceremony is not pinned to 2-of-3.\n *\n * **Non-custodial `[device, server, user_backup]` (#351/#78).** When the returned ceremony carries a\n * `user_backup` party ({@link WalletCeremony.additionalParties}), the platform signer drives ONLY the\n * `server` share, so this ONE device runs BOTH client parties in the SAME keygen ceremony — the\n * `device` party AND the client-held `user_backup` party — joining the same relay session with each\n * party's own relay token. It then persists the `device` share locally (as always) and, because there\n * is no platform recovery share, seals the `user_backup` share with the caller's recovery code and\n * registers the ciphertext server-side (reusing the recovery mechanism), so device-loss can never lock\n * funds. This path therefore REQUIRES `options.backup`. The sealed backup is persisted to a local\n * pending slot BEFORE the network call, so if registration fails the (non-re-derivable) share is not\n * lost — `create` throws `backup_failed` and {@link retryBackup} re-registers it (no re-keygen).\n *\n * Requires `mpc` + `shareStore` on the client. The device share is the user's half\n * of the key; without storing it the wallet would be unrecoverable.\n */\n async create(params: CreateWalletParams, options: CreateWalletOptions = {}): Promise<Wallet> {\n const { mpc, shareStore, primePool } = this.deps;\n if (!mpc || !shareStore) {\n throw new WaaskeyError('Creating a wallet requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n\n validateCustodyPolicy(params);\n\n const curve = curveForChain(params.chain);\n const { signal } = options;\n throwIfAborted(signal);\n\n // Only send the custody policy fields that were actually supplied — omitting them keeps the\n // default (embedded 2-of-3) topology, so existing callers are unchanged (back-compatible).\n const body: Record<string, unknown> = { label: params.label ?? params.chain, curve };\n if (params.threshold !== undefined) body['threshold'] = params.threshold;\n if (params.parties !== undefined) body['parties'] = params.parties;\n if (params.custodyKinds !== undefined) body['custodyKinds'] = params.custodyKinds;\n if (params.custodyType !== undefined) body['custodyType'] = params.custodyType;\n\n // ed25519 (FROST) DKG round-2 seals each secret share to the recipient's X25519 key (#114), so the\n // device must advertise its OWN encryption public key up front: the backend echoes the ordered\n // roster back on the ceremony (`encPubkeys`) and the device seals its packages to it. Get-or-create\n // the device's long-lived enc keypair (reused across wallets + reshares) and send its public key.\n let deviceEncKeypair: DeviceEncKeypair | undefined;\n if (curve === 'ed25519') {\n deviceEncKeypair = await getOrCreateDeviceEncKeypair(shareStore);\n body['deviceEncPubkey'] = deviceEncKeypair.publicHex;\n throwIfAborted(signal);\n }\n\n const created = await this.http.request<CreateWalletResponse>('POST', '/v1/wallets', body, signal);\n // This (embedded, non-member-bound) create path always gets a ceremony back — `ceremony` is\n // only ever absent for a member-bound wallet (#342, created via `createWallet`, never here).\n const { ceremony } = created;\n if (!ceremony) {\n throw new WaaskeyError('The API did not return a keygen ceremony to join.', 'keygen_failed', { details: created });\n }\n\n // Device half of the keygen ceremony — joins the server party over the relay. ed25519 (FROST) and\n // cggmp24 (secp256k1) diverge: FROST is curveless, has no Paillier primes, and yields a\n // `{keyPackage, publicKeyPackage}` share sealed distinctly from the cggmp24 KeyShare blob.\n throwIfAborted(signal);\n if (curve === 'ed25519') {\n // `deviceEncKeypair` is always set above in the same `curve === 'ed25519'` branch.\n await this.runEddsaKeygen(mpc, shareStore, created.id, ceremony, deviceEncKeypair!);\n } else {\n // `curve` is narrowed to a cggmp24 curve here (ed25519 handled above), so it is an MpcCurve.\n await this.runSecpKeygen(mpc, shareStore, primePool, created.id, ceremony, curve, options.backup, signal);\n }\n this.deps.analytics?.track('wallet.created', { walletId: created.id, chain: params.chain, curve });\n\n if (options.waitForActive === false) {\n return new Wallet(this.http, created, this.deps.analytics, this.walletDeviceDeps());\n }\n const active = await this.waitUntilActive(created.id, options);\n return new Wallet(this.http, active, this.deps.analytics, this.walletDeviceDeps());\n }\n\n /**\n * Create a **member-bound** wallet (#342-#349): an N+1 threshold topology where `N` specific ORG\n * MEMBERSHIPS (`shareholderMembershipIds`) each hold one share and the platform holds exactly\n * one (a derived `shared` custody topology — never `embedded`). Unlike {@link create} (the\n * embedded device+server(+recovery) flow, which runs the device's keygen inline and waits for\n * ACTIVE), this wallet is provisioned `pending_keygen` with **no ceremony to join here** — it\n * has no `mpc`/`shareStore` dependency and no custody-policy validation (that machinery is for\n * the raw `parties`/`custodyKinds` embedded topology, mutually exclusive with\n * `shareholderMembershipIds` server-side). Each invited member later runs {@link joinCeremony}\n * from their OWN device/session; the wallet only activates once every member has joined.\n */\n async createWallet(params: CreateMemberWalletParams, options: { signal?: AbortSignal } = {}): Promise<WalletData> {\n if (!Array.isArray(params.shareholderMembershipIds) || params.shareholderMembershipIds.length === 0) {\n throw new WaaskeyError('`shareholderMembershipIds` must list at least 1 member.', 'validation');\n }\n if (new Set(params.shareholderMembershipIds).size !== params.shareholderMembershipIds.length) {\n throw new WaaskeyError('`shareholderMembershipIds` must be distinct.', 'validation');\n }\n if (params.threshold !== undefined) {\n const n = params.shareholderMembershipIds.length + 1;\n if (!Number.isInteger(params.threshold) || params.threshold < 2 || params.threshold > n) {\n throw new WaaskeyError(`\\`threshold\\` must be an integer in [2, ${n}] (the ${n - 1} members + 1 platform party).`, 'validation');\n }\n }\n const { signal } = options;\n throwIfAborted(signal);\n\n const body: Record<string, unknown> = { label: params.label, shareholderMembershipIds: params.shareholderMembershipIds };\n if (params.curve !== undefined) body['curve'] = params.curve;\n if (params.threshold !== undefined) body['threshold'] = params.threshold;\n\n return this.http.request<WalletData>('POST', '/v1/wallets', body, signal);\n }\n\n /**\n * Warm the prime pool for a chain's curve OFF the hot path — call during onboarding/idle (ideally\n * from a Web Worker) so the next {@link create} on that chain doesn't pay the safe-prime cost.\n * No-op when no prime pool is configured.\n */\n async prewarm(chain: CreateWalletParams['chain']): Promise<void> {\n const curve = curveForChain(chain);\n // ed25519 (FROST) needs no Paillier safe-primes, so there is nothing to prewarm for it.\n if (curve === 'ed25519') return;\n await this.deps.primePool?.ensure(curve);\n }\n\n /**\n * List the tenant's wallets, newest first (paginated). Returns plain {@link WalletData}\n * rows — pass an `id` to {@link get} to obtain a signing-capable {@link Wallet}.\n */\n async list(query: PageQuery = {}, options: { signal?: AbortSignal } = {}): Promise<Page<WalletData>> {\n const qs = new URLSearchParams();\n if (query.page !== undefined) qs.set('page', String(query.page));\n if (query.limit !== undefined) qs.set('limit', String(query.limit));\n const suffix = qs.toString() ? `?${qs}` : '';\n return this.http.request<Page<WalletData>>('GET', `/v1/wallets${suffix}`, undefined, options.signal);\n }\n\n /** Load an existing wallet by id. */\n async get(id: string, options: { signal?: AbortSignal } = {}): Promise<Wallet> {\n const data = await this.http.request<WalletData>('GET', `/v1/wallets/${id}`, undefined, options.signal);\n return new Wallet(this.http, data, this.deps.analytics, this.walletDeviceDeps());\n }\n\n /** The device core + share store a {@link Wallet} needs to co-sign an ed25519 (FROST) tx locally. */\n private walletDeviceDeps(): { mpc?: MpcCore; shareStore?: ShareStore } {\n return { mpc: this.deps.mpc, shareStore: this.deps.shareStore };\n }\n\n /**\n * Join a **member-bound** wallet's multi-device keygen ceremony (#344, #349) as an invited org\n * member — call this from the member's OWN device/session (never a tenant API key: every HTTP\n * call here is member-session-authenticated, see {@link HttpClient.requestAsMember}). Unlike\n * {@link create}, every member (N of them) + the platform join the SAME relay session, so:\n *\n * 1. fetch this member's own party ({@link MemberCeremony}) plus the wallet's other\n * share-holders (to derive the full n-party relay roster the ceremony needs),\n * 2. ack readiness (`POST .../ceremony/join`) — the backend starts its platform party's own\n * relay connection only once EVERY member has acked, so this must happen before the ceremony\n * can complete,\n * 3. run this device's half of the n-party keygen over the relay (blocks until every party,\n * including the platform, is present and the ceremony completes),\n * 4. seal + persist the device's ONE share, keyed by `(walletId, membershipId)` — never by\n * `walletId` alone, since several members' shares for the SAME wallet may live in one\n * `shareStore` (e.g. a shared device, or a test harness).\n *\n * Safe to retry: a failed ceremony reopens the roster server-side, and re-acking/re-running is\n * idempotent from the caller's perspective.\n */\n async joinCeremony(walletId: string, options: JoinCeremonyOptions = {}): Promise<MemberCeremonyJoinResponse> {\n const { mpc, shareStore } = this.deps;\n if (!mpc || !shareStore) {\n throw new WaaskeyError('Joining a keygen ceremony requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n if (!mpc.runMemberKeygen) {\n throw new WaaskeyError('The configured MPC core does not support n-party (member-bound) keygen — use a client-wasm build with member-ceremony support.', 'unsupported');\n }\n const { signal } = options;\n throwIfAborted(signal);\n\n const [ceremony, shareholders] = await Promise.all([\n this.http.requestAsMember<MemberCeremony>('GET', `/v1/wallets/${walletId}/ceremony/mine`, undefined, signal),\n this.http.requestAsMember<WalletShareholder[]>('GET', `/v1/wallets/${walletId}/shareholders`, undefined, signal),\n ]);\n const roles = buildMemberRoster(shareholders, ceremony.parties);\n\n throwIfAborted(signal);\n // Ack BEFORE running the ceremony: the backend only starts its platform party's relay\n // connection once every member has joined, so acking first is what lets the ceremony proceed.\n const joined = await this.http.requestAsMember<MemberCeremonyJoinResponse>('POST', `/v1/wallets/${walletId}/ceremony/join`, undefined, signal);\n\n throwIfAborted(signal);\n let keygen: DeviceKeygenResult;\n try {\n keygen = await mpc.runMemberKeygen({\n curve: toMpcCurve(ceremony.curve),\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n roles,\n partyIndex: ceremony.partyIndex,\n threshold: ceremony.threshold,\n relayToken: ceremony.relayToken,\n });\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The member device keygen ceremony failed.', 'keygen_failed', { cause });\n }\n\n await shareStore.put(memberShareKey(walletId, membershipIdFromRole(ceremony.role)), serializeShare(keygen));\n return joined;\n }\n\n /**\n * Join a **member-bound** wallet's multi-device SIGN ceremony (#347, #349) as an invited org\n * member — the signing analogue of {@link joinCeremony}, called from the member's OWN\n * device/session. A sign is a `t`-of-`n` SELECTION (only `t` of the N+1 parties actually sign),\n * so the flow is:\n *\n * 1. cast this member's APPROVE vote (`POST .../sign-requests/:reqId/approve`) — a no-op if\n * already cast; once `t-1` members have approved, the backend fixes the signing quorum,\n * 2. poll this member's own sign-ceremony party (`GET .../sign-requests/:reqId/ceremony/mine`)\n * until the quorum is fixed AND this member was selected into it ({@link MemberSignCeremony.ready}),\n * 3. load this member's OWN stored share (keyed by `(walletId, membershipId)`, from\n * {@link joinCeremony}) and run this device's half of the fixed-quorum sign ceremony —\n * the interactive protocol's public output IS the completed signature.\n *\n * A member who is not selected into the fixed quorum, or whose approval never gets it there,\n * simply times out (`sign_ceremony_timeout`) rather than running anything.\n */\n async joinSignCeremony(walletId: string, reqId: string, options: JoinSignCeremonyOptions = {}): Promise<DeviceSignResult> {\n const { mpc, shareStore } = this.deps;\n if (!mpc || !shareStore) {\n throw new WaaskeyError('Joining a sign ceremony requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n if (!mpc.runMemberSign) {\n throw new WaaskeyError('The configured MPC core does not support n-party (member-bound) signing — use a client-wasm build with member-ceremony support.', 'unsupported');\n }\n const { signal } = options;\n throwIfAborted(signal);\n\n // Cast (or re-cast — idempotent) this member's APPROVE vote. The `session` field on the\n // response is the 2-party device+server shape; a member-bound ceremony always learns its OWN\n // params from `ceremony/mine` below instead, so the vote response itself is not used here.\n await this.http.requestAsMember<SigningRequestResponse>('POST', `/v1/wallets/${walletId}/sign-requests/${reqId}/approve`, undefined, signal);\n\n const ceremony = await this.waitUntilReady(walletId, reqId, options);\n const membershipId = membershipIdFromRole(ceremony.role);\n const blob = await shareStore.get(memberShareKey(walletId, membershipId));\n if (!blob) {\n throw new WaaskeyError(`No stored device share for wallet \"${walletId}\" / member \"${membershipId}\" — this device never completed joinCeremony.`, 'share_not_found', {\n details: { walletId, membershipId },\n });\n }\n // Unpack the on-device storage blob into the bare KeyShare (crypto material) BEFORE handing it\n // to the MPC core — the core signs with the KeyShare, never the `{ keyShare, auxInfo, ... }`\n // storage wrapper. Keeping the blob format in `deserializeShare` (the inverse of the\n // `serializeShare` seal) means the MPC layer never learns the storage shape.\n const { keyShare } = deserializeShare(blob);\n\n throwIfAborted(signal);\n try {\n return await mpc.runMemberSign({\n curve: toMpcCurve(ceremony.curve),\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n roles: ceremony.quorumRoles,\n share: keyShare,\n participants: ceremony.participants,\n signerPosition: ceremony.signerPosition,\n digest: ceremony.digest,\n relayToken: ceremony.relayToken,\n });\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The member device sign ceremony failed.', 'sign_failed', { cause });\n }\n }\n\n /**\n * Approve a pending async signing request (#229) — either completing a single\n * device-approval request outright, or casting one APPROVE vote in an M-of-N approver\n * quorum (#309) configured on the wallet (via the tenant dashboard's `PUT .../quorum`). A\n * non-quorum request starts the MPC ceremony immediately; a quorum request only starts\n * it once enough approvers vote, and until then the response reports how many\n * approvals are still needed via {@link SigningRequestResponse.approvalsRemaining}.\n *\n * Takes `walletId` + `reqId` directly (rather than a {@link Wallet} instance) since an\n * approver typically learns of a pending request out-of-band — e.g. a\n * `sign_request.created` webhook or push notification — without first loading the wallet.\n */\n async approveSignRequest(walletId: string, reqId: string, options: { signal?: AbortSignal } = {}): Promise<SigningRequestResponse> {\n return this.http.request<SigningRequestResponse>('POST', `/v1/wallets/${walletId}/sign-requests/${reqId}/approve`, undefined, options.signal);\n }\n\n /**\n * Decline a pending async signing request (#229) — either rejecting a single\n * device-approval request outright, or casting a REJECT vote in an M-of-N approver\n * quorum (#309), which declines the request as soon as one approver rejects it.\n */\n async declineSignRequest(walletId: string, reqId: string, options: { signal?: AbortSignal } = {}): Promise<SigningRequestResponse> {\n return this.http.request<SigningRequestResponse>('POST', `/v1/wallets/${walletId}/sign-requests/${reqId}/decline`, undefined, options.signal);\n }\n\n /**\n * List a wallet's async signing requests, newest first (paginated) — optionally filtered to\n * a single lifecycle {@link SignRequestsQuery.status} (#332). The API paginates the\n * *filtered* set, so `total`/`page` always describe what was actually matched.\n */\n async listSignRequests(walletId: string, query: SignRequestsQuery = {}, options: { signal?: AbortSignal } = {}): Promise<Page<SigningRequestResponse>> {\n const qs = new URLSearchParams();\n if (query.status !== undefined) qs.set('status', query.status);\n if (query.page !== undefined) qs.set('page', String(query.page));\n if (query.limit !== undefined) qs.set('limit', String(query.limit));\n const suffix = qs.toString() ? `?${qs}` : '';\n return this.http.request<Page<SigningRequestResponse>>('GET', `/v1/wallets/${walletId}/sign-requests${suffix}`, undefined, options.signal);\n }\n\n /**\n * List a wallet's **pending approver queue** — the ergonomic entry point over\n * {@link listSignRequests} pinned to `status: 'pending_approval'` (#309, #329): the\n * requests currently awaiting an approver's {@link approveSignRequest}/\n * {@link declineSignRequest} vote, either a single device-approval request or one still\n * short of its M-of-N quorum (see {@link SigningRequestResponse.approvalsRemaining}).\n */\n async listPendingApprovals(walletId: string, query: PageQuery = {}, options: { signal?: AbortSignal } = {}): Promise<Page<SigningRequestResponse>> {\n return this.listSignRequests(walletId, { ...query, status: 'pending_approval' }, options);\n }\n\n /**\n * Run the cggmp24 (secp256k1) device keygen and persist the resulting share(s) (#351/#78). Two shapes,\n * chosen by whether the ceremony carries client-held extra parties ({@link WalletCeremony.additionalParties}):\n *\n * - **Single client party** (today's path — `[device, server]` or custodial `[device, server, recovery]`,\n * where the platform drives every non-device party): run just the `device` party and seal its share\n * under the wallet id, exactly as before.\n * - **Non-custodial `[device, server, user_backup]`** (a `user_backup` extra party): run BOTH the\n * `device` and `user_backup` parties CONCURRENTLY in the SAME relay session (each with its own\n * role-scoped relay token + its OWN Paillier primes), then persist the `device` share locally and\n * seal + register the `user_backup` share as the non-custodial backup (requires `backup`).\n *\n * Any additional party the client cannot drive (a non-`user_backup` role) is refused up front — leaving\n * it unjoined would hang the whole ceremony, so failing loud beats silently deadlocking.\n */\n private async runSecpKeygen(\n mpc: MpcCore,\n shareStore: ShareStore,\n primePool: PrimePool | undefined,\n walletId: string,\n ceremony: WalletCeremony,\n curve: MpcCurve,\n backup: WalletBackupParams | undefined,\n signal?: AbortSignal,\n ): Promise<void> {\n const extras = ceremony.additionalParties ?? [];\n const unsupported = extras.filter((party) => party.role !== USER_BACKUP_ROLE);\n if (unsupported.length > 0) {\n throw new WaaskeyError(\n `The keygen ceremony carries an additional client party this SDK cannot drive (${unsupported.map((party) => party.role).join(', ')}) — refusing to keygen, since leaving a party unjoined would hang the ceremony.`,\n 'unsupported',\n { details: { roles: unsupported.map((party) => party.role) } },\n );\n }\n const userBackupParty = extras.find((party) => party.role === USER_BACKUP_ROLE);\n\n // Single client party (back-compatible default): the device runs one party, the platform the rest.\n if (!userBackupParty) {\n // Claim a pre-generated prime (instant when the pool is warm) so keygen doesn't pay the\n // safe-prime cost on the hot path. Without a pool the core generates inline (slow in WASM).\n const pregeneratedPrimes = primePool ? await primePool.take(curve) : undefined;\n throwIfAborted(signal);\n const [keygen] = await this.runKeygenParties(mpc, [{ ...ceremony, curve, pregeneratedPrimes }]);\n // Seal + persist the device share (never sent to the server), with the ceremony's relay URL so a\n // device-present sign can rejoin the same relay (see Wallet.sign).\n await shareStore.put(walletId, serializeShare(keygen!, ceremony.relayUrl));\n return;\n }\n\n // Non-custodial `[device, server, user_backup]` (#351/#78): the ONE device runs TWO client parties.\n // Without the recovery-backup material we cannot register the user_backup share — and an un-backed-up\n // user_backup share means a lost device locks funds — so refuse before running anything.\n if (!backup) {\n throw new WaaskeyError(\n 'This wallet is a non-custodial [device, server, user_backup] topology whose user_backup share must be backed up at keygen — pass `options.backup` (recoveryCode + totpSecret + email) to `wallets.create(...)`, otherwise the wallet would be unrecoverable on device loss.',\n 'validation',\n );\n }\n\n // Each client party needs its OWN private Paillier primes — never shared. Two independent takes.\n const [devicePrimes, backupPrimes] = primePool ? await Promise.all([primePool.take(curve), primePool.take(curve)]) : [undefined, undefined];\n throwIfAborted(signal);\n // Run both parties in the SAME ceremony/relay session, concurrently — the `device` party (party 0,\n // from `ceremony`) and the client-held `user_backup` party (party 2, from the additional descriptor,\n // with its OWN relay token). They exchange messages via the relay with the platform `server` party.\n const [deviceKeygen, backupKeygen] = await this.runKeygenParties(mpc, [\n { ...ceremony, curve, pregeneratedPrimes: devicePrimes },\n { ...userBackupParty, curve, pregeneratedPrimes: backupPrimes },\n ]);\n // The `device` share is persisted locally, exactly as in the single-party path.\n await shareStore.put(walletId, serializeShare(deviceKeygen!, ceremony.relayUrl));\n throwIfAborted(signal);\n\n // The `user_backup` share is the NON-CUSTODIAL BACKUP. It exists ONLY in memory here and is NOT\n // re-derivable (a fresh keygen would yield a DIFFERENT share), so it must be made durable BEFORE the\n // network call: seal it with the caller's recovery code (the raw code never leaves the client — only\n // its SHA-256 is enrolled) and persist the resulting ciphertext to a LOCAL pending-backup slot. That\n // ciphertext is opaque without the recovery code, so a local copy is safe — it is a retry buffer, not\n // the authoritative backup. Only THEN register it server-side (the authoritative copy). If register\n // ultimately fails, the sealed share survives locally and `retryBackup(...)` re-registers it — a\n // network blip can never silently void the no-lockout guarantee by discarding the share.\n const { payload } = await buildRecoveryRegistration({ share: serializeShare(backupKeygen!), ...backup });\n await shareStore.put(userBackupPendingKey(walletId), JSON.stringify(payload));\n await this.registerBackup(walletId, payload, signal);\n // Registered server-side (authoritative) — drop the local retry buffer so the plaintext-recoverable\n // ciphertext isn't retained on-device beyond the durability window.\n await shareStore.remove(userBackupPendingKey(walletId));\n }\n\n /**\n * Register a sealed user_backup {@link RecoveryRegisterPayload} server-side, with a small bounded retry\n * on TRANSIENT failures (network / 5xx / rate-limit) — a flaky moment must not cost the backup. A\n * non-transient failure (4xx) fails fast. On abort, the abort propagates unchanged. If it ultimately\n * cannot register, throws a distinct, actionable {@link WaaskeyError} `backup_failed` (NOT `keygen_failed`)\n * — the caller's cue that the wallet was created but its backup is only local, and pointing at\n * {@link retryBackup}. The pending slot is intentionally NOT touched here, so a failure leaves the\n * sealed share intact for the retry.\n */\n private async registerBackup(walletId: string, payload: RecoveryRegisterPayload, signal?: AbortSignal): Promise<RecoveryShareInfo> {\n let lastCause: unknown;\n for (let attempt = 1; attempt <= BACKUP_REGISTER_ATTEMPTS; attempt++) {\n throwIfAborted(signal);\n try {\n return await postRecoveryRegistration(this.http, walletId, payload, signal);\n } catch (cause) {\n // A cancellation is the caller's intent — surface it as `aborted`, never as a backup failure.\n if (cause instanceof WaaskeyError && cause.code === 'aborted') throw cause;\n lastCause = cause;\n const transient = cause instanceof WaaskeyError && (cause.code === 'network' || cause.code === 'server_error' || cause.code === 'rate_limited');\n if (!transient || attempt === BACKUP_REGISTER_ATTEMPTS) break;\n await delay(BACKUP_REGISTER_BACKOFF_MS * attempt, signal);\n }\n }\n throw new WaaskeyError(\n `The wallet \"${walletId}\" was created, but registering its user_backup recovery backup failed. The sealed backup is retained locally — retry with \\`wallets.retryBackup(\"${walletId}\")\\`.`,\n 'backup_failed',\n { cause: lastCause, details: { walletId } },\n );\n }\n\n /**\n * Re-register a non-custodial wallet's user_backup backup that a previous {@link create} sealed locally\n * but could not register (a `backup_failed` create) (#351/#78). Reads the LOCAL pending-backup slot's\n * sealed ciphertext and re-POSTs it — **no re-keygen** (the share is not re-derivable) — with the same\n * bounded transient retry, then clears the slot on success. Idempotent-ish: a no-op `share_not_found`\n * when nothing is pending (already registered, or never created here). Requires a share store.\n */\n async retryBackup(walletId: string, options: { signal?: AbortSignal } = {}): Promise<RecoveryShareInfo> {\n const { shareStore } = this.deps;\n if (!shareStore) {\n throw new WaaskeyError('Retrying a wallet backup requires a share store — pass `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n const { signal } = options;\n throwIfAborted(signal);\n const stored = await shareStore.get(userBackupPendingKey(walletId));\n if (!stored) {\n throw new WaaskeyError(\n `No pending user_backup backup for wallet \"${walletId}\" — nothing to retry (it was already registered, or this device never created it).`,\n 'share_not_found',\n { details: { walletId } },\n );\n }\n const payload = parseBackupPayload(stored, walletId);\n const share = await this.registerBackup(walletId, payload, signal);\n // Registered — the local retry buffer has served its purpose.\n await shareStore.remove(userBackupPendingKey(walletId));\n return share;\n }\n\n /**\n * Device-loss RECOVERY CO-SIGN for a non-custodial `[device, server, user_backup]` secp256k1 wallet\n * (#351/#78). When the device is lost, the user restores their client-held `user_backup` share from the\n * sealed server-side backup and co-signs `digest` with the platform's `server` party — the 2-party\n * `{server, user_backup}` quorum. This is NOT the platform-only custodial `{server, recovery}` recoverSign\n * (`recovery.recoverSign` / `POST …/recovery/recover-sign`): here the platform CANNOT sign alone; the\n * user's restored share is the co-signing factor.\n *\n * 1. **RESTORE** — retrieve the sealed `user_backup` ciphertext (the multi-factor recovery gate,\n * {@link RecoverParams}, releases it) and open it with the recovery code CLIENT-SIDE (Contract A: the\n * raw code never leaves the device), yielding the cggmp24 `user_backup` KeyShare. No registered backup\n * fails `share_not_found`; a wrong recovery code fails `invalid_recovery_code` — either BEFORE any\n * ceremony starts, so a bad restore never signs (and never hangs).\n * 2. **START** — `POST /v1/wallets/:id/recover-sign-session` with the digest (+ passkey step-up when the\n * wallet requires it, threaded exactly like a normal sign via `options`) → the `user_backup` party's\n * ceremony descriptor: its role, the `{server, user_backup}` keygen `participants`, this party's\n * `signerPosition`, and a `user_backup`-role relay token.\n * 3. **CO-SIGN** — run the `user_backup` MPC party ({@link MpcCore.runSign}) over the relay with the\n * restored share + that descriptor; the platform `server` party co-signs server-side. Returns the\n * resulting signature.\n *\n * The ONLY differences from a normal `{device, server}` device sign are the SHARE (the restored\n * `user_backup`, not the local device share) and the DESCRIPTOR (from the recover-sign session, not the\n * normal sign session) — the same {@link MpcCore.runSign} relay machinery drives both.\n *\n * Requires `mpc` on the client (the co-signing core). No share store is needed: the restored share is\n * held only in memory for the ceremony and never persisted (the device is lost/new). secp256k1 only —\n * re-provisioning a fresh device share (reshare back to a full 2-of-3) is a separate follow-up.\n */\n async recoverSign(walletId: string, params: RecoverSignParams, options: SignOptions = {}): Promise<string> {\n const { mpc } = this.deps;\n if (!mpc) {\n throw new WaaskeyError('Recovery co-signing requires a device MPC core — pass `mpc` to `new Waaskey(...)`.', 'device_core_required');\n }\n const { signal } = options;\n throwIfAborted(signal);\n const digest = normalizeDigest(params.digest);\n\n // STEP 1 — RESTORE the user_backup share. Fetch the sealed ciphertext (the recovery gate releases it),\n // then open it with the recovery code CLIENT-SIDE — the raw code never reaches the server (Contract A).\n // Both restore failures are terminal and precede any ceremony, so a bad restore can never sign or hang.\n const ciphertext = await this.fetchUserBackupCiphertext(walletId, params, signal);\n const share = await restoreUserBackupShare(ciphertext, params.recoveryCode);\n throwIfAborted(signal);\n\n // STEP 2 — START the {server, user_backup} recover-sign session. The passkey step-up rides the START\n // body exactly as on a normal sign; the backend fails closed when the wallet requires a passkey.\n const body: Record<string, unknown> = { digest };\n if (params.chainId !== undefined) body['chainId'] = params.chainId;\n await attachPasskeyStepUp(this.http, walletId, body, 'sign', options);\n throwIfAborted(signal);\n const session = await this.http.request<SignSessionResponse>('POST', `/v1/wallets/${walletId}/recover-sign-session`, body, signal);\n\n // STEP 3 — CO-SIGN as the user_backup party over the relay (the server co-signs server-side).\n throwIfAborted(signal);\n let signature: string;\n try {\n ({ signature } = await mpc.runSign(toSessionSignParams(session, share, digest)));\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The user_backup device recover-sign ceremony failed.', 'sign_failed', { cause });\n }\n this.deps.analytics?.track('wallet.recovered', { walletId, curve: session.curve });\n return signature;\n }\n\n /**\n * Retrieve the sealed `user_backup` ciphertext via the recovery gate ({@link fetchRecoveryCiphertext}),\n * mapping a \"no recovery share registered\" (404) to the actionable `share_not_found` — this wallet has no\n * client-held `user_backup` backup to co-sign with (its device-loss recovery is the custodial path instead).\n */\n private async fetchUserBackupCiphertext(walletId: string, params: RecoverSignParams, signal?: AbortSignal): Promise<string> {\n try {\n return await fetchRecoveryCiphertext(this.http, walletId, params, signal);\n } catch (cause) {\n if (cause instanceof WaaskeyError && cause.code === 'not_found') {\n throw new WaaskeyError(\n `No registered user_backup recovery backup for wallet \"${walletId}\" — device-loss recover-sign needs a non-custodial [device, server, user_backup] wallet whose backup was registered at create.`,\n 'share_not_found',\n { cause, details: { walletId } },\n );\n }\n throw cause;\n }\n }\n\n /**\n * Run one or more device keygen parties (each `mpc.runKeygen`), concurrently, mapping any failure to a\n * single `keygen_failed`. Used for both the single `device` party and the two-party non-custodial\n * `[device, user_backup]` ceremony — one place owns the error contract so both paths stay identical.\n */\n private async runKeygenParties(mpc: MpcCore, params: DeviceKeygenParams[]): Promise<DeviceKeygenResult[]> {\n try {\n return await Promise.all(params.map((party) => this.runKeygenParty(mpc, party, params)));\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The device keygen ceremony failed.', 'keygen_failed', { cause });\n }\n }\n\n /**\n * Run ONE client keygen party over the right transport. A 2-party ceremony uses the plain\n * single-peer path; anything larger MUST be roster-routed — the 2-party transport attributes\n * every inbound message to the one configured peer, so a third party's very first message\n * aborts the protocol with \"route received message\" (waas-core#131).\n */\n private runKeygenParty(mpc: MpcCore, party: DeviceKeygenParams, batch: DeviceKeygenParams[]): Promise<DeviceKeygenResult> {\n if (party.parties <= 2) {\n return mpc.runKeygen(party);\n }\n if (!mpc.runMemberKeygen) {\n throw new WaaskeyError(\n `This keygen ceremony has ${party.parties} parties, which needs an MPC core with routed (member-ceremony) keygen support — use a client-wasm build exposing keygenMember.`,\n 'unsupported',\n );\n }\n return mpc.runMemberKeygen({\n curve: party.curve,\n relayUrl: party.relayUrl,\n sessionId: party.sessionId,\n roles: ceremonyRoster(party, batch),\n partyIndex: party.partyIndex,\n threshold: party.threshold,\n relayToken: party.relayToken,\n pregeneratedPrimes: party.pregeneratedPrimes,\n });\n }\n\n /**\n * Run the device half of an ed25519 (FROST) keygen (#110) and seal the resulting `{keyPackage,\n * publicKeyPackage}` share — the EdDSA counterpart of the cggmp24 `runKeygen` branch in {@link create}.\n * The device co-generates the group key with the backend `server` party over the relay; the FROST DKG\n * is the 2-party {device, server} quorum the ceremony names (M6 scope), roster-addressed like the\n * member ceremony rather than the cggmp24 single-peer shape.\n */\n private async runEddsaKeygen(mpc: MpcCore, shareStore: ShareStore, walletId: string, ceremony: WalletCeremony, encKeypair: DeviceEncKeypair): Promise<void> {\n if (!mpc.runEddsaKeygen) {\n throw new WaaskeyError(\n 'The configured MPC core does not support ed25519 (FROST) keygen — use a client-wasm build with the ed25519 (keygenEddsa/signEddsa) exports.',\n 'unsupported',\n );\n }\n const roles = buildEddsaKeygenRoster(ceremony);\n // The FROST DKG round-2 encryption roster (#114) — validated to carry THIS device's own enc pubkey\n // at its party index, so a wrong roster fails fast instead of silently mis-sealing the DKG packages.\n const encPubkeys = readEddsaEncRoster(ceremony, encKeypair);\n let keygen: EddsaKeygenResult;\n try {\n keygen = await mpc.runEddsaKeygen({\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n roles,\n partyIndex: ceremony.partyIndex,\n threshold: ceremony.threshold,\n relayToken: ceremony.relayToken,\n encPubkeys,\n encSecret: encKeypair.secretHex,\n });\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The device ed25519 keygen ceremony failed.', 'keygen_failed', { cause });\n }\n // Seal + persist the FROST device share (its `keyPackage` is secret and never sent to the server).\n await shareStore.put(walletId, serializeEddsaShare(keygen));\n }\n\n /** Poll the wallet until keygen completes (ACTIVE), or throw on failure/timeout. */\n private async waitUntilActive(id: string, options: CreateWalletOptions): Promise<WalletData> {\n const timeoutMs = options.activationTimeoutMs ?? DEFAULT_ACTIVATION_TIMEOUT_MS;\n const intervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const { signal } = options;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n throwIfAborted(signal);\n const wallet = await this.http.request<WalletData>('GET', `/v1/wallets/${id}`, undefined, signal);\n if (wallet.status === 'active') return wallet;\n if (wallet.status === 'failed') {\n throw new WaaskeyError('Wallet keygen failed.', 'keygen_failed', { details: wallet });\n }\n if (Date.now() >= deadline) {\n throw new WaaskeyError('Wallet did not activate before the timeout.', 'wallet_activation_timeout', { details: wallet });\n }\n await delay(intervalMs, signal);\n }\n }\n\n /** Poll the member's own sign ceremony until the t-of-n quorum is fixed AND this member is selected, or throw on timeout. */\n private async waitUntilReady(walletId: string, reqId: string, options: JoinSignCeremonyOptions): Promise<ReadyMemberSignCeremony> {\n const timeoutMs = options.readyTimeoutMs ?? DEFAULT_ACTIVATION_TIMEOUT_MS;\n const intervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const { signal } = options;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n throwIfAborted(signal);\n const ceremony = await this.http.requestAsMember<MemberSignCeremony>('GET', `/v1/wallets/${walletId}/sign-requests/${reqId}/ceremony/mine`, undefined, signal);\n if (isReadyMemberSignCeremony(ceremony)) return ceremony;\n if (Date.now() >= deadline) {\n throw new WaaskeyError('The signing quorum did not fix (or did not select this member) before the timeout.', 'sign_ceremony_timeout', { details: { walletId, reqId } });\n }\n await delay(intervalMs, signal);\n }\n }\n}\n\n/**\n * Open a sealed `user_backup` backup with the recovery code and unpack the cggmp24 KeyShare (#351/#78).\n * The ciphertext decrypts to the SAME on-device storage blob a device share uses ({@link serializeShare},\n * `{ keyShare, auxInfo, sharedPublicKey }`), so {@link deserializeShare} extracts the bare KeyShare the MPC\n * core signs with. A wrong recovery code makes `openWithPassword` throw → a typed `invalid_recovery_code`\n * (never a hang; the caller never starts a ceremony), keeping the raw code client-side (Contract A).\n */\nasync function restoreUserBackupShare(ciphertext: string, recoveryCode: string): Promise<string> {\n let blob: string;\n try {\n blob = await openWithPassword(recoveryCode, ciphertext);\n } catch (cause) {\n throw new WaaskeyError('Could not open the user_backup backup — wrong recovery code?', 'invalid_recovery_code', { cause });\n }\n return deserializeShare(blob).keyShare;\n}\n\n/**\n * Storage key for a member-bound wallet's per-member share (#349) — distinct from the embedded\n * flow's bare `walletId` key ({@link Wallet}'s single device share), since several members' shares\n * for the SAME wallet may live in one {@link ShareStore} (e.g. a shared device, or a test harness).\n */\nexport function memberShareKey(walletId: string, membershipId: string): string {\n return `${walletId}@member-${membershipId}`;\n}\n\n/**\n * Storage key for a non-custodial wallet's PENDING user_backup backup (#351/#78) — the sealed\n * {@link RecoveryRegisterPayload} ciphertext {@link Wallets.create} persists before registering it\n * server-side, so a failed/interrupted registration never loses the (non-re-derivable) user_backup share.\n * Distinct from the device share's bare `walletId` key; cleared by {@link Wallets.retryBackup} on success.\n * The value is opaque without the recovery code, so a local copy is a safe retry buffer.\n */\nexport function userBackupPendingKey(walletId: string): string {\n return `${walletId}:user_backup_pending`;\n}\n\n/** Parse a pending-backup slot's stored JSON back into a {@link RecoveryRegisterPayload}, or throw if corrupt. */\nfunction parseBackupPayload(stored: string, walletId: string): RecoveryRegisterPayload {\n let parsed: { ciphertext?: unknown; factors?: unknown };\n try {\n parsed = JSON.parse(stored) as { ciphertext?: unknown; factors?: unknown };\n } catch (cause) {\n throw new WaaskeyError(`The pending user_backup backup for wallet \"${walletId}\" is corrupt — it is not valid JSON.`, 'backup_failed', { cause, details: { walletId } });\n }\n if (typeof parsed.ciphertext !== 'string' || !Array.isArray(parsed.factors)) {\n throw new WaaskeyError(`The pending user_backup backup for wallet \"${walletId}\" is malformed.`, 'backup_failed', { details: { walletId, keys: Object.keys(parsed) } });\n }\n return { ciphertext: parsed.ciphertext, factors: parsed.factors.map((factor) => normalizeStoredFactor(factor, walletId)) };\n}\n\n/**\n * Repair a factor enrolment persisted by an SDK <= 0.3.1, which wrote the recovery-code hash under\n * `credentialHash` — a property the API rejects (#91). Those slots hold the ONLY copy of a\n * non-re-derivable `user_backup` share, so `retryBackup` must be able to register them after the\n * upgrade instead of re-POSTing the rejected shape forever. The stored value is already the SHA-256\n * (Contract A held on both shapes), so this only renames the field — nothing is re-hashed.\n *\n * A slot carrying NEITHER value (or no factor type) is corrupt, not legacy: it fails here with the\n * same typed `backup_failed` error {@link parseBackupPayload} throws, rather than being coerced to\n * an empty credential that the API would reject as an opaque 400 on every retry. The caller still\n * holds the sealed ciphertext, so a loud, typed failure is what lets them act on it.\n */\nfunction normalizeStoredFactor(factor: unknown, walletId: string): RecoveryRegisterPayload['factors'][number] {\n const { type, credential, credentialHash } = (factor ?? {}) as { type?: unknown; credential?: unknown; credentialHash?: unknown };\n const value = typeof credential === 'string' && credential !== '' ? credential : credentialHash;\n if (typeof type !== 'string' || type === '' || typeof value !== 'string' || value === '') {\n throw new WaaskeyError(`The pending user_backup backup for wallet \"${walletId}\" is malformed — a factor entry is missing its type or credential.`, 'backup_failed', {\n details: { walletId, factorKeys: Object.keys((factor ?? {}) as object) },\n });\n }\n return { type: type as RecoveryFactor, credential: value };\n}\n\n/** Parse the membership id out of a member-bound relay role (`member:<membershipId>`). */\nfunction membershipIdFromRole(role: string): string {\n const prefix = 'member:';\n if (!role.startsWith(prefix)) {\n throw new WaaskeyError(`Unexpected relay role \"${role}\" — expected a member-bound \"member:<membershipId>\" role.`, 'validation');\n }\n return role.slice(prefix.length);\n}\n\n/**\n * Resolve the full relay roster for one client party of a `parties > 2` keygen (waas-core#131).\n * Prefers the backend-supplied roster (`ceremony.roles`); otherwise reconstructs it from every\n * party descriptor the client holds (`role`/`peerRole` of each batch entry), filling ONE remaining\n * slot with the platform's `'recovery'` role — the party older backends run but never name. More\n * than one unnamed slot cannot be guessed and fails fast, demanding a backend that sends `roles`.\n */\nfunction ceremonyRoster(party: DeviceKeygenParams, batch: DeviceKeygenParams[]): string[] {\n if (party.roles) {\n if (party.roles.length !== party.parties) {\n throw new WaaskeyError(`The ceremony roster names ${party.roles.length} parties but the ceremony has ${party.parties}.`, 'validation');\n }\n return party.roles;\n }\n const roles: (string | undefined)[] = new Array<string | undefined>(party.parties).fill(undefined);\n const put = (index: number, role: string | undefined) => {\n if (role === undefined) return;\n if (index < 0 || index >= party.parties) {\n throw new WaaskeyError(`Ceremony party index ${index} is out of range for a ${party.parties}-party ceremony.`, 'validation');\n }\n if (roles[index] !== undefined && roles[index] !== role) {\n throw new WaaskeyError(`Conflicting ceremony roles for party index ${index}: \"${roles[index]}\" vs \"${role}\".`, 'validation');\n }\n roles[index] = role;\n };\n for (const entry of batch) {\n put(entry.partyIndex, entry.role ?? 'device');\n put(entry.peerPartyIndex, entry.peerRole ?? 'server');\n }\n const gaps = roles.reduce<number[]>((acc, role, index) => (role === undefined ? [...acc, index] : acc), []);\n if (gaps.length > 1) {\n throw new WaaskeyError(\n `The ${party.parties}-party keygen ceremony leaves ${gaps.length} party slots unnamed — this backend must supply the full ceremony roster (roles).`,\n 'validation',\n );\n }\n if (gaps.length === 1) roles[gaps[0]!] = 'recovery';\n return roles as string[];\n}\n\n/**\n * Build the full n-party relay roster from a member-bound wallet's share-holders (#349):\n * `roles[i]` is party `i`'s relay role — the N member roles at their own `partyIndex`, plus the\n * platform's `'platform'` role filling the one remaining slot (the platform party is not a\n * `wallet_shareholders` row, so it never appears in `shareholders`).\n */\nfunction buildMemberRoster(shareholders: WalletShareholder[], parties: number): string[] {\n const roles: (string | undefined)[] = new Array(parties).fill(undefined);\n for (const shareholder of shareholders) {\n if (shareholder.partyIndex < 0 || shareholder.partyIndex >= parties) {\n throw new WaaskeyError(`Share-holder partyIndex ${shareholder.partyIndex} is out of range for a ${parties}-party ceremony.`, 'validation');\n }\n roles[shareholder.partyIndex] = shareholder.role;\n }\n const gaps = roles.reduce<number[]>((acc, role, index) => (role === undefined ? [...acc, index] : acc), []);\n if (gaps.length !== 1) {\n throw new WaaskeyError('Could not derive the platform party slot from the wallet share-holders.', 'validation', { details: { parties, shareholders } });\n }\n roles[gaps[0]!] = 'platform';\n return roles as string[];\n}\n\n/**\n * Build the FROST keygen roster from an ed25519 (#110) keygen ceremony. The 2-party ceremony names this\n * device (`role` at `partyIndex`) and its `server` peer (`peerRole` at `peerPartyIndex`); the M6 ed25519\n * scope is exactly this 2-party {device, server} FROST DKG, so the roster is those two in protocol-index\n * order (e.g. `['device','server']`). Guards against an underspecified roster (a future >2-party ed25519\n * topology would carry its own full roster) so a mis-threaded ceremony fails clean rather than silently\n * running a different-sized DKG.\n */\nexport function buildEddsaKeygenRoster(ceremony: WalletCeremony): string[] {\n const slots = Math.max(ceremony.partyIndex, ceremony.peerPartyIndex) + 1;\n const roles: (string | undefined)[] = new Array(slots).fill(undefined);\n roles[ceremony.partyIndex] = ceremony.role;\n roles[ceremony.peerPartyIndex] = ceremony.peerRole;\n if (roles.some((role) => role === undefined)) {\n throw new WaaskeyError('The ed25519 keygen ceremony did not fully describe its party roster (only the 2-party device+server topology is supported).', 'keygen_failed', {\n details: { ceremony },\n });\n }\n return roles as string[];\n}\n\n/**\n * Read + validate the FROST DKG round-2 encryption roster (#114) an ed25519 keygen ceremony carries.\n * The roster is the parties-order list of X25519 enc PUBLIC keys every party seals its round-2 packages\n * to (`encPubkeys[i]` ↔ FROST id `i + 1`); it is passed to `keygenEddsa` as `enc_pubkeys` verbatim. As\n * a sanity check the roster's entry at THIS device's own party index must equal the device's own enc\n * public key — a mismatched roster would silently mis-seal every package (funds-unrecoverable), so it\n * fails fast. Throws when the backend omitted the roster (e.g. a pre-#114 API) so keygen can't proceed.\n */\nexport function readEddsaEncRoster(ceremony: WalletCeremony, encKeypair: DeviceEncKeypair): string[] {\n const roster = ceremony.encPubkeys;\n if (!Array.isArray(roster) || roster.length === 0) {\n throw new WaaskeyError(\n 'The ed25519 keygen ceremony did not return the FROST DKG round-2 encryption roster (encPubkeys) — the backend must advertise it (#114) before the device can seal its DKG packages.',\n 'keygen_failed',\n { details: { ceremony } },\n );\n }\n const own = roster[ceremony.partyIndex];\n if (typeof own !== 'string' || own.toLowerCase() !== encKeypair.publicHex.toLowerCase()) {\n throw new WaaskeyError(\n \"The ed25519 keygen ceremony's encPubkeys roster does not carry this device's own encryption public key at its party index — refusing to keygen against a mismatched roster (it would mis-seal the DKG packages).\",\n 'keygen_failed',\n { details: { partyIndex: ceremony.partyIndex } },\n );\n }\n return roster;\n}\n\n/** {@link MemberSignCeremony} narrowed to the fields that are present once {@link MemberSignCeremony.ready} is true. */\ntype ReadyMemberSignCeremony = MemberSignCeremony & Required<Pick<MemberSignCeremony, 'quorumRoles' | 'signerPosition' | 'participants' | 'digest'>>;\n\nfunction isReadyMemberSignCeremony(ceremony: MemberSignCeremony): ceremony is ReadyMemberSignCeremony {\n return ceremony.ready && ceremony.quorumRoles !== undefined && ceremony.signerPosition !== undefined && ceremony.participants !== undefined && ceremony.digest !== undefined;\n}\n","import { Analytics, HttpAnalyticsSink } from './analytics';\nimport { Auth } from './auth';\nimport { Balances } from './balances';\nimport { broadcast } from './broadcast';\nimport { HttpClient } from './http';\nimport { Members } from './members';\nimport { Onramp } from './onramp';\nimport { Recovery } from './recovery';\nimport { Reshare } from './reshare';\nimport { Wallets } from './wallets';\nimport type { AnalyticsSink } from './analytics';\nimport type { BroadcastOptions, BroadcastResult, WaaskeyOptions } from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.waaskey.com';\n\n/**\n * The Waaskey client — entry point of the SDK.\n *\n * @example\n * ```ts\n * import { Waaskey, WasmMpcCore, EncryptedShareStore } from '@waaskey/sdk';\n *\n * const waaskey = new Waaskey({\n * apiKey: process.env.WAASKEY_PUBLISHABLE_KEY!,\n * mpc: new WasmMpcCore(loadClientWasm),\n * shareStore: EncryptedShareStore.browser(sessionSecret),\n * });\n * const wallet = await waaskey.wallets.create({ chain: 'ethereum' });\n * const signature = await wallet.sign(digestHex);\n * ```\n */\nexport class Waaskey {\n /** The `wallets` resource. */\n readonly wallets: Wallets;\n /** The `recovery` resource — multi-factor, client-encrypted wallet recovery. */\n readonly recovery: Recovery;\n /** The `reshare` resource — device-side completion of a device-retaining reshare (#318). */\n readonly reshare: Reshare;\n /** The `balances` resource — client-side balance reads from a chain provider (no backend). */\n readonly balances: Balances;\n /** The `auth` resource — embedded end-user login (email-OTP, …) → non-custodial wallet. */\n readonly auth: Auth;\n /** The `members` resource — org-member (dashboard \"plane B\") bearer login for headless consumers. */\n readonly members: Members;\n /** The `onramp` resource — fund the wallet with fiat via a provider on-ramp. */\n readonly onramp: Onramp;\n /** Default fetch used by the optional {@link broadcast} helper (from `WaaskeyOptions.fetch`). */\n private readonly defaultFetch?: typeof fetch;\n\n constructor(options: WaaskeyOptions) {\n if (!options?.apiKey) {\n throw new Error('Waaskey: `apiKey` is required.');\n }\n const http = new HttpClient(options.apiKey, options.baseUrl ?? DEFAULT_BASE_URL, options.fetch);\n const analytics = new Analytics(resolveSink(options.analytics, http));\n this.auth = new Auth(http);\n this.members = new Members(http);\n // Wire the held member bearer into member-scoped calls (requestAsMember). Injected as a provider\n // (not an import) so Members and HttpClient don't form a cycle; once `members.loginWithFirebase`\n // holds a session, `wallets.joinCeremony` / `joinSignCeremony` authenticate over the bearer.\n http.useMemberAccessToken(() => this.members.accessToken);\n this.wallets = new Wallets(http, { mpc: options.mpc, shareStore: options.shareStore, primePool: options.primePool, analytics });\n this.recovery = new Recovery(http, { shareStore: options.shareStore, analytics });\n this.reshare = new Reshare(http, { mpc: options.mpc, shareStore: options.shareStore, analytics });\n this.balances = new Balances(options.chains, options.fetch);\n this.onramp = new Onramp(http);\n this.defaultFetch = options.fetch;\n }\n\n /**\n * **Optional** client-side broadcast of a signed raw tx from {@link Wallet.send}.\n *\n * WaaS is a **signing service** — `wallet.send(...)` returns `signedTx` and WaaS never\n * submits it. This is a thin, best-effort convenience to broadcast from **your own**\n * node/provider (one JSON-RPC call, no status polling / no retries — tracking is your\n * concern). Most integrators broadcast with their own infra.\n *\n * @example\n * ```ts\n * const { signedTx } = await wallet.send({ chainId: 'evm:1', to, value });\n * const { txHash } = await waaskey.broadcast(signedTx, { rpcUrl: 'https://your-rpc' });\n * ```\n */\n broadcast(signedTx: string, options: BroadcastOptions): Promise<BroadcastResult> {\n return broadcast(signedTx, { fetch: this.defaultFetch, ...options });\n }\n}\n\n/** On by default (HTTP sink → API); a custom sink is used as-is; `false` opts out (no sink). */\nfunction resolveSink(analytics: AnalyticsSink | false | undefined, http: HttpClient): AnalyticsSink | undefined {\n if (analytics === false) return undefined;\n return analytics ?? new HttpAnalyticsSink(http);\n}\n","import type {\n DeviceCompleteReshareParams,\n DeviceCompleteReshareResult,\n DeviceKeygenParams,\n DeviceKeygenResult,\n DeviceReshareAssembleParams,\n DeviceReshareAssembleResult,\n DeviceSignParams,\n DeviceSignResult,\n CeremonyParams,\n EddsaCeremonyParams,\n EddsaKeygenParams,\n EddsaKeygenResult,\n EddsaSignParams,\n EddsaSignResult,\n MemberCeremonyParams,\n MemberKeygenParams,\n MemberSignParams,\n MpcCurve,\n MpcCore,\n} from './types';\n\n/** The subset of the client-wasm module the SDK drives. Each export takes one JSON string. */\nexport interface ClientWasmModule {\n /** Device half of keygen; resolves with `{ aux_info_json, keyshare_json, shared_public_key_json }`. */\n keygen(paramsJson: string): Promise<unknown>;\n /** Device half of sign; resolves with `{ signature_json }`. */\n sign(paramsJson: string): Promise<unknown>;\n /** Pre-generate Paillier safe-primes off the hot path; resolves with `{ primes_json }`. Optional. */\n pregeneratePrimes?(paramsJson: string): Promise<unknown>;\n /**\n * Device reshare **assemble** — compute the NEW-epoch bare core locally; returns\n * `{ core_json, shared_public_key_json }`. Present only in a `--features reshare` wasm build.\n * Synchronous in the core (no relay); the SDK awaits it uniformly.\n */\n reshareAssemble?(paramsJson: string): unknown | Promise<unknown>;\n /**\n * Device **complete-reshare** — run the aux ceremony over the new committee and return the\n * signable share as `{ keyshare_json, shared_public_key_json }`. Present only in a\n * `--features reshare` wasm build.\n */\n completeReshare?(paramsJson: string): Promise<unknown>;\n /**\n * This party's half of an n-party (member-bound wallet) keygen ceremony (#349); resolves with\n * `{ aux_info_json, keyshare_json, shared_public_key_json }`. Present only in a client-wasm\n * build with n-party (member-ceremony) support.\n */\n keygenMember?(paramsJson: string): Promise<unknown>;\n /**\n * This party's half of an n-party (member-bound wallet) sign ceremony over a fixed t-of-n\n * quorum (#349); resolves with `{ signature_json }`. Present only in a client-wasm build with\n * n-party (member-ceremony) support.\n */\n signMember?(paramsJson: string): Promise<unknown>;\n /**\n * This device's half of an ed25519 (FROST) DKG keygen ceremony (#110); resolves with\n * `{ key_package, public_key_package }` (JSON objects). Present only in a client-wasm build with\n * the ed25519 (FROST) exports.\n */\n keygenEddsa?(paramsJson: string): Promise<unknown>;\n /**\n * This device's half of an ed25519 (FROST) two-round sign ceremony (#110); resolves with\n * `{ signature }` (64-byte hex). Present only in a client-wasm build with the ed25519 (FROST) exports.\n */\n signEddsa?(paramsJson: string): Promise<unknown>;\n}\n\n/** Lazily loads + initializes the client-wasm module (e.g. dynamic `import()` of the wasm-pack pkg). */\nexport type ClientWasmLoader = () => Promise<ClientWasmModule>;\n\ninterface RawKeygenResult {\n aux_info_json: string;\n keyshare_json: string;\n shared_public_key_json?: string;\n}\n\ninterface RawSignResult {\n signature_json: string;\n}\n\ninterface RawPrimesResult {\n primes_json: string;\n}\n\ninterface RawReshareAssembleResult {\n core_json: string;\n shared_public_key_json: string;\n}\n\ninterface RawCompleteReshareResult {\n keyshare_json: string;\n shared_public_key_json: string;\n}\n\ninterface RawEddsaKeygenResult {\n key_package: unknown;\n public_key_package: unknown;\n}\n\ninterface RawEddsaSignResult {\n signature: string;\n}\n\n/**\n * {@link MpcCore} backed by the waas-core `client-wasm` module (`keygen` / `sign`).\n *\n * The wasm engine is injected via a loader so the SDK stays runtime-agnostic and\n * the core is unit-testable without a real ceremony. The device key share returned\n * by keygen must be sealed and stored on the device — it is never sent to the server.\n */\nexport class WasmMpcCore implements MpcCore {\n private modulePromise?: Promise<ClientWasmModule>;\n\n constructor(private readonly load: ClientWasmLoader) {}\n\n private init(): Promise<ClientWasmModule> {\n return (this.modulePromise ??= this.load());\n }\n\n async runKeygen(params: DeviceKeygenParams): Promise<DeviceKeygenResult> {\n const wasm = await this.init();\n const raw = (await wasm.keygen(\n this.encode(params, { parties: params.parties, threshold: params.threshold, pregenerated_primes_json: params.pregeneratedPrimes }),\n )) as RawKeygenResult;\n\n if (!raw || typeof raw.keyshare_json !== 'string') {\n throw new Error('client-wasm returned an unexpected keygen result');\n }\n return {\n keyShare: raw.keyshare_json,\n auxInfo: raw.aux_info_json,\n sharedPublicKey: extractSharedPublicKey(raw.keyshare_json),\n };\n }\n\n async runSign(params: DeviceSignParams): Promise<DeviceSignResult> {\n const wasm = await this.init();\n const raw = (await wasm.sign(\n this.encode(params, {\n // The wasm deserializes `share` with `serde_json::from_value::<KeyShare>`, so it must ride\n // the wire as the KeyShare OBJECT — not a JSON string, and not the storage blob.\n share: toShareObject(params.share),\n participants: params.participants,\n signer_position: params.signerPosition,\n digest: params.digest,\n }),\n )) as RawSignResult;\n\n if (!raw || typeof raw.signature_json !== 'string') {\n throw new Error('client-wasm returned an unexpected sign result');\n }\n return { signature: raw.signature_json };\n }\n\n async pregeneratePrimes(curve: MpcCurve): Promise<string> {\n const wasm = await this.init();\n if (!wasm.pregeneratePrimes) {\n throw new Error('client-wasm does not expose pregeneratePrimes');\n }\n const raw = (await wasm.pregeneratePrimes(JSON.stringify({ curve }))) as RawPrimesResult;\n if (!raw || typeof raw.primes_json !== 'string') {\n throw new Error('client-wasm returned an unexpected pregeneratePrimes result');\n }\n return raw.primes_json;\n }\n\n async runReshareAssemble(params: DeviceReshareAssembleParams): Promise<DeviceReshareAssembleResult> {\n const wasm = await this.init();\n if (!wasm.reshareAssemble) {\n throw new Error(reshareFeatureHint('reshareAssemble'));\n }\n // Pure + local (no relay), so no relay-URL allowlist here. `reshare_assemble` is synchronous\n // in the core; awaiting a non-promise is a no-op, so this works whether the export is sync or async.\n const raw = (await wasm.reshareAssemble(\n JSON.stringify({\n curve: params.curve,\n new_position: params.newPosition,\n new_preimages: params.newPreimages,\n new_threshold: params.newThreshold,\n wallet: params.wallet,\n commitments: params.commitments,\n sub_shares: params.subShares,\n }),\n )) as RawReshareAssembleResult;\n\n if (!raw || typeof raw.core_json !== 'string') {\n throw new Error('client-wasm returned an unexpected reshareAssemble result');\n }\n return { core: raw.core_json, sharedPublicKey: decodePublicKey(raw.shared_public_key_json) };\n }\n\n async runCompleteReshare(params: DeviceCompleteReshareParams): Promise<DeviceCompleteReshareResult> {\n const wasm = await this.init();\n if (!wasm.completeReshare) {\n throw new Error(reshareFeatureHint('completeReshare'));\n }\n const raw = (await wasm.completeReshare(\n this.encode(params, {\n // The wasm expects the bare core as an inline JSON object (serde_json::Value), not a string.\n core: JSON.parse(params.core),\n parties: params.parties,\n // The device's OWN primes for the aux ceremony — never server-provided. Absent ⇒ generated inline.\n ...(params.pregeneratedPrimes === undefined ? {} : { pregenerated_primes_json: params.pregeneratedPrimes }),\n }),\n )) as RawCompleteReshareResult;\n\n if (!raw || typeof raw.keyshare_json !== 'string') {\n throw new Error('client-wasm returned an unexpected completeReshare result');\n }\n // Derive the public key from the completed share itself (as keygen does), so the invariant\n // check downstream compares the share's own key, not a separately-serialized value.\n return { keyShare: raw.keyshare_json, sharedPublicKey: extractSharedPublicKey(raw.keyshare_json) };\n }\n\n async runMemberKeygen(params: MemberKeygenParams): Promise<DeviceKeygenResult> {\n const wasm = await this.init();\n if (!wasm.keygenMember) {\n throw new Error(memberCeremonyFeatureHint('keygenMember'));\n }\n const raw = (await wasm.keygenMember(\n this.encodeMember(params, {\n roles: params.roles,\n party_index: params.partyIndex,\n threshold: params.threshold,\n ...(params.pregeneratedPrimes === undefined ? {} : { pregenerated_primes_json: params.pregeneratedPrimes }),\n }),\n )) as RawKeygenResult;\n\n if (!raw || typeof raw.keyshare_json !== 'string') {\n throw new Error('client-wasm returned an unexpected keygenMember result');\n }\n return {\n keyShare: raw.keyshare_json,\n auxInfo: raw.aux_info_json,\n sharedPublicKey: extractSharedPublicKey(raw.keyshare_json),\n };\n }\n\n async runMemberSign(params: MemberSignParams): Promise<DeviceSignResult> {\n const wasm = await this.init();\n if (!wasm.signMember) {\n throw new Error(memberCeremonyFeatureHint('signMember'));\n }\n const raw = (await wasm.signMember(\n this.encodeMember(params, {\n roles: params.roles,\n // Mirrors runSign: the wasm deserializes `share` with `serde_json::from_value::<KeyShare>`,\n // so the KeyShare rides the wire as an OBJECT, not a JSON string (and not the storage blob).\n share: toShareObject(params.share),\n participants: params.participants,\n // This device's protocol index into `roles` (the value the SDK calls `signerPosition`).\n // The wire key is `party_index` — the same field keygen sends — NOT `signer_position`.\n party_index: params.signerPosition,\n digest: params.digest,\n }),\n )) as RawSignResult;\n\n if (!raw || typeof raw.signature_json !== 'string') {\n throw new Error('client-wasm returned an unexpected signMember result');\n }\n return { signature: raw.signature_json };\n }\n\n async runEddsaKeygen(params: EddsaKeygenParams): Promise<EddsaKeygenResult> {\n const wasm = await this.init();\n if (!wasm.keygenEddsa) {\n throw new Error(eddsaFeatureHint('keygenEddsa'));\n }\n const raw = (await wasm.keygenEddsa(\n this.encodeEddsa(params, {\n threshold: params.threshold,\n // The FROST DKG round-2 encryption roster (#114): every party's X25519 enc PUBLIC key in `roles`\n // order (`enc_pubkeys[i]` ↔ FROST id i+1) + THIS device's own X25519 enc SECRET. `enc_secret` is\n // secret and MUST NOT be logged; the wasm seals/opens the round-2 packages with these.\n enc_pubkeys: params.encPubkeys,\n enc_secret: params.encSecret,\n }),\n )) as RawEddsaKeygenResult;\n\n if (!raw || raw.key_package === undefined || raw.public_key_package === undefined) {\n throw new Error('client-wasm returned an unexpected keygenEddsa result');\n }\n return { keyPackage: raw.key_package, publicKeyPackage: raw.public_key_package };\n }\n\n async runEddsaSign(params: EddsaSignParams): Promise<EddsaSignResult> {\n const wasm = await this.init();\n if (!wasm.signEddsa) {\n throw new Error(eddsaFeatureHint('signEddsa'));\n }\n const raw = (await wasm.signEddsa(\n this.encodeEddsa(params, {\n // The wasm re-serializes these with `serde_json::to_vec` + `import_*_package`, so each MUST\n // ride the wire as the FROST JSON OBJECT — not a JSON string (and not a storage wrapper).\n key_package: toFrostPackage(params.keyPackage, 'key_package'),\n public_key_package: toFrostPackage(params.publicKeyPackage, 'public_key_package'),\n participants: params.participants,\n message: params.message,\n }),\n )) as RawEddsaSignResult;\n\n if (!raw || typeof raw.signature !== 'string') {\n throw new Error('client-wasm returned an unexpected signEddsa result');\n }\n return { signature: raw.signature };\n }\n\n /** Build the snake_case params JSON the wasm exports expect from the common routing + extras. */\n private encode(p: CeremonyParams, extra: Record<string, unknown>): string {\n // The relay URL is server-supplied and fed straight into the MPC core (issue #41);\n // allowlist its scheme/host so a compromised control-plane can't point the device party\n // at an attacker relay over an unencrypted transport.\n assertAllowedRelayUrl(p.relayUrl);\n return JSON.stringify({\n curve: p.curve,\n relay_url: p.relayUrl,\n session_id: p.sessionId,\n role: p.role ?? 'device',\n peer_role: p.peerRole ?? 'server',\n party_index: p.partyIndex,\n peer_party_index: p.peerPartyIndex,\n // Only present the relay token when set, so an auth-disabled ceremony's wire payload\n // is byte-identical to before (the client-wasm treats absent as an unauthenticated join).\n ...(p.relayToken === undefined ? {} : { relay_token: p.relayToken }),\n ...extra,\n });\n }\n\n /**\n * Build the snake_case params JSON for an n-party (member-bound, #349) member ceremony — the\n * roster-based routing shape (`roles` + `party_index`), not the 2-party `role`/`peer_role` shape\n * {@link encode} builds. The `roles` roster and `party_index` are passed through in `extra` by\n * the caller and land on the wire under those exact keys — what `keygenMember` / `signMember`\n * deserialize.\n */\n private encodeMember(p: MemberCeremonyParams, extra: Record<string, unknown>): string {\n assertAllowedRelayUrl(p.relayUrl);\n return JSON.stringify({\n curve: p.curve,\n relay_url: p.relayUrl,\n session_id: p.sessionId,\n ...(p.relayToken === undefined ? {} : { relay_token: p.relayToken }),\n ...extra,\n });\n }\n\n /**\n * Build the snake_case params JSON for an ed25519 (FROST, #110) ceremony — the roster-based routing\n * shape (`roles` + `party_index`) the `keygenEddsa` / `signEddsa` exports deserialize. Unlike\n * {@link encodeMember} there is NO `curve` (ed25519-only) and no Paillier primes; the caller passes\n * the ceremony-specific extras (keygen: `threshold`; sign: the FROST packages + participants + message).\n */\n private encodeEddsa(p: EddsaCeremonyParams, extra: Record<string, unknown>): string {\n assertAllowedRelayUrl(p.relayUrl);\n return JSON.stringify({\n relay_url: p.relayUrl,\n session_id: p.sessionId,\n roles: p.roles,\n party_index: p.partyIndex,\n ...(p.relayToken === undefined ? {} : { relay_token: p.relayToken }),\n ...extra,\n });\n }\n}\n\n/** Actionable error when a wasm build lacks the reshare exports (built without `--features reshare`). */\nfunction reshareFeatureHint(fn: string): string {\n return `client-wasm does not expose ${fn} — rebuild @waaskey/client-wasm with the \\`reshare\\` feature enabled (wasm-pack build … -- --features reshare).`;\n}\n\n/**\n * Actionable error when a wasm build lacks the n-party (member-bound wallet, #349) member-ceremony\n * exports (`keygenMember` / `signMember`). These drive the roster-based (`roles` + `party_index`)\n * transport — every member device + the platform on one relay session — that the native\n * `party-runner` already uses (mirroring `waas-mpc-transport::PartyRouting`).\n */\nfunction memberCeremonyFeatureHint(fn: string): string {\n return `client-wasm does not expose ${fn} — rebuild @waaskey/client-wasm with n-party (member-ceremony) support (the keygenMember/signMember exports).`;\n}\n\n/**\n * Actionable error when a wasm build lacks the ed25519 (FROST, #110) exports (`keygenEddsa` /\n * `signEddsa`). These drive the threshold-EdDSA choreography the server `party-runner-eddsa` runs,\n * so a device build without them cannot create or sign an ed25519 (Solana/NEAR/Aptos/Sui) wallet.\n */\nfunction eddsaFeatureHint(fn: string): string {\n return `client-wasm does not expose ${fn} — rebuild @waaskey/client-wasm with the ed25519 (FROST) exports (keygenEddsa/signEddsa).`;\n}\n\n/**\n * Allowlist a server-supplied relay URL (issue #41): only encrypted WebSocket\n * transports are accepted — `wss://` to a **public** host, and plaintext `ws://`\n * solely for loopback (local dev). Anything else is refused before it reaches the\n * wasm core.\n *\n * Beyond the scheme, the **host** is allowlisted too: a compromised control-plane\n * must not be able to point the device party at an internal/private endpoint\n * (loopback, RFC1918, link-local incl. cloud metadata `169.254.169.254`, IPv6\n * unique-/link-local, `.internal`/`.local`) — an SSRF-style redirect of the MPC\n * transport. Loopback is the one exception, and only over plaintext `ws://` for dev.\n */\nfunction assertAllowedRelayUrl(relayUrl: string): void {\n let url: URL;\n try {\n url = new URL(relayUrl);\n } catch (cause) {\n throw new Error(`Invalid relay URL \"${relayUrl}\".`, { cause });\n }\n // Dev: plaintext ws:// is tolerated, but only to loopback.\n if (url.protocol === 'ws:' && isLoopbackHost(url.hostname)) return;\n if (url.protocol !== 'wss:') {\n throw new Error(`Refusing server-supplied relay URL \"${relayUrl}\" — only wss:// (or ws:// on localhost) is allowed for the MPC transport.`);\n }\n // wss:// — reject internal/private hosts (loopback included: prod relays are public).\n if (isInternalHost(url.hostname)) {\n throw new Error(`Refusing server-supplied relay URL \"${relayUrl}\" — the relay host is internal/private; only a public wss:// endpoint is allowed.`);\n }\n}\n\n/** Loopback host literals (used to permit ws:// only for local dev). */\nfunction isLoopbackHost(hostname: string): boolean {\n const host = hostname.replace(/^\\[|\\]$/g, '').toLowerCase();\n return host === 'localhost' || host === '::1' || /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(host);\n}\n\n/**\n * Is `hostname` an internal/private address a server must never send a client to?\n * Covers loopback, RFC1918 private v4, link-local v4 (incl. cloud metadata),\n * IPv6 unique-local (`fc00::/7`) + link-local (`fe80::/10`), and internal name\n * suffixes (`.internal`, `.local`). Public DNS names pass.\n */\nfunction isInternalHost(hostname: string): boolean {\n const host = hostname.replace(/^\\[|\\]$/g, '').toLowerCase();\n if (isLoopbackHost(hostname)) return true;\n if (host.endsWith('.internal') || host.endsWith('.local')) return true;\n\n const v4 = host.match(/^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/);\n if (v4) {\n const [a, b] = [Number(v4[1]), Number(v4[2])];\n if (a === 10) return true; // 10.0.0.0/8\n if (a === 172 && b >= 16 && b <= 31) return true; // 172.16.0.0/12\n if (a === 192 && b === 168) return true; // 192.168.0.0/16\n if (a === 169 && b === 254) return true; // 169.254.0.0/16 link-local (cloud metadata)\n return false;\n }\n\n if (host.includes(':')) {\n // IPv6 unique-local (fc00::/7 → fc/fd) and link-local (fe80::/10).\n if (/^f[cd][0-9a-f]{0,2}:/.test(host)) return true;\n if (/^fe[89ab][0-9a-f]:/.test(host)) return true;\n }\n return false;\n}\n\n/**\n * Coerce a device KeyShare into the inline JSON OBJECT the wasm sign exports expect. Both the\n * 2-party `sign` and the n-party `signMember` exports deserialize the wire `share` with\n * `serde_json::from_value::<KeyShare>`, so it MUST be a JSON object — a `share` sent as a JSON\n * string fails Rust deserialization (\"invalid type: string, expected struct\"). The KeyShare normally\n * arrives as its JSON string ({@link DeviceSignParams.share}); accept an already-parsed object too so\n * a caller can never double-encode it. The storage-blob wrapper is unpacked upstream — the core only\n * ever sees the bare KeyShare.\n */\nfunction toShareObject(share: unknown): Record<string, unknown> {\n const value: unknown = typeof share === 'string' ? JSON.parse(share) : share;\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('KeyShare must be a JSON object (or its JSON string), not a scalar or array.');\n }\n return value as Record<string, unknown>;\n}\n\n/**\n * Coerce a FROST package (`key_package` / `public_key_package`) into the inline JSON OBJECT the wasm\n * `signEddsa` export expects. The wasm re-serializes each with `serde_json::to_vec` + `import_*_package`,\n * so it MUST be a JSON object — the ed25519 analogue of {@link toShareObject}. The package normally\n * arrives as its JSON object (from {@link EddsaKeygenResult}); accept its JSON string too (a\n * storage round-trip) so a caller can never double-encode it.\n */\nfunction toFrostPackage(pkg: unknown, which: string): Record<string, unknown> {\n const value: unknown = typeof pkg === 'string' ? JSON.parse(pkg) : pkg;\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`FROST ${which} must be a JSON object (or its JSON string), not a scalar or array.`);\n }\n return value as Record<string, unknown>;\n}\n\n/** Pull the shared public key out of a KeyShare JSON (`core.shared_public_key`). */\nfunction extractSharedPublicKey(keyShareJson: string): string {\n const parsed = JSON.parse(keyShareJson) as { core?: { shared_public_key?: unknown } };\n const pk = parsed.core?.shared_public_key;\n if (typeof pk !== 'string') {\n throw new Error('KeyShare is missing core.shared_public_key');\n }\n return pk;\n}\n\n/**\n * Decode the wasm's separately-surfaced `shared_public_key_json` (a JSON-encoded compressed-hex\n * point, e.g. `\"03ab…\"`) into the bare hex string. Used for the reshare **assemble** result, whose\n * bare core does not expose `core.shared_public_key` in the keygen shape.\n */\nfunction decodePublicKey(sharedPublicKeyJson: string): string {\n const pk = JSON.parse(sharedPublicKeyJson) as unknown;\n if (typeof pk !== 'string') {\n throw new Error('reshare assemble result is missing a shared_public_key');\n }\n return pk;\n}\n","import type { ClientWasmLoader, ClientWasmModule } from './wasm-core';\n\n/**\n * The optional peer dependency that ships the wasm engine (waas-core client-wasm, wasm-pack build).\n *\n * **Reshare (#318):** the device-side reshare exports (`reshareAssemble` / `completeReshare`, used by\n * the `reshare` resource) are behind the core's `reshare` Cargo feature, so the shipped module must be\n * built with it — `wasm-pack build client-wasm --release --target web --scope waaskey -- --features reshare`.\n * A build without the feature lacks those exports and `reshare.complete(...)` fails closed with an\n * actionable error; keygen/sign are unaffected. The base curve exports need no feature flag.\n */\nconst CLIENT_WASM_PACKAGE = '@waaskey/client-wasm';\n\n/**\n * The **exact** `@waaskey/client-wasm` version this SDK build is pinned to (issue #40).\n *\n * Pin an exact version — never a floating `^`/`~` range — so a compromised or\n * dependency-confused higher release can't be silently pulled in. Keep this in\n * lockstep with the `@waaskey/client-wasm` entry in `package.json` and with\n * {@link CLIENT_WASM_SHA384}.\n *\n * **`0.2.x` adds the ed25519 (FROST) exports** (`keygenEddsa` / `signEddsa`, waas-core #110) the SDK's\n * ed25519 wallet path drives. It is **published on npm** (`client-wasm-v0.2.1`) and pinned as the SDK's\n * exact, optional peer dependency in `package.json` — so an app that installs `@waaskey/client-wasm`\n * alongside the SDK runs the real ed25519 create/send path end to end.\n */\nexport const CLIENT_WASM_VERSION = '0.2.2';\n\n/**\n * Verify the integrity of raw wasm bytes against an expected **SHA-384** hash, in\n * Subresource-Integrity (`sha384-<base64>`) form (issue #40).\n *\n * The wasm MPC core handles the plaintext device share, so it must be\n * cryptographically verified **before** `WebAssembly.compile` / `instantiate` — a\n * registry compromise or malicious re-host otherwise silently exfiltrates share-1.\n * Throws (fails closed) on any mismatch.\n */\nexport async function verifyWasmIntegrity(bytes: BufferSource, expectedSha384: string): Promise<void> {\n if (!expectedSha384 || !expectedSha384.startsWith('sha384-')) {\n throw new Error('Waaskey: an expected SHA-384 integrity hash (sha384-<base64>) is required to load the wasm MPC core.');\n }\n const digest = await crypto.subtle.digest('SHA-384', bytes);\n const actual = `sha384-${toBase64(new Uint8Array(digest))}`;\n if (!timingSafeEqual(actual, expectedSha384)) {\n throw new Error(`Waaskey: client-wasm integrity check FAILED — refusing to instantiate the MPC core (expected ${expectedSha384}, got ${actual}).`);\n }\n}\n\n/** Options for {@link createVerifiedClientWasmLoader}. */\nexport interface VerifiedWasmLoaderOptions {\n /**\n * URL (or path the runtime's `fetch` accepts) of the `@waaskey/client-wasm` `.wasm`\n * binary — vendored/self-hosted so its bytes can be fetched and hashed before use.\n */\n wasmUrl: string | URL;\n /** Expected SHA-384 of the wasm binary, SRI form (`sha384-<base64>`). Pin per {@link CLIENT_WASM_VERSION}. */\n expectedSha384: string;\n /** Custom fetch (non-browser runtimes / tests). Defaults to global `fetch`. */\n fetch?: typeof fetch;\n}\n\n/**\n * Build an integrity-checked {@link ClientWasmLoader} (issue #40): it fetches the\n * pinned `.wasm` bytes, verifies their SHA-384 against `expectedSha384`, and only\n * **then** compiles + initializes the module — so a tampered binary is rejected\n * before any wasm code runs.\n *\n * Requires a non-auto-initializing (wasm-pack `--target web`) `@waaskey/client-wasm`\n * build, so the verified bytes drive initialization:\n *\n * ```ts\n * const mpc = new WasmMpcCore(\n * createVerifiedClientWasmLoader({ wasmUrl: '/waaskey_client_wasm_bg.wasm', expectedSha384: CLIENT_WASM_SHA384 }),\n * );\n * ```\n */\nexport function createVerifiedClientWasmLoader(options: VerifiedWasmLoaderOptions): ClientWasmLoader {\n return async (): Promise<ClientWasmModule> => {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n if (!fetchImpl) {\n throw new Error('Waaskey: no fetch implementation available to load the wasm MPC core — pass `fetch` in the loader options.');\n }\n\n let bytes: ArrayBuffer;\n try {\n const res = await fetchImpl(options.wasmUrl instanceof URL ? options.wasmUrl.href : options.wasmUrl);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n bytes = await res.arrayBuffer();\n } catch (cause) {\n throw new Error(`Waaskey: failed to fetch the client-wasm binary from ${String(options.wasmUrl)}.`, { cause });\n }\n\n // Verify BEFORE compile/instantiate — fail closed on any mismatch.\n await verifyWasmIntegrity(bytes, options.expectedSha384);\n const compiled = await WebAssembly.compile(bytes);\n\n let mod: Record<string, unknown>;\n try {\n mod = (await import(CLIENT_WASM_PACKAGE)) as Record<string, unknown>;\n } catch (cause) {\n throw new Error(\"Waaskey: creating a wallet needs the wasm engine — install '@waaskey/client-wasm' alongside '@waaskey/sdk'.\", { cause });\n }\n\n // Initialize the wasm-pack module with the VERIFIED, already-compiled module.\n const init = (mod['default'] ?? mod['init']) as ((moduleOrPath?: unknown) => Promise<unknown>) | undefined;\n const initSync = mod['initSync'] as ((moduleOrPath?: unknown) => unknown) | undefined;\n if (typeof init === 'function') {\n await init(compiled);\n } else if (typeof initSync === 'function') {\n initSync(compiled);\n }\n return mod as unknown as ClientWasmModule;\n };\n}\n\n/**\n * Convenience loader for the Waaskey client-wasm engine — dynamically imports `@waaskey/client-wasm`\n * (the wasm-pack/bundler build, auto-initialized on import) and returns it as a {@link ClientWasmModule}:\n *\n * ```ts\n * import { Waaskey, WasmMpcCore, loadClientWasm } from '@waaskey/sdk';\n * const waaskey = new Waaskey({ apiKey, mpc: new WasmMpcCore(loadClientWasm), shareStore });\n * ```\n *\n * ⚠️ **No integrity verification (issue #40).** A bundler-target build instantiates the wasm on\n * import, so its bytes cannot be checked first. For production — where a registry compromise or\n * dependency-confusion attack on `@waaskey/client-wasm` could exfiltrate the plaintext device share\n * — use {@link createVerifiedClientWasmLoader} with a vendored `.wasm` and the pinned SHA-384 instead.\n *\n * `@waaskey/client-wasm` is an OPTIONAL peer dependency pinned to {@link CLIENT_WASM_VERSION}: install\n * it alongside the SDK in apps that create wallets. The indirect import specifier keeps it out of\n * static module resolution — so a missing install fails here with an actionable message, not at build.\n */\nlet clientWasm: Promise<ClientWasmModule> | undefined;\n\nexport const loadClientWasm: ClientWasmLoader = async (): Promise<ClientWasmModule> => {\n // Memoized: the engine is a process-wide singleton, and initializing it twice re-instantiates\n // the wasm memory (throwing away any state the first instance holds).\n return (clientWasm ??= importAndInit());\n};\n\nasync function importAndInit(): Promise<ClientWasmModule> {\n let mod: Record<string, unknown>;\n try {\n mod = (await import(CLIENT_WASM_PACKAGE)) as Record<string, unknown>;\n } catch (cause) {\n throw new Error(\"Waaskey: creating a wallet needs the wasm engine — install '@waaskey/client-wasm' alongside '@waaskey/sdk'.\", { cause });\n }\n\n // The package is a wasm-pack `--target web` build, so it does NOT auto-initialize: every export\n // reads through an uninitialized binding and throws `Cannot read properties of undefined\n // (reading '__wbindgen_malloc')` until the module's default init has run. Run it here so callers\n // get a usable core rather than a module that fails on first use.\n const init = (mod['default'] ?? mod['init']) as ((moduleOrPath?: unknown) => Promise<unknown>) | undefined;\n if (typeof init === 'function') {\n try {\n await init();\n } catch (cause) {\n throw new Error(\n 'Waaskey: the wasm engine failed to initialize. In the browser this loader fetches the `.wasm` next to the module — serve it, or pass a loader built with `createVerifiedClientWasmLoader({ wasmUrl, expectedSha384 })`. On Node use `NodeWorkerMpcCore` from `@waaskey/sdk/node`, which loads the binary from disk in a worker thread.',\n { cause },\n );\n }\n }\n return mod as unknown as ClientWasmModule;\n}\n\n/** Drop the memoized engine — tests only, so a fresh import/init can be observed. */\nexport function resetClientWasmForTest(): void {\n clientWasm = undefined;\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\n/** Constant-time string equality (avoids leaking hash-comparison timing). */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n","import type { MpcCurve } from './types';\n\n/**\n * Client-side pool of pre-generated Paillier safe-primes (#2).\n *\n * Safe-prime generation is the slow part of a device keygen — minutes in single-threaded\n * browser WASM. Primes don't depend on the key, so we generate them **ahead of the hot path**\n * (a Web Worker during onboarding/idle) and cache a small pool; at keygen time we hand one over\n * instantly. The primes are this device's PRIVATE aux material — they are cached locally and\n * NEVER sent to the server (serving them from the API would let the server recover the device's\n * share). Use an encrypted store in production.\n */\n\n/** Where the pool persists cached primes. Swap in an encrypted IndexedDB store for production. */\nexport interface PrimePoolStore {\n /** Remove and return one cached prime for `curve`, or undefined if the pool is empty. */\n take(curve: MpcCurve): Promise<string | undefined>;\n /** Add a generated prime to the pool. */\n add(curve: MpcCurve, primes: string): Promise<void>;\n /** Current number of cached primes for `curve`. */\n size(curve: MpcCurve): Promise<number>;\n}\n\n/** Default in-memory store (lost on reload). Production should persist to an encrypted store. */\nexport class MemoryPrimeStore implements PrimePoolStore {\n private readonly pools = new Map<MpcCurve, string[]>();\n\n async take(curve: MpcCurve): Promise<string | undefined> {\n return this.pools.get(curve)?.shift();\n }\n\n async add(curve: MpcCurve, primes: string): Promise<void> {\n const pool = this.pools.get(curve) ?? [];\n pool.push(primes);\n this.pools.set(curve, pool);\n }\n\n async size(curve: MpcCurve): Promise<number> {\n return this.pools.get(curve)?.length ?? 0;\n }\n}\n\n/** The minimal core capability the pool needs — just prime generation. */\ninterface PrimeGenerator {\n pregeneratePrimes(curve: MpcCurve): Promise<string>;\n}\n\nexport interface PrimePoolOptions {\n /** How many spare primes to keep cached per curve. Default 2. */\n targetSize?: number;\n /** Persistence for the pool. Defaults to an in-memory store. */\n store?: PrimePoolStore;\n /**\n * Kick off a refill automatically after every {@link PrimePool.take}. Default `false`:\n * unless the core generates primes in a Web Worker, wasm prime generation is a\n * synchronous CPU burn on the calling thread — a \"background\" refill starves the event\n * loop and stalls the very keygen ceremony the take() was for (it also freezes a\n * browser UI). Refill explicitly via {@link PrimePool.ensure} (`wallets.prewarm`) at\n * boot/idle, or set `true` only when the core is worker-backed.\n */\n autoRefill?: boolean;\n}\n\nexport class PrimePool {\n private readonly store: PrimePoolStore;\n private readonly targetSize: number;\n private readonly autoRefill: boolean;\n /** Per-curve in-flight refill, so concurrent calls don't over-generate. */\n private readonly refilling = new Map<MpcCurve, Promise<void>>();\n\n constructor(\n private readonly core: PrimeGenerator,\n options: PrimePoolOptions = {},\n ) {\n this.store = options.store ?? new MemoryPrimeStore();\n this.targetSize = Math.max(1, options.targetSize ?? 2);\n this.autoRefill = options.autoRefill ?? false;\n }\n\n /**\n * Top up the pool to the target size — call this OFF the hot path (onboarding/idle, ideally a\n * Web Worker). Deduped per curve, so calling it repeatedly is safe and cheap.\n */\n ensure(curve: MpcCurve): Promise<void> {\n const inflight = this.refilling.get(curve);\n if (inflight) return inflight;\n const task = this.refill(curve).finally(() => this.refilling.delete(curve));\n this.refilling.set(curve, task);\n return task;\n }\n\n private async refill(curve: MpcCurve): Promise<void> {\n while ((await this.store.size(curve)) < this.targetSize) {\n await this.store.add(curve, await this.core.pregeneratePrimes(curve));\n }\n }\n\n /**\n * Claim a prime for a keygen. Returns a cached one instantly when the pool is warm; otherwise\n * generates one inline (the slow fallback) so keygen never fails on an empty pool. Refill the\n * pool for the next wallet via {@link ensure} at idle (or opt into `autoRefill` when the core\n * is worker-backed).\n */\n async take(curve: MpcCurve): Promise<string> {\n const cached = await this.store.take(curve);\n const primes = cached ?? (await this.core.pregeneratePrimes(curve));\n if (this.autoRefill) void this.ensure(curve).catch(() => undefined);\n return primes;\n }\n}\n","import type { KeyValueStore } from './types';\n\n/**\n * IndexedDB-backed {@link KeyValueStore} — the default persistent backend on web.\n * A single object store holds opaque ciphertext records keyed by string, so device\n * shares survive a reload. Stores only sealed data (see EncryptedShareStore).\n */\nexport class IndexedDbKeyValueStore implements KeyValueStore {\n private dbPromise?: Promise<IDBDatabase>;\n\n constructor(\n private readonly dbName = 'waaskey',\n private readonly storeName = 'shares',\n ) {}\n\n private db(): Promise<IDBDatabase> {\n return (this.dbPromise ??= new Promise<IDBDatabase>((resolve, reject) => {\n const idb = globalThis.indexedDB;\n if (!idb) {\n reject(new Error('IndexedDB is unavailable — pass a custom KeyValueStore (e.g. MemoryKeyValueStore) in this runtime.'));\n return;\n }\n const request = idb.open(this.dbName, 1);\n request.onupgradeneeded = () => {\n if (!request.result.objectStoreNames.contains(this.storeName)) {\n request.result.createObjectStore(this.storeName);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error ?? new Error('Failed to open IndexedDB.'));\n }));\n }\n\n private async run<T>(mode: IDBTransactionMode, op: (store: IDBObjectStore) => IDBRequest<T>): Promise<T> {\n const db = await this.db();\n return new Promise<T>((resolve, reject) => {\n const tx = db.transaction(this.storeName, mode);\n const request = op(tx.objectStore(this.storeName));\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error ?? new Error('IndexedDB request failed.'));\n });\n }\n\n async get(key: string): Promise<string | null> {\n const value = await this.run<unknown>('readonly', (store) => store.get(key));\n return typeof value === 'string' ? value : null;\n }\n\n async set(key: string, value: string): Promise<void> {\n await this.run('readwrite', (store) => store.put(value, key));\n }\n\n async delete(key: string): Promise<void> {\n await this.run('readwrite', (store) => store.delete(key));\n }\n\n async keys(): Promise<string[]> {\n const keys = await this.run<IDBValidKey[]>('readonly', (store) => store.getAllKeys());\n return keys.filter((key): key is string => typeof key === 'string');\n }\n\n async clear(): Promise<void> {\n await this.run('readwrite', (store) => store.clear());\n }\n}\n","import { deriveKey, freshSalt, open, seal } from './crypto';\nimport { IndexedDbKeyValueStore } from './indexeddb-store';\nimport type { KeyValueStore, ShareStore } from './types';\n\nconst SHARE_PREFIX = 'share:';\nconst SALT_KEY = 'meta:salt';\n\n/**\n * Minimum length of the sealing secret (issue #41). The recommended source is the\n * 32-byte passkey-PRF secret (44 base64 chars), which clears this comfortably. The\n * floor rejects trivially low-entropy device secrets that would be brute-forceable\n * offline if the IndexedDB ciphertext + salt leaked. Override only when the caller\n * guarantees entropy another way (`allowWeakSecret`).\n */\nconst MIN_SECRET_LENGTH = 16;\n\n/** Options for the {@link EncryptedShareStore} constructor / {@link EncryptedShareStore.browser}. */\nexport interface EncryptedShareStoreOptions {\n dbName?: string;\n storeName?: string;\n /** Bypass the {@link MIN_SECRET_LENGTH} entropy floor — only when the secret's entropy is guaranteed elsewhere. */\n allowWeakSecret?: boolean;\n}\n\nconst bytesToBase64 = (bytes: Uint8Array): string => {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n};\nconst base64ToBytes = (base64: string): Uint8Array => {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n};\n\n/**\n * {@link ShareStore} that seals every share with AES-256-GCM before handing it to a\n * {@link KeyValueStore}, so the backing storage only ever holds ciphertext.\n *\n * The AES key is derived (PBKDF2) from a **secret the app supplies** — from the\n * user's authenticated session, a passkey/PRF, or a device secret — never embedded\n * in the bundle. A random salt is generated once and persisted alongside the data;\n * `clear()` wipes both, so a subsequent login derives a fresh key.\n *\n * @example\n * ```ts\n * const store = EncryptedShareStore.browser(sessionSecret);\n * await store.put(wallet.id, keygen.keyShare); // sealed in IndexedDB\n * const share = await store.get(wallet.id); // decrypted, or null\n * await store.clear(); // on logout\n * ```\n */\nexport class EncryptedShareStore implements ShareStore {\n private keyPromise?: Promise<CryptoKey>;\n\n constructor(\n private readonly kv: KeyValueStore,\n private readonly secret: string,\n options: { allowWeakSecret?: boolean } = {},\n ) {\n if (!secret) throw new Error('EncryptedShareStore: a non-empty `secret` is required.');\n if (!options.allowWeakSecret && secret.length < MIN_SECRET_LENGTH) {\n throw new Error(\n `EncryptedShareStore: the sealing secret is too weak (< ${MIN_SECRET_LENGTH} chars) and is brute-forceable offline. ` +\n 'Use the 32-byte passkey-PRF secret (PasskeyPrfSecretProvider), or pass { allowWeakSecret: true } only when entropy is guaranteed elsewhere.',\n );\n }\n }\n\n /** Default web store: AES-GCM sealing over IndexedDB. */\n static browser(secret: string, options?: EncryptedShareStoreOptions): EncryptedShareStore {\n return new EncryptedShareStore(new IndexedDbKeyValueStore(options?.dbName, options?.storeName), secret, { allowWeakSecret: options?.allowWeakSecret });\n }\n\n async put(walletId: string, share: string): Promise<void> {\n const key = await this.key();\n await this.kv.set(SHARE_PREFIX + walletId, await seal(key, share));\n }\n\n async get(walletId: string): Promise<string | null> {\n const record = await this.kv.get(SHARE_PREFIX + walletId);\n if (record === null) return null;\n return open(await this.key(), record);\n }\n\n async has(walletId: string): Promise<boolean> {\n return (await this.kv.get(SHARE_PREFIX + walletId)) !== null;\n }\n\n async remove(walletId: string): Promise<void> {\n await this.kv.delete(SHARE_PREFIX + walletId);\n }\n\n async clear(): Promise<void> {\n // Drop the cached derived key so the next use re-generates a salt + key.\n this.keyPromise = undefined;\n await this.kv.clear();\n }\n\n /** Lazily load (or create) the persisted salt and derive the AES key once. */\n private key(): Promise<CryptoKey> {\n return (this.keyPromise ??= this.loadKey());\n }\n\n private async loadKey(): Promise<CryptoKey> {\n const stored = await this.kv.get(SALT_KEY);\n let salt: Uint8Array;\n if (stored) {\n salt = base64ToBytes(stored);\n } else {\n salt = freshSalt();\n await this.kv.set(SALT_KEY, bytesToBase64(salt));\n }\n return deriveKey(this.secret, salt);\n }\n}\n","import type { KeyValueStore } from './types';\n\n/**\n * In-memory {@link KeyValueStore} — non-persistent. Used in tests and as a fallback\n * where IndexedDB is unavailable (e.g. SSR). Shares stored here do NOT survive a\n * reload; for persistent device storage use {@link IndexedDbKeyValueStore}.\n */\nexport class MemoryKeyValueStore implements KeyValueStore {\n private readonly map = new Map<string, string>();\n\n async get(key: string): Promise<string | null> {\n return this.map.get(key) ?? null;\n }\n\n async set(key: string, value: string): Promise<void> {\n this.map.set(key, value);\n }\n\n async delete(key: string): Promise<void> {\n this.map.delete(key);\n }\n\n async keys(): Promise<string[]> {\n return [...this.map.keys()];\n }\n\n async clear(): Promise<void> {\n this.map.clear();\n }\n}\n","/**\n * PasskeyPrfSecretProvider — derives a stable AES-key secret from a passkey's\n * PRF extension output, so the device share in {@link EncryptedShareStore} is\n * sealed under a biometric-gated passkey rather than a password.\n *\n * ### How the secret stays stable\n * The PRF extension evaluates a pseudo-random function keyed by the credential\n * (stored in the authenticator) over a caller-supplied `salt`. `enroll()` mints a\n * **random per-user salt** (issue #41) and returns it alongside `credentialId`;\n * persist both (they are non-secret) and pass the salt back to `unlock()`. Because\n * the credential and the salt are the same, the PRF output — and therefore the\n * derived `secret` — is identical on every `unlock()`. (A random per-user salt,\n * rather than one global constant, prevents cross-context PRF correlation.)\n *\n * ### Wiring to EncryptedShareStore\n * ```ts\n * import { PasskeyPrfSecretProvider } from '@waaskey/sdk';\n * import { EncryptedShareStore } from '@waaskey/sdk';\n *\n * const prf = new PasskeyPrfSecretProvider();\n * const { credentialId, secret } = await prf.enroll({ rpName: 'My App', userName: user.email });\n * // persist credentialId (non-secret); keep secret in memory for this session\n * const store = EncryptedShareStore.browser(secret);\n *\n * // On a subsequent session:\n * const { secret } = await prf.unlock(credentialId);\n * const store = EncryptedShareStore.browser(secret);\n *\n * // @waaskey/react: usePrfStore() wraps the above + stores credentialId in localStorage.\n * // react-native: use a native PRF authenticator, supply a custom PrfCeremony.\n * ```\n */\n\nimport { WaaskeyError } from '../errors';\nimport type { AuthenticationExtensionsClientInputs, PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';\n\n// ─── PRF salt (determines the stable secret) ──────────────────────────────────\n// The salt (with the credential) determines the derived secret, so it must be the\n// SAME on enroll + every unlock — altering it makes existing sealed shares unreadable.\n// New enrollments use a RANDOM per-user salt (issue #41); the LEGACY constant below is\n// kept only as the unlock() fallback for credentials enrolled before per-user salts.\nconst LEGACY_PRF_SALT_STRING = 'waaskey-share-seal-v1';\n\n/** The legacy fixed salt (fallback for pre-#41 credentials), as an ArrayBuffer. */\nfunction legacyPrfSalt(): ArrayBuffer {\n return new TextEncoder().encode(LEGACY_PRF_SALT_STRING).buffer as ArrayBuffer;\n}\n\n/** A fresh random 32-byte per-user PRF evaluation salt. */\nfunction randomPrfSalt(): ArrayBuffer {\n return crypto.getRandomValues(new Uint8Array(32)).buffer;\n}\n\nfunction saltToBase64(salt: ArrayBuffer): string {\n let binary = '';\n for (const byte of new Uint8Array(salt)) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\nfunction saltFromBase64(base64: string): ArrayBuffer {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes.buffer;\n}\n\n// ─── PRF extension shape (WebAuthn L3 draft) ──────────────────────────────────\n\ninterface PrfExtensionOutput {\n results?: { first?: ArrayBuffer };\n enabled?: boolean;\n}\n\n/**\n * The PRF extension results as they appear on both registration and authentication\n * `clientExtensionResults`. The typing in @simplewebauthn/browser's\n * `AuthenticationExtensionsClientOutputs` isn't fully typed for PRF yet —\n * we cast through `unknown` at the boundary.\n */\ninterface PrfClientOutputs {\n prf?: PrfExtensionOutput;\n}\n\n// ─── Ceremony abstraction (same pattern as auth.ts PasskeyCeremony) ───────────\n\n/**\n * Override the underlying WebAuthn ceremony calls. Useful for React Native\n * (pass a native PRF authenticator module) or tests (mock the PRF output).\n */\nexport interface PrfCeremony {\n register(options: PublicKeyCredentialCreationOptionsJSON): Promise<{ credentialId: string; prfResult: ArrayBuffer | null }>;\n authenticate(credentialId: string, options: PublicKeyCredentialRequestOptionsJSON): Promise<{ prfResult: ArrayBuffer | null }>;\n}\n\n/** Options accepted by `PasskeyPrfSecretProvider.enroll(...)`. */\nexport interface PasskeyPrfEnrollOptions {\n /**\n * Human-readable name for the relying party (your app). Used in the\n * authenticator's registration ceremony UI.\n */\n rpName?: string;\n /** Display name shown in the authenticator UI for the user. */\n userName?: string;\n /**\n * Fully qualified domain name of the relying party. Defaults to the current\n * origin's hostname in the browser. Must match the value used for `unlock()`.\n */\n rpId?: string;\n /** Custom ceremony (for non-browser runtimes or tests). */\n ceremony?: PrfCeremony;\n}\n\n/** Result of a successful `enroll()` or `unlock()`. */\nexport interface PasskeyPrfResult {\n /** Credential id (Base64URL). Persist this — pass it to `unlock()` later. */\n credentialId: string;\n /**\n * Base64-encoded per-user PRF evaluation salt (issue #41). Non-secret — persist it\n * alongside `credentialId` and pass it back to `unlock({ salt })` so the same secret\n * is re-derived. Omitting it on `unlock` falls back to the legacy constant salt.\n */\n salt: string;\n /**\n * Base64-encoded 32-byte PRF output. Use as the `secret` argument to\n * `EncryptedShareStore.browser(secret)`. Keep in memory; never persist it.\n */\n secret: string;\n}\n\n// ─── Capability detection ─────────────────────────────────────────────────────\n\n/**\n * Returns `true` if the current runtime has WebAuthn available at all.\n * A `false` result means passkeys are completely unavailable; fall back to\n * password or device-secret share sealing.\n */\nexport function isPasskeySupported(): boolean {\n return typeof globalThis.navigator !== 'undefined' && typeof (globalThis.navigator as { credentials?: unknown }).credentials !== 'undefined';\n}\n\n/**\n * Returns `true` if the current platform authenticator supports the PRF\n * extension (needed for passkey share sealing).\n *\n * This is a best-effort probe — not all browsers expose `credentials.get` in a\n * way that lets us query PRF support without a full ceremony. For definitive\n * detection, attempt `enroll()` and handle the `unsupported` error.\n *\n * In practice: Chrome 116+ / Edge 116+ on a platform authenticator support PRF;\n * Safari / iOS 17 do not yet.\n */\nexport async function isPrfSupported(): Promise<boolean> {\n if (!isPasskeySupported()) return false;\n // The CTAP2.1 PRF extension is exposed when the browser supports conditional\n // mediation on credentials.get — use that as a proxy where available.\n try {\n const cred = globalThis.PublicKeyCredential as { isConditionalMediationAvailable?: () => Promise<boolean> } | undefined;\n if (typeof cred?.isConditionalMediationAvailable === 'function') {\n return cred.isConditionalMediationAvailable();\n }\n } catch {\n // Ignore\n }\n // Fall back: assume supported if WebAuthn is available at all.\n return isPasskeySupported();\n}\n\n// ─── Default ceremony (uses @simplewebauthn/browser) ─────────────────────────\n\nasync function loadSimpleWebAuthn(): Promise<typeof import('@simplewebauthn/browser')> {\n try {\n return await import('@simplewebauthn/browser');\n } catch {\n throw new WaaskeyError('Passkey PRF requires \"@simplewebauthn/browser\" installed, or pass a custom ceremony.', 'unsupported');\n }\n}\n\n/** Build the default browser PRF ceremony from @simplewebauthn/browser. */\nasync function defaultPrfCeremony(): Promise<PrfCeremony> {\n const mod = await loadSimpleWebAuthn();\n return {\n async register(options): Promise<{ credentialId: string; prfResult: ArrayBuffer | null }> {\n const response = await mod.startRegistration({ optionsJSON: options });\n const outputs = response.clientExtensionResults as unknown as PrfClientOutputs;\n const prfResult = outputs.prf?.results?.first ?? null;\n return { credentialId: response.id, prfResult };\n },\n async authenticate(_credentialId, options): Promise<{ prfResult: ArrayBuffer | null }> {\n const response = await mod.startAuthentication({ optionsJSON: options });\n const outputs = response.clientExtensionResults as unknown as PrfClientOutputs;\n const prfResult = outputs.prf?.results?.first ?? null;\n return { prfResult };\n },\n };\n}\n\n// ─── PasskeyPrfSecretProvider ─────────────────────────────────────────────────\n\n/**\n * Derives a stable AES-key `secret` from a passkey's PRF extension for use with\n * {@link EncryptedShareStore}. The secret is deterministic: same credential +\n * same fixed salt → same 32 bytes every time.\n */\nexport class PasskeyPrfSecretProvider {\n /**\n * Register a new passkey that supports PRF and derive the initial secret from it.\n *\n * @returns `{ credentialId, secret }` — persist `credentialId`; use `secret`\n * to construct `EncryptedShareStore.browser(secret)` for this session only.\n *\n * @throws `WaaskeyError('unsupported')` when PRF isn't available in this runtime.\n * @throws `WaaskeyError('aborted')` when the user cancels the authenticator dialog.\n */\n async enroll(opts: PasskeyPrfEnrollOptions = {}): Promise<PasskeyPrfResult> {\n const ceremony = opts.ceremony ?? (await defaultPrfCeremony());\n\n const salt = randomPrfSalt();\n const rpId = opts.rpId ?? (typeof location === 'undefined' ? undefined : location.hostname);\n\n const creationOptions: PublicKeyCredentialCreationOptionsJSON = {\n rp: { name: opts.rpName ?? 'Waaskey', ...(rpId ? { id: rpId } : {}) },\n user: {\n id: btoa(String.fromCharCode(...new Uint8Array(crypto.getRandomValues(new Uint8Array(16))))),\n name: opts.userName ?? 'user',\n displayName: opts.userName ?? 'User',\n },\n challenge: btoa(String.fromCharCode(...new Uint8Array(crypto.getRandomValues(new Uint8Array(32))))),\n pubKeyCredParams: [\n { type: 'public-key', alg: -7 }, // ES256 (secp256r1)\n { type: 'public-key', alg: -257 }, // RS256\n ],\n authenticatorSelection: { userVerification: 'required', residentKey: 'required' },\n extensions: { prf: { eval: { first: salt } } } as AuthenticationExtensionsClientInputs,\n };\n\n let credentialId: string;\n let prfResult: ArrayBuffer | null;\n try {\n ({ credentialId, prfResult } = await ceremony.register(creationOptions));\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n const msg = cause instanceof Error ? cause.message : String(cause);\n if (/cancel|abort|not allowed|user gesture/i.test(msg)) {\n throw new WaaskeyError('Passkey registration was cancelled by the user.', 'aborted', { cause });\n }\n throw new WaaskeyError('Passkey registration failed.', 'unsupported', { cause });\n }\n\n if (prfResult === null) {\n throw new WaaskeyError('This authenticator does not support the PRF extension. Use a password or device-secret share instead.', 'unsupported');\n }\n\n return { credentialId, salt: saltToBase64(salt), secret: prfOutputToSecret(prfResult) };\n }\n\n /**\n * Authenticate with an existing passkey and re-derive the same stable secret.\n *\n * @param credentialId — the id returned by `enroll()`.\n * @param opts.salt — the per-user salt `enroll()` returned (issue #41). Pass it to\n * re-derive the same secret; omit only for legacy credentials enrolled before\n * per-user salts (falls back to the constant salt).\n * @returns `{ credentialId, salt, secret }` — reconstruct `EncryptedShareStore.browser(secret)`.\n *\n * @throws `WaaskeyError('unsupported')` when PRF isn't available.\n * @throws `WaaskeyError('aborted')` when the user cancels.\n */\n async unlock(credentialId: string, opts: { rpId?: string; ceremony?: PrfCeremony; salt?: string } = {}): Promise<PasskeyPrfResult> {\n const ceremony = opts.ceremony ?? (await defaultPrfCeremony());\n\n const salt = opts.salt ? saltFromBase64(opts.salt) : legacyPrfSalt();\n const rpId = opts.rpId ?? (typeof location === 'undefined' ? undefined : location.hostname);\n\n const requestOptions: PublicKeyCredentialRequestOptionsJSON = {\n challenge: btoa(String.fromCharCode(...new Uint8Array(crypto.getRandomValues(new Uint8Array(32))))),\n allowCredentials: [{ id: credentialId, type: 'public-key' }],\n userVerification: 'required',\n ...(rpId ? { rpId } : {}),\n extensions: { prf: { eval: { first: salt } } } as AuthenticationExtensionsClientInputs,\n };\n\n let prfResult: ArrayBuffer | null;\n try {\n ({ prfResult } = await ceremony.authenticate(credentialId, requestOptions));\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n const msg = cause instanceof Error ? cause.message : String(cause);\n if (/cancel|abort|not allowed|user gesture/i.test(msg)) {\n throw new WaaskeyError('Passkey authentication was cancelled by the user.', 'aborted', { cause });\n }\n throw new WaaskeyError('Passkey authentication failed.', 'unsupported', { cause });\n }\n\n if (prfResult === null) {\n throw new WaaskeyError('Passkey PRF output was not returned — authenticator may not support PRF or the credential was not created with PRF enabled.', 'unsupported');\n }\n\n return { credentialId, salt: saltToBase64(salt), secret: prfOutputToSecret(prfResult) };\n }\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\n/**\n * Convert a PRF result (exactly 32 bytes) to a base64 string suitable as the\n * `secret` argument to `EncryptedShareStore`.\n */\nfunction prfOutputToSecret(prfResult: ArrayBuffer): string {\n const bytes = new Uint8Array(prfResult);\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n"]}
1
+ {"version":3,"sources":["../src/analytics/analytics.ts","../src/analytics/http-sink.ts","../src/errors.ts","../src/auth.ts","../src/balances/evm-provider.ts","../src/balances/format.ts","../src/balances/balances.ts","../src/broadcast.ts","../src/http.ts","../src/members.ts","../src/onramp.ts","../src/storage/crypto.ts","../src/recovery-envelope.ts","../src/recovery.ts","../src/chains.ts","../src/enc-keys.ts","../src/internal.ts","../src/reshare.ts","../src/custody.ts","../src/eddsa-share.ts","../src/session-sign.ts","../src/share-blob.ts","../src/passkey/assertion.ts","../src/wallet.ts","../src/wallets.ts","../src/client.ts","../src/passkey/recovery-factor.ts","../src/mpc/wasm-core.ts","../src/mpc/load-wasm.ts","../src/mpc/prime-pool.ts","../src/storage/indexeddb-store.ts","../src/storage/encrypted-share-store.ts","../src/storage/memory-store.ts","../src/passkey/prf.ts"],"names":["x25519","USER_BACKUP_ROLE","bytesToBase64","base64ToBytes"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AnalyticsEvent, AnalyticsEventType, AnalyticsSink } from './types';\n\n/**\n * Emits lifecycle events to a {@link AnalyticsSink}; a no-op when analytics is disabled (no sink).\n * Fire-and-forget and exception-safe — analytics must NEVER break or slow a wallet operation.\n */\nexport class Analytics {\n constructor(private readonly sink?: AnalyticsSink) {}\n\n track(type: AnalyticsEventType, props: Omit<AnalyticsEvent, 'type' | 'timestamp'> = {}): void {\n if (!this.sink) return;\n try {\n this.sink.track({ type, timestamp: new Date().toISOString(), ...props });\n } catch {\n // Swallow — a broken analytics sink must not surface to the caller.\n }\n }\n}\n","import type { HttpClient } from '../http';\nimport type { AnalyticsEvent, AnalyticsSink } from './types';\n\n/** Default sink: POST events to the Waaskey API, fire-and-forget — delivery failures are swallowed. */\nexport class HttpAnalyticsSink implements AnalyticsSink {\n constructor(private readonly http: HttpClient) {}\n\n track(event: AnalyticsEvent): void {\n void this.http.request<unknown>('POST', '/v1/analytics/events', event).catch(() => undefined);\n }\n}\n","/**\n * Structured error model for the SDK.\n *\n * Every failure surfaces as a {@link WaaskeyError} carrying a typed {@link WaaskeyErrorCode}\n * — never a bare string — so callers can branch on `error.code` instead of matching\n * message text. Transport/HTTP failures map the API's error envelope\n * (`{ statusCode, message, error }`) to a code; orchestration failures (device keygen,\n * missing share, cancellation) use the SDK-side codes.\n */\n\nexport type WaaskeyErrorCode =\n // Transport / HTTP (mapped from the API response status).\n | 'unauthorized' // 401 — missing/invalid API key\n | 'forbidden' // 403 — key scope or policy denied the action\n | 'not_found' // 404 — resource (e.g. wallet) does not exist for this tenant\n | 'validation' // 400 — request failed validation\n | 'conflict' // 409 — e.g. signing a wallet that is not active\n | 'rate_limited' // 429 — throttled\n | 'server_error' // 5xx — upstream/server failure\n | 'network' // fetch threw (offline, DNS, CORS, …)\n // SDK orchestration (client-side).\n | 'unsupported_chain' // no signing curve / chain provider for the requested chain\n | 'provider_error' // a chain RPC provider call failed (balances)\n | 'device_core_required' // create needs a configured MpcCore + ShareStore\n | 'keygen_failed' // the device half of the keygen ceremony failed\n | 'sign_failed' // the device half of an n-party (member-bound) sign ceremony failed\n | 'reshare_failed' // the device half of a reshare completion (assemble / aux ceremony) failed\n | 'reshare_pubkey_mismatch' // the completed reshared share reproduced a DIFFERENT public key — aborted (funds-safety)\n | 'share_not_found' // no stored device share for the wallet (or no registered user_backup backup)\n | 'recovery_failed' // could not decrypt the recovery share (wrong recovery code?)\n | 'invalid_recovery_code' // the recovery code could not open the sealed user_backup backup (device-loss recover-sign, #351/#78)\n | 'backup_failed' // the user_backup share was keygen'd + sealed locally but its server-side registration failed — retry with wallets.retryBackup(walletId)\n | 'wallet_activation_timeout' // keygen did not finish (wallet stayed PENDING)\n | 'sign_ceremony_timeout' // the t-of-n quorum did not fix (or select this member) before the timeout\n | 'unauthenticated' // no end-user session — call auth.email.verify(...) first\n | 'firebase_not_enabled' // 412 — embedded Firebase sign-in is not enabled for this tenant\n | 'mfa_required' // 401 — a 2FA member's Firebase token did not pass a second factor\n | 'no_member' // 401 — no org member exists for the Firebase identity (never self-provisioned)\n | 'unsupported' // a capability isn't available in this runtime (e.g. passkeys without @simplewebauthn/browser)\n | 'aborted' // cancelled via an AbortSignal\n | 'unknown';\n\nexport interface WaaskeyErrorOptions {\n /** HTTP status, when the error originates from an API response. */\n status?: number;\n /** Raw error payload from the API (or other context), for debugging. */\n details?: unknown;\n /** The underlying error that triggered this one. */\n cause?: unknown;\n}\n\n/** The single error type thrown by the SDK. */\nexport class WaaskeyError extends Error {\n readonly code: WaaskeyErrorCode;\n readonly status?: number;\n readonly details?: unknown;\n\n constructor(message: string, code: WaaskeyErrorCode, options: WaaskeyErrorOptions = {}) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = 'WaaskeyError';\n this.code = code;\n this.status = options.status;\n this.details = options.details;\n }\n}\n\nconst STATUS_CODES: Record<number, WaaskeyErrorCode> = {\n 400: 'validation',\n 401: 'unauthorized',\n 403: 'forbidden',\n 404: 'not_found',\n 409: 'conflict',\n 429: 'rate_limited',\n};\n\n/** Map an API error response (status + parsed body) to a typed {@link WaaskeyError}. */\nexport function errorFromResponse(status: number, body: unknown): WaaskeyError {\n const code: WaaskeyErrorCode = STATUS_CODES[status] ?? (status >= 500 ? 'server_error' : 'unknown');\n return new WaaskeyError(messageFromBody(body, status), code, { status, details: body });\n}\n\n/** The API envelope is `{ statusCode, message, error }`; `message` may be a string or string[] (validation). */\nfunction messageFromBody(body: unknown, status: number): string {\n if (body && typeof body === 'object') {\n const { message, error } = body as { message?: unknown; error?: unknown };\n if (Array.isArray(message)) return message.filter((m): m is string => typeof m === 'string').join('; ');\n if (typeof message === 'string' && message) return message;\n if (typeof error === 'string' && error) return error;\n }\n return `Request failed with status ${status}`;\n}\n","import { WaaskeyError } from './errors';\nimport type { HttpClient } from './http';\nimport type { EmailStartResult, EmbeddedSession, EndUser } from './types';\n\n/**\n * Embedded end-user authentication (#6) — Privy-style login that maps an end-user to a\n * non-custodial wallet, distinct from the dashboard member auth. The developer's API key\n * authorizes the flow; a successful login yields an end-user **session token** the SDK\n * holds and sends on end-user-scoped calls.\n *\n * Methods (email-OTP, phone-OTP, …) live behind the same `auth` surface and all establish\n * the same session; social / passkey are added the same way.\n */\nexport class Auth {\n private current?: EmbeddedSession;\n\n constructor(private readonly http: HttpClient) {}\n\n /** Email one-time-code login. */\n readonly email = {\n /** Send a login code to `email`. */\n start: (email: string, signal?: AbortSignal): Promise<EmailStartResult> => this.http.request<EmailStartResult>('POST', '/v1/embedded/auth/email/start', { email }, signal),\n /** Verify the code; on success the end-user is provisioned and the session is established. */\n verify: (email: string, code: string, signal?: AbortSignal): Promise<EmbeddedSession> => this.establish('/v1/embedded/auth/email/verify', { email, code }, signal),\n };\n\n /** Phone one-time-code (SMS) login. `phone` is E.164, e.g. `+14155550123`. */\n readonly phone = {\n /** Send a login code to `phone`. */\n start: (phone: string, signal?: AbortSignal): Promise<EmailStartResult> => this.http.request<EmailStartResult>('POST', '/v1/embedded/auth/phone/start', { phone }, signal),\n /** Verify the code; on success the end-user is provisioned and the session is established. */\n verify: (phone: string, code: string, signal?: AbortSignal): Promise<EmbeddedSession> => this.establish('/v1/embedded/auth/phone/verify', { phone, code }, signal),\n };\n\n /** Social / federated-provider login. */\n readonly social = {\n /**\n * Exchange a Google ID token (obtained on the client via Google Identity Services) for a\n * session. Requires the tenant's Google client id to be configured server-side.\n */\n google: (idToken: string, signal?: AbortSignal): Promise<EmbeddedSession> => this.establish('/v1/embedded/auth/social/google', { idToken }, signal),\n /**\n * Exchange a Firebase ID token (obtained on the client via the Firebase Auth SDK) for a session\n * — the Firebase analogue of {@link social.google}. Requires the tenant to have opted into\n * embedded Firebase sign-in (`firebaseAuthEnabled`); when it hasn't, the API replies 412 and the\n * SDK surfaces a typed `firebase_not_enabled` {@link WaaskeyError}.\n */\n firebase: (idToken: string, signal?: AbortSignal): Promise<EmbeddedSession> =>\n this.establish('/v1/embedded/auth/firebase', { idToken }, signal).catch((error: unknown) => {\n if (error instanceof WaaskeyError && error.status === 412) {\n throw new WaaskeyError('Firebase sign-in is not enabled for this tenant.', 'firebase_not_enabled', { status: 412, cause: error, details: error.details });\n }\n throw error;\n }),\n };\n\n /**\n * Passkey (WebAuthn) login. `register` adds a passkey to the **currently logged-in** end-user;\n * `login` is usernameless (a passkey assertion resolves the user and establishes a session).\n *\n * The browser ceremony uses `@simplewebauthn/browser` (an optional peer dependency, loaded on\n * demand). Pass a `ceremony` to override it — e.g. on React Native with a native authenticator.\n */\n readonly passkey = {\n /** Add a passkey to the logged-in end-user. Requires an active session. */\n register: async (ceremony?: PasskeyCeremony): Promise<void> => {\n const token = this.requireToken();\n const options = await this.http.request<unknown>('POST', '/v1/embedded/auth/passkey/register/options', undefined, undefined, token);\n const response = await (ceremony ?? (await defaultCeremony())).create(options);\n await this.http.request<void>('POST', '/v1/embedded/auth/passkey/register/verify', { response }, undefined, token);\n },\n /** Usernameless passkey login — establishes the session on success. */\n login: async (ceremony?: PasskeyCeremony): Promise<EmbeddedSession> => {\n const { challengeId, options } = await this.http.request<PasskeyLoginOptions>('POST', '/v1/embedded/auth/passkey/login/options', {});\n const response = await (ceremony ?? (await defaultCeremony())).get(options);\n return this.establish('/v1/embedded/auth/passkey/login/verify', { challengeId, response } as unknown as Record<string, string>);\n },\n };\n\n /** The active session, or `undefined` when not logged in. */\n get session(): EmbeddedSession | undefined {\n return this.current;\n }\n\n /** The end-user session token, or `undefined` when not logged in. */\n get token(): string | undefined {\n return this.current?.token;\n }\n\n /** Whether an end-user is currently logged in. */\n get isAuthenticated(): boolean {\n return this.current !== undefined;\n }\n\n /** The logged-in end-user (re-fetched from the session token). Rejects if not logged in. */\n async me(signal?: AbortSignal): Promise<EndUser> {\n return this.http.request<EndUser>('GET', '/v1/embedded/auth/me', undefined, signal, this.requireToken());\n }\n\n /** Restore a session from a previously stored token (e.g. across reloads). */\n restore(session: EmbeddedSession): void {\n this.current = session;\n }\n\n /** Clear the session (sign out). */\n logout(): void {\n this.current = undefined;\n }\n\n /** POST a verify request, store the resulting session, and return it. */\n private async establish(path: string, body: Record<string, unknown>, signal?: AbortSignal): Promise<EmbeddedSession> {\n const session = await this.http.request<EmbeddedSession>('POST', path, body, signal);\n this.current = session;\n return session;\n }\n\n private requireToken(): string {\n if (!this.current) throw new WaaskeyError('Not authenticated — verify a login code first.', 'unauthenticated');\n return this.current.token;\n }\n}\n\n/** WebAuthn options + the id under which the server tracked the login challenge. */\ninterface PasskeyLoginOptions {\n challengeId: string;\n options: unknown;\n}\n\n/**\n * The browser WebAuthn ceremony. Defaults to `@simplewebauthn/browser`; override for non-DOM\n * runtimes (e.g. a React Native native-passkey module). `create` runs registration\n * (navigator.credentials.create), `get` runs authentication (navigator.credentials.get).\n */\nexport interface PasskeyCeremony {\n create(options: unknown): Promise<unknown>;\n get(options: unknown): Promise<unknown>;\n}\n\n/** Lazily load `@simplewebauthn/browser` and adapt it to {@link PasskeyCeremony}. */\nasync function defaultCeremony(): Promise<PasskeyCeremony> {\n let mod: typeof import('@simplewebauthn/browser');\n try {\n mod = await import('@simplewebauthn/browser');\n } catch {\n throw new WaaskeyError('Passkeys need \"@simplewebauthn/browser\" installed, or pass a custom ceremony.', 'unsupported');\n }\n return {\n create: (options) => mod.startRegistration({ optionsJSON: options as Parameters<typeof mod.startRegistration>[0]['optionsJSON'] }),\n get: (options) => mod.startAuthentication({ optionsJSON: options as Parameters<typeof mod.startAuthentication>[0]['optionsJSON'] }),\n };\n}\n","import { WaaskeyError } from '../errors';\nimport type { ChainProvider } from './types';\n\n// ERC-20 function selectors.\nconst SELECTOR_BALANCE_OF = '0x70a08231'; // balanceOf(address)\nconst SELECTOR_DECIMALS = '0x313ce567'; // decimals()\n\n/**\n * {@link ChainProvider} backed by an EVM JSON-RPC endpoint (`eth_getBalance`,\n * `eth_call`). Reads are dApp-style and need no backend. A custom `fetch` can be\n * injected (non-browser runtimes / tests).\n */\nexport class EvmRpcProvider implements ChainProvider {\n private readonly fetchImpl: typeof fetch;\n\n constructor(\n private readonly rpcUrl: string,\n fetchImpl?: typeof fetch,\n ) {\n const resolved = fetchImpl ?? globalThis.fetch;\n if (!resolved) throw new WaaskeyError('No fetch implementation for the EVM provider.', 'provider_error');\n this.fetchImpl = resolved.bind(globalThis);\n }\n\n async getNativeBalance(address: string): Promise<bigint> {\n return this.toBigInt(await this.call('eth_getBalance', [address, 'latest']));\n }\n\n async getTokenBalance(token: string, owner: string): Promise<bigint> {\n const data = SELECTOR_BALANCE_OF + padAddress(owner);\n return this.toBigInt(await this.call('eth_call', [{ to: token, data }, 'latest']));\n }\n\n async getTokenDecimals(token: string): Promise<number> {\n const result = await this.call('eth_call', [{ to: token, data: SELECTOR_DECIMALS }, 'latest']);\n return result === '0x' || result === undefined ? 18 : Number(this.toBigInt(result));\n }\n\n private async call(method: string, params: unknown[]): Promise<string | undefined> {\n let res: Response;\n try {\n res = await this.fetchImpl(this.rpcUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),\n });\n } catch (cause) {\n throw new WaaskeyError(`Chain RPC request failed (${method}).`, 'provider_error', { cause });\n }\n if (!res.ok) throw new WaaskeyError(`Chain RPC returned ${res.status} (${method}).`, 'provider_error', { status: res.status });\n\n const json = (await res.json().catch(() => ({}))) as { result?: string; error?: { message?: string } };\n if (json.error) throw new WaaskeyError(`Chain RPC error (${method}): ${json.error.message ?? 'unknown'}.`, 'provider_error', { details: json.error });\n return json.result;\n }\n\n private toBigInt(hex: string | undefined): bigint {\n return hex && hex !== '0x' ? BigInt(hex) : 0n;\n }\n}\n\n/** 20-byte address → 32-byte left-padded hex (no `0x`), for ABI encoding. */\nfunction padAddress(address: string): string {\n return address.replace(/^0x/i, '').toLowerCase().padStart(64, '0');\n}\n","/** Render a base-unit integer as a decimal string (e.g. `formatUnits(1500000n, 6)` → `\"1.5\"`). No float. */\nexport function formatUnits(raw: bigint, decimals: number): string {\n if (decimals === 0) return raw.toString();\n const negative = raw < 0n;\n const value = negative ? -raw : raw;\n const base = 10n ** BigInt(decimals);\n const whole = value / base;\n const fraction = (value % base).toString().padStart(decimals, '0').replace(/0+$/, '');\n const text = fraction ? `${whole}.${fraction}` : `${whole}`;\n return negative ? `-${text}` : text;\n}\n","import { WaaskeyError } from '../errors';\nimport { EvmRpcProvider } from './evm-provider';\nimport { formatUnits } from './format';\nimport type { Chain } from '../types';\nimport type { Balance, ChainConfig, ChainProvider, TokenBalanceOptions } from './types';\n\ninterface NativeAsset {\n symbol: string;\n decimals: number;\n}\n\n/** Native asset (gas token) metadata per chain, for formatting native balances. */\nconst NATIVE_ASSETS: Record<Chain, NativeAsset> = {\n ethereum: { symbol: 'ETH', decimals: 18 },\n polygon: { symbol: 'POL', decimals: 18 },\n arbitrum: { symbol: 'ETH', decimals: 18 },\n base: { symbol: 'ETH', decimals: 18 },\n optimism: { symbol: 'ETH', decimals: 18 },\n bitcoin: { symbol: 'BTC', decimals: 8 },\n solana: { symbol: 'SOL', decimals: 9 },\n};\n\n/** EVM chains with a built-in public JSON-RPC default (overridable via config). */\nconst DEFAULT_EVM_RPC: Partial<Record<Chain, string>> = {\n ethereum: 'https://eth.llamarpc.com',\n polygon: 'https://polygon-rpc.com',\n arbitrum: 'https://arb1.arbitrum.io/rpc',\n base: 'https://mainnet.base.org',\n optimism: 'https://mainnet.optimism.io',\n};\n\nconst isEvm = (chain: Chain): boolean => chain in DEFAULT_EVM_RPC;\n\n/**\n * Reads balances directly from a chain provider (never the backend). EVM chains work\n * out of the box via a default public RPC; override per chain with `chains` (an RPC\n * URL or a custom {@link ChainProvider}), and supply a provider for non-EVM chains.\n */\nexport class Balances {\n private readonly providers = new Map<Chain, ChainProvider>();\n\n constructor(\n private readonly config: Partial<Record<Chain, ChainConfig>> = {},\n private readonly fetchImpl?: typeof fetch,\n ) {}\n\n /** Native (gas-token) balance of an address on a chain. */\n async getBalance(chain: Chain, address: string): Promise<Balance> {\n const { symbol, decimals } = NATIVE_ASSETS[chain];\n const raw = await this.provider(chain).getNativeBalance(address);\n return { raw, decimals, symbol, formatted: formatUnits(raw, decimals) };\n }\n\n /** Token balance of `owner` for `token` on a chain (ERC-20 on EVM). */\n async getTokenBalance(chain: Chain, token: string, owner: string, options: TokenBalanceOptions = {}): Promise<Balance> {\n const provider = this.provider(chain);\n const raw = await provider.getTokenBalance(token, owner);\n const decimals = options.decimals ?? (provider.getTokenDecimals ? await provider.getTokenDecimals(token) : 18);\n return { raw, decimals, symbol: options.symbol, formatted: formatUnits(raw, decimals) };\n }\n\n /** Resolve (and cache) the provider for a chain: custom → configured RPC → default EVM RPC. */\n private provider(chain: Chain): ChainProvider {\n const cached = this.providers.get(chain);\n if (cached) return cached;\n\n const cfg = this.config[chain];\n let provider: ChainProvider | undefined = cfg?.provider;\n if (!provider) {\n const rpcUrl = cfg?.rpcUrl ?? DEFAULT_EVM_RPC[chain];\n if (rpcUrl && isEvm(chain)) provider = new EvmRpcProvider(rpcUrl, this.fetchImpl);\n }\n if (!provider) {\n throw new WaaskeyError(`No chain provider configured for \"${chain}\". Pass chains: { ${chain}: { rpcUrl } } or a custom provider.`, 'unsupported_chain');\n }\n this.providers.set(chain, provider);\n return provider;\n }\n}\n","import { WaaskeyError } from './errors';\nimport type { BroadcastOptions, BroadcastResult } from './types';\n\n/**\n * **Optional** client-side broadcast helper.\n *\n * WaaS is a **signing service**, not a broadcaster: `wallet.send(...)` returns the\n * signed raw transaction (`signedTx`) and WaaS never submits it. Broadcasting,\n * nonce/mempool handling and status-tracking are the integrator's concern — that\n * is what non-custodial means. This helper is a thin convenience so you can submit\n * a signed tx from **your own** node/provider; it is deliberately best-effort:\n * one JSON-RPC call, **no status polling and no retries**. For production you will\n * usually broadcast (and track) with your own infra.\n *\n * Today it submits an EVM raw transaction via `eth_sendRawTransaction`. The node's\n * returned hash is passed through as {@link BroadcastResult.txHash}.\n */\nexport async function broadcast(signedTx: string, options: BroadcastOptions): Promise<BroadcastResult> {\n if (!signedTx) throw new WaaskeyError('`signedTx` is required to broadcast.', 'validation');\n if (!options?.rpcUrl) throw new WaaskeyError('`rpcUrl` is required — broadcast from your own node/provider.', 'validation');\n\n const fetchImpl = (options.fetch ?? globalThis.fetch)?.bind(globalThis);\n if (!fetchImpl) throw new WaaskeyError('No fetch implementation for broadcast — pass `fetch`.', 'provider_error');\n\n const rawTx = signedTx.startsWith('0x') ? signedTx : `0x${signedTx}`;\n\n let res: Response;\n try {\n res = await fetchImpl(options.rpcUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_sendRawTransaction', params: [rawTx] }),\n signal: options.signal,\n });\n } catch (cause) {\n if (options.signal?.aborted) throw new WaaskeyError('Broadcast aborted.', 'aborted', { cause });\n throw new WaaskeyError('Broadcast request failed.', 'provider_error', { cause });\n }\n if (!res.ok) throw new WaaskeyError(`Broadcast RPC returned ${res.status}.`, 'provider_error', { status: res.status });\n\n const json = (await res.json().catch(() => ({}))) as { result?: string; error?: { message?: string } };\n if (json.error) throw new WaaskeyError(`Broadcast rejected by the node: ${json.error.message ?? 'unknown'}.`, 'provider_error', { details: json.error });\n if (!json.result) throw new WaaskeyError('Broadcast returned no transaction hash.', 'provider_error');\n\n return { txHash: json.result };\n}\n","import { errorFromResponse, WaaskeyError } from './errors';\n\n/** Thin typed HTTP client over fetch — the single place requests are issued. */\nexport class HttpClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof fetch;\n private memberAccessToken?: () => string | undefined;\n\n constructor(apiKey: string, baseUrl: string, fetchImpl?: typeof fetch) {\n this.apiKey = apiKey;\n this.baseUrl = assertSecureBaseUrl(baseUrl).replace(/\\/$/, '');\n const resolved = fetchImpl ?? globalThis.fetch;\n if (!resolved) {\n throw new Error('No fetch implementation available — pass `fetch` in WaaskeyOptions.');\n }\n this.fetchImpl = resolved.bind(globalThis);\n }\n\n /**\n * Wire a provider of the held org-member access token (from {@link Members}). When it returns a\n * token, {@link requestAsMember} authenticates member calls with `Authorization: Bearer <token>`\n * rather than the ambient dashboard cookie. Injected by the client (not imported) so `Members` and\n * `HttpClient` don't form an import cycle.\n */\n useMemberAccessToken(provider: () => string | undefined): void {\n this.memberAccessToken = provider;\n }\n\n async request<T>(method: string, path: string, body?: unknown, signal?: AbortSignal, bearer?: string): Promise<T> {\n // `bearer` overrides the API key for end-user-scoped calls (embedded session token).\n return this.send<T>(method, path, { authorization: `Bearer ${bearer ?? this.apiKey}`, 'content-type': 'application/json' }, body, signal);\n }\n\n /**\n * `@Public` request: NO `Authorization` header and NO cookie. Used by the org-member Firebase\n * login exchange (`POST /v1/auth/firebase`), which authenticates from the Firebase ID token in the\n * body alone and returns the member bearer tokens in its response.\n */\n async requestPublic<T>(method: string, path: string, body?: unknown, signal?: AbortSignal): Promise<T> {\n return this.send<T>(method, path, { 'content-type': 'application/json' }, body, signal);\n }\n\n /**\n * Member-session request (#349). Authenticates as the org member in one of two ways, transparent\n * to the caller ({@link Wallets.joinCeremony} / {@link Wallets.joinSignCeremony}):\n *\n * - **Held bearer session** (a {@link memberAccessToken} provider returns a token — e.g. after\n * {@link Members.loginWithFirebase}): sends `Authorization: Bearer <accessToken>`. The backend's\n * `ApiKeyAuthGuard` recognises a non-API-key bearer and falls through to the member-session\n * resolver, so a headless (non-browser) consumer authenticates without a cookie.\n * - **No held session** (the browser dashboard path): sends NO `Authorization` header and\n * `credentials: 'include'`, relying on the caller's own same-site httpOnly member cookie. The\n * guard only falls back to the cookie resolver when the header is absent entirely, so it is\n * omitted here.\n *\n * Never used by the tenant-apiKey ({@link request}) or embedded-end-user paths.\n */\n async requestAsMember<T>(method: string, path: string, body?: unknown, signal?: AbortSignal): Promise<T> {\n const token = this.memberAccessToken?.();\n if (token) {\n return this.send<T>(method, path, { authorization: `Bearer ${token}`, 'content-type': 'application/json' }, body, signal);\n }\n return this.send<T>(method, path, { 'content-type': 'application/json' }, body, signal, 'include');\n }\n\n private async send<T>(method: string, path: string, headers: Record<string, string>, body: unknown, signal?: AbortSignal, credentials?: RequestCredentials): Promise<T> {\n let res: Response;\n try {\n res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n signal,\n ...(credentials === undefined ? {} : { credentials }),\n });\n } catch (cause) {\n if (signal?.aborted) throw new WaaskeyError('Request aborted.', 'aborted', { cause });\n throw new WaaskeyError('Network request failed.', 'network', { cause });\n }\n\n if (!res.ok) {\n const detail = await res.json().catch(() => ({}) as unknown);\n throw errorFromResponse(res.status, detail);\n }\n\n // Some endpoints (e.g. passkey register/verify) reply 200/204 with no body.\n const text = await res.text();\n return (text ? JSON.parse(text) : undefined) as T;\n }\n}\n\n/**\n * Enforce TLS on the API base URL (issue #41): the API key / bearer travels in the\n * `Authorization` header, so a plaintext `http://` origin would leak it. Only\n * `https://` is allowed, with `http://` permitted solely for loopback (local dev).\n */\nfunction assertSecureBaseUrl(baseUrl: string): string {\n let url: URL;\n try {\n url = new URL(baseUrl);\n } catch (cause) {\n throw new WaaskeyError(`Invalid API baseUrl \"${baseUrl}\" — expected an absolute URL.`, 'validation', { cause });\n }\n const isLoopback = url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.hostname === '[::1]' || url.hostname === '::1';\n if (url.protocol === 'https:') return baseUrl;\n if (url.protocol === 'http:' && isLoopback) return baseUrl;\n throw new WaaskeyError(`Insecure API baseUrl \"${baseUrl}\" — the API key would be sent in cleartext. Use https:// (http:// is allowed only for localhost).`, 'validation');\n}\n","import { WaaskeyError } from './errors';\nimport type { HttpClient } from './http';\nimport type { FirebaseAuthRequest, Member, MemberSession } from './types';\n\n/**\n * Org-member (dashboard \"plane B\") authentication — a bearer member login for a NON-browser\n * consumer (a Node app, or the browser extension via the SDK) that cannot carry the ambient\n * same-site dashboard session cookie the browser console relies on.\n *\n * {@link loginWithFirebase} exchanges a Firebase ID token at the `@Public` `POST /v1/auth/firebase`\n * (no API key, no cookie) for a member session `{ accessToken, refreshToken, member }`, which the\n * client HOLDS. Once held, member-scoped calls ({@link Wallets.joinCeremony} /\n * {@link Wallets.joinSignCeremony}, which go through {@link HttpClient.requestAsMember}) send\n * `Authorization: Bearer <accessToken>` rather than relying on the cookie — so a headless consumer\n * can drive the member-bound ceremonies.\n *\n * **Refresh is out of scope for now:** the SDK holds `refreshToken` but does not yet auto-refresh.\n * Once the access token expires a member call surfaces a 401 (`unauthorized`) error; a future\n * revision will exchange the refresh token at `/v1/auth/refresh` from here.\n */\nexport class Members {\n private held?: MemberSession;\n\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Exchange a Firebase ID token for an org-member session and hold it.\n *\n * The token must belong to an ALREADY-INVITED member — Firebase never self-provisions a member, so\n * an unknown email is rejected (`no_member`). A member with 2FA enrolled must present a Firebase\n * token that itself passed a second factor, or the login is refused (`mfa_required`).\n *\n * @throws {WaaskeyError} `no_member` — no org member exists for the token's Firebase identity (401).\n * @throws {WaaskeyError} `mfa_required` — the member needs a second factor the token didn't carry (401).\n */\n async loginWithFirebase(idToken: string, signal?: AbortSignal): Promise<MemberSession> {\n const body: FirebaseAuthRequest = { idToken };\n let session: MemberSession;\n try {\n session = await this.http.requestPublic<MemberSession>('POST', '/v1/auth/firebase', body, signal);\n } catch (error) {\n throw mapFirebaseMemberError(error);\n }\n this.held = session;\n return session;\n }\n\n /** The current member, or `undefined` when not logged in. */\n get member(): Member | undefined {\n return this.held?.member;\n }\n\n /** The held member session (access + refresh tokens + member), or `undefined` when not logged in. */\n get session(): MemberSession | undefined {\n return this.held;\n }\n\n /** The held member access token — the value the client wires into {@link HttpClient.requestAsMember}. */\n get accessToken(): string | undefined {\n return this.held?.accessToken;\n }\n\n /** Whether an org member is currently logged in over a held bearer session. */\n get isAuthenticated(): boolean {\n return this.held !== undefined;\n }\n\n /** Restore a previously stored member session (e.g. across process restarts). */\n restore(session: MemberSession): void {\n this.held = session;\n }\n\n /** Clear the held member session (sign out); member calls fall back to the cookie path afterwards. */\n memberSignOut(): void {\n this.held = undefined;\n }\n}\n\n/**\n * The member Firebase login rejects with 401 for BOTH \"no member for this email\" and \"second factor\n * required\" (and a handful of other link failures). Re-map the two the caller must branch on to\n * specific codes by the backend message; leave every other error unchanged (so an invalid/unverified\n * token stays a plain `unauthorized`).\n */\nfunction mapFirebaseMemberError(error: unknown): unknown {\n if (error instanceof WaaskeyError && error.status === 401) {\n const message = error.message.toLowerCase();\n if (message.includes('multi-factor') || message.includes('second factor')) {\n return new WaaskeyError(error.message, 'mfa_required', { status: 401, cause: error, details: error.details });\n }\n if (message.includes('no member account')) {\n return new WaaskeyError(error.message, 'no_member', { status: 401, cause: error, details: error.details });\n }\n }\n return error;\n}\n","import type { HttpClient } from './http';\nimport type { OnrampWidgetParams, OnrampWidgetUrl } from './types';\n\n/**\n * The `onramp` resource — fund an embedded wallet with fiat (card/bank) via a provider\n * (e.g. Transak). The SDK returns a provider widget URL to open; the purchase settles on\n * chain to the wallet address and the on-chain balance reflects it once the provider delivers.\n */\nexport class Onramp {\n constructor(private readonly http: HttpClient) {}\n\n /** Get a provider widget URL to buy `cryptoCurrency` on `chainId` for `walletAddress`. */\n widgetUrl(params: OnrampWidgetParams, signal?: AbortSignal): Promise<OnrampWidgetUrl> {\n return this.http.request<OnrampWidgetUrl>('POST', '/onramp/widget-url', params, signal);\n }\n}\n","/**\n * WebCrypto sealing primitives for the device share store.\n *\n * The encryption key is **derived** from a user/device secret via PBKDF2 (never\n * embedded in the bundle) with a per-store random salt, and shares are sealed with\n * AES-256-GCM (authenticated) using a fresh random IV per record. Runs on the\n * WebCrypto `SubtleCrypto` available in browsers and Node ≥ 22.\n */\n\nconst PBKDF2_ITERATIONS = 210_000;\nconst PBKDF2_HASH = 'SHA-256';\nconst SALT_BYTES = 16;\nconst IV_BYTES = 12;\nconst AES_KEY_BITS = 256;\n\nfunction subtle(): SubtleCrypto {\n const c = globalThis.crypto;\n if (!c?.subtle) {\n throw new Error('WebCrypto (crypto.subtle) is unavailable — a secure context (https/localhost) or Node ≥ 22 is required for share storage.');\n }\n return c.subtle;\n}\n\n/** Cryptographically-random bytes. */\nexport function randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n}\n\n/**\n * Lowercase-hex SHA-256 of a UTF-8 string.\n *\n * Used to derive the recovery **credential hash** (Contract A): the client hashes\n * the recovery code and sends only the hash, so the server never receives the\n * sealing secret and therefore can never unseal the backup ciphertext it stores.\n */\nexport async function sha256Hex(input: string): Promise<string> {\n const digest = await subtle().digest('SHA-256', new TextEncoder().encode(input) as BufferSource);\n return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nexport function freshSalt(): Uint8Array {\n return randomBytes(SALT_BYTES);\n}\n\n/** Derive a non-extractable AES-GCM key from a secret + salt (PBKDF2-HMAC-SHA256). */\nexport async function deriveKey(secret: string, salt: Uint8Array): Promise<CryptoKey> {\n const s = subtle();\n const baseKey = await s.importKey('raw', new TextEncoder().encode(secret), 'PBKDF2', false, ['deriveKey']);\n return s.deriveKey({ name: 'PBKDF2', salt: salt as BufferSource, iterations: PBKDF2_ITERATIONS, hash: PBKDF2_HASH }, baseKey, { name: 'AES-GCM', length: AES_KEY_BITS }, false, [\n 'encrypt',\n 'decrypt',\n ]);\n}\n\n/**\n * Derive a non-extractable AES-GCM key from HIGH-ENTROPY key material (HKDF-SHA256).\n *\n * The counterpart to {@link deriveKey}: PBKDF2's iteration count exists to make a guessable secret\n * expensive to try, which buys nothing for 32 random bytes out of an authenticator — HKDF is the right\n * primitive there, and it is not slow. `info` domain-separates the derivation, so the same PRF output\n * cannot yield the same key for two different purposes.\n */\nexport async function deriveKeyFromBytes(material: Uint8Array, salt: Uint8Array, info: string): Promise<CryptoKey> {\n const s = subtle();\n const baseKey = await s.importKey('raw', material as BufferSource, 'HKDF', false, ['deriveKey']);\n return s.deriveKey(\n { name: 'HKDF', hash: 'SHA-256', salt: salt as BufferSource, info: new TextEncoder().encode(info) as BufferSource },\n baseKey,\n { name: 'AES-GCM', length: AES_KEY_BITS },\n false,\n ['encrypt', 'decrypt'],\n );\n}\n\n/** Seal `plaintext` into a self-describing `<iv>.<ciphertext>` base64 record. */\nexport async function seal(key: CryptoKey, plaintext: string): Promise<string> {\n const iv = randomBytes(IV_BYTES);\n const data = new TextEncoder().encode(plaintext);\n const ct = await subtle().encrypt({ name: 'AES-GCM', iv: iv as BufferSource }, key, data);\n return `${bytesToBase64(iv)}.${bytesToBase64(new Uint8Array(ct))}`;\n}\n\n/** Open a `<iv>.<ciphertext>` record produced by {@link seal}. Throws if the secret is wrong or the data is tampered. */\nexport async function open(key: CryptoKey, record: string): Promise<string> {\n const dot = record.indexOf('.');\n if (dot <= 0) throw new Error('Malformed encrypted share record.');\n const iv = base64ToBytes(record.slice(0, dot));\n const ct = base64ToBytes(record.slice(dot + 1));\n try {\n const plain = await subtle().decrypt({ name: 'AES-GCM', iv: iv as BufferSource }, key, ct as BufferSource);\n return new TextDecoder().decode(plain);\n } catch {\n throw new Error('Failed to decrypt share — wrong secret or corrupted data.');\n }\n}\n\n/**\n * Self-contained password sealing: derive a key from `password` with a fresh random\n * salt and seal `plaintext`, embedding the salt so the blob can be opened anywhere\n * with only the password. Format: `<salt>.<iv>.<ciphertext>` (base64). Used for the\n * recovery share, which carries no external salt store (unlike {@link seal}).\n */\nexport async function sealWithPassword(password: string, plaintext: string): Promise<string> {\n const salt = freshSalt();\n const key = await deriveKey(password, salt);\n return `${bytesToBase64(salt)}.${await seal(key, plaintext)}`;\n}\n\n/** Open a `<salt>.<iv>.<ciphertext>` blob produced by {@link sealWithPassword}. Throws on a wrong password / tamper. */\nexport async function openWithPassword(password: string, record: string): Promise<string> {\n const dot = record.indexOf('.');\n if (dot <= 0) throw new Error('Malformed password-sealed record.');\n const salt = base64ToBytes(record.slice(0, dot));\n const key = await deriveKey(password, salt);\n return open(key, record.slice(dot + 1));\n}\n\nexport function bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\nexport function base64ToBytes(base64: string): Uint8Array {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n","import { WaaskeyError } from './errors';\nimport { base64ToBytes, bytesToBase64, deriveKey, deriveKeyFromBytes, freshSalt, open, randomBytes, seal } from './storage/crypto';\nimport type { RecoveryKeyWrap } from './types';\n\n/**\n * Domain separator for every backup key-encryption key. Changing it invalidates existing wraps, so\n * treat it as part of the on-the-wire format.\n */\nconst KEK_INFO = 'waaskey-backup-kek-v1';\n/** Domain separator for the data key itself — distinct from {@link KEK_INFO}, so the two never collide. */\nconst DEK_INFO = 'waaskey-backup-dek-v1';\n\n/** A backup blob plus the wrapped copies of the key that opens it. */\nexport interface RecoveryBackupEnvelope {\n /** The share, sealed under a random data key. Opaque to the server. */\n ciphertext: string;\n /** One wrapped copy of that data key per enrolled method. */\n keyWraps: RecoveryKeyWrap[];\n}\n\n/** A passkey PRF secret to wrap the backup key with — the exact shape `PasskeyPrfSecretProvider` returns. */\nexport interface PasskeyBackupKey {\n /** Base64 PRF output (32 bytes). Never persisted, never sent to the server. */\n secret: string;\n /** Base64 PRF evaluation salt — non-secret, stored with the wrap so it can be reproduced. */\n salt: string;\n /** The credential whose PRF derives this key, so recovery asserts the right passkey. */\n credentialId: string;\n}\n\n/**\n * Seal a share into an envelope: a random data key encrypts the share, and that data key is wrapped\n * once per method (#510 / waas-backend#510).\n *\n * The point of the indirection is that EVERY wrapping opens the SAME share. A user whose passkey is\n * gone still has the recovery code; a user who never wrote the code down still has the passkey. Sealing\n * the share directly under one secret — which is what this SDK did before — makes losing that one\n * secret the same as losing the wallet.\n *\n * The recovery-code wrap is always produced: it is the path that works on any device, in any browser,\n * with no authenticator support. The passkey wrap is added when the caller supplies a PRF secret.\n *\n * Nothing here is decryptable server-side. The server receives the ciphertext, the wrapped keys, their\n * salts and a credential id — none of which yields a key-encryption key. That is what keeps the\n * platform below the signing threshold; a change that lets the server derive one would quietly make a\n * non-custodial wallet custodial.\n */\nexport async function sealRecoveryBackup(share: string, recoveryCode: string, passkey?: PasskeyBackupKey): Promise<RecoveryBackupEnvelope> {\n const dataKeyBytes = randomBytes(32);\n const dataKey = await deriveKeyFromBytes(dataKeyBytes, new Uint8Array(0), DEK_INFO);\n const ciphertext = await seal(dataKey, share);\n\n const codeSalt = freshSalt();\n const keyWraps: RecoveryKeyWrap[] = [\n {\n method: 'passphrase',\n wrapped: await seal(await deriveKey(recoveryCode, codeSalt), bytesToBase64(dataKeyBytes)),\n salt: bytesToBase64(codeSalt),\n },\n ];\n\n if (passkey) {\n const prfSalt = base64ToBytes(passkey.salt);\n keyWraps.push({\n method: 'passkey_prf',\n wrapped: await seal(await deriveKeyFromBytes(base64ToBytes(passkey.secret), prfSalt, KEK_INFO), bytesToBase64(dataKeyBytes)),\n salt: passkey.salt,\n credentialId: passkey.credentialId,\n });\n }\n\n return { ciphertext, keyWraps };\n}\n\n/**\n * Open an envelope with whichever key the user still has.\n *\n * A passkey secret is preferred when one is supplied and the enrollment carries a matching wrap —\n * that is the path with nothing to remember. Otherwise the recovery code opens it.\n *\n * A blob registered before envelopes existed arrives with NO wraps; that case is handled by the\n * caller ({@link Recovery}), which falls back to opening the ciphertext with the recovery code\n * directly. Deciding by `keyWraps.length` rather than by sniffing the blob's shape keeps the two\n * formats from ever being confused for one another.\n */\nexport async function openRecoveryBackup(envelope: RecoveryBackupEnvelope, opener: { recoveryCode?: string; passkeySecret?: string }): Promise<string> {\n const prfWrap = envelope.keyWraps.find((w) => w.method === 'passkey_prf');\n if (opener.passkeySecret !== undefined && prfWrap) {\n const kek = await deriveKeyFromBytes(base64ToBytes(opener.passkeySecret), base64ToBytes(prfWrap.salt), KEK_INFO);\n return openWith(envelope.ciphertext, prfWrap, kek, 'passkey');\n }\n\n const codeWrap = envelope.keyWraps.find((w) => w.method === 'passphrase');\n if (opener.recoveryCode !== undefined && codeWrap) {\n const kek = await deriveKey(opener.recoveryCode, base64ToBytes(codeWrap.salt));\n return openWith(envelope.ciphertext, codeWrap, kek, 'recovery code');\n }\n\n // Say which keys the backup actually accepts: the alternative is a user hunting for a passphrase\n // that was never enrolled, on a device they are already recovering from a loss.\n const enrolled = envelope.keyWraps.map((w) => w.method).join(', ') || 'none';\n throw new WaaskeyError(`No key available to open this backup — it is wrapped for [${enrolled}] and none of those was supplied.`, 'recovery_failed');\n}\n\nasync function openWith(ciphertext: string, wrap: RecoveryKeyWrap, kek: CryptoKey, label: string): Promise<string> {\n let dataKeyBytes: Uint8Array;\n try {\n dataKeyBytes = base64ToBytes(await open(kek, wrap.wrapped));\n } catch (cause) {\n throw new WaaskeyError(`Could not unwrap the backup key with the ${label} — wrong ${label}?`, 'recovery_failed', { cause });\n }\n try {\n return await open(await deriveKeyFromBytes(dataKeyBytes, new Uint8Array(0), DEK_INFO), ciphertext);\n } catch (cause) {\n // The wrap opened but the share did not: the two halves belong to different backups, which a\n // partial write or a hand-edited enrollment can produce. Distinct from a wrong key on purpose.\n throw new WaaskeyError('The backup key does not open this backup — the stored ciphertext and key wrap do not belong together.', 'recovery_failed', { cause });\n }\n}\n","import { WaaskeyError } from './errors';\nimport { openRecoveryBackup, sealRecoveryBackup } from './recovery-envelope';\nimport { openWithPassword, randomBytes, sealWithPassword, sha256Hex } from './storage/crypto';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { ShareStore } from './storage';\nimport type {\n FactorEnrollment,\n FactorVerification,\n RecoverParams,\n RecoverWalletResponse,\n RecoveryChallengeResponse,\n RecoveryRetrieveResponse,\n RecoveryKeyWrap,\n RecoveryShareInfo,\n RegisterRecoveryParams,\n} from './types';\n\nconst MIN_FACTORS = 3;\n\n/** Dependencies the {@link Recovery} resource needs. */\nexport interface RecoveryDeps {\n shareStore?: ShareStore;\n /** Optional analytics emitter for the wallet.recovered event. */\n analytics?: Analytics;\n}\n\n/**\n * Multi-factor wallet recovery.\n *\n * The recovery share is encrypted **client-side** with the user's recovery code\n * (the server stores only the opaque ciphertext) and its release is gated behind\n * ≥3 factors (recovery code + TOTP + email OTP). Device-loss recovery verifies the\n * factors, has the server rotate the key shares (invalidating the lost device\n * share), then decrypts the backup and restores it on the new device.\n */\nexport class Recovery {\n constructor(\n private readonly http: HttpClient,\n private readonly deps: RecoveryDeps = {},\n ) {}\n\n /**\n * Back up a wallet's device share: encrypt it with the recovery code and enrol the\n * factors. Returns the (possibly generated) recovery code — show it to the user\n * once; it is the only key to the backup and is never recoverable from the server.\n */\n async register(walletId: string, params: RegisterRecoveryParams, options: { signal?: AbortSignal } = {}): Promise<{ recoveryCode: string; share: RecoveryShareInfo }> {\n return registerRecoveryShare(this.http, walletId, params, options.signal);\n }\n\n /** The registered recovery factors for a wallet (no secrets). */\n getInfo(walletId: string, options: { signal?: AbortSignal } = {}): Promise<RecoveryShareInfo> {\n return this.http.request<RecoveryShareInfo>('GET', `/v1/wallets/${walletId}/recovery/info`, undefined, options.signal);\n }\n\n /** Start a recovery session — returns the challengeId + the factors the user must verify. */\n challenge(walletId: string, options: { signal?: AbortSignal } = {}): Promise<RecoveryChallengeResponse> {\n return this.http.request<RecoveryChallengeResponse>('POST', `/v1/wallets/${walletId}/recovery/challenge`, undefined, options.signal);\n }\n\n /**\n * Device-loss recovery: verify factors, have the server rotate the key shares,\n * then decrypt the backup with the recovery code and restore it to the share store\n * (when one is configured). Returns when the share is restored.\n */\n async recover(walletId: string, params: RecoverParams, options: { signal?: AbortSignal } = {}): Promise<{ share: string; refreshedAt: string }> {\n const res = await this.http.request<RecoverWalletResponse>(\n 'POST',\n `/v1/wallets/${walletId}/recovery/recover`,\n { challengeId: params.challengeId, verifications: await hashRecoveryFactors(params.verifications) },\n options.signal,\n );\n const share = await this.decrypt(res, params);\n await this.deps.shareStore?.put(walletId, share);\n this.deps.analytics?.track('wallet.recovered', { walletId });\n return { share, refreshedAt: res.refreshedAt };\n }\n\n /**\n * Verify factors and decrypt the backed-up share **without** rotating keys — for a\n * read-only restore. Use {@link recover} for true device-loss (which re-keys).\n *\n * NOTE (issue #41, LOW): because this path does not rotate the (possibly lost) device\n * share, the server `/verify` endpoint must enforce that **all ≥3 factors** were\n * satisfied before releasing the ciphertext; prefer {@link recover} (always-rotate) for\n * device-loss so a leaked backup can't be replayed against a still-valid old share.\n */\n async retrieveShare(walletId: string, params: RecoverParams, options: { signal?: AbortSignal } = {}): Promise<string> {\n return this.decrypt(await fetchRecoveryBackup(this.http, walletId, params, options.signal), params);\n }\n\n private decrypt(backup: { ciphertext: string; keyWraps?: RecoveryKeyWrap[] }, params: RecoverParams): Promise<string> {\n return openRecoveryBlob(backup, params);\n }\n}\n\n/**\n * The exact `POST /v1/wallets/:id/recovery/register` request body — the sealed share ciphertext plus the\n * enrolled factors. Split out from the seal step ({@link buildRecoveryRegistration}) and the POST\n * ({@link postRecoveryRegistration}) so a caller can persist it as a durable retry buffer BEFORE the\n * network call: it is opaque without the recovery code (which never leaves the device), so caching a\n * copy locally is safe. Used by the non-custodial `create` flow to make the user_backup backup\n * crash/network-safe (the sealed share is not lost if registration throws).\n */\nexport interface RecoveryRegisterPayload {\n ciphertext: string;\n factors: FactorEnrollment[];\n /** Wrapped copies of the key that opens `ciphertext` (#510) — absent when only a recovery code guards it. */\n keyWraps?: RecoveryKeyWrap[];\n}\n\n/**\n * Seal a NAMED key share with a recovery code and build the register payload — WITHOUT the network call.\n * Contract A: the raw recovery code NEVER leaves the device (the share is sealed with it client-side via\n * `sealWithPassword`, and only the code's SHA-256 is enrolled), so the server holds an undecryptable blob\n * and can never reconstruct the key. Returns the effective recovery code (caller-supplied, or generated)\n * + the {@link RecoveryRegisterPayload} ready to POST (or to persist as a retry buffer, then POST).\n */\nexport async function buildRecoveryRegistration(params: RegisterRecoveryParams): Promise<{ recoveryCode: string; payload: RecoveryRegisterPayload }> {\n const recoveryCode = params.recoveryCode ?? generateRecoveryCode();\n // #510: with a passkey the share goes into an ENVELOPE — a random data key seals it, and that key is\n // wrapped under both the passkey's PRF output and the recovery code, so either one opens the backup.\n //\n // WITHOUT a passkey the share is sealed under the recovery code exactly as before. That is not\n // laziness: the two formats are told apart by the presence of `keyWraps`, so writing envelopes\n // unconditionally would hand an older SDK — still installed in someone's app, still opening backups\n // with the code alone — a blob it cannot read.\n const backup = params.passkey\n ? await sealRecoveryBackup(params.share, recoveryCode, params.passkey)\n : { ciphertext: await sealWithPassword(recoveryCode, params.share), keyWraps: undefined };\n\n // Contract A: never transmit the sealing secret. Enrol a SHA-256 of the code so the\n // server (which holds share-2 + this ciphertext) can never derive the code to unseal.\n // The hash travels in the SAME `credential` field every factor uses — that is the field\n // the API's FactorEnrollmentDto declares, and its validation pipe (whitelist +\n // forbidNonWhitelisted) rejects the request outright under any other name (#91).\n const factors: FactorEnrollment[] = [\n { type: 'recovery_code', credential: await sha256Hex(recoveryCode) },\n { type: 'totp', credential: params.totpSecret },\n { type: 'email_otp', credential: params.email },\n ...(params.extraFactors ?? []),\n ];\n if (factors.length < MIN_FACTORS) {\n throw new WaaskeyError(`Recovery requires at least ${MIN_FACTORS} factors.`, 'validation');\n }\n return { recoveryCode, payload: { ciphertext: backup.ciphertext, factors, ...(backup.keyWraps ? { keyWraps: backup.keyWraps } : {}) } };\n}\n\n/** POST an already-built {@link RecoveryRegisterPayload} to the recovery-register endpoint. */\nexport function postRecoveryRegistration(http: HttpClient, walletId: string, payload: RecoveryRegisterPayload, signal?: AbortSignal): Promise<RecoveryShareInfo> {\n return http.request<RecoveryShareInfo>('POST', `/v1/wallets/${walletId}/recovery/register`, payload, signal);\n}\n\n/**\n * Verify the recovery factors and fetch the sealed share ciphertext (`POST /v1/wallets/:id/recovery/verify`),\n * WITHOUT decrypting it — the retrieval half of {@link Recovery.retrieveShare}, split out so a caller that\n * decrypts with its OWN error contract can reuse the gate. Contract A: the `recovery_code` factor is proven\n * with its SHA-256 (via {@link hashRecoveryFactors}), never the plaintext code. The returned ciphertext is\n * opaque to the server; only the recovery code opens it. Reused by the non-custodial device-loss recover-sign\n * ({@link Wallets.recoverSign}, #351/#78) to restore the client-held `user_backup` share.\n */\nexport async function fetchRecoveryCiphertext(http: HttpClient, walletId: string, params: RecoverParams, signal?: AbortSignal): Promise<string> {\n return (await fetchRecoveryBackup(http, walletId, params, signal)).ciphertext;\n}\n\n/**\n * The same gate as {@link fetchRecoveryCiphertext}, returning the WHOLE backup — ciphertext plus the\n * key wraps (#510) — because a caller that means to decrypt needs both. `keyWraps` is absent for a\n * backup registered before envelopes existed, which is exactly what {@link openRecoveryBlob} keys its\n * legacy path off.\n */\nexport async function fetchRecoveryBackup(http: HttpClient, walletId: string, params: RecoverParams, signal?: AbortSignal): Promise<RecoveryRetrieveResponse> {\n return http.request<RecoveryRetrieveResponse>(\n 'POST',\n `/v1/wallets/${walletId}/recovery/verify`,\n { challengeId: params.challengeId, verifications: await hashRecoveryFactors(params.verifications) },\n signal,\n );\n}\n\n/**\n * Open a retrieved backup with whichever key the caller holds — the single decrypt path for every\n * recovery flow (device-loss recover, read-only restore, the non-custodial recover-sign).\n *\n * Two formats coexist and always will: a backup registered before #510 is the share sealed DIRECTLY\n * under the recovery code and carries no wraps, while a newer one is an envelope. The presence of\n * `keyWraps` decides, so neither can be mistaken for the other, and an old backup keeps opening years\n * after the client that wrote it was replaced.\n */\nexport async function openRecoveryBlob(backup: { ciphertext: string; keyWraps?: RecoveryKeyWrap[] }, opener: { recoveryCode?: string; passkeySecret?: string }): Promise<string> {\n if (backup.keyWraps?.length) {\n return openRecoveryBackup({ ciphertext: backup.ciphertext, keyWraps: backup.keyWraps }, opener);\n }\n if (opener.recoveryCode === undefined) {\n // A passkey cannot open a pre-envelope backup: there was no data key to wrap. Saying so beats a\n // decryption error the user cannot act on.\n throw new WaaskeyError('This backup predates passkey wrapping and can only be opened with the recovery code.', 'recovery_failed');\n }\n try {\n return await openWithPassword(opener.recoveryCode, backup.ciphertext);\n } catch (cause) {\n throw new WaaskeyError('Could not decrypt the recovery share — wrong recovery code?', 'recovery_failed', { cause });\n }\n}\n\n/**\n * Seal a NAMED key share with a recovery code and register the resulting ciphertext + enrolled factors\n * server-side (`POST /v1/wallets/:id/recovery/register`) in one shot. The single source of truth for the\n * recovery backup mechanism, reused by two callers:\n *\n * - {@link Recovery.register} — back up the **device** share after keygen (recovery code generated if omitted);\n * - the non-custodial `create` flow ({@link Wallets.create}, #351/#78) — back up the client-held\n * **user_backup** share inline at keygen (which additionally persists a local retry buffer first, so a\n * failed register never loses the share).\n *\n * Returns the effective recovery code + the registered share metadata.\n */\nexport async function registerRecoveryShare(\n http: HttpClient,\n walletId: string,\n params: RegisterRecoveryParams,\n signal?: AbortSignal,\n): Promise<{ recoveryCode: string; share: RecoveryShareInfo }> {\n const { recoveryCode, payload } = await buildRecoveryRegistration(params);\n const share = await postRecoveryRegistration(http, walletId, payload, signal);\n return { recoveryCode, share };\n}\n\n/**\n * Contract A: replace a `recovery_code` proof's plaintext `token` with its SHA-256\n * before it leaves the device, so the server verifies possession against the stored\n * hash and never sees the code. The hash stays in the SAME `token` field — that is the\n * field the API's FactorVerificationDto declares, and its validation pipe rejects any\n * other property name (#91). Other factors pass through untouched.\n *\n * A `recovery_code` proof with no `token` (only reachable from untyped JS) is passed through as-is\n * rather than hashed: `sha256Hex(undefined)` would digest the literal string and turn a precise\n * \"token should not be empty\" 400 into an opaque 401 at the factor gate.\n */\nasync function hashRecoveryFactors(verifications: FactorVerification[]): Promise<FactorVerification[]> {\n return Promise.all(verifications.map(async (v) => (v.type === 'recovery_code' && typeof v.token === 'string' ? { type: v.type, token: await sha256Hex(v.token) } : v)));\n}\n\n/** A high-entropy (128-bit) recovery code, grouped for readability — e.g. `7F3A-9C21-...`. */\nexport function generateRecoveryCode(): string {\n const alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // Crockford-ish base32 (no I/O/0/1)\n const bytes = randomBytes(20);\n let out = '';\n for (let i = 0; i < bytes.length; i++) {\n out += alphabet[bytes[i]! % alphabet.length];\n if ((i + 1) % 4 === 0 && i + 1 < bytes.length) out += '-';\n }\n return out;\n}\n","import { WaaskeyError } from './errors';\nimport type { MpcCurve } from './mpc';\nimport type { Chain, WalletCurve } from './types';\n\n/** Maps a chain to the threshold-signing curve its wallet uses. `null` = not creatable yet. */\nconst CHAIN_CURVES: Record<Chain, WalletCurve | null> = {\n ethereum: 'secp256k1',\n polygon: 'secp256k1',\n arbitrum: 'secp256k1',\n base: 'secp256k1',\n optimism: 'secp256k1',\n bitcoin: 'secp256k1',\n // Solana signs with threshold EdDSA (ed25519 / FROST, #110): the device co-signs 2-party with the\n // server `server` party over the relay (keygenEddsa / signEddsa), distinct from the cggmp24 path.\n solana: 'ed25519',\n};\n\n/** The signing curve for a chain, or a typed `unsupported_chain` error if not supported yet. */\nexport function curveForChain(chain: Chain): WalletCurve {\n const curve = CHAIN_CURVES[chain];\n if (!curve) {\n throw new WaaskeyError(`Chain \"${chain}\" is not supported yet.`, 'unsupported_chain');\n }\n return curve;\n}\n\n/**\n * Narrow a {@link WalletCurve} to the cggmp24 {@link MpcCurve} the curve-based device core runs\n * (`secp256k1`). `ed25519` (FROST) is curveless and drives the separate\n * `runEddsaKeygen` / `runEddsaSign` path, so it is refused here — the guard keeps a cggmp24-only flow\n * (member keygen/sign, reshare, prime prewarm) from ever mis-running an ed25519 wallet.\n */\nexport function toMpcCurve(curve: WalletCurve): MpcCurve {\n if (curve === 'ed25519') {\n throw new WaaskeyError('ed25519 (FROST) wallets do not use the cggmp24 curve-based MPC path.', 'unsupported');\n }\n return curve;\n}\n","import { x25519 } from '@noble/curves/ed25519.js';\nimport { WaaskeyError } from './errors';\nimport type { ShareStore } from './storage';\n\n/**\n * The device's long-lived X25519 encryption keypair for FROST ed25519 (FROST) keygen (#114).\n *\n * FROST DKG round-2 sends each party a secret share sealed to the recipient's X25519 key (libsodium\n * `crypto_box`), so no share ever crosses the relay in the clear. The device therefore needs its OWN\n * encryption keypair: the PUBLIC key is advertised on wallet create (`deviceEncPubkey`) and echoed back\n * to every party in the ceremony's `encPubkeys` roster; the SECRET key opens the round-2 packages sealed\n * to this device. It is device-private and long-lived — the SAME keypair is reused for later reshare aux\n * ceremonies — so it is generated + sealed ONCE into the (encrypted) {@link ShareStore} and reused after.\n *\n * The raw 32-byte X25519 keys are compatible with waas-core's `crypto_box` (`PublicKey`/`SecretKey::from_bytes`).\n */\n\n/** Reserved {@link ShareStore} key the device encryption keypair is sealed under — never a wallet id. */\nconst DEVICE_ENC_STORE_KEY = '__waaskey_device_enc_v1__';\n\n/** The device's X25519 encryption keypair (hex), sealed in the {@link ShareStore}. */\nexport interface DeviceEncKeypair {\n /** X25519 secret key, 32-byte lowercase hex. SECRET — never logged, never sent to the server. */\n secretHex: string;\n /** X25519 public key, 32-byte lowercase hex (non-zero) — the `deviceEncPubkey` supplied on create. */\n publicHex: string;\n}\n\n/**\n * Get-or-create the device's long-lived X25519 encryption keypair (#114). Reuses the keypair already\n * sealed in `shareStore` when present (so it stays stable across wallets and across reshares); otherwise\n * generates a fresh one, verifies its public key is non-zero, and seals it once. The secret never leaves\n * the device and is never logged.\n */\nexport async function getOrCreateDeviceEncKeypair(shareStore: ShareStore): Promise<DeviceEncKeypair> {\n const existing = await shareStore.get(DEVICE_ENC_STORE_KEY);\n if (existing !== null) return parseDeviceEncKeypair(existing);\n const keypair = generateDeviceEncKeypair();\n await shareStore.put(DEVICE_ENC_STORE_KEY, JSON.stringify(keypair));\n return keypair;\n}\n\n/** Generate a fresh X25519 encryption keypair, refusing an all-zero (invalid) public key. */\nfunction generateDeviceEncKeypair(): DeviceEncKeypair {\n const secret = x25519.utils.randomSecretKey();\n const publicKey = x25519.getPublicKey(secret);\n if (isAllZero(publicKey)) {\n throw new WaaskeyError('Generated an all-zero X25519 encryption public key — refusing to seal keygen packages to it.', 'keygen_failed');\n }\n return { secretHex: bytesToHex(secret), publicHex: bytesToHex(publicKey) };\n}\n\n/** Inverse of the seal in {@link getOrCreateDeviceEncKeypair}: parse + validate a stored keypair blob. */\nfunction parseDeviceEncKeypair(blob: string): DeviceEncKeypair {\n let parsed: { secretHex?: unknown; publicHex?: unknown };\n try {\n parsed = JSON.parse(blob) as { secretHex?: unknown; publicHex?: unknown };\n } catch (cause) {\n throw new WaaskeyError('Stored device encryption keypair is corrupt — it is not valid JSON.', 'keygen_failed', { cause });\n }\n if (!isHex32(parsed.secretHex) || !isHex32(parsed.publicHex)) {\n throw new WaaskeyError('Stored device encryption keypair is malformed — expected 32-byte (64 hex) secret + public keys.', 'keygen_failed', {\n details: { keys: Object.keys(parsed) },\n });\n }\n return { secretHex: parsed.secretHex, publicHex: parsed.publicHex };\n}\n\n/** Is `v` a 32-byte (64 hex char) hex string? */\nfunction isHex32(v: unknown): v is string {\n return typeof v === 'string' && /^[0-9a-fA-F]{64}$/.test(v);\n}\n\n/** Are all bytes zero? An all-zero X25519 public key is a low-order (invalid) point. */\nfunction isAllZero(bytes: Uint8Array): boolean {\n return bytes.every((byte) => byte === 0);\n}\n\n/** Lowercase-hex encode raw bytes (no external hex-codec dependency). */\nfunction bytesToHex(bytes: Uint8Array): string {\n let hex = '';\n for (const byte of bytes) hex += byte.toString(16).padStart(2, '0');\n return hex;\n}\n","import { WaaskeyError } from './errors';\n\n/** Throw a typed `aborted` error if the signal is already aborted. */\nexport function throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw new WaaskeyError('Operation aborted.', 'aborted');\n}\n\n/** Resolve after `ms`, or reject with a typed `aborted` error if the signal fires first. */\nexport function delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new WaaskeyError('Operation aborted.', 'aborted'));\n return;\n }\n const handle: { timer?: ReturnType<typeof setTimeout> } = {};\n const onAbort = (): void => {\n if (handle.timer) clearTimeout(handle.timer);\n reject(new WaaskeyError('Operation aborted.', 'aborted'));\n };\n handle.timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","import { toMpcCurve } from './chains';\nimport { getOrCreateDeviceEncKeypair } from './enc-keys';\nimport { WaaskeyError } from './errors';\nimport { throwIfAborted } from './internal';\nimport { sealWithPassword } from './storage/crypto';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { DeviceCompleteReshareResult, MpcCore } from './mpc';\nimport type { ShareStore } from './storage';\nimport type {\n CustodyKind,\n ReshareAssemblyMaterial,\n ReshareCeremony,\n ReshareCompletionParams,\n ReshareCompletionResult,\n ReshareRotateParams,\n ReshareRotateResult,\n WalletData,\n} from './types';\n\n/** The client-held BACKUP party — the only holder whose ack must carry a re-sealed share. */\nconst USER_BACKUP_ROLE = 'user_backup';\n\n/** Dependencies the {@link Reshare} resource needs for the device-side completion ceremony. */\nexport interface ReshareDeps {\n mpc?: MpcCore;\n shareStore?: ShareStore;\n /** Optional analytics emitter for the wallet.reshared event. */\n analytics?: Analytics;\n}\n\n/**\n * Device-side completion of a **device-retaining** reshare (#318 phase 2b).\n *\n * A backend reshare that keeps a USER_DEVICE holder commits a NEW epoch whose shares are CORE-ONLY\n * (no aux) — the wallet is `reshareAuxPending` and cannot sign until the aux material is generated\n * over the new committee. The platform signer drives its server + recovery parties of that aux\n * ceremony; the DEVICE must join it or the ceremony can't complete. This resource is the device's\n * half: it assembles its NEW-epoch bare core locally from the reshare's {@link DeviceReshareMaterial},\n * runs the `<sessionId>/reshare-aux` aux ceremony over the relay alongside the platform parties, and\n * seals the resulting COMPLETE share on the device under the new epoch.\n *\n * The device is never left worse off: nothing is stored until the completed share's public key is\n * verified equal to the wallet's (unchanged across a reshare — the funds-safety invariant), and the\n * OLD-epoch share is kept intact, so an interrupted completion can simply be retried.\n */\nexport class Reshare {\n constructor(\n private readonly http: HttpClient,\n private readonly deps: ReshareDeps = {},\n ) {}\n\n /**\n * Rotate the wallet onto a NEW committee, keeping its address, and drive this device's whole half of\n * the ceremony (#488).\n *\n * The client is not a bystander here: the platform holds ONE share and cannot reach the threshold, so\n * without this device's deal there is no ceremony at all.\n *\n * 1. Open the ceremony with the committee asked for (an empty request re-issues the current one).\n * 2. DEAL from this device's current-epoch share — pure and local; every sub-share leaves sealed.\n * 3. For each CLIENT-held new holder — identified by custody KIND, never by role name — fetch its\n * material and assemble its new-epoch core locally, refusing any share that reproduces a different\n * public key.\n * 4. Acknowledge each one. The `user_backup` holder's ack carries its new share re-sealed under the\n * user's EXISTING recovery code, so the wallet's no-lock-out property survives the rotation; the\n * last acknowledgement drives the backend's atomic cutover.\n *\n * The assembled cores are BARE (no aux): the wallet is `reshareAuxPending` until aux-completion, which\n * is {@link complete}'s job — and which re-assembles from the material itself, so nothing here needs\n * to be kept on the device between the two. Nothing here can leave the device worse off — the old-epoch share is\n * untouched, and a ceremony that fails cuts nothing over.\n */\n async rotate(walletId: string, params: ReshareRotateParams = {}, options: { signal?: AbortSignal } = {}): Promise<ReshareRotateResult> {\n const { mpc, shareStore } = this.deps;\n if (!mpc || !shareStore) {\n throw new WaaskeyError('Driving a reshare requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n if (!mpc.runReshareDeal || !mpc.runReshareAssemble) {\n throw new WaaskeyError('The configured MPC core does not support reshare — use a client-wasm built with the `reshare` feature.', 'unsupported');\n }\n const { signal } = options;\n throwIfAborted(signal);\n\n // The wallet is the source of truth for BOTH the epoch whose share deals and the public key every\n // assembled share must reproduce — neither is taken from the caller.\n const wallet = await this.http.request<WalletData>('GET', `/v1/wallets/${walletId}`, undefined, signal);\n if (!wallet.publicKey) {\n throw new WaaskeyError('The wallet has no public key yet — only an ACTIVE wallet can be reshared.', 'reshare_failed', { details: { walletId } });\n }\n const share = await shareStore.get(epochShareKey(walletId, wallet.keyEpoch));\n if (!share) {\n throw new WaaskeyError(`This device holds no share for wallet \"${walletId}\" at epoch ${wallet.keyEpoch} — it cannot deal the reshare.`, 'reshare_failed');\n }\n\n throwIfAborted(signal);\n const ceremony = await this.http.request<ReshareCeremony>('POST', `/v1/wallets/${walletId}/reshare-embedded`, params, signal);\n const encKeypair = await getOrCreateDeviceEncKeypair(shareStore);\n const curve = toMpcCurve(ceremony.curve);\n\n // Which new holders are THIS client's. Asked of the custody kinds because role names are\n // topology-specific — the platform's party is `server` here and `platform` on a member committee.\n const clientHolders = ceremony.newParties.filter((_role, i) => isClientCustody(ceremony.newCustodyKinds[i]));\n\n try {\n throwIfAborted(signal);\n const dealt = await mpc.runReshareDeal({\n curve,\n share,\n quorumIndices: ceremony.quorumIndices,\n newPreimages: ceremony.newPreimages,\n newThreshold: ceremony.newThreshold,\n recipientPubkeys: ceremony.recipientPubkeys,\n });\n await this.http.request(\n 'POST',\n `/v1/wallets/${walletId}/reshare-drop/${ceremony.id}/deal`,\n { commitments: dealt.commitments, sealedSubShares: dealt.sealedSubShares },\n signal,\n );\n\n let { status } = ceremony;\n for (const role of clientHolders) {\n throwIfAborted(signal);\n const material = await this.http.request<ReshareAssemblyMaterial>(\n 'GET',\n `/v1/wallets/${walletId}/reshare-drop/${ceremony.id}/assembly?role=${encodeURIComponent(role)}`,\n undefined,\n signal,\n );\n const assembled = await mpc.runReshareAssemble({\n curve,\n newPosition: material.newPosition,\n newPreimages: material.newPreimages,\n newThreshold: material.newThreshold,\n wallet: material.wallet,\n commitments: material.commitments,\n subShares: material.subShares,\n encryptionSecret: encKeypair.secretHex,\n });\n // FUNDS-SAFETY: a reshare that changed the key would change the address, so refuse before this\n // core is stored or acknowledged.\n assertPublicKey(assembled.sharedPublicKey, wallet.publicKey, walletId);\n\n const body = role === USER_BACKUP_ROLE ? { backupCiphertext: await this.sealBackup(assembled.core, params.recoveryCode) } : {};\n const ack = await this.http.request<{ status: string }>(\n 'POST',\n `/v1/wallets/${walletId}/reshare-drop/${ceremony.id}/assembled?role=${encodeURIComponent(role)}`,\n body,\n signal,\n );\n ({ status } = ack);\n }\n\n this.deps.analytics?.track('wallet.reshared', { walletId, curve: ceremony.curve });\n return { walletId, ceremonyId: ceremony.id, status, keyEpoch: ceremony.keyEpoch, assembledRoles: clientHolders, sharedPublicKey: wallet.publicKey };\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The reshare ceremony failed.', 'reshare_failed', { cause });\n }\n }\n\n /**\n * Re-seal the new `user_backup` core under the user's EXISTING recovery code. The code never leaves\n * the device — only the ciphertext does — which is the same trust model registration has, and the\n * reason the server cannot check WHICH code sealed it.\n */\n private async sealBackup(core: string, recoveryCode?: string): Promise<string> {\n if (!recoveryCode) {\n throw new WaaskeyError(\n 'This committee keeps a `user_backup` holder, so its new share must be re-sealed under the wallet existing recovery code — pass `recoveryCode` to `reshare.rotate(...)`.',\n 'reshare_failed',\n );\n }\n return sealWithPassword(recoveryCode, core);\n }\n\n /**\n * Complete this device's share for a device-retaining reshare and make the wallet signable on the\n * device under the new epoch.\n *\n * 1. Fetch the wallet to learn its (unchanged) public key — the invariant the completion is checked\n * against, taken from the server's truth rather than the caller.\n * 2. Assemble the NEW-epoch bare core locally from {@link ReshareCompletionParams.material} (no relay).\n * 3. Run the aux-completion ceremony over the relay ({@link ReshareCompletionParams.ceremony}),\n * alongside the platform server + recovery parties, to obtain the COMPLETE signable share.\n * 4. Verify the completed share's public key equals the wallet's (fail closed on any mismatch).\n * 5. Seal + persist the completed share under `(walletId, keyEpoch)`, keeping the old-epoch share.\n *\n * Requires `mpc` (built with the reshare capability) + `shareStore`. Idempotent/recoverable: safe to\n * retry, since nothing is overwritten until the new share is assembled, verified, and stored.\n */\n async complete(walletId: string, params: ReshareCompletionParams, options: { signal?: AbortSignal } = {}): Promise<ReshareCompletionResult> {\n const { mpc, shareStore } = this.deps;\n if (!mpc || !shareStore) {\n throw new WaaskeyError('Completing a reshare requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n if (!mpc.runReshareAssemble || !mpc.runCompleteReshare) {\n throw new WaaskeyError('The configured MPC core does not support reshare — use a client-wasm built with the `reshare` feature.', 'unsupported');\n }\n\n const { material, ceremony, keyEpoch } = params;\n const { signal } = options;\n throwIfAborted(signal);\n\n // The wallet's public key is UNCHANGED across a reshare; take it from the server as the invariant.\n const wallet = await this.http.request<WalletData>('GET', `/v1/wallets/${walletId}`, undefined, signal);\n if (!wallet.publicKey) {\n throw new WaaskeyError('The wallet has no public key yet — it must be an ACTIVE reshared wallet to complete on device.', 'reshare_failed', { details: { walletId } });\n }\n\n // The dealers SEALED every sub-share to this device's long-lived encryption key (waas-core\n // #365 M-A), so the assemble cannot even parse its inputs without the matching secret. It is the\n // same keypair `deviceEncPubkey` was taken from at create, which is why it must be get-or-CREATE:\n // a device that never ran a keygen through this SDK has none, and the assemble would be\n // unopenable rather than merely unauthorised.\n const encKeypair = await getOrCreateDeviceEncKeypair(shareStore);\n\n throwIfAborted(signal);\n let completed: DeviceCompleteReshareResult;\n try {\n // Stage 1 — assemble the NEW-epoch bare core locally (pure, no relay).\n const assembled = await mpc.runReshareAssemble({\n curve: toMpcCurve(material.curve),\n newPosition: material.newPosition,\n newPreimages: material.newPreimages,\n newThreshold: material.newThreshold,\n wallet: material.wallet,\n commitments: material.commitments,\n subShares: material.subShares,\n encryptionSecret: encKeypair.secretHex,\n });\n // Fail fast BEFORE the relay ceremony if assemble already reproduced a different key.\n assertPublicKey(assembled.sharedPublicKey, wallet.publicKey, walletId);\n\n throwIfAborted(signal);\n // Stage 2 — aux-completion over the new committee (relay), yielding the complete signable share.\n completed = await mpc.runCompleteReshare({\n curve: toMpcCurve(material.curve),\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n role: ceremony.role,\n peerRole: ceremony.peerRole,\n partyIndex: ceremony.partyIndex,\n peerPartyIndex: ceremony.peerPartyIndex,\n parties: ceremony.parties,\n relayToken: ceremony.relayToken,\n core: assembled.core,\n pregeneratedPrimes: params.pregeneratedPrimes,\n });\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The device reshare-completion ceremony failed.', 'reshare_failed', { cause });\n }\n\n // Funds-safety invariant: the completed share MUST reproduce the wallet's public key. Verify\n // before adopting it — a mismatch means the reshare is corrupt; store nothing (old share intact).\n assertPublicKey(completed.sharedPublicKey, wallet.publicKey, walletId);\n\n // Seal + persist under the NEW epoch, keeping the old-epoch share until cutover is confirmed\n // (mirrors the backend's epoch-keyed `(walletId, keyEpoch)` model). Sealed exactly like keygen.\n await shareStore.put(epochShareKey(walletId, keyEpoch), serializeCompletedShare(completed));\n this.deps.analytics?.track('wallet.reshared', { walletId, curve: material.curve });\n\n return { walletId, keyEpoch, sharedPublicKey: completed.sharedPublicKey };\n }\n}\n\n/**\n * Compose the epoch-keyed device-share storage key `(walletId, keyEpoch)`, mirroring the backend's\n * epoch-keyed share model (#295). Epoch 1 (a fresh keygen) keeps the bare `walletId` key for\n * back-compat with existing stored shares; later epochs (reshares) use a distinct suffixed key, so a\n * completed reshare never overwrites the old-epoch share until cutover is confirmed.\n */\nexport function epochShareKey(walletId: string, keyEpoch: number): string {\n return keyEpoch <= 1 ? walletId : `${walletId}@epoch-${keyEpoch}`;\n}\n\n/** Whether a custody kind names a holder the CLIENT runs (and must therefore assemble and acknowledge). */\nfunction isClientCustody(kind: CustodyKind | undefined): boolean {\n return kind !== undefined && kind !== 'platform_signer' && kind !== 'platform_recovery';\n}\n\n/** Fail closed unless the assembled/completed share reproduces the wallet's (unchanged) public key. */\nfunction assertPublicKey(actual: string, expected: string, walletId: string): void {\n if (actual !== expected) {\n throw new WaaskeyError('The reshared share reproduced a DIFFERENT public key than the wallet — aborting (device share not stored).', 'reshare_pubkey_mismatch', {\n details: { walletId, expected, actual },\n });\n }\n}\n\n/** The on-device record persisted per completed reshare — the same sealed shape a keygen share uses. */\nfunction serializeCompletedShare(completed: DeviceCompleteReshareResult): string {\n return JSON.stringify({ keyShare: completed.keyShare, sharedPublicKey: completed.sharedPublicKey });\n}\n","import { WaaskeyError } from './errors';\nimport type { CreateWalletParams, CustodyKind, CustodyType, WalletData } from './types';\n\nconst CUSTODY_KINDS: ReadonlySet<CustodyKind> = new Set<CustodyKind>(['user_device', 'user_backup', 'platform_signer', 'platform_recovery', 'external_party']);\nconst CUSTODY_TYPES: ReadonlySet<CustodyType> = new Set<CustodyType>(['embedded', 'shared', 'self_custody']);\n\n/**\n * Whether a wallet is **non-custodial** — the platform alone cannot produce a\n * signature because the shares it holds do not meet the threshold\n * (`platformShareCount < threshold`, i.e. custody type `shared` or `self_custody`).\n *\n * This mirrors the server-attested invariant `platformShares < t ⟺ non-custodial`,\n * so an app can display the custody guarantee straight off the returned wallet.\n */\nexport function isNonCustodial(wallet: Pick<WalletData, 'platformShareCount' | 'threshold'>): boolean {\n return wallet.platformShareCount < wallet.threshold;\n}\n\n/**\n * Validate a create-wallet custody policy client-side, before the request — clear\n * errors instead of a round-trip to a 400. A no-op when no policy is supplied\n * (the default embedded 2-of-3 topology).\n *\n * The rules mirror the backend contract: `parties` (when supplied) are ≥2 distinct,\n * non-empty roles that define `n`; `threshold` is an integer in `[2, n]`; and\n * `custodyKinds` has exactly one known kind per party.\n */\nexport function validateCustodyPolicy(params: Pick<CreateWalletParams, 'threshold' | 'parties' | 'custodyKinds' | 'custodyType'>): void {\n const { threshold, parties, custodyKinds, custodyType } = params;\n if (threshold === undefined && parties === undefined && custodyKinds === undefined && custodyType === undefined) return;\n\n if (parties !== undefined) {\n if (!Array.isArray(parties) || parties.length < 2) {\n throw new WaaskeyError('`parties` must list at least 2 party roles.', 'validation');\n }\n if (parties.some((role) => typeof role !== 'string' || role.trim() === '')) {\n throw new WaaskeyError('`parties` roles must be non-empty strings.', 'validation');\n }\n if (new Set(parties).size !== parties.length) {\n throw new WaaskeyError('`parties` roles must be distinct.', 'validation');\n }\n }\n\n if (threshold !== undefined) {\n if (!Number.isInteger(threshold) || threshold < 2) {\n throw new WaaskeyError('`threshold` must be an integer of at least 2.', 'validation');\n }\n if (parties !== undefined && threshold > parties.length) {\n throw new WaaskeyError('`threshold` cannot exceed the number of parties.', 'validation');\n }\n }\n\n if (custodyKinds !== undefined) {\n if (parties === undefined) {\n throw new WaaskeyError('`custodyKinds` requires `parties` — they are parallel arrays.', 'validation');\n }\n if (custodyKinds.length !== parties.length) {\n throw new WaaskeyError('`custodyKinds` must have exactly one entry per party (same length as `parties`).', 'validation');\n }\n const unknown = custodyKinds.find((kind) => !CUSTODY_KINDS.has(kind));\n if (unknown !== undefined) {\n throw new WaaskeyError(`\\`custodyKinds\\` contains an unknown custody kind: ${String(unknown)}.`, 'validation');\n }\n }\n\n if (custodyType !== undefined && !CUSTODY_TYPES.has(custodyType)) {\n throw new WaaskeyError(`\\`custodyType\\` is not a valid custody type: ${String(custodyType)}.`, 'validation');\n }\n}\n","import { WaaskeyError } from './errors';\nimport type { EddsaKeygenResult } from './mpc';\n\n/**\n * On-device storage codec for an ed25519 (FROST) wallet's device share — the FROST `keyPackage`\n * (secret) + the group `publicKeyPackage`. Kept DISTINCT from the cggmp24 `{ keyShare, auxInfo,\n * sharedPublicKey }` blob (see `wallets.ts` `serializeShare`): the two share shapes never mix. This\n * leaf module is imported by both the keygen (persist, in `wallets.ts`) and the sign (read, in\n * `wallet.ts`) paths, so neither file forms an import cycle with the other.\n */\n\n/** Seal-input for the device's ed25519 share: the two FROST packages, as the `signEddsa` path reads them back. */\nexport function serializeEddsaShare(keygen: EddsaKeygenResult): string {\n return JSON.stringify({ keyPackage: keygen.keyPackage, publicKeyPackage: keygen.publicKeyPackage });\n}\n\n/** Inverse of {@link serializeEddsaShare}: parse a stored blob back into the FROST packages `signEddsa` needs. */\nexport function deserializeEddsaShare(blob: string): { keyPackage: unknown; publicKeyPackage: unknown } {\n let parsed: { keyPackage?: unknown; publicKeyPackage?: unknown };\n try {\n parsed = JSON.parse(blob) as { keyPackage?: unknown; publicKeyPackage?: unknown };\n } catch (cause) {\n throw new WaaskeyError('Stored ed25519 device share is corrupt — it is not valid JSON.', 'share_not_found', { cause });\n }\n if (parsed.keyPackage === undefined || parsed.publicKeyPackage === undefined) {\n throw new WaaskeyError('Stored ed25519 device share is malformed — it is missing its FROST key/public-key package.', 'share_not_found', {\n details: { keys: Object.keys(parsed) },\n });\n }\n return { keyPackage: parsed.keyPackage, publicKeyPackage: parsed.publicKeyPackage };\n}\n","import { toMpcCurve } from './chains';\nimport { WaaskeyError } from './errors';\nimport type { DeviceSignParams } from './mpc';\nimport type { SignSessionResponse, WalletCurve } from './types';\n\n/**\n * The relay coordination a device party needs to run its half of a started ceremony, normalized from\n * whichever backend descriptor started it — the sign session (which names this party + its peer) or\n * the send session (which names the whole quorum roster). Both reduce to: where the relay is, who is\n * in the quorum (in `participants` order), and which slot this device holds.\n */\nexport interface DeviceCeremony {\n curve: WalletCurve;\n /** Relay websocket URL every party connects to. */\n relayUrl: string;\n /** Ceremony id shared by every party; derives the execution ids. */\n sessionId: string;\n /** The quorum's relay roles, in `participants` order (`roles[i]` ↔ `participants[i]`). */\n roles: string[];\n /** The quorum's keygen indices, in protocol order. */\n participants: number[];\n /** This device's own 0-based slot into {@link roles} / {@link participants}. */\n signerPosition: number;\n /** Short-lived relay token (JWT) this device presents to join as `roles[signerPosition]`. */\n relayToken?: string;\n}\n\n/**\n * Map a started ceremony onto the {@link DeviceSignParams} the device party runs. This is the single\n * place that translation happens — the raw `sign`, the device-co-signed `send` and recover-sign all\n * share it, so they cannot drift on how a quorum is addressed.\n *\n * Only the 2-party shape is handled: cggmp24's plain `sign` transport addresses exactly one peer, so a\n * larger quorum needs the roster-routed member path (see waas-core#131) and is refused here rather\n * than silently mis-routed.\n *\n * `partyIndex`/`peerPartyIndex` are quorum POSITIONS, not keygen indices — the keygen indices ride in\n * `participants` (e.g. a `{server, user_backup}` recover-sign runs at positions 0/1 over participants\n * `[1, 2]`).\n */\nexport function toDeviceSignParams(ceremony: DeviceCeremony, share: string, digest: string): DeviceSignParams {\n const { roles, participants, signerPosition } = ceremony;\n if (participants.length !== 2 || roles.length !== 2 || signerPosition < 0 || signerPosition > 1) {\n throw new WaaskeyError(\n `Unexpected sign descriptor: the quorum must be exactly 2 parties with signerPosition in {0, 1} (got ${participants.length} participants, ${roles.length} roles, signerPosition ${signerPosition}).`,\n 'sign_failed',\n { details: { roles, participants, signerPosition } },\n );\n }\n const peerPosition = 1 - signerPosition;\n return {\n curve: toMpcCurve(ceremony.curve),\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n role: roles[signerPosition]!,\n peerRole: roles[peerPosition]!,\n partyIndex: signerPosition,\n peerPartyIndex: peerPosition,\n relayToken: ceremony.relayToken,\n share,\n participants,\n signerPosition,\n digest,\n };\n}\n\n/**\n * Map a backend **sign-session** descriptor onto the device party's params.\n *\n * The descriptor is authoritative: the backend derives the quorum from the wallet's own party list and\n * issues the relay token bound to `{sessionId, role}`, so the client must NOT re-derive indices or join\n * unauthenticated. It names only this party and its peer (never a roster), so the pair is ordered by\n * `signerPosition` before it reaches {@link toDeviceSignParams}.\n */\nexport function toSessionSignParams(session: SignSessionResponse, share: string, digest: string): DeviceSignParams {\n return toDeviceSignParams(\n {\n curve: session.curve,\n relayUrl: session.relayUrl,\n sessionId: session.sessionId,\n roles: sessionRoles(session),\n participants: session.participants,\n signerPosition: session.signerPosition,\n relayToken: session.relayToken,\n },\n share,\n digest,\n );\n}\n\n/**\n * The 2-party roster a sign-session descriptor names: this party's `role` sits at its `signerPosition`,\n * `peerRole` takes the other slot. (A larger quorum carries no roster on that descriptor — the caller\n * supplies the wallet's own party slice instead.)\n */\nexport function sessionRoles(session: Pick<SignSessionResponse, 'role' | 'peerRole' | 'signerPosition'>): string[] {\n return session.signerPosition === 0 ? [session.role, session.peerRole] : [session.peerRole, session.role];\n}\n","import { WaaskeyError } from './errors';\nimport type { DeviceKeygenResult } from './mpc';\n\n/**\n * The on-device storage blob persisted per wallet — the device key share plus the data sign\n * needs. `relayUrl` (when known, i.e. for shares persisted at keygen) lets a later\n * device-present sign rejoin the SAME relay the ceremony used without any extra round-trip\n * (waas-core#131 follow-up: the sign quorum includes the device, so it must co-sign).\n */\nexport function serializeShare(keygen: DeviceKeygenResult, relayUrl?: string): string {\n return JSON.stringify({\n keyShare: keygen.keyShare,\n auxInfo: keygen.auxInfo,\n sharedPublicKey: keygen.sharedPublicKey,\n ...(relayUrl === undefined ? {} : { relayUrl }),\n });\n}\n\n/**\n * Inverse of {@link serializeShare}: parse a persisted storage blob back into its parts — the bare\n * KeyShare (its JSON string, the crypto material the MPC core signs with), the wallet's shared\n * public key, and the keygen relay URL when the blob recorded one. This is the ONE place that knows\n * the on-device storage shape, so the MPC layer only ever receives the KeyShare, never the wrapper.\n */\nexport function deserializeShare(blob: string): { keyShare: string; sharedPublicKey?: string; relayUrl?: string } {\n let parsed: { keyShare?: unknown; sharedPublicKey?: unknown; relayUrl?: unknown };\n try {\n parsed = JSON.parse(blob) as { keyShare?: unknown; sharedPublicKey?: unknown; relayUrl?: unknown };\n } catch (cause) {\n throw new WaaskeyError('Stored device share is corrupt — it is not valid JSON.', 'share_not_found', { cause });\n }\n if (typeof parsed.keyShare !== 'string') {\n throw new WaaskeyError('Stored device share is malformed — it is missing its KeyShare.', 'share_not_found', { details: { keys: Object.keys(parsed) } });\n }\n return {\n keyShare: parsed.keyShare,\n sharedPublicKey: typeof parsed.sharedPublicKey === 'string' ? parsed.sharedPublicKey : undefined,\n relayUrl: typeof parsed.relayUrl === 'string' ? parsed.relayUrl : undefined,\n };\n}\n","/**\n * Passkey step-up signing assertion (Pattern B).\n *\n * The backend accepts an optional `passkeyAssertion` (`AuthenticationResponseJSON`)\n * on sign/send/recover DTOs and verifies it server-side. This module runs the\n * WebAuthn assertion over a **server-issued one-time challenge** and returns the\n * typed `AuthenticationResponseJSON` ready to be included in the POST body.\n *\n * ### Challenge (issue #39 — replay-safe)\n * The challenge is a random nonce the **server** mints (via a step-up challenge\n * endpoint), NOT a value derived from the request payload. `Wallet.sign`/`send`\n * fetch it, run the assertion over it, and echo its `challengeId` on the request;\n * the server verifies the assertion against the stored challenge and **burns** it,\n * so a captured assertion cannot be replayed for a later identical payload.\n *\n * ### Wiring in Wallet\n * ```ts\n * // In wallet.sign() (handled by Wallet.resolveStepUp):\n * const { challengeId, challenge } = await http.request('POST', '/v1/wallets/${id}/stepup/challenge', { operation: 'sign' });\n * const assertion = await getSigningAssertion(challenge, { credentialId });\n * await http.request('POST', '/v1/wallets/${id}/sign', { message, passkeyAssertion: assertion, passkeyChallengeId: challengeId });\n *\n * // Caller opts in:\n * await wallet.sign(digest, { requirePasskey: true });\n * ```\n */\n\nimport { WaaskeyError } from '../errors';\nimport type { AuthenticationResponseJSON, PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';\n\n// ─── Capability detection ─────────────────────────────────────────────────────\n\n/**\n * Returns `true` if the current runtime has WebAuthn available — i.e. the SDK\n * can attempt a passkey assertion. Use this as a fast pre-flight before calling\n * `getSigningAssertion()` when you want to show/hide a \"sign with passkey\" button.\n */\nexport function isPasskeyAssertionSupported(): boolean {\n return typeof globalThis.navigator !== 'undefined' && typeof (globalThis.navigator as { credentials?: unknown }).credentials !== 'undefined';\n}\n\n// ─── SigningAssertionCeremony (override for non-browser / tests) ──────────────\n\n/**\n * Override the WebAuthn `credentials.get` call. Useful for React Native (native\n * passkey module) or unit tests (mock the assertion response).\n */\nexport interface SigningAssertionCeremony {\n get(options: PublicKeyCredentialRequestOptionsJSON): Promise<AuthenticationResponseJSON>;\n}\n\n/** @internal Default ceremony backed by @simplewebauthn/browser. */\nasync function defaultAssertionCeremony(): Promise<SigningAssertionCeremony> {\n let mod: typeof import('@simplewebauthn/browser');\n try {\n mod = await import('@simplewebauthn/browser');\n } catch {\n throw new WaaskeyError('Passkey step-up requires \"@simplewebauthn/browser\" installed, or pass a custom ceremony.', 'unsupported');\n }\n return {\n get: (options) => mod.startAuthentication({ optionsJSON: options }),\n };\n}\n\n// ─── getSigningAssertion ──────────────────────────────────────────────────────\n\n/** Options for `getSigningAssertion()`. */\nexport interface SigningAssertionOptions {\n /**\n * Restrict the assertion to a specific credential. Pass the `credentialId`\n * that was enrolled (e.g. from `PasskeyPrfSecretProvider.enroll()`). When\n * omitted the browser presents all resident credentials for the RP.\n */\n credentialId?: string;\n /**\n * Fully qualified domain name of the relying party. Defaults to the current\n * origin's hostname in the browser.\n */\n rpId?: string;\n /**\n * Custom ceremony implementation (for React Native or tests).\n */\n ceremony?: SigningAssertionCeremony;\n}\n\n/**\n * Run a WebAuthn assertion over a **server-issued one-time `challenge`** and return\n * the typed `AuthenticationResponseJSON` to attach as `passkeyAssertion` in the\n * request body.\n *\n * @param challenge — the base64url one-time challenge nonce from the server's\n * step-up challenge endpoint ({@link StepUpChallengeResponse.challenge}). It is\n * passed to the authenticator verbatim; the server verifies the assertion against\n * the stored challenge and burns it, so the assertion cannot be replayed.\n * @param options — optional ceremony override and credential hint.\n *\n * @throws `WaaskeyError('unsupported')` when WebAuthn is not available in this runtime.\n * @throws `WaaskeyError('aborted')` when the user cancels the authenticator prompt.\n */\nexport async function getSigningAssertion(challenge: string, options: SigningAssertionOptions = {}): Promise<AuthenticationResponseJSON> {\n // Skip the availability check when a custom ceremony is supplied — the caller\n // is responsible for the platform (e.g. React Native native passkey, or tests).\n if (options.ceremony === undefined && !isPasskeyAssertionSupported()) {\n throw new WaaskeyError('Passkey step-up is not available in this runtime (no WebAuthn API).', 'unsupported');\n }\n\n const ceremony = options.ceremony ?? (await defaultAssertionCeremony());\n\n const rpId = options.rpId ?? (typeof location === 'undefined' ? undefined : location.hostname);\n\n const requestOptions: PublicKeyCredentialRequestOptionsJSON = {\n challenge,\n userVerification: 'required',\n ...(rpId ? { rpId } : {}),\n ...(options.credentialId ? { allowCredentials: [{ id: options.credentialId, type: 'public-key' }] } : {}),\n };\n\n try {\n return await ceremony.get(requestOptions);\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n const msg = cause instanceof Error ? cause.message : String(cause);\n if (/cancel|abort|not allowed|user gesture/i.test(msg)) {\n throw new WaaskeyError('Passkey authentication was cancelled by the user.', 'aborted', { cause });\n }\n throw new WaaskeyError('Passkey step-up assertion failed.', 'unsupported', { cause });\n }\n}\n","import { toMpcCurve } from './chains';\nimport { isNonCustodial } from './custody';\nimport { deserializeEddsaShare } from './eddsa-share';\nimport { WaaskeyError } from './errors';\nimport { throwIfAborted } from './internal';\nimport { getSigningAssertion } from './passkey/assertion';\nimport { sessionRoles, toDeviceSignParams } from './session-sign';\nimport { deserializeShare } from './share-blob';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { MpcCore } from './mpc';\nimport type { DeviceCeremony } from './session-sign';\nimport type { ShareStore } from './storage';\nimport type {\n CustodyKind,\n CustodyType,\n EddsaAssembleRequest,\n Page,\n PageQuery,\n SendOptions,\n SendParams,\n SendResult,\n Signature,\n SignMessageResponse,\n SignOptions,\n SendSessionResponse,\n SignSessionResponse,\n StepUpChallengeResponse,\n StepUpOperation,\n WalletCurve,\n WalletData,\n WalletStatus,\n} from './types';\n\n/** Device-party dependencies a {@link Wallet} needs to co-sign an ed25519 (FROST) transaction locally. */\nexport interface WalletDeviceDeps {\n mpc?: MpcCore;\n shareStore?: ShareStore;\n}\n\n/** The relay role of the user's own party — the one this SDK can run. Mirrors the backend's `DEVICE_ROLE`. */\nconst DEVICE_ROLE = 'device';\n\n/**\n * A handle to a single wallet. Returned by `waaskey.wallets.create(...)` /\n * `waaskey.wallets.get(...)`.\n */\nexport class Wallet {\n /** Waaskey wallet id, e.g. `wlt_…`. */\n readonly id: string;\n /** The full wallet record as returned by the API. */\n readonly data: WalletData;\n\n constructor(\n private readonly http: HttpClient,\n data: WalletData,\n private readonly analytics?: Analytics,\n /** Device core + share store, threaded from {@link Wallets}, so an ed25519 wallet can co-sign locally. */\n private readonly device: WalletDeviceDeps = {},\n ) {\n this.id = data.id;\n this.data = data;\n }\n\n /** On-chain address (set once keygen completes). */\n get address(): string | undefined {\n return this.data.address;\n }\n\n /** Lifecycle state (`pending` until keygen completes, then `active`). */\n get status(): WalletStatus {\n return this.data.status;\n }\n\n /** Signing curve of the wallet. */\n get curve(): WalletCurve {\n return this.data.curve;\n }\n\n /** Signing threshold `t` of the wallet's `t`-of-`n` MPC key. */\n get threshold(): number {\n return this.data.threshold;\n }\n\n /** Ordered party roles of the wallet's keygen topology, length `n`. */\n get parties(): string[] {\n return this.data.parties;\n }\n\n /** Per-party custody kind, parallel to {@link parties}. */\n get custodyKinds(): CustodyKind[] {\n return this.data.custodyKinds;\n }\n\n /** How many of the wallet's shares the platform itself holds. */\n get platformShareCount(): number {\n return this.data.platformShareCount;\n }\n\n /**\n * The wallet's custody attestation (`embedded` / `shared` / `self_custody`) — display\n * it to prove the custody guarantee to the end-user (see {@link isNonCustodial}).\n */\n get custodyType(): CustodyType {\n return this.data.custodyType;\n }\n\n /**\n * Whether this wallet is **non-custodial** — the platform's shares alone do not meet\n * the threshold (`platformShareCount < threshold`, i.e. custody type `shared` or\n * `self_custody`), so WaaS cannot sign without the user/external party.\n */\n get isNonCustodial(): boolean {\n return isNonCustodial(this.data);\n }\n\n /**\n * Sign a 32-byte message digest with this wallet's key (2-of-3 threshold MPC).\n *\n * `digest` is a 32-byte hash as hex (the `0x` prefix is optional) — e.g. the\n * keccak-256 of an EVM transaction. Hashing a higher-level message/transaction\n * into a digest is the caller's (or a chain helper's) responsibility.\n *\n * **Passkey step-up (Pattern B / issue #21, #39):** pass `{ requirePasskey: true }` to run a\n * WebAuthn assertion before signing. The SDK fetches a **server-issued one-time challenge**,\n * prompts the user's authenticator over it, and attaches `passkeyAssertion` + its\n * `passkeyChallengeId` to the POST body; the backend verifies both the MPC signature and the\n * assertion, then burns the challenge (so it cannot be replayed). Alternatively supply a\n * pre-built assertion via `options.passkeyAssertion` (with its `options.passkeyChallengeId`).\n */\n async sign(digest: string, options: SignOptions = {}): Promise<string> {\n const message = normalizeDigest(digest);\n const quorum = this.signQuorum();\n const devicePosition = quorum?.indexOf(DEVICE_ROLE) ?? -1;\n\n // Platform-only quorum (custodial wallets): the server holds enough shares to sign alone, so the\n // one blocking POST is both correct and cheapest. Unknown topology falls here too — the server decides.\n if (devicePosition < 0) {\n const body: Record<string, unknown> = { message };\n await this.attachStepUp(body, 'sign', options);\n const res = await this.http.request<SignMessageResponse>('POST', `/v1/wallets/${this.id}/sign`, body, options.signal);\n this.analytics?.track('wallet.signed', { walletId: this.id, curve: this.data.curve });\n return res.signature;\n }\n\n // Device-present quorum: START the ceremony and let it run on the RELAY, off the request path.\n // The blocking `POST /sign` cannot serve this shape — it holds the HTTP request open for the\n // whole ceremony, which a proxy cuts (Cloudflare drops a proxied request idle ~100s) — and it\n // makes the client guess the routing. The session descriptor is authoritative instead: the\n // backend derives the quorum from the wallet's own party list and mints the relay token bound\n // to `{sessionId, role}`, which an unauthenticated device join would otherwise be refused.\n const { mpc, keyShare } = await this.loadDeviceParty(quorum!, 'signing');\n\n const startBody: Record<string, unknown> = { digest: message };\n await this.attachStepUp(startBody, 'sign', options);\n const session = await this.http.request<SignSessionResponse>('POST', `/v1/wallets/${this.id}/sign-session`, startBody, options.signal);\n\n // cggmp24's interactive sign hands the completed signature to BOTH parties, so the device's own\n // result IS the signature — there is nothing left to fetch or assemble server-side.\n const { signature } = await this.runDeviceSign(mpc, this.toSignCeremony(session, quorum!), keyShare, message);\n this.analytics?.track('wallet.signed', { walletId: this.id, curve: this.data.curve });\n return signature;\n }\n\n /**\n * The roles that will actually sign — the first `threshold` of the wallet's party list (#292),\n * mirroring the signer's own derivation. `undefined` when the topology is unknown (a legacy\n * wallet record), which callers treat as \"let the server decide\".\n */\n private signQuorum(): string[] | undefined {\n if (this.data.curve === 'ed25519') return undefined; // FROST signs through the send-session flow\n const roles = this.data.parties;\n const { threshold } = this.data;\n if (!Array.isArray(roles) || typeof threshold !== 'number') return undefined;\n return roles.slice(0, threshold);\n }\n\n /**\n * Everything this device needs to join a ceremony, resolved BEFORE one is started (#89): the MPC\n * core, the routed-sign capability a >2-party quorum needs, and the stored key share.\n *\n * Each failure is a typed error thrown straight to the caller, and the ordering is the point: a\n * device that cannot co-sign must never leave the platform party waiting on the relay for a\n * counterpart that will never arrive. That wait ends at the party-runner timeout (~210s) and\n * reaches the caller as an opaque 5xx — minutes after a knowable, local cause.\n */\n private async loadDeviceParty(quorum: string[], action: 'signing' | 'sending'): Promise<{ mpc: MpcCore; keyShare: string }> {\n const { mpc, shareStore } = this.device;\n if (!mpc || !shareStore) {\n throw new WaaskeyError(\n `This wallet's signing quorum [${quorum.join(', ')}] includes the device, so ${action} requires the device MPC core and share store — pass \\`mpc\\` and \\`shareStore\\` to \\`new Waaskey(...)\\`.`,\n 'device_core_required',\n );\n }\n // Hoisted out of the ceremony itself: a core without the routed export can never run a >2-party\n // quorum, and learning that only AFTER the platform party is on the relay is the #89 failure.\n if (quorum.length > 2 && !mpc.runMemberSign) {\n throw new WaaskeyError(`This wallet's sign quorum has ${quorum.length} parties, which needs an MPC core with routed (member-ceremony) sign support.`, 'unsupported');\n }\n const blob = await shareStore.get(this.id);\n if (!blob) {\n throw new WaaskeyError(`No stored device share for wallet ${this.id} — this device cannot join the signing quorum.`, 'share_not_found');\n }\n const { keyShare } = deserializeShare(blob);\n return { mpc, keyShare };\n }\n\n /**\n * Normalize a sign-session descriptor into the shared {@link DeviceCeremony}. The 2-party roster\n * comes from the descriptor's own `role`/`peerRole` (authoritative — the relay token is bound to\n * that role); a larger quorum carries no server-sent roster, so the wallet's own party slice — the\n * same slice the signer derives — supplies it.\n */\n private toSignCeremony(session: SignSessionResponse, quorum: string[]): DeviceCeremony {\n return {\n curve: session.curve,\n relayUrl: session.relayUrl,\n sessionId: session.sessionId,\n roles: session.participants.length === 2 ? sessionRoles(session) : quorum,\n participants: session.participants,\n signerPosition: session.signerPosition,\n relayToken: session.relayToken,\n };\n }\n\n /**\n * Run this device's half of a started ceremony. A 2-party quorum uses the plain single-peer\n * transport; anything larger MUST be roster-routed, or the transport attributes every inbound\n * message to the one configured peer and the protocol aborts on the third party's first message\n * (waas-core#131).\n */\n private runDeviceSign(mpc: MpcCore, ceremony: DeviceCeremony, keyShare: string, digest: string): Promise<{ signature: string }> {\n if (ceremony.participants.length === 2) {\n return mpc.runSign(toDeviceSignParams(ceremony, keyShare, digest));\n }\n // Normally unreachable — `loadDeviceParty` refuses a >2-party quorum without the routed export\n // before anything starts. It still guards here, because the STARTED ceremony's size is the\n // server's word and could exceed the quorum the wallet record described.\n if (!mpc.runMemberSign) {\n throw new WaaskeyError(\n `This wallet's sign quorum has ${ceremony.participants.length} parties, which needs an MPC core with routed (member-ceremony) sign support.`,\n 'unsupported',\n );\n }\n return mpc.runMemberSign({\n curve: toMpcCurve(ceremony.curve),\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n relayToken: ceremony.relayToken,\n roles: ceremony.roles,\n share: keyShare,\n participants: ceremony.participants,\n signerPosition: ceremony.signerPosition,\n digest,\n });\n }\n\n /**\n * Send a transaction from this wallet. The platform builds the chain-specific transaction\n * and co-signs it with the 2-of-3 MPC quorum, returning the **signed raw transaction**.\n * `value` is in the chain's base unit (wei) as a numeric string.\n *\n * **WaaS is sign-only — it never broadcasts.** The result's {@link SendResult.signedTx} is\n * the signed raw tx the *client* submits to its own node/provider (see\n * {@link Waaskey.broadcast} or your own submitter); {@link SendResult.txHash} is a\n * deterministic offline id for reference, not proof of broadcast.\n *\n * **Passkey step-up (Pattern B / issue #21, #39):** pass `{ requirePasskey: true }` to run a\n * WebAuthn assertion before sending, over a server-issued one-time challenge (verified + burned\n * server-side). Alternatively supply a pre-built assertion via `options.passkeyAssertion`.\n */\n async send(params: SendParams, options: SendOptions = {}): Promise<SendResult> {\n // An ed25519 (FROST) wallet is always device-co-signed — the platform cannot sign alone.\n if (this.data.curve === 'ed25519') {\n return this.sendEd25519(params, options);\n }\n // A secp wallet whose signing quorum holds the device is co-signed the same way: only the\n // platform can build the transaction (the client has no chain adapter to derive its digest),\n // so the ceremony must be split across three short requests rather than one held-open POST.\n const quorum = this.signQuorum();\n if ((quorum?.indexOf(DEVICE_ROLE) ?? -1) >= 0) {\n return this.sendWithDevice(params, options, quorum!);\n }\n // Platform-only quorum (custodial): the server signs alone — one request, no client party.\n const body: Record<string, unknown> = { ...params };\n await this.attachStepUp(body, 'send', options);\n const res = await this.http.request<SendResult>('POST', `/v1/wallets/${this.id}/send`, body, options.signal);\n this.analytics?.track('wallet.sent', { walletId: this.id, chain: params.chainId });\n return res;\n }\n\n /**\n * Device-co-signed send for a secp wallet — the cggmp24 counterpart of {@link sendEd25519}:\n *\n * 1. **START** (`POST …/send-session`): the platform runs the transfer gates, builds the unsigned\n * tx, puts its own party on the relay in the background, and returns the 32-byte digest plus\n * the relay coordination. It does NOT wait for the ceremony.\n * 2. **CO-SIGN**: this device runs its half over the relay with its stored share; cggmp24 hands\n * the completed signature to both parties.\n * 3. **ASSEMBLE** (`POST …/send-session/:txId/assemble`): the platform verifies the signature\n * (recovers to the wallet key AND equals its own party's) and embeds it into the wire tx.\n *\n * Every device-side precondition is resolved BEFORE the START (see {@link loadDeviceParty}), so a\n * device that cannot co-sign costs nothing: no tx is built and no platform party is left waiting.\n *\n * **A co-sign that fails after a successful START rejects with its typed error.** START is not the\n * commit point — it yields an *unsigned* tx and a pending session, and nothing broadcastable exists\n * until ASSEMBLE returns a `signedTx` — so there is no result to salvage by swallowing the failure,\n * and no fallback to `POST /send` (the platform cannot reach the threshold on this wallet alone, so\n * a retry there would only hang). The backend expires the abandoned session and fails the tx row.\n */\n private async sendWithDevice(params: SendParams, options: SendOptions, quorum: string[]): Promise<SendResult> {\n const { signal } = options;\n const { mpc, keyShare } = await this.loadDeviceParty(quorum, 'sending');\n throwIfAborted(signal);\n\n const startBody: Record<string, unknown> = { ...params };\n await this.attachStepUp(startBody, 'send', options);\n throwIfAborted(signal);\n const session = await this.http.request<SendSessionResponse>('POST', `/v1/wallets/${this.id}/send-session`, startBody, signal);\n const digest = sendPayload(session, 'digest');\n\n throwIfAborted(signal);\n const { signature } = await this.runDeviceSign(mpc, toSendCeremony(session), keyShare, digest);\n throwIfAborted(signal);\n const assemble: EddsaAssembleRequest = { signature };\n const res = await this.http.request<SendResult>('POST', `/v1/wallets/${this.id}/send-session/${session.txId}/assemble`, assemble, signal);\n this.analytics?.track('wallet.sent', { walletId: this.id, chain: params.chainId });\n return res;\n }\n\n /**\n * Device-co-signed send for an ed25519 (FROST) wallet (#110) — the browser holds the device FROST\n * share and co-signs 2-party with the backend `server` party over the relay:\n *\n * 1. **START** (`POST …/send-session`): the backend builds the unsigned tx (chain adapter), starts\n * its server FROST party on the relay in the background, and returns the raw `message` bytes to\n * sign + the relay coordination ({@link SendSessionResponse}).\n * 2. **CO-SIGN**: the device runs `signEddsa` over the relay with its stored `{keyPackage,\n * publicKeyPackage}` share; the two parties aggregate the RFC 8032 signature (returned locally).\n * 3. **ASSEMBLE** (`POST …/send-session/:txId/assemble`): the backend embeds the aggregated\n * signature into the wire tx (chain adapter) and returns the signed raw tx + offline `txHash`.\n *\n * WaaS stays sign-only: the returned {@link SendResult.signedTx} is what the client broadcasts.\n */\n private async sendEd25519(params: SendParams, options: SendOptions): Promise<SendResult> {\n const { mpc, shareStore } = this.device;\n if (!mpc || !shareStore) {\n throw new WaaskeyError(\n 'Signing an ed25519 transaction requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.',\n 'device_core_required',\n );\n }\n if (!mpc.runEddsaSign) {\n throw new WaaskeyError(\n 'The configured MPC core does not support ed25519 (FROST) signing — use a client-wasm build with the ed25519 (keygenEddsa/signEddsa) exports.',\n 'unsupported',\n );\n }\n const { signal } = options;\n throwIfAborted(signal);\n\n // Load this device's FROST share (persisted by the ed25519 keygen), keyed by wallet id.\n const blob = await shareStore.get(this.id);\n if (!blob) {\n throw new WaaskeyError(`No stored device share for wallet \"${this.id}\" — this device never completed the ed25519 keygen.`, 'share_not_found', {\n details: { walletId: this.id },\n });\n }\n const { keyPackage, publicKeyPackage } = deserializeEddsaShare(blob);\n\n // PHASE 1 — START. Passkey step-up (server-issued one-time challenge) rides the START body, exactly\n // as it does on the secp send; the backend verifies + burns it before its server party joins.\n const startBody: Record<string, unknown> = { ...params };\n await this.attachStepUp(startBody, 'send', options);\n throwIfAborted(signal);\n const session = await this.http.request<SendSessionResponse>('POST', `/v1/wallets/${this.id}/send-session`, startBody, signal);\n const message = sendPayload(session, 'message');\n\n // PHASE 2 — CO-SIGN over the relay. The device holds the FROST share; the server co-signs concurrently.\n throwIfAborted(signal);\n let signature: string;\n try {\n ({ signature } = await mpc.runEddsaSign({\n relayUrl: session.relayUrl,\n sessionId: session.sessionId,\n roles: session.roles,\n partyIndex: session.signerPosition,\n keyPackage,\n publicKeyPackage,\n participants: session.participants,\n message,\n relayToken: session.relayToken,\n }));\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The device ed25519 sign ceremony failed.', 'sign_failed', { cause });\n }\n\n // PHASE 3 — ASSEMBLE the wire tx from the aggregated signature.\n throwIfAborted(signal);\n const assemble: EddsaAssembleRequest = { signature };\n const res = await this.http.request<SendResult>('POST', `/v1/wallets/${this.id}/send-session/${session.txId}/assemble`, assemble, signal);\n this.analytics?.track('wallet.sent', { walletId: this.id, chain: params.chainId });\n return res;\n }\n\n /**\n * Attach a passkey step-up assertion to `body` when the caller requests one (issue #39).\n *\n * The challenge is a **server-issued one-time nonce**, never derived from the request\n * payload: the SDK fetches it from the step-up challenge endpoint, runs the WebAuthn\n * assertion over it, and echoes its `challengeId` so the server can verify and burn it —\n * making a captured assertion non-replayable. A pre-built `passkeyAssertion` (with its\n * `passkeyChallengeId`) is attached as-is and takes precedence over `requirePasskey`.\n */\n private attachStepUp(body: Record<string, unknown>, operation: StepUpOperation, options: SignOptions | SendOptions): Promise<void> {\n return attachPasskeyStepUp(this.http, this.id, body, operation, options);\n }\n\n /**\n * List this wallet's **signing activity**, newest first (paginated) — the unified audit\n * trail of what this key signed (raw signs and send/sweep signed txs, #289). A send/sweep\n * record carries the `signedTx` the client broadcasts.\n */\n async signatures(query: PageQuery = {}, options: SendOptions = {}): Promise<Page<Signature>> {\n const qs = new URLSearchParams();\n if (query.page !== undefined) qs.set('page', String(query.page));\n if (query.limit !== undefined) qs.set('limit', String(query.limit));\n const suffix = qs.toString() ? `?${qs}` : '';\n return this.http.request<Page<Signature>>('GET', `/v1/wallets/${this.id}/signatures${suffix}`, undefined, options.signal);\n }\n}\n\n/**\n * Attach a passkey step-up assertion to a sign/send request `body` when the caller requests one\n * (issue #39) — the standalone form of {@link Wallet}'s step-up, so other sign flows on a walletId\n * (e.g. {@link Wallets.recoverSign}, #351/#78) thread the SAME replay-safe challenge without\n * duplicating it. A pre-built `passkeyAssertion` (with its `passkeyChallengeId`) is attached as-is and\n * takes precedence over `requirePasskey`; otherwise, when `requirePasskey`, the SDK fetches a\n * server-issued one-time challenge, runs the WebAuthn assertion over it, and echoes its `challengeId`\n * so the server can verify and burn it. No-op when neither is set.\n */\nexport async function attachPasskeyStepUp(\n http: HttpClient,\n walletId: string,\n body: Record<string, unknown>,\n operation: StepUpOperation,\n options: SignOptions | SendOptions,\n): Promise<void> {\n if (options.passkeyAssertion !== undefined) {\n body['passkeyAssertion'] = options.passkeyAssertion;\n if (options.passkeyChallengeId !== undefined) body['passkeyChallengeId'] = options.passkeyChallengeId;\n return;\n }\n if (!options.requirePasskey) return;\n\n const { challengeId, challenge } = await http.request<StepUpChallengeResponse>('POST', `/v1/wallets/${walletId}/stepup/challenge`, { operation }, options.signal);\n body['passkeyAssertion'] = await getSigningAssertion(challenge, { credentialId: options.passkeyCredentialId });\n body['passkeyChallengeId'] = challengeId;\n}\n\n/**\n * Normalize a send descriptor into the shared {@link DeviceCeremony}. The send session names the whole\n * quorum (`roles` parallel to `participants`), so nothing has to be re-derived client-side.\n */\nfunction toSendCeremony(session: SendSessionResponse): DeviceCeremony {\n return {\n curve: session.curve,\n relayUrl: session.relayUrl,\n sessionId: session.sessionId,\n roles: session.roles,\n participants: session.participants,\n signerPosition: session.signerPosition,\n relayToken: session.relayToken,\n };\n}\n\n/**\n * The payload this curve's device party signs, taken off the send descriptor — the tx `digest` for\n * secp256k1 (cggmp24 signs a hash), the raw `message` bytes for ed25519 (FROST signs the message).\n * Exactly one is populated per curve, so a missing one means the descriptor does not match the wallet\n * being signed for; failing here keeps the device from joining a ceremony over undefined bytes.\n *\n * `details` carries only the ids — never the descriptor itself, which holds the short-lived\n * `relayToken` an app would then ship to its error reporter.\n */\nfunction sendPayload(session: SendSessionResponse, field: 'digest' | 'message'): string {\n const payload = session[field];\n if (!payload) {\n throw new WaaskeyError(`The send session did not return the \\`${field}\\` this wallet's curve (${session.curve}) signs.`, 'sign_failed', {\n details: { txId: session.txId, curve: session.curve },\n });\n }\n return payload;\n}\n\n/** Strip an optional `0x` and validate the digest is exactly 32 bytes of hex. */\nexport function normalizeDigest(digest: string): string {\n const hex = digest.startsWith('0x') || digest.startsWith('0X') ? digest.slice(2) : digest;\n if (!/^[0-9a-fA-F]{64}$/.test(hex)) {\n throw new WaaskeyError('`digest` must be a 32-byte hex string (64 hex chars, optional 0x prefix).', 'validation');\n }\n return hex;\n}\n","import { curveForChain, toMpcCurve } from './chains';\nimport { validateCustodyPolicy } from './custody';\nimport { serializeEddsaShare } from './eddsa-share';\nimport { getOrCreateDeviceEncKeypair, type DeviceEncKeypair } from './enc-keys';\nimport { WaaskeyError } from './errors';\nimport { delay, throwIfAborted } from './internal';\nimport { buildRecoveryRegistration, fetchRecoveryBackup, openRecoveryBlob, postRecoveryRegistration, type RecoveryRegisterPayload } from './recovery';\nimport { toSessionSignParams } from './session-sign';\nimport { serializeShare, deserializeShare } from './share-blob';\nimport { attachPasskeyStepUp, normalizeDigest, Wallet } from './wallet';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { DeviceKeygenParams, DeviceKeygenResult, DeviceSignResult, EddsaKeygenResult, MpcCore, MpcCurve, PrimePool } from './mpc';\nimport type { ShareStore } from './storage';\nimport type {\n CreateMemberWalletParams,\n CreateWalletOptions,\n CreateWalletParams,\n CreateWalletResponse,\n JoinCeremonyOptions,\n JoinSignCeremonyOptions,\n MemberCeremony,\n MemberCeremonyJoinResponse,\n MemberSignCeremony,\n Page,\n PageQuery,\n RecoverSignParams,\n RecoveryRetrieveResponse,\n RecoveryFactor,\n RecoveryShareInfo,\n SigningRequestResponse,\n SignOptions,\n SignRequestsQuery,\n SignSessionResponse,\n WalletBackupParams,\n WalletCeremony,\n WalletData,\n WalletShareholder,\n} from './types';\n\n/** Bounded retry for the user_backup backup registration — transient failures only, short backoff. */\nconst BACKUP_REGISTER_ATTEMPTS = 3;\nconst BACKUP_REGISTER_BACKOFF_MS = 200;\n\n/**\n * The client-held second-user party role in the non-custodial default roster `[device, server, user_backup]`\n * (#351/#78). The ONE device runs it as a SECOND keygen party alongside `device` (the platform signer\n * drives only `server`), and its share is the non-custodial backup — sealed + registered, never platform-held.\n */\nconst USER_BACKUP_ROLE = 'user_backup';\n\nconst DEFAULT_ACTIVATION_TIMEOUT_MS = 60_000;\nconst DEFAULT_POLL_INTERVAL_MS = 1_000;\n\n/** Dependencies a {@link Wallets} resource needs for the non-custodial ceremony. */\nexport interface WalletsDeps {\n mpc?: MpcCore;\n shareStore?: ShareStore;\n /** Optional pool of pre-generated primes; when present, keygen claims one instead of generating inline. */\n primePool?: PrimePool;\n /** Optional analytics emitter for wallet lifecycle events. */\n analytics?: Analytics;\n}\n\n/**\n * The `wallets` resource: create and load wallets, plus the approver actions\n * ({@link Wallets.approveSignRequest}/{@link Wallets.declineSignRequest}) and the approver\n * queue listing ({@link Wallets.listSignRequests}/{@link Wallets.listPendingApprovals}) on\n * their async signing requests (#229, #309, #329).\n */\nexport class Wallets {\n constructor(\n private readonly http: HttpClient,\n private readonly deps: WalletsDeps = {},\n ) {}\n\n /**\n * Create a new MPC wallet on the given chain. The keygen is a `t`-of-`n` ceremony:\n *\n * 1. ask the API to start a wallet + the server party (returns the ceremony params),\n * 2. run the **device** half of keygen locally (in WASM) against the relay,\n * 3. seal + persist the device share (it never leaves the device),\n * 4. wait until the wallet is ACTIVE (server party finished) and return it.\n *\n * By default (no custody policy) this is the embedded **2-of-3** topology. Supply an\n * explicit `{ threshold, parties, custodyKinds }` and/or a requested `custodyType` to\n * change the topology / custody posture — the SDK validates it client-side (see\n * {@link validateCustodyPolicy}) and the backend enforces the attested invariant. The\n * device runs whatever `t`-of-`n` the returned ceremony describes (its `parties` /\n * `threshold`), so the ceremony is not pinned to 2-of-3.\n *\n * **Non-custodial `[device, server, user_backup]` (#351/#78).** When the returned ceremony carries a\n * `user_backup` party ({@link WalletCeremony.additionalParties}), the platform signer drives ONLY the\n * `server` share, so this ONE device runs BOTH client parties in the SAME keygen ceremony — the\n * `device` party AND the client-held `user_backup` party — joining the same relay session with each\n * party's own relay token. It then persists the `device` share locally (as always) and, because there\n * is no platform recovery share, seals the `user_backup` share with the caller's recovery code and\n * registers the ciphertext server-side (reusing the recovery mechanism), so device-loss can never lock\n * funds. This path therefore REQUIRES `options.backup`. The sealed backup is persisted to a local\n * pending slot BEFORE the network call, so if registration fails the (non-re-derivable) share is not\n * lost — `create` throws `backup_failed` and {@link retryBackup} re-registers it (no re-keygen).\n *\n * Requires `mpc` + `shareStore` on the client. The device share is the user's half\n * of the key; without storing it the wallet would be unrecoverable.\n */\n async create(params: CreateWalletParams, options: CreateWalletOptions = {}): Promise<Wallet> {\n const { mpc, shareStore, primePool } = this.deps;\n if (!mpc || !shareStore) {\n throw new WaaskeyError('Creating a wallet requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n\n validateCustodyPolicy(params);\n\n const curve = curveForChain(params.chain);\n const { signal } = options;\n throwIfAborted(signal);\n\n // Only send the custody policy fields that were actually supplied — omitting them keeps the\n // default (embedded 2-of-3) topology, so existing callers are unchanged (back-compatible).\n const body: Record<string, unknown> = { label: params.label ?? params.chain, curve };\n if (params.threshold !== undefined) body['threshold'] = params.threshold;\n if (params.parties !== undefined) body['parties'] = params.parties;\n if (params.custodyKinds !== undefined) body['custodyKinds'] = params.custodyKinds;\n if (params.custodyType !== undefined) body['custodyType'] = params.custodyType;\n\n // ed25519 (FROST) DKG round-2 seals each secret share to the recipient's X25519 key (#114), so the\n // device must advertise its OWN encryption public key up front: the backend echoes the ordered\n // roster back on the ceremony (`encPubkeys`) and the device seals its packages to it. Get-or-create\n // the device's long-lived enc keypair (reused across wallets + reshares) and send its public key.\n let deviceEncKeypair: DeviceEncKeypair | undefined;\n if (curve === 'ed25519') {\n deviceEncKeypair = await getOrCreateDeviceEncKeypair(shareStore);\n body['deviceEncPubkey'] = deviceEncKeypair.publicHex;\n throwIfAborted(signal);\n }\n\n const created = await this.http.request<CreateWalletResponse>('POST', '/v1/wallets', body, signal);\n // This (embedded, non-member-bound) create path always gets a ceremony back — `ceremony` is\n // only ever absent for a member-bound wallet (#342, created via `createWallet`, never here).\n const { ceremony } = created;\n if (!ceremony) {\n throw new WaaskeyError('The API did not return a keygen ceremony to join.', 'keygen_failed', { details: created });\n }\n\n // Device half of the keygen ceremony — joins the server party over the relay. ed25519 (FROST) and\n // cggmp24 (secp256k1) diverge: FROST is curveless, has no Paillier primes, and yields a\n // `{keyPackage, publicKeyPackage}` share sealed distinctly from the cggmp24 KeyShare blob.\n throwIfAborted(signal);\n if (curve === 'ed25519') {\n // `deviceEncKeypair` is always set above in the same `curve === 'ed25519'` branch.\n await this.runEddsaKeygen(mpc, shareStore, created.id, ceremony, deviceEncKeypair!);\n } else {\n // `curve` is narrowed to a cggmp24 curve here (ed25519 handled above), so it is an MpcCurve.\n await this.runSecpKeygen(mpc, shareStore, primePool, created.id, ceremony, curve, options.backup, signal);\n }\n this.deps.analytics?.track('wallet.created', { walletId: created.id, chain: params.chain, curve });\n\n if (options.waitForActive === false) {\n return new Wallet(this.http, created, this.deps.analytics, this.walletDeviceDeps());\n }\n const active = await this.waitUntilActive(created.id, options);\n return new Wallet(this.http, active, this.deps.analytics, this.walletDeviceDeps());\n }\n\n /**\n * Create a **member-bound** wallet (#342-#349): an N+1 threshold topology where `N` specific ORG\n * MEMBERSHIPS (`shareholderMembershipIds`) each hold one share and the platform holds exactly\n * one (a derived `shared` custody topology — never `embedded`). Unlike {@link create} (the\n * embedded device+server(+recovery) flow, which runs the device's keygen inline and waits for\n * ACTIVE), this wallet is provisioned `pending_keygen` with **no ceremony to join here** — it\n * has no `mpc`/`shareStore` dependency and no custody-policy validation (that machinery is for\n * the raw `parties`/`custodyKinds` embedded topology, mutually exclusive with\n * `shareholderMembershipIds` server-side). Each invited member later runs {@link joinCeremony}\n * from their OWN device/session; the wallet only activates once every member has joined.\n */\n async createWallet(params: CreateMemberWalletParams, options: { signal?: AbortSignal } = {}): Promise<WalletData> {\n if (!Array.isArray(params.shareholderMembershipIds) || params.shareholderMembershipIds.length === 0) {\n throw new WaaskeyError('`shareholderMembershipIds` must list at least 1 member.', 'validation');\n }\n if (new Set(params.shareholderMembershipIds).size !== params.shareholderMembershipIds.length) {\n throw new WaaskeyError('`shareholderMembershipIds` must be distinct.', 'validation');\n }\n if (params.threshold !== undefined) {\n const n = params.shareholderMembershipIds.length + 1;\n if (!Number.isInteger(params.threshold) || params.threshold < 2 || params.threshold > n) {\n throw new WaaskeyError(`\\`threshold\\` must be an integer in [2, ${n}] (the ${n - 1} members + 1 platform party).`, 'validation');\n }\n }\n const { signal } = options;\n throwIfAborted(signal);\n\n const body: Record<string, unknown> = { label: params.label, shareholderMembershipIds: params.shareholderMembershipIds };\n if (params.curve !== undefined) body['curve'] = params.curve;\n if (params.threshold !== undefined) body['threshold'] = params.threshold;\n\n return this.http.request<WalletData>('POST', '/v1/wallets', body, signal);\n }\n\n /**\n * Warm the prime pool for a chain's curve OFF the hot path — call during onboarding/idle (ideally\n * from a Web Worker) so the next {@link create} on that chain doesn't pay the safe-prime cost.\n * No-op when no prime pool is configured.\n */\n async prewarm(chain: CreateWalletParams['chain']): Promise<void> {\n const curve = curveForChain(chain);\n // ed25519 (FROST) needs no Paillier safe-primes, so there is nothing to prewarm for it.\n if (curve === 'ed25519') return;\n await this.deps.primePool?.ensure(curve);\n }\n\n /**\n * List the tenant's wallets, newest first (paginated). Returns plain {@link WalletData}\n * rows — pass an `id` to {@link get} to obtain a signing-capable {@link Wallet}.\n */\n async list(query: PageQuery = {}, options: { signal?: AbortSignal } = {}): Promise<Page<WalletData>> {\n const qs = new URLSearchParams();\n if (query.page !== undefined) qs.set('page', String(query.page));\n if (query.limit !== undefined) qs.set('limit', String(query.limit));\n const suffix = qs.toString() ? `?${qs}` : '';\n return this.http.request<Page<WalletData>>('GET', `/v1/wallets${suffix}`, undefined, options.signal);\n }\n\n /** Load an existing wallet by id. */\n async get(id: string, options: { signal?: AbortSignal } = {}): Promise<Wallet> {\n const data = await this.http.request<WalletData>('GET', `/v1/wallets/${id}`, undefined, options.signal);\n return new Wallet(this.http, data, this.deps.analytics, this.walletDeviceDeps());\n }\n\n /** The device core + share store a {@link Wallet} needs to co-sign an ed25519 (FROST) tx locally. */\n private walletDeviceDeps(): { mpc?: MpcCore; shareStore?: ShareStore } {\n return { mpc: this.deps.mpc, shareStore: this.deps.shareStore };\n }\n\n /**\n * Join a **member-bound** wallet's multi-device keygen ceremony (#344, #349) as an invited org\n * member — call this from the member's OWN device/session (never a tenant API key: every HTTP\n * call here is member-session-authenticated, see {@link HttpClient.requestAsMember}). Unlike\n * {@link create}, every member (N of them) + the platform join the SAME relay session, so:\n *\n * 1. fetch this member's own party ({@link MemberCeremony}) plus the wallet's other\n * share-holders (to derive the full n-party relay roster the ceremony needs),\n * 2. ack readiness (`POST .../ceremony/join`) — the backend starts its platform party's own\n * relay connection only once EVERY member has acked, so this must happen before the ceremony\n * can complete,\n * 3. run this device's half of the n-party keygen over the relay (blocks until every party,\n * including the platform, is present and the ceremony completes),\n * 4. seal + persist the device's ONE share, keyed by `(walletId, membershipId)` — never by\n * `walletId` alone, since several members' shares for the SAME wallet may live in one\n * `shareStore` (e.g. a shared device, or a test harness).\n *\n * Safe to retry: a failed ceremony reopens the roster server-side, and re-acking/re-running is\n * idempotent from the caller's perspective.\n */\n async joinCeremony(walletId: string, options: JoinCeremonyOptions = {}): Promise<MemberCeremonyJoinResponse> {\n const { mpc, shareStore } = this.deps;\n if (!mpc || !shareStore) {\n throw new WaaskeyError('Joining a keygen ceremony requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n if (!mpc.runMemberKeygen) {\n throw new WaaskeyError('The configured MPC core does not support n-party (member-bound) keygen — use a client-wasm build with member-ceremony support.', 'unsupported');\n }\n const { signal } = options;\n throwIfAborted(signal);\n\n const [ceremony, shareholders] = await Promise.all([\n this.http.requestAsMember<MemberCeremony>('GET', `/v1/wallets/${walletId}/ceremony/mine`, undefined, signal),\n this.http.requestAsMember<WalletShareholder[]>('GET', `/v1/wallets/${walletId}/shareholders`, undefined, signal),\n ]);\n const roles = buildMemberRoster(shareholders, ceremony.parties);\n\n throwIfAborted(signal);\n // Ack BEFORE running the ceremony: the backend only starts its platform party's relay\n // connection once every member has joined, so acking first is what lets the ceremony proceed.\n const joined = await this.http.requestAsMember<MemberCeremonyJoinResponse>('POST', `/v1/wallets/${walletId}/ceremony/join`, undefined, signal);\n\n throwIfAborted(signal);\n let keygen: DeviceKeygenResult;\n try {\n keygen = await mpc.runMemberKeygen({\n curve: toMpcCurve(ceremony.curve),\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n roles,\n partyIndex: ceremony.partyIndex,\n threshold: ceremony.threshold,\n relayToken: ceremony.relayToken,\n });\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The member device keygen ceremony failed.', 'keygen_failed', { cause });\n }\n\n await shareStore.put(memberShareKey(walletId, membershipIdFromRole(ceremony.role)), serializeShare(keygen));\n return joined;\n }\n\n /**\n * Join a **member-bound** wallet's multi-device SIGN ceremony (#347, #349) as an invited org\n * member — the signing analogue of {@link joinCeremony}, called from the member's OWN\n * device/session. A sign is a `t`-of-`n` SELECTION (only `t` of the N+1 parties actually sign),\n * so the flow is:\n *\n * 1. cast this member's APPROVE vote (`POST .../sign-requests/:reqId/approve`) — a no-op if\n * already cast; once `t-1` members have approved, the backend fixes the signing quorum,\n * 2. poll this member's own sign-ceremony party (`GET .../sign-requests/:reqId/ceremony/mine`)\n * until the quorum is fixed AND this member was selected into it ({@link MemberSignCeremony.ready}),\n * 3. load this member's OWN stored share (keyed by `(walletId, membershipId)`, from\n * {@link joinCeremony}) and run this device's half of the fixed-quorum sign ceremony —\n * the interactive protocol's public output IS the completed signature.\n *\n * A member who is not selected into the fixed quorum, or whose approval never gets it there,\n * simply times out (`sign_ceremony_timeout`) rather than running anything.\n */\n async joinSignCeremony(walletId: string, reqId: string, options: JoinSignCeremonyOptions = {}): Promise<DeviceSignResult> {\n const { mpc, shareStore } = this.deps;\n if (!mpc || !shareStore) {\n throw new WaaskeyError('Joining a sign ceremony requires a device MPC core and a share store — pass `mpc` and `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n if (!mpc.runMemberSign) {\n throw new WaaskeyError('The configured MPC core does not support n-party (member-bound) signing — use a client-wasm build with member-ceremony support.', 'unsupported');\n }\n const { signal } = options;\n throwIfAborted(signal);\n\n // Cast (or re-cast — idempotent) this member's APPROVE vote. The `session` field on the\n // response is the 2-party device+server shape; a member-bound ceremony always learns its OWN\n // params from `ceremony/mine` below instead, so the vote response itself is not used here.\n await this.http.requestAsMember<SigningRequestResponse>('POST', `/v1/wallets/${walletId}/sign-requests/${reqId}/approve`, undefined, signal);\n\n const ceremony = await this.waitUntilReady(walletId, reqId, options);\n const membershipId = membershipIdFromRole(ceremony.role);\n const blob = await shareStore.get(memberShareKey(walletId, membershipId));\n if (!blob) {\n throw new WaaskeyError(`No stored device share for wallet \"${walletId}\" / member \"${membershipId}\" — this device never completed joinCeremony.`, 'share_not_found', {\n details: { walletId, membershipId },\n });\n }\n // Unpack the on-device storage blob into the bare KeyShare (crypto material) BEFORE handing it\n // to the MPC core — the core signs with the KeyShare, never the `{ keyShare, auxInfo, ... }`\n // storage wrapper. Keeping the blob format in `deserializeShare` (the inverse of the\n // `serializeShare` seal) means the MPC layer never learns the storage shape.\n const { keyShare } = deserializeShare(blob);\n\n throwIfAborted(signal);\n try {\n return await mpc.runMemberSign({\n curve: toMpcCurve(ceremony.curve),\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n roles: ceremony.quorumRoles,\n share: keyShare,\n participants: ceremony.participants,\n signerPosition: ceremony.signerPosition,\n digest: ceremony.digest,\n relayToken: ceremony.relayToken,\n });\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The member device sign ceremony failed.', 'sign_failed', { cause });\n }\n }\n\n /**\n * Approve a pending async signing request (#229) — either completing a single\n * device-approval request outright, or casting one APPROVE vote in an M-of-N approver\n * quorum (#309) configured on the wallet (via the tenant dashboard's `PUT .../quorum`). A\n * non-quorum request starts the MPC ceremony immediately; a quorum request only starts\n * it once enough approvers vote, and until then the response reports how many\n * approvals are still needed via {@link SigningRequestResponse.approvalsRemaining}.\n *\n * Takes `walletId` + `reqId` directly (rather than a {@link Wallet} instance) since an\n * approver typically learns of a pending request out-of-band — e.g. a\n * `sign_request.created` webhook or push notification — without first loading the wallet.\n */\n async approveSignRequest(walletId: string, reqId: string, options: { signal?: AbortSignal } = {}): Promise<SigningRequestResponse> {\n return this.http.request<SigningRequestResponse>('POST', `/v1/wallets/${walletId}/sign-requests/${reqId}/approve`, undefined, options.signal);\n }\n\n /**\n * Decline a pending async signing request (#229) — either rejecting a single\n * device-approval request outright, or casting a REJECT vote in an M-of-N approver\n * quorum (#309), which declines the request as soon as one approver rejects it.\n */\n async declineSignRequest(walletId: string, reqId: string, options: { signal?: AbortSignal } = {}): Promise<SigningRequestResponse> {\n return this.http.request<SigningRequestResponse>('POST', `/v1/wallets/${walletId}/sign-requests/${reqId}/decline`, undefined, options.signal);\n }\n\n /**\n * List a wallet's async signing requests, newest first (paginated) — optionally filtered to\n * a single lifecycle {@link SignRequestsQuery.status} (#332). The API paginates the\n * *filtered* set, so `total`/`page` always describe what was actually matched.\n */\n async listSignRequests(walletId: string, query: SignRequestsQuery = {}, options: { signal?: AbortSignal } = {}): Promise<Page<SigningRequestResponse>> {\n const qs = new URLSearchParams();\n if (query.status !== undefined) qs.set('status', query.status);\n if (query.page !== undefined) qs.set('page', String(query.page));\n if (query.limit !== undefined) qs.set('limit', String(query.limit));\n const suffix = qs.toString() ? `?${qs}` : '';\n return this.http.request<Page<SigningRequestResponse>>('GET', `/v1/wallets/${walletId}/sign-requests${suffix}`, undefined, options.signal);\n }\n\n /**\n * List a wallet's **pending approver queue** — the ergonomic entry point over\n * {@link listSignRequests} pinned to `status: 'pending_approval'` (#309, #329): the\n * requests currently awaiting an approver's {@link approveSignRequest}/\n * {@link declineSignRequest} vote, either a single device-approval request or one still\n * short of its M-of-N quorum (see {@link SigningRequestResponse.approvalsRemaining}).\n */\n async listPendingApprovals(walletId: string, query: PageQuery = {}, options: { signal?: AbortSignal } = {}): Promise<Page<SigningRequestResponse>> {\n return this.listSignRequests(walletId, { ...query, status: 'pending_approval' }, options);\n }\n\n /**\n * Run the cggmp24 (secp256k1) device keygen and persist the resulting share(s) (#351/#78). Two shapes,\n * chosen by whether the ceremony carries client-held extra parties ({@link WalletCeremony.additionalParties}):\n *\n * - **Single client party** (today's path — `[device, server]` or custodial `[device, server, recovery]`,\n * where the platform drives every non-device party): run just the `device` party and seal its share\n * under the wallet id, exactly as before.\n * - **Non-custodial `[device, server, user_backup]`** (a `user_backup` extra party): run BOTH the\n * `device` and `user_backup` parties CONCURRENTLY in the SAME relay session (each with its own\n * role-scoped relay token + its OWN Paillier primes), then persist the `device` share locally and\n * seal + register the `user_backup` share as the non-custodial backup (requires `backup`).\n *\n * Any additional party the client cannot drive (a non-`user_backup` role) is refused up front — leaving\n * it unjoined would hang the whole ceremony, so failing loud beats silently deadlocking.\n */\n private async runSecpKeygen(\n mpc: MpcCore,\n shareStore: ShareStore,\n primePool: PrimePool | undefined,\n walletId: string,\n ceremony: WalletCeremony,\n curve: MpcCurve,\n backup: WalletBackupParams | undefined,\n signal?: AbortSignal,\n ): Promise<void> {\n const extras = ceremony.additionalParties ?? [];\n const unsupported = extras.filter((party) => party.role !== USER_BACKUP_ROLE);\n if (unsupported.length > 0) {\n throw new WaaskeyError(\n `The keygen ceremony carries an additional client party this SDK cannot drive (${unsupported.map((party) => party.role).join(', ')}) — refusing to keygen, since leaving a party unjoined would hang the ceremony.`,\n 'unsupported',\n { details: { roles: unsupported.map((party) => party.role) } },\n );\n }\n const userBackupParty = extras.find((party) => party.role === USER_BACKUP_ROLE);\n\n // Single client party (back-compatible default): the device runs one party, the platform the rest.\n if (!userBackupParty) {\n // Claim a pre-generated prime (instant when the pool is warm) so keygen doesn't pay the\n // safe-prime cost on the hot path. Without a pool the core generates inline (slow in WASM).\n const pregeneratedPrimes = primePool ? await primePool.take(curve) : undefined;\n throwIfAborted(signal);\n const [keygen] = await this.runKeygenParties(mpc, [{ ...ceremony, curve, pregeneratedPrimes }]);\n // Seal + persist the device share (never sent to the server), with the ceremony's relay URL so a\n // device-present sign can rejoin the same relay (see Wallet.sign).\n await shareStore.put(walletId, serializeShare(keygen!, ceremony.relayUrl));\n return;\n }\n\n // Non-custodial `[device, server, user_backup]` (#351/#78): the ONE device runs TWO client parties.\n // Without the recovery-backup material we cannot register the user_backup share — and an un-backed-up\n // user_backup share means a lost device locks funds — so refuse before running anything.\n if (!backup) {\n throw new WaaskeyError(\n 'This wallet is a non-custodial [device, server, user_backup] topology whose user_backup share must be backed up at keygen — pass `options.backup` (recoveryCode + totpSecret + email) to `wallets.create(...)`, otherwise the wallet would be unrecoverable on device loss.',\n 'validation',\n );\n }\n\n // Each client party needs its OWN private Paillier primes — never shared. Two independent takes.\n const [devicePrimes, backupPrimes] = primePool ? await Promise.all([primePool.take(curve), primePool.take(curve)]) : [undefined, undefined];\n throwIfAborted(signal);\n // Run both parties in the SAME ceremony/relay session, concurrently — the `device` party (party 0,\n // from `ceremony`) and the client-held `user_backup` party (party 2, from the additional descriptor,\n // with its OWN relay token). They exchange messages via the relay with the platform `server` party.\n const [deviceKeygen, backupKeygen] = await this.runKeygenParties(mpc, [\n { ...ceremony, curve, pregeneratedPrimes: devicePrimes },\n { ...userBackupParty, curve, pregeneratedPrimes: backupPrimes },\n ]);\n // The `device` share is persisted locally, exactly as in the single-party path.\n await shareStore.put(walletId, serializeShare(deviceKeygen!, ceremony.relayUrl));\n throwIfAborted(signal);\n\n // The `user_backup` share is the NON-CUSTODIAL BACKUP. It exists ONLY in memory here and is NOT\n // re-derivable (a fresh keygen would yield a DIFFERENT share), so it must be made durable BEFORE the\n // network call: seal it with the caller's recovery code (the raw code never leaves the client — only\n // its SHA-256 is enrolled) and persist the resulting ciphertext to a LOCAL pending-backup slot. That\n // ciphertext is opaque without the recovery code, so a local copy is safe — it is a retry buffer, not\n // the authoritative backup. Only THEN register it server-side (the authoritative copy). If register\n // ultimately fails, the sealed share survives locally and `retryBackup(...)` re-registers it — a\n // network blip can never silently void the no-lockout guarantee by discarding the share.\n const { payload } = await buildRecoveryRegistration({ share: serializeShare(backupKeygen!), ...backup });\n await shareStore.put(userBackupPendingKey(walletId), JSON.stringify(payload));\n await this.registerBackup(walletId, payload, signal);\n // Registered server-side (authoritative) — drop the local retry buffer so the plaintext-recoverable\n // ciphertext isn't retained on-device beyond the durability window.\n await shareStore.remove(userBackupPendingKey(walletId));\n }\n\n /**\n * Register a sealed user_backup {@link RecoveryRegisterPayload} server-side, with a small bounded retry\n * on TRANSIENT failures (network / 5xx / rate-limit) — a flaky moment must not cost the backup. A\n * non-transient failure (4xx) fails fast. On abort, the abort propagates unchanged. If it ultimately\n * cannot register, throws a distinct, actionable {@link WaaskeyError} `backup_failed` (NOT `keygen_failed`)\n * — the caller's cue that the wallet was created but its backup is only local, and pointing at\n * {@link retryBackup}. The pending slot is intentionally NOT touched here, so a failure leaves the\n * sealed share intact for the retry.\n */\n private async registerBackup(walletId: string, payload: RecoveryRegisterPayload, signal?: AbortSignal): Promise<RecoveryShareInfo> {\n let lastCause: unknown;\n for (let attempt = 1; attempt <= BACKUP_REGISTER_ATTEMPTS; attempt++) {\n throwIfAborted(signal);\n try {\n return await postRecoveryRegistration(this.http, walletId, payload, signal);\n } catch (cause) {\n // A cancellation is the caller's intent — surface it as `aborted`, never as a backup failure.\n if (cause instanceof WaaskeyError && cause.code === 'aborted') throw cause;\n lastCause = cause;\n const transient = cause instanceof WaaskeyError && (cause.code === 'network' || cause.code === 'server_error' || cause.code === 'rate_limited');\n if (!transient || attempt === BACKUP_REGISTER_ATTEMPTS) break;\n await delay(BACKUP_REGISTER_BACKOFF_MS * attempt, signal);\n }\n }\n throw new WaaskeyError(\n `The wallet \"${walletId}\" was created, but registering its user_backup recovery backup failed. The sealed backup is retained locally — retry with \\`wallets.retryBackup(\"${walletId}\")\\`.`,\n 'backup_failed',\n { cause: lastCause, details: { walletId } },\n );\n }\n\n /**\n * Re-register a non-custodial wallet's user_backup backup that a previous {@link create} sealed locally\n * but could not register (a `backup_failed` create) (#351/#78). Reads the LOCAL pending-backup slot's\n * sealed ciphertext and re-POSTs it — **no re-keygen** (the share is not re-derivable) — with the same\n * bounded transient retry, then clears the slot on success. Idempotent-ish: a no-op `share_not_found`\n * when nothing is pending (already registered, or never created here). Requires a share store.\n */\n async retryBackup(walletId: string, options: { signal?: AbortSignal } = {}): Promise<RecoveryShareInfo> {\n const { shareStore } = this.deps;\n if (!shareStore) {\n throw new WaaskeyError('Retrying a wallet backup requires a share store — pass `shareStore` to `new Waaskey(...)`.', 'device_core_required');\n }\n const { signal } = options;\n throwIfAborted(signal);\n const stored = await shareStore.get(userBackupPendingKey(walletId));\n if (!stored) {\n throw new WaaskeyError(\n `No pending user_backup backup for wallet \"${walletId}\" — nothing to retry (it was already registered, or this device never created it).`,\n 'share_not_found',\n { details: { walletId } },\n );\n }\n const payload = parseBackupPayload(stored, walletId);\n const share = await this.registerBackup(walletId, payload, signal);\n // Registered — the local retry buffer has served its purpose.\n await shareStore.remove(userBackupPendingKey(walletId));\n return share;\n }\n\n /**\n * Device-loss RECOVERY CO-SIGN for a non-custodial `[device, server, user_backup]` secp256k1 wallet\n * (#351/#78). When the device is lost, the user restores their client-held `user_backup` share from the\n * sealed server-side backup and co-signs `digest` with the platform's `server` party — the 2-party\n * `{server, user_backup}` quorum. This is NOT the platform-only custodial `{server, recovery}` recoverSign\n * (`recovery.recoverSign` / `POST …/recovery/recover-sign`): here the platform CANNOT sign alone; the\n * user's restored share is the co-signing factor.\n *\n * 1. **RESTORE** — retrieve the sealed `user_backup` ciphertext (the multi-factor recovery gate,\n * {@link RecoverParams}, releases it) and open it with the recovery code CLIENT-SIDE (Contract A: the\n * raw code never leaves the device), yielding the cggmp24 `user_backup` KeyShare. No registered backup\n * fails `share_not_found`; a wrong recovery code fails `invalid_recovery_code` — either BEFORE any\n * ceremony starts, so a bad restore never signs (and never hangs).\n * 2. **START** — `POST /v1/wallets/:id/recover-sign-session` with the digest (+ passkey step-up when the\n * wallet requires it, threaded exactly like a normal sign via `options`) → the `user_backup` party's\n * ceremony descriptor: its role, the `{server, user_backup}` keygen `participants`, this party's\n * `signerPosition`, and a `user_backup`-role relay token.\n * 3. **CO-SIGN** — run the `user_backup` MPC party ({@link MpcCore.runSign}) over the relay with the\n * restored share + that descriptor; the platform `server` party co-signs server-side. Returns the\n * resulting signature.\n *\n * The ONLY differences from a normal `{device, server}` device sign are the SHARE (the restored\n * `user_backup`, not the local device share) and the DESCRIPTOR (from the recover-sign session, not the\n * normal sign session) — the same {@link MpcCore.runSign} relay machinery drives both.\n *\n * Requires `mpc` on the client (the co-signing core). No share store is needed: the restored share is\n * held only in memory for the ceremony and never persisted (the device is lost/new). secp256k1 only —\n * re-provisioning a fresh device share (reshare back to a full 2-of-3) is a separate follow-up.\n */\n async recoverSign(walletId: string, params: RecoverSignParams, options: SignOptions = {}): Promise<string> {\n const { mpc } = this.deps;\n if (!mpc) {\n throw new WaaskeyError('Recovery co-signing requires a device MPC core — pass `mpc` to `new Waaskey(...)`.', 'device_core_required');\n }\n const { signal } = options;\n throwIfAborted(signal);\n const digest = normalizeDigest(params.digest);\n\n // STEP 1 — RESTORE the user_backup share. Fetch the sealed ciphertext (the recovery gate releases it),\n // then open it with the recovery code CLIENT-SIDE — the raw code never reaches the server (Contract A).\n // Both restore failures are terminal and precede any ceremony, so a bad restore can never sign or hang.\n const backup = await this.fetchUserBackup(walletId, params, signal);\n const share = await restoreUserBackupShare(backup, params);\n throwIfAborted(signal);\n\n // STEP 2 — START the {server, user_backup} recover-sign session. The passkey step-up rides the START\n // body exactly as on a normal sign; the backend fails closed when the wallet requires a passkey.\n const body: Record<string, unknown> = { digest };\n if (params.chainId !== undefined) body['chainId'] = params.chainId;\n await attachPasskeyStepUp(this.http, walletId, body, 'sign', options);\n throwIfAborted(signal);\n const session = await this.http.request<SignSessionResponse>('POST', `/v1/wallets/${walletId}/recover-sign-session`, body, signal);\n\n // STEP 3 — CO-SIGN as the user_backup party over the relay (the server co-signs server-side).\n throwIfAborted(signal);\n let signature: string;\n try {\n ({ signature } = await mpc.runSign(toSessionSignParams(session, share, digest)));\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The user_backup device recover-sign ceremony failed.', 'sign_failed', { cause });\n }\n this.deps.analytics?.track('wallet.recovered', { walletId, curve: session.curve });\n return signature;\n }\n\n /**\n * Retrieve the sealed `user_backup` backup via the recovery gate ({@link fetchRecoveryBackup}) — the\n * ciphertext AND its key wraps (#510), since a backup registered with a passkey is an envelope and\n * the wraps are what open it. Maps a \"no recovery share registered\" (404) to the actionable\n * `share_not_found` — this wallet has no client-held `user_backup` backup to co-sign with (its\n * device-loss recovery is the custodial path instead).\n */\n private async fetchUserBackup(walletId: string, params: RecoverSignParams, signal?: AbortSignal): Promise<RecoveryRetrieveResponse> {\n try {\n return await fetchRecoveryBackup(this.http, walletId, params, signal);\n } catch (cause) {\n if (cause instanceof WaaskeyError && cause.code === 'not_found') {\n throw new WaaskeyError(\n `No registered user_backup recovery backup for wallet \"${walletId}\" — device-loss recover-sign needs a non-custodial [device, server, user_backup] wallet whose backup was registered at create.`,\n 'share_not_found',\n { cause, details: { walletId } },\n );\n }\n throw cause;\n }\n }\n\n /**\n * Run one or more device keygen parties (each `mpc.runKeygen`), concurrently, mapping any failure to a\n * single `keygen_failed`. Used for both the single `device` party and the two-party non-custodial\n * `[device, user_backup]` ceremony — one place owns the error contract so both paths stay identical.\n */\n private async runKeygenParties(mpc: MpcCore, params: DeviceKeygenParams[]): Promise<DeviceKeygenResult[]> {\n try {\n return await Promise.all(params.map((party) => this.runKeygenParty(mpc, party, params)));\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The device keygen ceremony failed.', 'keygen_failed', { cause });\n }\n }\n\n /**\n * Run ONE client keygen party over the right transport. A 2-party ceremony uses the plain\n * single-peer path; anything larger MUST be roster-routed — the 2-party transport attributes\n * every inbound message to the one configured peer, so a third party's very first message\n * aborts the protocol with \"route received message\" (waas-core#131).\n */\n private runKeygenParty(mpc: MpcCore, party: DeviceKeygenParams, batch: DeviceKeygenParams[]): Promise<DeviceKeygenResult> {\n if (party.parties <= 2) {\n return mpc.runKeygen(party);\n }\n if (!mpc.runMemberKeygen) {\n throw new WaaskeyError(\n `This keygen ceremony has ${party.parties} parties, which needs an MPC core with routed (member-ceremony) keygen support — use a client-wasm build exposing keygenMember.`,\n 'unsupported',\n );\n }\n return mpc.runMemberKeygen({\n curve: party.curve,\n relayUrl: party.relayUrl,\n sessionId: party.sessionId,\n roles: ceremonyRoster(party, batch),\n partyIndex: party.partyIndex,\n threshold: party.threshold,\n relayToken: party.relayToken,\n pregeneratedPrimes: party.pregeneratedPrimes,\n });\n }\n\n /**\n * Run the device half of an ed25519 (FROST) keygen (#110) and seal the resulting `{keyPackage,\n * publicKeyPackage}` share — the EdDSA counterpart of the cggmp24 `runKeygen` branch in {@link create}.\n * The device co-generates the group key with the backend `server` party over the relay; the FROST DKG\n * is the 2-party {device, server} quorum the ceremony names (M6 scope), roster-addressed like the\n * member ceremony rather than the cggmp24 single-peer shape.\n */\n private async runEddsaKeygen(mpc: MpcCore, shareStore: ShareStore, walletId: string, ceremony: WalletCeremony, encKeypair: DeviceEncKeypair): Promise<void> {\n if (!mpc.runEddsaKeygen) {\n throw new WaaskeyError(\n 'The configured MPC core does not support ed25519 (FROST) keygen — use a client-wasm build with the ed25519 (keygenEddsa/signEddsa) exports.',\n 'unsupported',\n );\n }\n const roles = buildEddsaKeygenRoster(ceremony);\n // The FROST DKG round-2 encryption roster (#114) — validated to carry THIS device's own enc pubkey\n // at its party index, so a wrong roster fails fast instead of silently mis-sealing the DKG packages.\n const encPubkeys = readEddsaEncRoster(ceremony, encKeypair);\n let keygen: EddsaKeygenResult;\n try {\n keygen = await mpc.runEddsaKeygen({\n relayUrl: ceremony.relayUrl,\n sessionId: ceremony.sessionId,\n roles,\n partyIndex: ceremony.partyIndex,\n threshold: ceremony.threshold,\n relayToken: ceremony.relayToken,\n encPubkeys,\n encSecret: encKeypair.secretHex,\n });\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n throw new WaaskeyError('The device ed25519 keygen ceremony failed.', 'keygen_failed', { cause });\n }\n // Seal + persist the FROST device share (its `keyPackage` is secret and never sent to the server).\n await shareStore.put(walletId, serializeEddsaShare(keygen));\n }\n\n /** Poll the wallet until keygen completes (ACTIVE), or throw on failure/timeout. */\n private async waitUntilActive(id: string, options: CreateWalletOptions): Promise<WalletData> {\n const timeoutMs = options.activationTimeoutMs ?? DEFAULT_ACTIVATION_TIMEOUT_MS;\n const intervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const { signal } = options;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n throwIfAborted(signal);\n const wallet = await this.http.request<WalletData>('GET', `/v1/wallets/${id}`, undefined, signal);\n if (wallet.status === 'active') return wallet;\n if (wallet.status === 'failed') {\n throw new WaaskeyError('Wallet keygen failed.', 'keygen_failed', { details: wallet });\n }\n if (Date.now() >= deadline) {\n throw new WaaskeyError('Wallet did not activate before the timeout.', 'wallet_activation_timeout', { details: wallet });\n }\n await delay(intervalMs, signal);\n }\n }\n\n /** Poll the member's own sign ceremony until the t-of-n quorum is fixed AND this member is selected, or throw on timeout. */\n private async waitUntilReady(walletId: string, reqId: string, options: JoinSignCeremonyOptions): Promise<ReadyMemberSignCeremony> {\n const timeoutMs = options.readyTimeoutMs ?? DEFAULT_ACTIVATION_TIMEOUT_MS;\n const intervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const { signal } = options;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n throwIfAborted(signal);\n const ceremony = await this.http.requestAsMember<MemberSignCeremony>('GET', `/v1/wallets/${walletId}/sign-requests/${reqId}/ceremony/mine`, undefined, signal);\n if (isReadyMemberSignCeremony(ceremony)) return ceremony;\n if (Date.now() >= deadline) {\n throw new WaaskeyError('The signing quorum did not fix (or did not select this member) before the timeout.', 'sign_ceremony_timeout', { details: { walletId, reqId } });\n }\n await delay(intervalMs, signal);\n }\n }\n}\n\n/**\n * Open a sealed `user_backup` backup — with the passkey when one is supplied, else the recovery code —\n * and unpack the cggmp24 KeyShare (#351/#78, #510). The blob decrypts to the SAME on-device storage\n * shape a device share uses ({@link serializeShare}, `{ keyShare, auxInfo, sharedPublicKey }`), so\n * {@link deserializeShare} extracts the bare KeyShare the MPC core signs with. A wrong key throws a\n * typed `invalid_recovery_code` (never a hang; the caller never starts a ceremony), and neither the raw\n * code nor the PRF output ever leaves the device (Contract A).\n */\nasync function restoreUserBackupShare(backup: RecoveryRetrieveResponse, opener: { recoveryCode?: string; passkeySecret?: string }): Promise<string> {\n let blob: string;\n try {\n blob = await openRecoveryBlob(backup, opener);\n } catch (cause) {\n throw new WaaskeyError('Could not open the user_backup backup — wrong recovery code or passkey?', 'invalid_recovery_code', { cause });\n }\n return deserializeShare(blob).keyShare;\n}\n\n/**\n * Storage key for a member-bound wallet's per-member share (#349) — distinct from the embedded\n * flow's bare `walletId` key ({@link Wallet}'s single device share), since several members' shares\n * for the SAME wallet may live in one {@link ShareStore} (e.g. a shared device, or a test harness).\n */\nexport function memberShareKey(walletId: string, membershipId: string): string {\n return `${walletId}@member-${membershipId}`;\n}\n\n/**\n * Storage key for a non-custodial wallet's PENDING user_backup backup (#351/#78) — the sealed\n * {@link RecoveryRegisterPayload} ciphertext {@link Wallets.create} persists before registering it\n * server-side, so a failed/interrupted registration never loses the (non-re-derivable) user_backup share.\n * Distinct from the device share's bare `walletId` key; cleared by {@link Wallets.retryBackup} on success.\n * The value is opaque without the recovery code, so a local copy is a safe retry buffer.\n */\nexport function userBackupPendingKey(walletId: string): string {\n return `${walletId}:user_backup_pending`;\n}\n\n/** Parse a pending-backup slot's stored JSON back into a {@link RecoveryRegisterPayload}, or throw if corrupt. */\nfunction parseBackupPayload(stored: string, walletId: string): RecoveryRegisterPayload {\n let parsed: { ciphertext?: unknown; factors?: unknown };\n try {\n parsed = JSON.parse(stored) as { ciphertext?: unknown; factors?: unknown };\n } catch (cause) {\n throw new WaaskeyError(`The pending user_backup backup for wallet \"${walletId}\" is corrupt — it is not valid JSON.`, 'backup_failed', { cause, details: { walletId } });\n }\n if (typeof parsed.ciphertext !== 'string' || !Array.isArray(parsed.factors)) {\n throw new WaaskeyError(`The pending user_backup backup for wallet \"${walletId}\" is malformed.`, 'backup_failed', { details: { walletId, keys: Object.keys(parsed) } });\n }\n return { ciphertext: parsed.ciphertext, factors: parsed.factors.map((factor) => normalizeStoredFactor(factor, walletId)) };\n}\n\n/**\n * Repair a factor enrolment persisted by an SDK <= 0.3.1, which wrote the recovery-code hash under\n * `credentialHash` — a property the API rejects (#91). Those slots hold the ONLY copy of a\n * non-re-derivable `user_backup` share, so `retryBackup` must be able to register them after the\n * upgrade instead of re-POSTing the rejected shape forever. The stored value is already the SHA-256\n * (Contract A held on both shapes), so this only renames the field — nothing is re-hashed.\n *\n * A slot carrying NEITHER value (or no factor type) is corrupt, not legacy: it fails here with the\n * same typed `backup_failed` error {@link parseBackupPayload} throws, rather than being coerced to\n * an empty credential that the API would reject as an opaque 400 on every retry. The caller still\n * holds the sealed ciphertext, so a loud, typed failure is what lets them act on it.\n */\nfunction normalizeStoredFactor(factor: unknown, walletId: string): RecoveryRegisterPayload['factors'][number] {\n const { type, credential, credentialHash } = (factor ?? {}) as { type?: unknown; credential?: unknown; credentialHash?: unknown };\n const value = typeof credential === 'string' && credential !== '' ? credential : credentialHash;\n if (typeof type !== 'string' || type === '' || typeof value !== 'string' || value === '') {\n throw new WaaskeyError(`The pending user_backup backup for wallet \"${walletId}\" is malformed — a factor entry is missing its type or credential.`, 'backup_failed', {\n details: { walletId, factorKeys: Object.keys((factor ?? {}) as object) },\n });\n }\n return { type: type as RecoveryFactor, credential: value };\n}\n\n/** Parse the membership id out of a member-bound relay role (`member:<membershipId>`). */\nfunction membershipIdFromRole(role: string): string {\n const prefix = 'member:';\n if (!role.startsWith(prefix)) {\n throw new WaaskeyError(`Unexpected relay role \"${role}\" — expected a member-bound \"member:<membershipId>\" role.`, 'validation');\n }\n return role.slice(prefix.length);\n}\n\n/**\n * Resolve the full relay roster for one client party of a `parties > 2` keygen (waas-core#131).\n * Prefers the backend-supplied roster (`ceremony.roles`); otherwise reconstructs it from every\n * party descriptor the client holds (`role`/`peerRole` of each batch entry), filling ONE remaining\n * slot with the platform's `'recovery'` role — the party older backends run but never name. More\n * than one unnamed slot cannot be guessed and fails fast, demanding a backend that sends `roles`.\n */\nfunction ceremonyRoster(party: DeviceKeygenParams, batch: DeviceKeygenParams[]): string[] {\n if (party.roles) {\n if (party.roles.length !== party.parties) {\n throw new WaaskeyError(`The ceremony roster names ${party.roles.length} parties but the ceremony has ${party.parties}.`, 'validation');\n }\n return party.roles;\n }\n const roles: (string | undefined)[] = new Array<string | undefined>(party.parties).fill(undefined);\n const put = (index: number, role: string | undefined) => {\n if (role === undefined) return;\n if (index < 0 || index >= party.parties) {\n throw new WaaskeyError(`Ceremony party index ${index} is out of range for a ${party.parties}-party ceremony.`, 'validation');\n }\n if (roles[index] !== undefined && roles[index] !== role) {\n throw new WaaskeyError(`Conflicting ceremony roles for party index ${index}: \"${roles[index]}\" vs \"${role}\".`, 'validation');\n }\n roles[index] = role;\n };\n for (const entry of batch) {\n put(entry.partyIndex, entry.role ?? 'device');\n put(entry.peerPartyIndex, entry.peerRole ?? 'server');\n }\n const gaps = roles.reduce<number[]>((acc, role, index) => (role === undefined ? [...acc, index] : acc), []);\n if (gaps.length > 1) {\n throw new WaaskeyError(\n `The ${party.parties}-party keygen ceremony leaves ${gaps.length} party slots unnamed — this backend must supply the full ceremony roster (roles).`,\n 'validation',\n );\n }\n if (gaps.length === 1) roles[gaps[0]!] = 'recovery';\n return roles as string[];\n}\n\n/**\n * Build the full n-party relay roster from a member-bound wallet's share-holders (#349):\n * `roles[i]` is party `i`'s relay role — the N member roles at their own `partyIndex`, plus the\n * platform's `'platform'` role filling the one remaining slot (the platform party is not a\n * `wallet_shareholders` row, so it never appears in `shareholders`).\n */\nfunction buildMemberRoster(shareholders: WalletShareholder[], parties: number): string[] {\n const roles: (string | undefined)[] = new Array(parties).fill(undefined);\n for (const shareholder of shareholders) {\n if (shareholder.partyIndex < 0 || shareholder.partyIndex >= parties) {\n throw new WaaskeyError(`Share-holder partyIndex ${shareholder.partyIndex} is out of range for a ${parties}-party ceremony.`, 'validation');\n }\n roles[shareholder.partyIndex] = shareholder.role;\n }\n const gaps = roles.reduce<number[]>((acc, role, index) => (role === undefined ? [...acc, index] : acc), []);\n if (gaps.length !== 1) {\n throw new WaaskeyError('Could not derive the platform party slot from the wallet share-holders.', 'validation', { details: { parties, shareholders } });\n }\n roles[gaps[0]!] = 'platform';\n return roles as string[];\n}\n\n/**\n * Build the FROST keygen roster from an ed25519 (#110) keygen ceremony. The 2-party ceremony names this\n * device (`role` at `partyIndex`) and its `server` peer (`peerRole` at `peerPartyIndex`); the M6 ed25519\n * scope is exactly this 2-party {device, server} FROST DKG, so the roster is those two in protocol-index\n * order (e.g. `['device','server']`). Guards against an underspecified roster (a future >2-party ed25519\n * topology would carry its own full roster) so a mis-threaded ceremony fails clean rather than silently\n * running a different-sized DKG.\n */\nexport function buildEddsaKeygenRoster(ceremony: WalletCeremony): string[] {\n const slots = Math.max(ceremony.partyIndex, ceremony.peerPartyIndex) + 1;\n const roles: (string | undefined)[] = new Array(slots).fill(undefined);\n roles[ceremony.partyIndex] = ceremony.role;\n roles[ceremony.peerPartyIndex] = ceremony.peerRole;\n if (roles.some((role) => role === undefined)) {\n throw new WaaskeyError('The ed25519 keygen ceremony did not fully describe its party roster (only the 2-party device+server topology is supported).', 'keygen_failed', {\n details: { ceremony },\n });\n }\n return roles as string[];\n}\n\n/**\n * Read + validate the FROST DKG round-2 encryption roster (#114) an ed25519 keygen ceremony carries.\n * The roster is the parties-order list of X25519 enc PUBLIC keys every party seals its round-2 packages\n * to (`encPubkeys[i]` ↔ FROST id `i + 1`); it is passed to `keygenEddsa` as `enc_pubkeys` verbatim. As\n * a sanity check the roster's entry at THIS device's own party index must equal the device's own enc\n * public key — a mismatched roster would silently mis-seal every package (funds-unrecoverable), so it\n * fails fast. Throws when the backend omitted the roster (e.g. a pre-#114 API) so keygen can't proceed.\n */\nexport function readEddsaEncRoster(ceremony: WalletCeremony, encKeypair: DeviceEncKeypair): string[] {\n const roster = ceremony.encPubkeys;\n if (!Array.isArray(roster) || roster.length === 0) {\n throw new WaaskeyError(\n 'The ed25519 keygen ceremony did not return the FROST DKG round-2 encryption roster (encPubkeys) — the backend must advertise it (#114) before the device can seal its DKG packages.',\n 'keygen_failed',\n { details: { ceremony } },\n );\n }\n const own = roster[ceremony.partyIndex];\n if (typeof own !== 'string' || own.toLowerCase() !== encKeypair.publicHex.toLowerCase()) {\n throw new WaaskeyError(\n \"The ed25519 keygen ceremony's encPubkeys roster does not carry this device's own encryption public key at its party index — refusing to keygen against a mismatched roster (it would mis-seal the DKG packages).\",\n 'keygen_failed',\n { details: { partyIndex: ceremony.partyIndex } },\n );\n }\n return roster;\n}\n\n/** {@link MemberSignCeremony} narrowed to the fields that are present once {@link MemberSignCeremony.ready} is true. */\ntype ReadyMemberSignCeremony = MemberSignCeremony & Required<Pick<MemberSignCeremony, 'quorumRoles' | 'signerPosition' | 'participants' | 'digest'>>;\n\nfunction isReadyMemberSignCeremony(ceremony: MemberSignCeremony): ceremony is ReadyMemberSignCeremony {\n return ceremony.ready && ceremony.quorumRoles !== undefined && ceremony.signerPosition !== undefined && ceremony.participants !== undefined && ceremony.digest !== undefined;\n}\n","import { Analytics, HttpAnalyticsSink } from './analytics';\nimport { Auth } from './auth';\nimport { Balances } from './balances';\nimport { broadcast } from './broadcast';\nimport { HttpClient } from './http';\nimport { Members } from './members';\nimport { Onramp } from './onramp';\nimport { Recovery } from './recovery';\nimport { Reshare } from './reshare';\nimport { Wallets } from './wallets';\nimport type { AnalyticsSink } from './analytics';\nimport type { BroadcastOptions, BroadcastResult, WaaskeyOptions } from './types';\n\n/**\n * The Waaskey client — entry point of the SDK.\n *\n * @example\n * ```ts\n * import { Waaskey, WasmMpcCore, EncryptedShareStore } from '@waaskey/sdk';\n *\n * const waaskey = new Waaskey({\n * apiKey: process.env.WAASKEY_PUBLISHABLE_KEY!,\n * baseUrl: process.env.WAASKEY_API_URL!,\n * mpc: new WasmMpcCore(loadClientWasm),\n * shareStore: EncryptedShareStore.browser(sessionSecret),\n * });\n * const wallet = await waaskey.wallets.create({ chain: 'ethereum' });\n * const signature = await wallet.sign(digestHex);\n * ```\n */\nexport class Waaskey {\n /** The `wallets` resource. */\n readonly wallets: Wallets;\n /** The `recovery` resource — multi-factor, client-encrypted wallet recovery. */\n readonly recovery: Recovery;\n /** The `reshare` resource — this device's half of a committee rotation (#488) and the aux-completion that follows (#318). */\n readonly reshare: Reshare;\n /** The `balances` resource — client-side balance reads from a chain provider (no backend). */\n readonly balances: Balances;\n /** The `auth` resource — embedded end-user login (email-OTP, …) → non-custodial wallet. */\n readonly auth: Auth;\n /** The `members` resource — org-member (dashboard \"plane B\") bearer login for headless consumers. */\n readonly members: Members;\n /** The `onramp` resource — fund the wallet with fiat via a provider on-ramp. */\n readonly onramp: Onramp;\n /** Default fetch used by the optional {@link broadcast} helper (from `WaaskeyOptions.fetch`). */\n private readonly defaultFetch?: typeof fetch;\n\n constructor(options: WaaskeyOptions) {\n if (!options?.apiKey) {\n throw new Error('Waaskey: `apiKey` is required.');\n }\n // Checked at construction, not per request: the removed default pointed at a hostname that does\n // not resolve, so omitting this used to surface as a `network` error on every call instead of one\n // obvious error here. The type makes it required; this guards the JS callers types cannot reach.\n if (!options.baseUrl) {\n throw new Error('Waaskey: `baseUrl` is required — pass the URL of your Waaskey API (there is no default).');\n }\n const http = new HttpClient(options.apiKey, options.baseUrl, options.fetch);\n const analytics = new Analytics(resolveSink(options.analytics, http));\n this.auth = new Auth(http);\n this.members = new Members(http);\n // Wire the held member bearer into member-scoped calls (requestAsMember). Injected as a provider\n // (not an import) so Members and HttpClient don't form a cycle; once `members.loginWithFirebase`\n // holds a session, `wallets.joinCeremony` / `joinSignCeremony` authenticate over the bearer.\n http.useMemberAccessToken(() => this.members.accessToken);\n this.wallets = new Wallets(http, { mpc: options.mpc, shareStore: options.shareStore, primePool: options.primePool, analytics });\n this.recovery = new Recovery(http, { shareStore: options.shareStore, analytics });\n this.reshare = new Reshare(http, { mpc: options.mpc, shareStore: options.shareStore, analytics });\n this.balances = new Balances(options.chains, options.fetch);\n this.onramp = new Onramp(http);\n this.defaultFetch = options.fetch;\n }\n\n /**\n * **Optional** client-side broadcast of a signed raw tx from {@link Wallet.send}.\n *\n * WaaS is a **signing service** — `wallet.send(...)` returns `signedTx` and WaaS never\n * submits it. This is a thin, best-effort convenience to broadcast from **your own**\n * node/provider (one JSON-RPC call, no status polling / no retries — tracking is your\n * concern). Most integrators broadcast with their own infra.\n *\n * @example\n * ```ts\n * const { signedTx } = await wallet.send({ chainId: 'evm:1', to, value });\n * const { txHash } = await waaskey.broadcast(signedTx, { rpcUrl: 'https://your-rpc' });\n * ```\n */\n broadcast(signedTx: string, options: BroadcastOptions): Promise<BroadcastResult> {\n return broadcast(signedTx, { fetch: this.defaultFetch, ...options });\n }\n}\n\n/** On by default (HTTP sink → API); a custom sink is used as-is; `false` opts out (no sink). */\nfunction resolveSink(analytics: AnalyticsSink | false | undefined, http: HttpClient): AnalyticsSink | undefined {\n if (analytics === false) return undefined;\n return analytics ?? new HttpAnalyticsSink(http);\n}\n","import { getSigningAssertion, type SigningAssertionOptions } from './assertion';\nimport type { FactorEnrollment, FactorVerification } from '../types';\n\n/**\n * The `passkey` recovery factor (waas-backend#510) — proving possession of a registered passkey\n * instead of typing a recovery code.\n *\n * This is what lets an app offer `{passkey, totp, email_otp}`: three factors, none of them a secret\n * the user has to remember. The PRF wrap protects the backup blob at rest, but the blob is only\n * released once every enrolled factor verifies, so as long as the only strong factor was a memorized\n * code, the code stayed mandatory.\n *\n * The factor's token is a WebAuthn assertion, not a value a person can type — which is why an app\n * needs this helper rather than an input field.\n */\n\n/**\n * Enrol a registered passkey as a recovery factor.\n *\n * The `credential` is the credential id, which is public and useless on its own — the private key\n * never leaves the authenticator. The credential must ALREADY be registered with the platform: the\n * server refuses an unknown id, because a factor that can never be satisfied is a lock-out the user\n * would discover only while recovering from a device they no longer have.\n */\nexport function passkeyFactorEnrollment(credentialId: string): FactorEnrollment {\n return { type: 'passkey', credential: credentialId };\n}\n\n/**\n * Produce the `passkey` factor's proof for a recovery challenge.\n *\n * Pass the `passkeyChallenge` the challenge endpoint issued for THIS session: the server checks the\n * assertion against those exact bytes and consumes them, so an assertion captured from an earlier\n * attempt is worthless. The assertion travels as JSON in the factor's `token`, which is the only value\n * property the API's factor DTO accepts.\n *\n * ```ts\n * const { challengeId, requiredFactors, passkeyChallenge } = await waaskey.recovery.challenge(walletId);\n * const verifications = [\n * await passkeyFactorVerification(passkeyChallenge!),\n * { type: 'totp', token: code },\n * { type: 'email_otp', token: otp },\n * ];\n * await waaskey.recovery.recover(walletId, { challengeId, verifications, passkeySecret });\n * ```\n *\n * @throws `WaaskeyError('unsupported')` when WebAuthn is unavailable in this runtime (pass a\n * `ceremony` for React Native or tests).\n * @throws `WaaskeyError('aborted')` when the user cancels the authenticator prompt.\n */\nexport async function passkeyFactorVerification(challenge: string, options: SigningAssertionOptions = {}): Promise<FactorVerification> {\n const assertion = await getSigningAssertion(challenge, options);\n // Serialized rather than sent as an object: every factor's proof rides the same `token` string, and\n // the API's DTO rejects a request carrying any other property.\n return { type: 'passkey', token: JSON.stringify(assertion) };\n}\n","import type {\n DeviceCompleteReshareParams,\n DeviceCompleteReshareResult,\n DeviceKeygenParams,\n DeviceKeygenResult,\n DeviceReshareAssembleParams,\n DeviceReshareAssembleResult,\n DeviceReshareDealParams,\n DeviceReshareDealResult,\n DeviceSignParams,\n DeviceSignResult,\n CeremonyParams,\n EddsaCeremonyParams,\n EddsaKeygenParams,\n EddsaKeygenResult,\n EddsaSignParams,\n EddsaSignResult,\n MemberCeremonyParams,\n MemberKeygenParams,\n MemberSignParams,\n MpcCurve,\n MpcCore,\n} from './types';\n\n/** The subset of the client-wasm module the SDK drives. Each export takes one JSON string. */\nexport interface ClientWasmModule {\n /** Device half of keygen; resolves with `{ aux_info_json, keyshare_json, shared_public_key_json }`. */\n keygen(paramsJson: string): Promise<unknown>;\n /** Device half of sign; resolves with `{ signature_json }`. */\n sign(paramsJson: string): Promise<unknown>;\n /** Pre-generate Paillier safe-primes off the hot path; resolves with `{ primes_json }`. Optional. */\n pregeneratePrimes?(paramsJson: string): Promise<unknown>;\n /**\n * Device reshare **assemble** — compute the NEW-epoch bare core locally; returns\n * `{ core_json, shared_public_key_json }`. Present only in a `--features reshare` wasm build.\n * Synchronous in the core (no relay); the SDK awaits it uniformly.\n */\n reshareAssemble?(paramsJson: string): unknown | Promise<unknown>;\n /**\n * Device reshare **deal** — the old holder's local contribution; returns\n * `{ commitments_json, sealed_sub_shares_hex }`. Present only in a `--features reshare` build.\n */\n reshareDeal?(paramsJson: string): unknown | Promise<unknown>;\n /**\n * Device **complete-reshare** — run the aux ceremony over the new committee and return the\n * signable share as `{ keyshare_json, shared_public_key_json }`. Present only in a\n * `--features reshare` wasm build.\n */\n completeReshare?(paramsJson: string): Promise<unknown>;\n /**\n * This party's half of an n-party (member-bound wallet) keygen ceremony (#349); resolves with\n * `{ aux_info_json, keyshare_json, shared_public_key_json }`. Present only in a client-wasm\n * build with n-party (member-ceremony) support.\n */\n keygenMember?(paramsJson: string): Promise<unknown>;\n /**\n * This party's half of an n-party (member-bound wallet) sign ceremony over a fixed t-of-n\n * quorum (#349); resolves with `{ signature_json }`. Present only in a client-wasm build with\n * n-party (member-ceremony) support.\n */\n signMember?(paramsJson: string): Promise<unknown>;\n /**\n * This device's half of an ed25519 (FROST) DKG keygen ceremony (#110); resolves with\n * `{ key_package, public_key_package }` (JSON objects). Present only in a client-wasm build with\n * the ed25519 (FROST) exports.\n */\n keygenEddsa?(paramsJson: string): Promise<unknown>;\n /**\n * This device's half of an ed25519 (FROST) two-round sign ceremony (#110); resolves with\n * `{ signature }` (64-byte hex). Present only in a client-wasm build with the ed25519 (FROST) exports.\n */\n signEddsa?(paramsJson: string): Promise<unknown>;\n}\n\n/** Lazily loads + initializes the client-wasm module (e.g. dynamic `import()` of the wasm-pack pkg). */\nexport type ClientWasmLoader = () => Promise<ClientWasmModule>;\n\ninterface RawKeygenResult {\n aux_info_json: string;\n keyshare_json: string;\n shared_public_key_json?: string;\n}\n\ninterface RawSignResult {\n signature_json: string;\n}\n\ninterface RawPrimesResult {\n primes_json: string;\n}\n\ninterface RawReshareAssembleResult {\n core_json: string;\n shared_public_key_json: string;\n}\n\ninterface RawReshareDealResult {\n commitments_json: unknown;\n sealed_sub_shares_hex: string[];\n}\n\ninterface RawCompleteReshareResult {\n keyshare_json: string;\n shared_public_key_json: string;\n}\n\ninterface RawEddsaKeygenResult {\n key_package: unknown;\n public_key_package: unknown;\n}\n\ninterface RawEddsaSignResult {\n signature: string;\n}\n\n/**\n * {@link MpcCore} backed by the waas-core `client-wasm` module (`keygen` / `sign`).\n *\n * The wasm engine is injected via a loader so the SDK stays runtime-agnostic and\n * the core is unit-testable without a real ceremony. The device key share returned\n * by keygen must be sealed and stored on the device — it is never sent to the server.\n */\nexport class WasmMpcCore implements MpcCore {\n private modulePromise?: Promise<ClientWasmModule>;\n\n constructor(private readonly load: ClientWasmLoader) {}\n\n private init(): Promise<ClientWasmModule> {\n return (this.modulePromise ??= this.load());\n }\n\n async runKeygen(params: DeviceKeygenParams): Promise<DeviceKeygenResult> {\n const wasm = await this.init();\n const raw = (await wasm.keygen(\n this.encode(params, { parties: params.parties, threshold: params.threshold, pregenerated_primes_json: params.pregeneratedPrimes }),\n )) as RawKeygenResult;\n\n if (!raw || typeof raw.keyshare_json !== 'string') {\n throw new Error('client-wasm returned an unexpected keygen result');\n }\n return {\n keyShare: raw.keyshare_json,\n auxInfo: raw.aux_info_json,\n sharedPublicKey: extractSharedPublicKey(raw.keyshare_json),\n };\n }\n\n async runSign(params: DeviceSignParams): Promise<DeviceSignResult> {\n const wasm = await this.init();\n const raw = (await wasm.sign(\n this.encode(params, {\n // The wasm deserializes `share` with `serde_json::from_value::<KeyShare>`, so it must ride\n // the wire as the KeyShare OBJECT — not a JSON string, and not the storage blob.\n share: toShareObject(params.share),\n participants: params.participants,\n signer_position: params.signerPosition,\n digest: params.digest,\n }),\n )) as RawSignResult;\n\n if (!raw || typeof raw.signature_json !== 'string') {\n throw new Error('client-wasm returned an unexpected sign result');\n }\n return { signature: raw.signature_json };\n }\n\n async pregeneratePrimes(curve: MpcCurve): Promise<string> {\n const wasm = await this.init();\n if (!wasm.pregeneratePrimes) {\n throw new Error('client-wasm does not expose pregeneratePrimes');\n }\n const raw = (await wasm.pregeneratePrimes(JSON.stringify({ curve }))) as RawPrimesResult;\n if (!raw || typeof raw.primes_json !== 'string') {\n throw new Error('client-wasm returned an unexpected pregeneratePrimes result');\n }\n return raw.primes_json;\n }\n\n async runReshareAssemble(params: DeviceReshareAssembleParams): Promise<DeviceReshareAssembleResult> {\n const wasm = await this.init();\n if (!wasm.reshareAssemble) {\n throw new Error(reshareFeatureHint('reshareAssemble'));\n }\n // Pure + local (no relay), so no relay-URL allowlist here. `reshare_assemble` is synchronous\n // in the core; awaiting a non-promise is a no-op, so this works whether the export is sync or async.\n const raw = (await wasm.reshareAssemble(\n JSON.stringify({\n curve: params.curve,\n new_position: params.newPosition,\n new_preimages: params.newPreimages,\n new_threshold: params.newThreshold,\n wallet: params.wallet,\n commitments: params.commitments,\n sub_shares: params.subShares,\n // The core opens the SEALED sub-shares with this before it can verify or assemble anything;\n // omitting it (as this did until #488) makes the call fail on its own parameter parse.\n encryption_secret: params.encryptionSecret,\n }),\n )) as RawReshareAssembleResult;\n\n if (!raw || typeof raw.core_json !== 'string') {\n throw new Error('client-wasm returned an unexpected reshareAssemble result');\n }\n return { core: raw.core_json, sharedPublicKey: decodePublicKey(raw.shared_public_key_json) };\n }\n\n async runReshareDeal(params: DeviceReshareDealParams): Promise<DeviceReshareDealResult> {\n const wasm = await this.init();\n if (!wasm.reshareDeal) {\n throw new Error(reshareFeatureHint('reshareDeal'));\n }\n // Pure + local like the assemble: the dealer reads its own share, seals a sub-share to each new\n // holder's key, and returns ciphertext. No relay, so no relay-URL allowlist here.\n const raw = (await wasm.reshareDeal(\n JSON.stringify({\n curve: params.curve,\n share: JSON.parse(params.share),\n quorum_indices: params.quorumIndices,\n new_preimages: params.newPreimages,\n new_threshold: params.newThreshold,\n recipient_pubkeys: params.recipientPubkeys,\n }),\n )) as RawReshareDealResult;\n\n if (!raw || !Array.isArray(raw.sealed_sub_shares_hex)) {\n throw new Error('client-wasm returned an unexpected reshareDeal result');\n }\n return { commitments: raw.commitments_json, sealedSubShares: raw.sealed_sub_shares_hex };\n }\n\n async runCompleteReshare(params: DeviceCompleteReshareParams): Promise<DeviceCompleteReshareResult> {\n const wasm = await this.init();\n if (!wasm.completeReshare) {\n throw new Error(reshareFeatureHint('completeReshare'));\n }\n const raw = (await wasm.completeReshare(\n this.encode(params, {\n // The wasm expects the bare core as an inline JSON object (serde_json::Value), not a string.\n core: JSON.parse(params.core),\n parties: params.parties,\n // The device's OWN primes for the aux ceremony — never server-provided. Absent ⇒ generated inline.\n ...(params.pregeneratedPrimes === undefined ? {} : { pregenerated_primes_json: params.pregeneratedPrimes }),\n }),\n )) as RawCompleteReshareResult;\n\n if (!raw || typeof raw.keyshare_json !== 'string') {\n throw new Error('client-wasm returned an unexpected completeReshare result');\n }\n // Derive the public key from the completed share itself (as keygen does), so the invariant\n // check downstream compares the share's own key, not a separately-serialized value.\n return { keyShare: raw.keyshare_json, sharedPublicKey: extractSharedPublicKey(raw.keyshare_json) };\n }\n\n async runMemberKeygen(params: MemberKeygenParams): Promise<DeviceKeygenResult> {\n const wasm = await this.init();\n if (!wasm.keygenMember) {\n throw new Error(memberCeremonyFeatureHint('keygenMember'));\n }\n const raw = (await wasm.keygenMember(\n this.encodeMember(params, {\n roles: params.roles,\n party_index: params.partyIndex,\n threshold: params.threshold,\n ...(params.pregeneratedPrimes === undefined ? {} : { pregenerated_primes_json: params.pregeneratedPrimes }),\n }),\n )) as RawKeygenResult;\n\n if (!raw || typeof raw.keyshare_json !== 'string') {\n throw new Error('client-wasm returned an unexpected keygenMember result');\n }\n return {\n keyShare: raw.keyshare_json,\n auxInfo: raw.aux_info_json,\n sharedPublicKey: extractSharedPublicKey(raw.keyshare_json),\n };\n }\n\n async runMemberSign(params: MemberSignParams): Promise<DeviceSignResult> {\n const wasm = await this.init();\n if (!wasm.signMember) {\n throw new Error(memberCeremonyFeatureHint('signMember'));\n }\n const raw = (await wasm.signMember(\n this.encodeMember(params, {\n roles: params.roles,\n // Mirrors runSign: the wasm deserializes `share` with `serde_json::from_value::<KeyShare>`,\n // so the KeyShare rides the wire as an OBJECT, not a JSON string (and not the storage blob).\n share: toShareObject(params.share),\n participants: params.participants,\n // This device's protocol index into `roles` (the value the SDK calls `signerPosition`).\n // The wire key is `party_index` — the same field keygen sends — NOT `signer_position`.\n party_index: params.signerPosition,\n digest: params.digest,\n }),\n )) as RawSignResult;\n\n if (!raw || typeof raw.signature_json !== 'string') {\n throw new Error('client-wasm returned an unexpected signMember result');\n }\n return { signature: raw.signature_json };\n }\n\n async runEddsaKeygen(params: EddsaKeygenParams): Promise<EddsaKeygenResult> {\n const wasm = await this.init();\n if (!wasm.keygenEddsa) {\n throw new Error(eddsaFeatureHint('keygenEddsa'));\n }\n const raw = (await wasm.keygenEddsa(\n this.encodeEddsa(params, {\n threshold: params.threshold,\n // The FROST DKG round-2 encryption roster (#114): every party's X25519 enc PUBLIC key in `roles`\n // order (`enc_pubkeys[i]` ↔ FROST id i+1) + THIS device's own X25519 enc SECRET. `enc_secret` is\n // secret and MUST NOT be logged; the wasm seals/opens the round-2 packages with these.\n enc_pubkeys: params.encPubkeys,\n enc_secret: params.encSecret,\n }),\n )) as RawEddsaKeygenResult;\n\n if (!raw || raw.key_package === undefined || raw.public_key_package === undefined) {\n throw new Error('client-wasm returned an unexpected keygenEddsa result');\n }\n return { keyPackage: raw.key_package, publicKeyPackage: raw.public_key_package };\n }\n\n async runEddsaSign(params: EddsaSignParams): Promise<EddsaSignResult> {\n const wasm = await this.init();\n if (!wasm.signEddsa) {\n throw new Error(eddsaFeatureHint('signEddsa'));\n }\n const raw = (await wasm.signEddsa(\n this.encodeEddsa(params, {\n // The wasm re-serializes these with `serde_json::to_vec` + `import_*_package`, so each MUST\n // ride the wire as the FROST JSON OBJECT — not a JSON string (and not a storage wrapper).\n key_package: toFrostPackage(params.keyPackage, 'key_package'),\n public_key_package: toFrostPackage(params.publicKeyPackage, 'public_key_package'),\n participants: params.participants,\n message: params.message,\n }),\n )) as RawEddsaSignResult;\n\n if (!raw || typeof raw.signature !== 'string') {\n throw new Error('client-wasm returned an unexpected signEddsa result');\n }\n return { signature: raw.signature };\n }\n\n /** Build the snake_case params JSON the wasm exports expect from the common routing + extras. */\n private encode(p: CeremonyParams, extra: Record<string, unknown>): string {\n // The relay URL is server-supplied and fed straight into the MPC core (issue #41);\n // allowlist its scheme/host so a compromised control-plane can't point the device party\n // at an attacker relay over an unencrypted transport.\n assertAllowedRelayUrl(p.relayUrl);\n return JSON.stringify({\n curve: p.curve,\n relay_url: p.relayUrl,\n session_id: p.sessionId,\n role: p.role ?? 'device',\n peer_role: p.peerRole ?? 'server',\n party_index: p.partyIndex,\n peer_party_index: p.peerPartyIndex,\n // Only present the relay token when set, so an auth-disabled ceremony's wire payload\n // is byte-identical to before (the client-wasm treats absent as an unauthenticated join).\n ...(p.relayToken === undefined ? {} : { relay_token: p.relayToken }),\n ...extra,\n });\n }\n\n /**\n * Build the snake_case params JSON for an n-party (member-bound, #349) member ceremony — the\n * roster-based routing shape (`roles` + `party_index`), not the 2-party `role`/`peer_role` shape\n * {@link encode} builds. The `roles` roster and `party_index` are passed through in `extra` by\n * the caller and land on the wire under those exact keys — what `keygenMember` / `signMember`\n * deserialize.\n */\n private encodeMember(p: MemberCeremonyParams, extra: Record<string, unknown>): string {\n assertAllowedRelayUrl(p.relayUrl);\n return JSON.stringify({\n curve: p.curve,\n relay_url: p.relayUrl,\n session_id: p.sessionId,\n ...(p.relayToken === undefined ? {} : { relay_token: p.relayToken }),\n ...extra,\n });\n }\n\n /**\n * Build the snake_case params JSON for an ed25519 (FROST, #110) ceremony — the roster-based routing\n * shape (`roles` + `party_index`) the `keygenEddsa` / `signEddsa` exports deserialize. Unlike\n * {@link encodeMember} there is NO `curve` (ed25519-only) and no Paillier primes; the caller passes\n * the ceremony-specific extras (keygen: `threshold`; sign: the FROST packages + participants + message).\n */\n private encodeEddsa(p: EddsaCeremonyParams, extra: Record<string, unknown>): string {\n assertAllowedRelayUrl(p.relayUrl);\n return JSON.stringify({\n relay_url: p.relayUrl,\n session_id: p.sessionId,\n roles: p.roles,\n party_index: p.partyIndex,\n ...(p.relayToken === undefined ? {} : { relay_token: p.relayToken }),\n ...extra,\n });\n }\n}\n\n/** Actionable error when a wasm build lacks the reshare exports (built without `--features reshare`). */\nfunction reshareFeatureHint(fn: string): string {\n return `client-wasm does not expose ${fn} — rebuild @waaskey/client-wasm with the \\`reshare\\` feature enabled (wasm-pack build … -- --features reshare).`;\n}\n\n/**\n * Actionable error when a wasm build lacks the n-party (member-bound wallet, #349) member-ceremony\n * exports (`keygenMember` / `signMember`). These drive the roster-based (`roles` + `party_index`)\n * transport — every member device + the platform on one relay session — that the native\n * `party-runner` already uses (mirroring `waas-mpc-transport::PartyRouting`).\n */\nfunction memberCeremonyFeatureHint(fn: string): string {\n return `client-wasm does not expose ${fn} — rebuild @waaskey/client-wasm with n-party (member-ceremony) support (the keygenMember/signMember exports).`;\n}\n\n/**\n * Actionable error when a wasm build lacks the ed25519 (FROST, #110) exports (`keygenEddsa` /\n * `signEddsa`). These drive the threshold-EdDSA choreography the server `party-runner-eddsa` runs,\n * so a device build without them cannot create or sign an ed25519 (Solana/NEAR/Aptos/Sui) wallet.\n */\nfunction eddsaFeatureHint(fn: string): string {\n return `client-wasm does not expose ${fn} — rebuild @waaskey/client-wasm with the ed25519 (FROST) exports (keygenEddsa/signEddsa).`;\n}\n\n/**\n * Allowlist a server-supplied relay URL (issue #41): only encrypted WebSocket\n * transports are accepted — `wss://` to a **public** host, and plaintext `ws://`\n * solely for loopback (local dev). Anything else is refused before it reaches the\n * wasm core.\n *\n * Beyond the scheme, the **host** is allowlisted too: a compromised control-plane\n * must not be able to point the device party at an internal/private endpoint\n * (loopback, RFC1918, link-local incl. cloud metadata `169.254.169.254`, IPv6\n * unique-/link-local, `.internal`/`.local`) — an SSRF-style redirect of the MPC\n * transport. Loopback is the one exception, and only over plaintext `ws://` for dev.\n */\nfunction assertAllowedRelayUrl(relayUrl: string): void {\n let url: URL;\n try {\n url = new URL(relayUrl);\n } catch (cause) {\n throw new Error(`Invalid relay URL \"${relayUrl}\".`, { cause });\n }\n // Dev: plaintext ws:// is tolerated, but only to loopback.\n if (url.protocol === 'ws:' && isLoopbackHost(url.hostname)) return;\n if (url.protocol !== 'wss:') {\n throw new Error(`Refusing server-supplied relay URL \"${relayUrl}\" — only wss:// (or ws:// on localhost) is allowed for the MPC transport.`);\n }\n // wss:// — reject internal/private hosts (loopback included: prod relays are public).\n if (isInternalHost(url.hostname)) {\n throw new Error(`Refusing server-supplied relay URL \"${relayUrl}\" — the relay host is internal/private; only a public wss:// endpoint is allowed.`);\n }\n}\n\n/** Loopback host literals (used to permit ws:// only for local dev). */\nfunction isLoopbackHost(hostname: string): boolean {\n const host = hostname.replace(/^\\[|\\]$/g, '').toLowerCase();\n return host === 'localhost' || host === '::1' || /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(host);\n}\n\n/**\n * Is `hostname` an internal/private address a server must never send a client to?\n * Covers loopback, RFC1918 private v4, link-local v4 (incl. cloud metadata),\n * IPv6 unique-local (`fc00::/7`) + link-local (`fe80::/10`), and internal name\n * suffixes (`.internal`, `.local`). Public DNS names pass.\n */\nfunction isInternalHost(hostname: string): boolean {\n const host = hostname.replace(/^\\[|\\]$/g, '').toLowerCase();\n if (isLoopbackHost(hostname)) return true;\n if (host.endsWith('.internal') || host.endsWith('.local')) return true;\n\n const v4 = host.match(/^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/);\n if (v4) {\n const [a, b] = [Number(v4[1]), Number(v4[2])];\n if (a === 10) return true; // 10.0.0.0/8\n if (a === 172 && b >= 16 && b <= 31) return true; // 172.16.0.0/12\n if (a === 192 && b === 168) return true; // 192.168.0.0/16\n if (a === 169 && b === 254) return true; // 169.254.0.0/16 link-local (cloud metadata)\n return false;\n }\n\n if (host.includes(':')) {\n // IPv6 unique-local (fc00::/7 → fc/fd) and link-local (fe80::/10).\n if (/^f[cd][0-9a-f]{0,2}:/.test(host)) return true;\n if (/^fe[89ab][0-9a-f]:/.test(host)) return true;\n }\n return false;\n}\n\n/**\n * Coerce a device KeyShare into the inline JSON OBJECT the wasm sign exports expect. Both the\n * 2-party `sign` and the n-party `signMember` exports deserialize the wire `share` with\n * `serde_json::from_value::<KeyShare>`, so it MUST be a JSON object — a `share` sent as a JSON\n * string fails Rust deserialization (\"invalid type: string, expected struct\"). The KeyShare normally\n * arrives as its JSON string ({@link DeviceSignParams.share}); accept an already-parsed object too so\n * a caller can never double-encode it. The storage-blob wrapper is unpacked upstream — the core only\n * ever sees the bare KeyShare.\n */\nfunction toShareObject(share: unknown): Record<string, unknown> {\n const value: unknown = typeof share === 'string' ? JSON.parse(share) : share;\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('KeyShare must be a JSON object (or its JSON string), not a scalar or array.');\n }\n return value as Record<string, unknown>;\n}\n\n/**\n * Coerce a FROST package (`key_package` / `public_key_package`) into the inline JSON OBJECT the wasm\n * `signEddsa` export expects. The wasm re-serializes each with `serde_json::to_vec` + `import_*_package`,\n * so it MUST be a JSON object — the ed25519 analogue of {@link toShareObject}. The package normally\n * arrives as its JSON object (from {@link EddsaKeygenResult}); accept its JSON string too (a\n * storage round-trip) so a caller can never double-encode it.\n */\nfunction toFrostPackage(pkg: unknown, which: string): Record<string, unknown> {\n const value: unknown = typeof pkg === 'string' ? JSON.parse(pkg) : pkg;\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`FROST ${which} must be a JSON object (or its JSON string), not a scalar or array.`);\n }\n return value as Record<string, unknown>;\n}\n\n/** Pull the shared public key out of a KeyShare JSON (`core.shared_public_key`). */\nfunction extractSharedPublicKey(keyShareJson: string): string {\n const parsed = JSON.parse(keyShareJson) as { core?: { shared_public_key?: unknown } };\n const pk = parsed.core?.shared_public_key;\n if (typeof pk !== 'string') {\n throw new Error('KeyShare is missing core.shared_public_key');\n }\n return pk;\n}\n\n/**\n * Decode the wasm's separately-surfaced `shared_public_key_json` (a JSON-encoded compressed-hex\n * point, e.g. `\"03ab…\"`) into the bare hex string. Used for the reshare **assemble** result, whose\n * bare core does not expose `core.shared_public_key` in the keygen shape.\n */\nfunction decodePublicKey(sharedPublicKeyJson: string): string {\n const pk = JSON.parse(sharedPublicKeyJson) as unknown;\n if (typeof pk !== 'string') {\n throw new Error('reshare assemble result is missing a shared_public_key');\n }\n return pk;\n}\n","import type { ClientWasmLoader, ClientWasmModule } from './wasm-core';\n\n/**\n * The optional peer dependency that ships the wasm engine (waas-core client-wasm, wasm-pack build).\n *\n * **Reshare (#318):** the device-side reshare exports (`reshareAssemble` / `completeReshare`, used by\n * the `reshare` resource) are behind the core's `reshare` Cargo feature, so the shipped module must be\n * built with it — `wasm-pack build client-wasm --release --target web --scope waaskey -- --features reshare`.\n * A build without the feature lacks those exports and `reshare.complete(...)` fails closed with an\n * actionable error; keygen/sign are unaffected. The base curve exports need no feature flag.\n */\nconst CLIENT_WASM_PACKAGE = '@waaskey/client-wasm';\n\n/**\n * The **exact** `@waaskey/client-wasm` version this SDK build is pinned to (issue #40).\n *\n * Pin an exact version — never a floating `^`/`~` range — so a compromised or\n * dependency-confused higher release can't be silently pulled in. Keep this in\n * lockstep with the `@waaskey/client-wasm` entry in `package.json` and with\n * {@link CLIENT_WASM_SHA384}.\n *\n * **`0.2.x` adds the ed25519 (FROST) exports** (`keygenEddsa` / `signEddsa`, waas-core #110) the SDK's\n * ed25519 wallet path drives. It is **published on npm** (`client-wasm-v0.2.1`) and pinned as the SDK's\n * exact, optional peer dependency in `package.json` — so an app that installs `@waaskey/client-wasm`\n * alongside the SDK runs the real ed25519 create/send path end to end.\n */\nexport const CLIENT_WASM_VERSION = '0.2.2';\n\n/**\n * Verify the integrity of raw wasm bytes against an expected **SHA-384** hash, in\n * Subresource-Integrity (`sha384-<base64>`) form (issue #40).\n *\n * The wasm MPC core handles the plaintext device share, so it must be\n * cryptographically verified **before** `WebAssembly.compile` / `instantiate` — a\n * registry compromise or malicious re-host otherwise silently exfiltrates share-1.\n * Throws (fails closed) on any mismatch.\n */\nexport async function verifyWasmIntegrity(bytes: BufferSource, expectedSha384: string): Promise<void> {\n if (!expectedSha384 || !expectedSha384.startsWith('sha384-')) {\n throw new Error('Waaskey: an expected SHA-384 integrity hash (sha384-<base64>) is required to load the wasm MPC core.');\n }\n const digest = await crypto.subtle.digest('SHA-384', bytes);\n const actual = `sha384-${toBase64(new Uint8Array(digest))}`;\n if (!timingSafeEqual(actual, expectedSha384)) {\n throw new Error(`Waaskey: client-wasm integrity check FAILED — refusing to instantiate the MPC core (expected ${expectedSha384}, got ${actual}).`);\n }\n}\n\n/** Options for {@link createVerifiedClientWasmLoader}. */\nexport interface VerifiedWasmLoaderOptions {\n /**\n * URL (or path the runtime's `fetch` accepts) of the `@waaskey/client-wasm` `.wasm`\n * binary — vendored/self-hosted so its bytes can be fetched and hashed before use.\n */\n wasmUrl: string | URL;\n /** Expected SHA-384 of the wasm binary, SRI form (`sha384-<base64>`). Pin per {@link CLIENT_WASM_VERSION}. */\n expectedSha384: string;\n /** Custom fetch (non-browser runtimes / tests). Defaults to global `fetch`. */\n fetch?: typeof fetch;\n}\n\n/**\n * Build an integrity-checked {@link ClientWasmLoader} (issue #40): it fetches the\n * pinned `.wasm` bytes, verifies their SHA-384 against `expectedSha384`, and only\n * **then** compiles + initializes the module — so a tampered binary is rejected\n * before any wasm code runs.\n *\n * Requires a non-auto-initializing (wasm-pack `--target web`) `@waaskey/client-wasm`\n * build, so the verified bytes drive initialization:\n *\n * ```ts\n * const mpc = new WasmMpcCore(\n * createVerifiedClientWasmLoader({ wasmUrl: '/waaskey_client_wasm_bg.wasm', expectedSha384: CLIENT_WASM_SHA384 }),\n * );\n * ```\n */\nexport function createVerifiedClientWasmLoader(options: VerifiedWasmLoaderOptions): ClientWasmLoader {\n return async (): Promise<ClientWasmModule> => {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n if (!fetchImpl) {\n throw new Error('Waaskey: no fetch implementation available to load the wasm MPC core — pass `fetch` in the loader options.');\n }\n\n let bytes: ArrayBuffer;\n try {\n const res = await fetchImpl(options.wasmUrl instanceof URL ? options.wasmUrl.href : options.wasmUrl);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n bytes = await res.arrayBuffer();\n } catch (cause) {\n throw new Error(`Waaskey: failed to fetch the client-wasm binary from ${String(options.wasmUrl)}.`, { cause });\n }\n\n // Verify BEFORE compile/instantiate — fail closed on any mismatch.\n await verifyWasmIntegrity(bytes, options.expectedSha384);\n const compiled = await WebAssembly.compile(bytes);\n\n let mod: Record<string, unknown>;\n try {\n mod = (await import(CLIENT_WASM_PACKAGE)) as Record<string, unknown>;\n } catch (cause) {\n throw new Error(\"Waaskey: creating a wallet needs the wasm engine — install '@waaskey/client-wasm' alongside '@waaskey/sdk'.\", { cause });\n }\n\n // Initialize the wasm-pack module with the VERIFIED, already-compiled module.\n const init = (mod['default'] ?? mod['init']) as ((moduleOrPath?: unknown) => Promise<unknown>) | undefined;\n const initSync = mod['initSync'] as ((moduleOrPath?: unknown) => unknown) | undefined;\n if (typeof init === 'function') {\n await init(compiled);\n } else if (typeof initSync === 'function') {\n initSync(compiled);\n }\n return mod as unknown as ClientWasmModule;\n };\n}\n\n/**\n * Convenience loader for the Waaskey client-wasm engine — dynamically imports `@waaskey/client-wasm`\n * (the wasm-pack/bundler build, auto-initialized on import) and returns it as a {@link ClientWasmModule}:\n *\n * ```ts\n * import { Waaskey, WasmMpcCore, loadClientWasm } from '@waaskey/sdk';\n * const waaskey = new Waaskey({ apiKey, baseUrl, mpc: new WasmMpcCore(loadClientWasm), shareStore });\n * ```\n *\n * ⚠️ **No integrity verification (issue #40).** A bundler-target build instantiates the wasm on\n * import, so its bytes cannot be checked first. For production — where a registry compromise or\n * dependency-confusion attack on `@waaskey/client-wasm` could exfiltrate the plaintext device share\n * — use {@link createVerifiedClientWasmLoader} with a vendored `.wasm` and the pinned SHA-384 instead.\n *\n * `@waaskey/client-wasm` is an OPTIONAL peer dependency pinned to {@link CLIENT_WASM_VERSION}: install\n * it alongside the SDK in apps that create wallets. The indirect import specifier keeps it out of\n * static module resolution — so a missing install fails here with an actionable message, not at build.\n */\nlet clientWasm: Promise<ClientWasmModule> | undefined;\n\nexport const loadClientWasm: ClientWasmLoader = async (): Promise<ClientWasmModule> => {\n // Memoized: the engine is a process-wide singleton, and initializing it twice re-instantiates\n // the wasm memory (throwing away any state the first instance holds).\n return (clientWasm ??= importAndInit());\n};\n\nasync function importAndInit(): Promise<ClientWasmModule> {\n let mod: Record<string, unknown>;\n try {\n mod = (await import(CLIENT_WASM_PACKAGE)) as Record<string, unknown>;\n } catch (cause) {\n throw new Error(\"Waaskey: creating a wallet needs the wasm engine — install '@waaskey/client-wasm' alongside '@waaskey/sdk'.\", { cause });\n }\n\n // The package is a wasm-pack `--target web` build, so it does NOT auto-initialize: every export\n // reads through an uninitialized binding and throws `Cannot read properties of undefined\n // (reading '__wbindgen_malloc')` until the module's default init has run. Run it here so callers\n // get a usable core rather than a module that fails on first use.\n const init = (mod['default'] ?? mod['init']) as ((moduleOrPath?: unknown) => Promise<unknown>) | undefined;\n if (typeof init === 'function') {\n try {\n await init();\n } catch (cause) {\n throw new Error(\n 'Waaskey: the wasm engine failed to initialize. In the browser this loader fetches the `.wasm` next to the module — serve it, or pass a loader built with `createVerifiedClientWasmLoader({ wasmUrl, expectedSha384 })`. On Node use `NodeWorkerMpcCore` from `@waaskey/sdk/node`, which loads the binary from disk in a worker thread.',\n { cause },\n );\n }\n }\n return mod as unknown as ClientWasmModule;\n}\n\n/** Drop the memoized engine — tests only, so a fresh import/init can be observed. */\nexport function resetClientWasmForTest(): void {\n clientWasm = undefined;\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\n/** Constant-time string equality (avoids leaking hash-comparison timing). */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n","import type { MpcCurve } from './types';\n\n/**\n * Client-side pool of pre-generated Paillier safe-primes (#2).\n *\n * Safe-prime generation is the slow part of a device keygen — minutes in single-threaded\n * browser WASM. Primes don't depend on the key, so we generate them **ahead of the hot path**\n * (a Web Worker during onboarding/idle) and cache a small pool; at keygen time we hand one over\n * instantly. The primes are this device's PRIVATE aux material — they are cached locally and\n * NEVER sent to the server (serving them from the API would let the server recover the device's\n * share). Use an encrypted store in production.\n */\n\n/** Where the pool persists cached primes. Swap in an encrypted IndexedDB store for production. */\nexport interface PrimePoolStore {\n /** Remove and return one cached prime for `curve`, or undefined if the pool is empty. */\n take(curve: MpcCurve): Promise<string | undefined>;\n /** Add a generated prime to the pool. */\n add(curve: MpcCurve, primes: string): Promise<void>;\n /** Current number of cached primes for `curve`. */\n size(curve: MpcCurve): Promise<number>;\n}\n\n/** Default in-memory store (lost on reload). Production should persist to an encrypted store. */\nexport class MemoryPrimeStore implements PrimePoolStore {\n private readonly pools = new Map<MpcCurve, string[]>();\n\n async take(curve: MpcCurve): Promise<string | undefined> {\n return this.pools.get(curve)?.shift();\n }\n\n async add(curve: MpcCurve, primes: string): Promise<void> {\n const pool = this.pools.get(curve) ?? [];\n pool.push(primes);\n this.pools.set(curve, pool);\n }\n\n async size(curve: MpcCurve): Promise<number> {\n return this.pools.get(curve)?.length ?? 0;\n }\n}\n\n/** The minimal core capability the pool needs — just prime generation. */\ninterface PrimeGenerator {\n pregeneratePrimes(curve: MpcCurve): Promise<string>;\n}\n\nexport interface PrimePoolOptions {\n /** How many spare primes to keep cached per curve. Default 2. */\n targetSize?: number;\n /** Persistence for the pool. Defaults to an in-memory store. */\n store?: PrimePoolStore;\n /**\n * Kick off a refill automatically after every {@link PrimePool.take}. Default `false`:\n * unless the core generates primes in a Web Worker, wasm prime generation is a\n * synchronous CPU burn on the calling thread — a \"background\" refill starves the event\n * loop and stalls the very keygen ceremony the take() was for (it also freezes a\n * browser UI). Refill explicitly via {@link PrimePool.ensure} (`wallets.prewarm`) at\n * boot/idle, or set `true` only when the core is worker-backed.\n */\n autoRefill?: boolean;\n}\n\nexport class PrimePool {\n private readonly store: PrimePoolStore;\n private readonly targetSize: number;\n private readonly autoRefill: boolean;\n /** Per-curve in-flight refill, so concurrent calls don't over-generate. */\n private readonly refilling = new Map<MpcCurve, Promise<void>>();\n\n constructor(\n private readonly core: PrimeGenerator,\n options: PrimePoolOptions = {},\n ) {\n this.store = options.store ?? new MemoryPrimeStore();\n this.targetSize = Math.max(1, options.targetSize ?? 2);\n this.autoRefill = options.autoRefill ?? false;\n }\n\n /**\n * Top up the pool to the target size — call this OFF the hot path (onboarding/idle, ideally a\n * Web Worker). Deduped per curve, so calling it repeatedly is safe and cheap.\n */\n ensure(curve: MpcCurve): Promise<void> {\n const inflight = this.refilling.get(curve);\n if (inflight) return inflight;\n const task = this.refill(curve).finally(() => this.refilling.delete(curve));\n this.refilling.set(curve, task);\n return task;\n }\n\n private async refill(curve: MpcCurve): Promise<void> {\n while ((await this.store.size(curve)) < this.targetSize) {\n await this.store.add(curve, await this.core.pregeneratePrimes(curve));\n }\n }\n\n /**\n * Claim a prime for a keygen. Returns a cached one instantly when the pool is warm; otherwise\n * generates one inline (the slow fallback) so keygen never fails on an empty pool. Refill the\n * pool for the next wallet via {@link ensure} at idle (or opt into `autoRefill` when the core\n * is worker-backed).\n */\n async take(curve: MpcCurve): Promise<string> {\n const cached = await this.store.take(curve);\n const primes = cached ?? (await this.core.pregeneratePrimes(curve));\n if (this.autoRefill) void this.ensure(curve).catch(() => undefined);\n return primes;\n }\n}\n","import type { KeyValueStore } from './types';\n\n/**\n * IndexedDB-backed {@link KeyValueStore} — the default persistent backend on web.\n * A single object store holds opaque ciphertext records keyed by string, so device\n * shares survive a reload. Stores only sealed data (see EncryptedShareStore).\n */\nexport class IndexedDbKeyValueStore implements KeyValueStore {\n private dbPromise?: Promise<IDBDatabase>;\n\n constructor(\n private readonly dbName = 'waaskey',\n private readonly storeName = 'shares',\n ) {}\n\n private db(): Promise<IDBDatabase> {\n return (this.dbPromise ??= new Promise<IDBDatabase>((resolve, reject) => {\n const idb = globalThis.indexedDB;\n if (!idb) {\n reject(new Error('IndexedDB is unavailable — pass a custom KeyValueStore (e.g. MemoryKeyValueStore) in this runtime.'));\n return;\n }\n const request = idb.open(this.dbName, 1);\n request.onupgradeneeded = () => {\n if (!request.result.objectStoreNames.contains(this.storeName)) {\n request.result.createObjectStore(this.storeName);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error ?? new Error('Failed to open IndexedDB.'));\n }));\n }\n\n private async run<T>(mode: IDBTransactionMode, op: (store: IDBObjectStore) => IDBRequest<T>): Promise<T> {\n const db = await this.db();\n return new Promise<T>((resolve, reject) => {\n const tx = db.transaction(this.storeName, mode);\n const request = op(tx.objectStore(this.storeName));\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error ?? new Error('IndexedDB request failed.'));\n });\n }\n\n async get(key: string): Promise<string | null> {\n const value = await this.run<unknown>('readonly', (store) => store.get(key));\n return typeof value === 'string' ? value : null;\n }\n\n async set(key: string, value: string): Promise<void> {\n await this.run('readwrite', (store) => store.put(value, key));\n }\n\n async delete(key: string): Promise<void> {\n await this.run('readwrite', (store) => store.delete(key));\n }\n\n async keys(): Promise<string[]> {\n const keys = await this.run<IDBValidKey[]>('readonly', (store) => store.getAllKeys());\n return keys.filter((key): key is string => typeof key === 'string');\n }\n\n async clear(): Promise<void> {\n await this.run('readwrite', (store) => store.clear());\n }\n}\n","import { deriveKey, freshSalt, open, seal } from './crypto';\nimport { IndexedDbKeyValueStore } from './indexeddb-store';\nimport type { KeyValueStore, ShareStore } from './types';\n\nconst SHARE_PREFIX = 'share:';\nconst SALT_KEY = 'meta:salt';\n\n/**\n * Minimum length of the sealing secret (issue #41). The recommended source is the\n * 32-byte passkey-PRF secret (44 base64 chars), which clears this comfortably. The\n * floor rejects trivially low-entropy device secrets that would be brute-forceable\n * offline if the IndexedDB ciphertext + salt leaked. Override only when the caller\n * guarantees entropy another way (`allowWeakSecret`).\n */\nconst MIN_SECRET_LENGTH = 16;\n\n/** Options for the {@link EncryptedShareStore} constructor / {@link EncryptedShareStore.browser}. */\nexport interface EncryptedShareStoreOptions {\n dbName?: string;\n storeName?: string;\n /** Bypass the {@link MIN_SECRET_LENGTH} entropy floor — only when the secret's entropy is guaranteed elsewhere. */\n allowWeakSecret?: boolean;\n}\n\nconst bytesToBase64 = (bytes: Uint8Array): string => {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n};\nconst base64ToBytes = (base64: string): Uint8Array => {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n};\n\n/**\n * {@link ShareStore} that seals every share with AES-256-GCM before handing it to a\n * {@link KeyValueStore}, so the backing storage only ever holds ciphertext.\n *\n * The AES key is derived (PBKDF2) from a **secret the app supplies** — from the\n * user's authenticated session, a passkey/PRF, or a device secret — never embedded\n * in the bundle. A random salt is generated once and persisted alongside the data;\n * `clear()` wipes both, so a subsequent login derives a fresh key.\n *\n * @example\n * ```ts\n * const store = EncryptedShareStore.browser(sessionSecret);\n * await store.put(wallet.id, keygen.keyShare); // sealed in IndexedDB\n * const share = await store.get(wallet.id); // decrypted, or null\n * await store.clear(); // on logout\n * ```\n */\nexport class EncryptedShareStore implements ShareStore {\n private keyPromise?: Promise<CryptoKey>;\n\n constructor(\n private readonly kv: KeyValueStore,\n private readonly secret: string,\n options: { allowWeakSecret?: boolean } = {},\n ) {\n if (!secret) throw new Error('EncryptedShareStore: a non-empty `secret` is required.');\n if (!options.allowWeakSecret && secret.length < MIN_SECRET_LENGTH) {\n throw new Error(\n `EncryptedShareStore: the sealing secret is too weak (< ${MIN_SECRET_LENGTH} chars) and is brute-forceable offline. ` +\n 'Use the 32-byte passkey-PRF secret (PasskeyPrfSecretProvider), or pass { allowWeakSecret: true } only when entropy is guaranteed elsewhere.',\n );\n }\n }\n\n /** Default web store: AES-GCM sealing over IndexedDB. */\n static browser(secret: string, options?: EncryptedShareStoreOptions): EncryptedShareStore {\n return new EncryptedShareStore(new IndexedDbKeyValueStore(options?.dbName, options?.storeName), secret, { allowWeakSecret: options?.allowWeakSecret });\n }\n\n async put(walletId: string, share: string): Promise<void> {\n const key = await this.key();\n await this.kv.set(SHARE_PREFIX + walletId, await seal(key, share));\n }\n\n async get(walletId: string): Promise<string | null> {\n const record = await this.kv.get(SHARE_PREFIX + walletId);\n if (record === null) return null;\n return open(await this.key(), record);\n }\n\n async has(walletId: string): Promise<boolean> {\n return (await this.kv.get(SHARE_PREFIX + walletId)) !== null;\n }\n\n async remove(walletId: string): Promise<void> {\n await this.kv.delete(SHARE_PREFIX + walletId);\n }\n\n async clear(): Promise<void> {\n // Drop the cached derived key so the next use re-generates a salt + key.\n this.keyPromise = undefined;\n await this.kv.clear();\n }\n\n /** Lazily load (or create) the persisted salt and derive the AES key once. */\n private key(): Promise<CryptoKey> {\n return (this.keyPromise ??= this.loadKey());\n }\n\n private async loadKey(): Promise<CryptoKey> {\n const stored = await this.kv.get(SALT_KEY);\n let salt: Uint8Array;\n if (stored) {\n salt = base64ToBytes(stored);\n } else {\n salt = freshSalt();\n await this.kv.set(SALT_KEY, bytesToBase64(salt));\n }\n return deriveKey(this.secret, salt);\n }\n}\n","import type { KeyValueStore } from './types';\n\n/**\n * In-memory {@link KeyValueStore} — non-persistent. Used in tests and as a fallback\n * where IndexedDB is unavailable (e.g. SSR). Shares stored here do NOT survive a\n * reload; for persistent device storage use {@link IndexedDbKeyValueStore}.\n */\nexport class MemoryKeyValueStore implements KeyValueStore {\n private readonly map = new Map<string, string>();\n\n async get(key: string): Promise<string | null> {\n return this.map.get(key) ?? null;\n }\n\n async set(key: string, value: string): Promise<void> {\n this.map.set(key, value);\n }\n\n async delete(key: string): Promise<void> {\n this.map.delete(key);\n }\n\n async keys(): Promise<string[]> {\n return [...this.map.keys()];\n }\n\n async clear(): Promise<void> {\n this.map.clear();\n }\n}\n","/**\n * PasskeyPrfSecretProvider — derives a stable AES-key secret from a passkey's\n * PRF extension output, so the device share in {@link EncryptedShareStore} is\n * sealed under a biometric-gated passkey rather than a password.\n *\n * ### How the secret stays stable\n * The PRF extension evaluates a pseudo-random function keyed by the credential\n * (stored in the authenticator) over a caller-supplied `salt`. `enroll()` mints a\n * **random per-user salt** (issue #41) and returns it alongside `credentialId`;\n * persist both (they are non-secret) and pass the salt back to `unlock()`. Because\n * the credential and the salt are the same, the PRF output — and therefore the\n * derived `secret` — is identical on every `unlock()`. (A random per-user salt,\n * rather than one global constant, prevents cross-context PRF correlation.)\n *\n * ### Wiring to EncryptedShareStore\n * ```ts\n * import { PasskeyPrfSecretProvider } from '@waaskey/sdk';\n * import { EncryptedShareStore } from '@waaskey/sdk';\n *\n * const prf = new PasskeyPrfSecretProvider();\n * const { credentialId, secret } = await prf.enroll({ rpName: 'My App', userName: user.email });\n * // persist credentialId (non-secret); keep secret in memory for this session\n * const store = EncryptedShareStore.browser(secret);\n *\n * // On a subsequent session:\n * const { secret } = await prf.unlock(credentialId);\n * const store = EncryptedShareStore.browser(secret);\n *\n * // @waaskey/react: usePrfStore() wraps the above + stores credentialId in localStorage.\n * // react-native: use a native PRF authenticator, supply a custom PrfCeremony.\n * ```\n */\n\nimport { WaaskeyError } from '../errors';\nimport type { AuthenticationExtensionsClientInputs, PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';\n\n// ─── PRF salt (determines the stable secret) ──────────────────────────────────\n// The salt (with the credential) determines the derived secret, so it must be the\n// SAME on enroll + every unlock — altering it makes existing sealed shares unreadable.\n// New enrollments use a RANDOM per-user salt (issue #41); the LEGACY constant below is\n// kept only as the unlock() fallback for credentials enrolled before per-user salts.\nconst LEGACY_PRF_SALT_STRING = 'waaskey-share-seal-v1';\n\n/** The legacy fixed salt (fallback for pre-#41 credentials), as an ArrayBuffer. */\nfunction legacyPrfSalt(): ArrayBuffer {\n return new TextEncoder().encode(LEGACY_PRF_SALT_STRING).buffer as ArrayBuffer;\n}\n\n/** A fresh random 32-byte per-user PRF evaluation salt. */\nfunction randomPrfSalt(): ArrayBuffer {\n return crypto.getRandomValues(new Uint8Array(32)).buffer;\n}\n\nfunction saltToBase64(salt: ArrayBuffer): string {\n let binary = '';\n for (const byte of new Uint8Array(salt)) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\nfunction saltFromBase64(base64: string): ArrayBuffer {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes.buffer;\n}\n\n// ─── PRF extension shape (WebAuthn L3 draft) ──────────────────────────────────\n\ninterface PrfExtensionOutput {\n results?: { first?: ArrayBuffer };\n enabled?: boolean;\n}\n\n/**\n * The PRF extension results as they appear on both registration and authentication\n * `clientExtensionResults`. The typing in @simplewebauthn/browser's\n * `AuthenticationExtensionsClientOutputs` isn't fully typed for PRF yet —\n * we cast through `unknown` at the boundary.\n */\ninterface PrfClientOutputs {\n prf?: PrfExtensionOutput;\n}\n\n// ─── Ceremony abstraction (same pattern as auth.ts PasskeyCeremony) ───────────\n\n/**\n * Override the underlying WebAuthn ceremony calls. Useful for React Native\n * (pass a native PRF authenticator module) or tests (mock the PRF output).\n */\nexport interface PrfCeremony {\n register(options: PublicKeyCredentialCreationOptionsJSON): Promise<{ credentialId: string; prfResult: ArrayBuffer | null }>;\n authenticate(credentialId: string, options: PublicKeyCredentialRequestOptionsJSON): Promise<{ prfResult: ArrayBuffer | null }>;\n}\n\n/** Options accepted by `PasskeyPrfSecretProvider.enroll(...)`. */\nexport interface PasskeyPrfEnrollOptions {\n /**\n * Human-readable name for the relying party (your app). Used in the\n * authenticator's registration ceremony UI.\n */\n rpName?: string;\n /** Display name shown in the authenticator UI for the user. */\n userName?: string;\n /**\n * Fully qualified domain name of the relying party. Defaults to the current\n * origin's hostname in the browser. Must match the value used for `unlock()`.\n */\n rpId?: string;\n /** Custom ceremony (for non-browser runtimes or tests). */\n ceremony?: PrfCeremony;\n}\n\n/** Result of a successful `enroll()` or `unlock()`. */\nexport interface PasskeyPrfResult {\n /** Credential id (Base64URL). Persist this — pass it to `unlock()` later. */\n credentialId: string;\n /**\n * Base64-encoded per-user PRF evaluation salt (issue #41). Non-secret — persist it\n * alongside `credentialId` and pass it back to `unlock({ salt })` so the same secret\n * is re-derived. Omitting it on `unlock` falls back to the legacy constant salt.\n */\n salt: string;\n /**\n * Base64-encoded 32-byte PRF output. Use as the `secret` argument to\n * `EncryptedShareStore.browser(secret)`. Keep in memory; never persist it.\n */\n secret: string;\n}\n\n// ─── Capability detection ─────────────────────────────────────────────────────\n\n/**\n * Returns `true` if the current runtime has WebAuthn available at all.\n * A `false` result means passkeys are completely unavailable; fall back to\n * password or device-secret share sealing.\n */\nexport function isPasskeySupported(): boolean {\n return typeof globalThis.navigator !== 'undefined' && typeof (globalThis.navigator as { credentials?: unknown }).credentials !== 'undefined';\n}\n\n/**\n * Returns `true` if the current platform authenticator supports the PRF\n * extension (needed for passkey share sealing).\n *\n * This is a best-effort probe — not all browsers expose `credentials.get` in a\n * way that lets us query PRF support without a full ceremony. For definitive\n * detection, attempt `enroll()` and handle the `unsupported` error.\n *\n * In practice: Chrome 116+ / Edge 116+ on a platform authenticator support PRF;\n * Safari / iOS 17 do not yet.\n */\nexport async function isPrfSupported(): Promise<boolean> {\n if (!isPasskeySupported()) return false;\n // The CTAP2.1 PRF extension is exposed when the browser supports conditional\n // mediation on credentials.get — use that as a proxy where available.\n try {\n const cred = globalThis.PublicKeyCredential as { isConditionalMediationAvailable?: () => Promise<boolean> } | undefined;\n if (typeof cred?.isConditionalMediationAvailable === 'function') {\n return cred.isConditionalMediationAvailable();\n }\n } catch {\n // Ignore\n }\n // Fall back: assume supported if WebAuthn is available at all.\n return isPasskeySupported();\n}\n\n// ─── Default ceremony (uses @simplewebauthn/browser) ─────────────────────────\n\nasync function loadSimpleWebAuthn(): Promise<typeof import('@simplewebauthn/browser')> {\n try {\n return await import('@simplewebauthn/browser');\n } catch {\n throw new WaaskeyError('Passkey PRF requires \"@simplewebauthn/browser\" installed, or pass a custom ceremony.', 'unsupported');\n }\n}\n\n/** Build the default browser PRF ceremony from @simplewebauthn/browser. */\nasync function defaultPrfCeremony(): Promise<PrfCeremony> {\n const mod = await loadSimpleWebAuthn();\n return {\n async register(options): Promise<{ credentialId: string; prfResult: ArrayBuffer | null }> {\n const response = await mod.startRegistration({ optionsJSON: options });\n const outputs = response.clientExtensionResults as unknown as PrfClientOutputs;\n const prfResult = outputs.prf?.results?.first ?? null;\n return { credentialId: response.id, prfResult };\n },\n async authenticate(_credentialId, options): Promise<{ prfResult: ArrayBuffer | null }> {\n const response = await mod.startAuthentication({ optionsJSON: options });\n const outputs = response.clientExtensionResults as unknown as PrfClientOutputs;\n const prfResult = outputs.prf?.results?.first ?? null;\n return { prfResult };\n },\n };\n}\n\n// ─── PasskeyPrfSecretProvider ─────────────────────────────────────────────────\n\n/**\n * Derives a stable AES-key `secret` from a passkey's PRF extension for use with\n * {@link EncryptedShareStore}. The secret is deterministic: same credential +\n * same fixed salt → same 32 bytes every time.\n */\nexport class PasskeyPrfSecretProvider {\n /**\n * Register a new passkey that supports PRF and derive the initial secret from it.\n *\n * @returns `{ credentialId, secret }` — persist `credentialId`; use `secret`\n * to construct `EncryptedShareStore.browser(secret)` for this session only.\n *\n * @throws `WaaskeyError('unsupported')` when PRF isn't available in this runtime.\n * @throws `WaaskeyError('aborted')` when the user cancels the authenticator dialog.\n */\n async enroll(opts: PasskeyPrfEnrollOptions = {}): Promise<PasskeyPrfResult> {\n const ceremony = opts.ceremony ?? (await defaultPrfCeremony());\n\n const salt = randomPrfSalt();\n const rpId = opts.rpId ?? (typeof location === 'undefined' ? undefined : location.hostname);\n\n const creationOptions: PublicKeyCredentialCreationOptionsJSON = {\n rp: { name: opts.rpName ?? 'Waaskey', ...(rpId ? { id: rpId } : {}) },\n user: {\n id: btoa(String.fromCharCode(...new Uint8Array(crypto.getRandomValues(new Uint8Array(16))))),\n name: opts.userName ?? 'user',\n displayName: opts.userName ?? 'User',\n },\n challenge: btoa(String.fromCharCode(...new Uint8Array(crypto.getRandomValues(new Uint8Array(32))))),\n pubKeyCredParams: [\n { type: 'public-key', alg: -7 }, // ES256 (secp256r1)\n { type: 'public-key', alg: -257 }, // RS256\n ],\n authenticatorSelection: { userVerification: 'required', residentKey: 'required' },\n extensions: { prf: { eval: { first: salt } } } as AuthenticationExtensionsClientInputs,\n };\n\n let credentialId: string;\n let prfResult: ArrayBuffer | null;\n try {\n ({ credentialId, prfResult } = await ceremony.register(creationOptions));\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n const msg = cause instanceof Error ? cause.message : String(cause);\n if (/cancel|abort|not allowed|user gesture/i.test(msg)) {\n throw new WaaskeyError('Passkey registration was cancelled by the user.', 'aborted', { cause });\n }\n throw new WaaskeyError('Passkey registration failed.', 'unsupported', { cause });\n }\n\n if (prfResult === null) {\n throw new WaaskeyError('This authenticator does not support the PRF extension. Use a password or device-secret share instead.', 'unsupported');\n }\n\n return { credentialId, salt: saltToBase64(salt), secret: prfOutputToSecret(prfResult) };\n }\n\n /**\n * Authenticate with an existing passkey and re-derive the same stable secret.\n *\n * @param credentialId — the id returned by `enroll()`.\n * @param opts.salt — the per-user salt `enroll()` returned (issue #41). Pass it to\n * re-derive the same secret; omit only for legacy credentials enrolled before\n * per-user salts (falls back to the constant salt).\n * @returns `{ credentialId, salt, secret }` — reconstruct `EncryptedShareStore.browser(secret)`.\n *\n * @throws `WaaskeyError('unsupported')` when PRF isn't available.\n * @throws `WaaskeyError('aborted')` when the user cancels.\n */\n async unlock(credentialId: string, opts: { rpId?: string; ceremony?: PrfCeremony; salt?: string } = {}): Promise<PasskeyPrfResult> {\n const ceremony = opts.ceremony ?? (await defaultPrfCeremony());\n\n const salt = opts.salt ? saltFromBase64(opts.salt) : legacyPrfSalt();\n const rpId = opts.rpId ?? (typeof location === 'undefined' ? undefined : location.hostname);\n\n const requestOptions: PublicKeyCredentialRequestOptionsJSON = {\n challenge: btoa(String.fromCharCode(...new Uint8Array(crypto.getRandomValues(new Uint8Array(32))))),\n allowCredentials: [{ id: credentialId, type: 'public-key' }],\n userVerification: 'required',\n ...(rpId ? { rpId } : {}),\n extensions: { prf: { eval: { first: salt } } } as AuthenticationExtensionsClientInputs,\n };\n\n let prfResult: ArrayBuffer | null;\n try {\n ({ prfResult } = await ceremony.authenticate(credentialId, requestOptions));\n } catch (cause) {\n if (cause instanceof WaaskeyError) throw cause;\n const msg = cause instanceof Error ? cause.message : String(cause);\n if (/cancel|abort|not allowed|user gesture/i.test(msg)) {\n throw new WaaskeyError('Passkey authentication was cancelled by the user.', 'aborted', { cause });\n }\n throw new WaaskeyError('Passkey authentication failed.', 'unsupported', { cause });\n }\n\n if (prfResult === null) {\n throw new WaaskeyError('Passkey PRF output was not returned — authenticator may not support PRF or the credential was not created with PRF enabled.', 'unsupported');\n }\n\n return { credentialId, salt: saltToBase64(salt), secret: prfOutputToSecret(prfResult) };\n }\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\n/**\n * Convert a PRF result (exactly 32 bytes) to a base64 string suitable as the\n * `secret` argument to `EncryptedShareStore`.\n */\nfunction prfOutputToSecret(prfResult: ArrayBuffer): string {\n const bytes = new Uint8Array(prfResult);\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n"]}