@waaskey/sdk 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +153 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -18
- package/dist/index.d.ts +28 -18
- package/dist/index.js +153 -22
- package/dist/index.js.map +1 -1
- package/dist/node-mpc-worker.d.ts +2 -0
- package/dist/node-mpc-worker.js +142 -0
- package/dist/node-mpc-worker.js.map +1 -0
- package/dist/node.d.ts +426 -0
- package/dist/node.js +466 -0
- package/dist/node.js.map +1 -0
- package/package.json +8 -2
package/dist/index.cjs.map
CHANGED
|
@@ -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/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 const factors: FactorEnrollment[] = [\n { type: 'recovery_code', credentialHash: 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 * `credentialHash` before it leaves the device, so the server verifies possession\n * against the stored hash and never sees the code. Other factors pass through untouched.\n */\nasync function hashRecoveryFactors(verifications: FactorVerification[]): Promise<FactorVerification[]> {\n return Promise.all(verifications.map(async (v) => (v.type === 'recovery_code' && v.token !== undefined ? { type: v.type, credentialHash: 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","/**\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 { isNonCustodial } from './custody';\nimport { deserializeEddsaShare } from './eddsa-share';\nimport { WaaskeyError } from './errors';\nimport { throwIfAborted } from './internal';\nimport { getSigningAssertion } from './passkey/assertion';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { MpcCore } from './mpc';\nimport type { ShareStore } from './storage';\nimport type {\n CustodyKind,\n CustodyType,\n EddsaAssembleRequest,\n EddsaSendSession,\n Page,\n PageQuery,\n SendOptions,\n SendParams,\n SendResult,\n Signature,\n SignMessageResponse,\n SignOptions,\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/**\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 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 /**\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 non-custodial 2-party {device, server}: the platform can't sign\n // alone, so the browser device must co-sign each tx over the relay (a 3-phase flow), unlike the\n // embedded-secp single server-side POST below. Same public method — the curve picks the path.\n if (this.data.curve === 'ed25519') {\n return this.sendEd25519(params, options);\n }\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 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 EddsaSendSession}).\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<EddsaSendSession>('POST', `/v1/wallets/${this.id}/send-session`, startBody, signal);\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: session.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/** 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 { openWithPassword } from './storage/crypto';\nimport { attachPasskeyStepUp, normalizeDigest, Wallet } from './wallet';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { DeviceKeygenParams, DeviceKeygenResult, DeviceSignParams, 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 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).\n await shareStore.put(walletId, serializeShare(keygen!));\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!));\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(toUserBackupSignParams(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) => mpc.runKeygen(party)));\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 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/** The on-device record persisted per wallet — the device key share plus the data sign needs. */\nfunction serializeShare(keygen: DeviceKeygenResult): string {\n return JSON.stringify({ keyShare: keygen.keyShare, auxInfo: keygen.auxInfo, sharedPublicKey: keygen.sharedPublicKey });\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) and the wallet's shared\n * public key. This is the ONE place that knows the on-device storage shape, so the MPC layer only\n * ever receives the KeyShare, never the `{ keyShare, auxInfo, sharedPublicKey }` wrapper.\n */\nfunction deserializeShare(blob: string): { keyShare: string; sharedPublicKey?: string } {\n let parsed: { keyShare?: unknown; sharedPublicKey?: unknown };\n try {\n parsed = JSON.parse(blob) as { keyShare?: unknown; sharedPublicKey?: 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 { keyShare: parsed.keyShare, sharedPublicKey: typeof parsed.sharedPublicKey === 'string' ? parsed.sharedPublicKey : undefined };\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 * Map a recover-sign-session descriptor to the 2-party {@link DeviceSignParams} the `user_backup` party runs\n * (#351/#78). The descriptor addresses the `{server, user_backup}` quorum by keygen index (`participants`,\n * ascending) with this party at `signerPosition`. cggmp24 attributes each signer by its POSITION WITHIN THE\n * QUORUM (not its keygen index), and `runSign`'s 2-party routing carries those positions as\n * `partyIndex`/`peerPartyIndex` — so this party's is `signerPosition` and the peer's is the other slot of the\n * 2-party quorum (`1 - signerPosition`). The `participants` (keygen indices) pass through unchanged; the\n * digest is the caller's own (the descriptor omits it, since the caller supplied it). Refuse a non-2-party\n * descriptor — the `{server, user_backup}` quorum is always exactly 2 — rather than hand cggmp24 a mis-sized\n * signer set.\n */\nfunction toUserBackupSignParams(session: SignSessionResponse, share: string, digest: string): DeviceSignParams {\n if (session.participants.length !== 2 || session.signerPosition < 0 || session.signerPosition > 1) {\n throw new WaaskeyError(\n `Unexpected recover-sign descriptor: the {server, user_backup} quorum must be exactly 2 parties with signerPosition in {0, 1} (got ${session.participants.length} participants, signerPosition ${session.signerPosition}).`,\n 'sign_failed',\n { details: { participants: session.participants, signerPosition: session.signerPosition } },\n );\n }\n return {\n curve: toMpcCurve(session.curve),\n relayUrl: session.relayUrl,\n sessionId: session.sessionId,\n role: session.role,\n peerRole: session.peerRole,\n partyIndex: session.signerPosition,\n peerPartyIndex: 1 - session.signerPosition,\n relayToken: session.relayToken,\n share,\n participants: session.participants,\n signerPosition: session.signerPosition,\n digest,\n };\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 as RecoveryRegisterPayload['factors'] };\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 * 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.1';\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 */\nexport const loadClientWasm: ClientWasmLoader = async (): Promise<ClientWasmModule> => {\n try {\n const mod = await import(CLIENT_WASM_PACKAGE);\n return mod as ClientWasmModule;\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\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.ts","../src/chains.ts","../src/internal.ts","../src/reshare.ts","../src/custody.ts","../src/eddsa-share.ts","../src/enc-keys.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 const factors: FactorEnrollment[] = [\n { type: 'recovery_code', credentialHash: 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 * `credentialHash` before it leaves the device, so the server verifies possession\n * against the stored hash and never sees the code. Other factors pass through untouched.\n */\nasync function hashRecoveryFactors(verifications: FactorVerification[]): Promise<FactorVerification[]> {\n return Promise.all(verifications.map(async (v) => (v.type === 'recovery_code' && v.token !== undefined ? { type: v.type, credentialHash: 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 { 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 { deserializeShare } from './share-blob';\nimport type { Analytics } from './analytics';\nimport type { HttpClient } from './http';\nimport type { MpcCore } from './mpc';\nimport type { ShareStore } from './storage';\nimport type {\n CustodyKind,\n CustodyType,\n EddsaAssembleRequest,\n EddsaSendSession,\n Page,\n PageQuery,\n SendOptions,\n SendParams,\n SendResult,\n Signature,\n SignMessageResponse,\n SignOptions,\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/**\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 body: Record<string, unknown> = { message };\n await this.attachStepUp(body, 'sign', options);\n // A device-present quorum (#292) needs this device to co-sign over the relay CONCURRENTLY\n // with the blocking POST — the server party otherwise waits for a device that never joins\n // and the request times out. Start the device party first, then POST; the POST's result is\n // authoritative (a device-party error alone must not mask it).\n const coSign = this.startDeviceCoSign(message);\n const post = this.http.request<SignMessageResponse>('POST', `/v1/wallets/${this.id}/sign`, body, options.signal);\n const [res] = coSign === undefined ? [await post] : await Promise.all([post, coSign.catch(() => undefined)]);\n this.analytics?.track('wallet.signed', { walletId: this.id, curve: this.data.curve });\n return res.signature;\n }\n\n /**\n * Start this device's half of a secp sign ceremony when the wallet's sign quorum requires it.\n * The quorum is the first `threshold` roles of the wallet's party list (#292) — for the default\n * `[device, server, recovery]`/2 that is `[device, server]`, so the device MUST be online and\n * co-signing. Returns `undefined` when the quorum is platform-only (or the wallet is not secp) —\n * the POST then completes alone, unchanged. A device-present quorum without the device deps or\n * stored share fails fast with a typed error instead of a guaranteed server-side timeout.\n */\n private startDeviceCoSign(digest: string): Promise<unknown> | undefined {\n if (this.data.curve === 'ed25519') return undefined; // FROST signs via the 3-phase send-session flow\n const roles = this.data.parties;\n const { threshold } = this.data;\n if (!Array.isArray(roles) || typeof threshold !== 'number') return undefined; // legacy/unknown topology — server decides\n const quorum = roles.slice(0, threshold);\n const pos = quorum.indexOf('device');\n if (pos < 0) return undefined; // platform-only quorum — nothing to co-sign\n const { mpc, shareStore } = this.device;\n if (!mpc || !shareStore) {\n throw new WaaskeyError(\n `This wallet's sign quorum [${quorum.join(', ')}] includes the device, so signing requires the device MPC core and share store — pass \\`mpc\\` and \\`shareStore\\` to \\`new Waaskey(...)\\`.`,\n 'device_core_required',\n );\n }\n return (async () => {\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 sign quorum.`, 'share_not_found');\n }\n const { keyShare, relayUrl } = deserializeShare(blob);\n if (!relayUrl) {\n throw new WaaskeyError('The stored device share predates relay-URL persistence — re-create the wallet (or recover) to enable device-present signing.', 'share_not_found');\n }\n // The quorum are the first `threshold` parties, so their keygen indices are 0..threshold-1\n // (mirrors the signer's quorum derivation).\n const participants = quorum.map((_role, index) => index);\n const base = { curve: toMpcCurve(this.data.curve), relayUrl, sessionId: this.id, share: keyShare, participants, signerPosition: pos, digest };\n if (quorum.length === 2) {\n return mpc.runSign({ ...base, role: quorum[pos]!, peerRole: quorum[1 - pos]!, partyIndex: pos, peerPartyIndex: 1 - pos });\n }\n if (!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 return mpc.runMemberSign({ ...base, roles: quorum });\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 non-custodial 2-party {device, server}: the platform can't sign\n // alone, so the browser device must co-sign each tx over the relay (a 3-phase flow), unlike the\n // embedded-secp single server-side POST below. Same public method — the curve picks the path.\n if (this.data.curve === 'ed25519') {\n return this.sendEd25519(params, options);\n }\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 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 EddsaSendSession}).\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<EddsaSendSession>('POST', `/v1/wallets/${this.id}/send-session`, startBody, signal);\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: session.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/** 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 { 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, DeviceSignParams, 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 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(toUserBackupSignParams(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 * Map a recover-sign-session descriptor to the 2-party {@link DeviceSignParams} the `user_backup` party runs\n * (#351/#78). The descriptor addresses the `{server, user_backup}` quorum by keygen index (`participants`,\n * ascending) with this party at `signerPosition`. cggmp24 attributes each signer by its POSITION WITHIN THE\n * QUORUM (not its keygen index), and `runSign`'s 2-party routing carries those positions as\n * `partyIndex`/`peerPartyIndex` — so this party's is `signerPosition` and the peer's is the other slot of the\n * 2-party quorum (`1 - signerPosition`). The `participants` (keygen indices) pass through unchanged; the\n * digest is the caller's own (the descriptor omits it, since the caller supplied it). Refuse a non-2-party\n * descriptor — the `{server, user_backup}` quorum is always exactly 2 — rather than hand cggmp24 a mis-sized\n * signer set.\n */\nfunction toUserBackupSignParams(session: SignSessionResponse, share: string, digest: string): DeviceSignParams {\n if (session.participants.length !== 2 || session.signerPosition < 0 || session.signerPosition > 1) {\n throw new WaaskeyError(\n `Unexpected recover-sign descriptor: the {server, user_backup} quorum must be exactly 2 parties with signerPosition in {0, 1} (got ${session.participants.length} participants, signerPosition ${session.signerPosition}).`,\n 'sign_failed',\n { details: { participants: session.participants, signerPosition: session.signerPosition } },\n );\n }\n return {\n curve: toMpcCurve(session.curve),\n relayUrl: session.relayUrl,\n sessionId: session.sessionId,\n role: session.role,\n peerRole: session.peerRole,\n partyIndex: session.signerPosition,\n peerPartyIndex: 1 - session.signerPosition,\n relayToken: session.relayToken,\n share,\n participants: session.participants,\n signerPosition: session.signerPosition,\n digest,\n };\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 as RecoveryRegisterPayload['factors'] };\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.1';\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"]}
|