@cef-ai/wallet 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transport/origin.ts","../src/transport/PopupTransport.ts","../src/EmbedWallet.ts","../src/protocol.ts","../src/transport/PopupHostBridge.ts","../src/transport/BroadcastSessionShare.ts"],"names":["WalletError","data","pending","EthersSigner","PolkadotSigner","SolanaSigner","decodeEd25519Pubkey"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Origin verification helpers used by both ends of the popup transport.\n * Spec §5.3.\n */\n\n/**\n * Schemes that we accept for origins. Production uses https only; we allow\n * http here so test setups and `localhost:port` work — callers can layer\n * tighter rules (e.g. \"only https in production\") on top.\n */\nexport const ALLOWED_ORIGIN_SCHEMES: readonly string[] = ['https:', 'http:'];\n\n/**\n * Strict origin equality check. Returns true iff both inputs are non-empty,\n * URL-parseable, and have matching `origin` (scheme + host + port).\n */\nexport function isMatchingOrigin(a: string | undefined, b: string | undefined): boolean {\n if (!a || !b) return false;\n try {\n const ua = new URL(a);\n const ub = new URL(b);\n return ua.origin === ub.origin;\n } catch {\n return false;\n }\n}\n","import { WalletError, type WalletErrorCode } from '@cef-ai/wallet-api-client';\nimport type { HostToPopup, PopupToHost } from '../protocol';\nimport { isMatchingOrigin } from './origin';\nimport type { PopupHandle, PopupOpener } from './types';\n\nexport interface PopupTransportOptions {\n /** Expected origin of the wallet popup, e.g. 'https://wallet.example.com'. */\n walletOrigin: string;\n /** Defaults to `(url, features) => window.open(url, '_blank', features)`. */\n openPopup?: PopupOpener;\n /** Window object hosting the event listener. Defaults to `globalThis.window`. */\n hostWindow?: Window;\n /** Default per-request timeout. Defaults to 60_000 ms. */\n defaultTimeoutMs?: number;\n}\n\ninterface PendingRequest {\n expectedTypes: PopupToHost['type'][];\n resolve: (msg: PopupToHost) => void;\n reject: (err: WalletError) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\nconst DEFAULT_FEATURES = 'width=420,height=640,resizable=yes,scrollbars=yes';\n\n/**\n * Host-side popup transport. Spec §5.\n *\n * Use one `PopupTransport` instance per `EmbedWallet`. The instance owns a\n * single popup window at a time, opens it on demand, auto-reopens on the next\n * `request()` after it's been closed, and correlates each in-flight request\n * by its message `id`.\n *\n * Wire handshake: every freshly opened popup must send `wallet:ready` before\n * this transport will post any `HostToPopup` envelope. Without the handshake,\n * `postMessage` may fire before the popup document has executed its `message`\n * listener and the message is dropped. Outbound messages are queued in\n * `outbox` while `popupReady === false`; `wallet:ready` flushes them.\n */\nexport class PopupTransport {\n private readonly opts: Required<PopupTransportOptions>;\n private popup: PopupHandle | null = null;\n private pending: Map<string, PendingRequest> = new Map();\n private listener: ((event: MessageEvent) => void) | null = null;\n private popupReady = false;\n private outbox: HostToPopup[] = [];\n\n constructor(options: PopupTransportOptions) {\n this.opts = {\n openPopup: defaultOpener,\n hostWindow: (globalThis as any).window,\n defaultTimeoutMs: 60_000,\n ...options,\n };\n }\n\n async request<T extends PopupToHost>(\n message: HostToPopup,\n expectedTypes: T['type'][],\n init: { timeoutMs?: number } = {},\n ): Promise<T> {\n if (!this.popup || this.popup.closed) {\n const hostOrigin = (globalThis as any).location?.origin ?? '';\n const url = `${this.opts.walletOrigin}/embed/wallet?origin=${encodeURIComponent(hostOrigin)}`;\n this.popup = this.opts.openPopup(url, DEFAULT_FEATURES);\n if (!this.popup) {\n throw new WalletError('popup-blocked', 'popup window failed to open');\n }\n // Fresh popup: reset handshake state. Any in-flight outbox from a prior\n // popup session is dropped; those requests have their own timers and\n // will fail through the normal timeout path.\n this.popupReady = false;\n this.outbox = [];\n this.ensureListening();\n }\n\n const id = message.id;\n const timeoutMs = init.timeoutMs ?? this.opts.defaultTimeoutMs;\n\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n if (this.pending.has(id)) {\n this.pending.delete(id);\n // Also drop from the outbox if it never got flushed.\n this.outbox = this.outbox.filter((m) => m.id !== id);\n reject(new WalletError('internal', `request \"${message.type}\" (id=${id}) timed out after ${timeoutMs}ms`));\n }\n }, timeoutMs);\n\n this.pending.set(id, {\n expectedTypes,\n resolve: (msg) => resolve(msg as T),\n reject,\n timer,\n });\n\n if (this.popupReady) {\n this.popup!.postMessage(message, this.opts.walletOrigin);\n } else {\n // Queue until the popup announces `wallet:ready`.\n this.outbox.push(message);\n }\n });\n }\n\n /** Close the popup if open. Pending requests will time out normally. */\n close(): void {\n if (this.popup && !this.popup.closed) {\n this.popup.close();\n }\n this.popup = null;\n this.popupReady = false;\n this.outbox = [];\n }\n\n /**\n * Tear down the transport entirely. Closes the popup AND removes the host-\n * window message listener. After `destroy()`, the transport instance cannot\n * be reused — callers should drop the reference.\n *\n * Use `close()` if you only want to close the popup but keep the transport\n * alive for a later re-open.\n */\n destroy(): void {\n this.close();\n if (this.listener) {\n this.opts.hostWindow.removeEventListener('message', this.listener);\n this.listener = null;\n }\n }\n\n // ---- internal -------------------------------------------------------------\n\n private ensureListening(): void {\n if (this.listener) return;\n this.listener = (event: MessageEvent) => this.onMessage(event);\n this.opts.hostWindow.addEventListener('message', this.listener);\n }\n\n private onMessage(event: MessageEvent): void {\n if (!isMatchingOrigin(event.origin, this.opts.walletOrigin)) {\n // Origin-mismatched messages might still target a pending request id —\n // we reject that pending request explicitly so callers get a clear signal\n // rather than waiting for a timeout.\n const data = event.data as PopupToHost | undefined;\n if (data && typeof data.id === 'string' && this.pending.has(data.id)) {\n const pending = this.pending.get(data.id)!;\n this.pending.delete(data.id);\n clearTimeout(pending.timer);\n pending.reject(\n new WalletError(\n 'origin-mismatch',\n `message from \"${event.origin}\" rejected (expected \"${this.opts.walletOrigin}\")`,\n ),\n );\n }\n return;\n }\n\n const data = event.data as PopupToHost | undefined;\n if (!data || typeof data.type !== 'string' || typeof data.id !== 'string') return;\n\n // Handshake: a freshly loaded popup announces itself with `wallet:ready`.\n // Flush any messages that were queued before the popup's listener was wired.\n if (data.type === 'wallet:ready') {\n if (this.popupReady) return;\n this.popupReady = true;\n const toFlush = this.outbox;\n this.outbox = [];\n if (this.popup && !this.popup.closed) {\n for (const m of toFlush) {\n this.popup.postMessage(m, this.opts.walletOrigin);\n }\n }\n return;\n }\n\n const pending = this.pending.get(data.id);\n if (!pending) return;\n\n clearTimeout(pending.timer);\n this.pending.delete(data.id);\n\n if (data.type === 'wallet:error') {\n pending.reject(new WalletError(data.code as WalletErrorCode, data.message, data.traceId));\n return;\n }\n\n if (!pending.expectedTypes.includes(data.type)) {\n pending.reject(\n new WalletError('internal', `received unexpected response type \"${data.type}\" for id \"${data.id}\"`),\n );\n return;\n }\n\n pending.resolve(data);\n }\n}\n\nfunction defaultOpener(url: string, features?: string): PopupHandle | null {\n const w = (globalThis as any).window;\n const opened = w?.open(url, '_blank', features);\n return opened as PopupHandle | null;\n}\n","import { WalletError } from '@cef-ai/wallet-api-client';\nimport type { Addresses } from '@cef-ai/wallet-identity';\nimport { decodeEd25519Pubkey } from '@cef-ai/wallet-identity';\nimport { EthersSigner, PolkadotSigner, SolanaSigner, type InternalSign } from '@cef-ai/wallet-signers';\nimport type { CefSigner, SignIntent } from './signer';\nimport type {\n EmbedWalletOptions,\n LoginResult,\n DelegationRequest,\n DelegationResult,\n SignerSpec,\n WalletEvent,\n WalletEventListener,\n ApplicationFilter,\n ApplicationBody,\n ApplicationRecord,\n} from './types';\nimport type { AppContext, HostToPopup, PopupToHost } from './protocol';\nimport { PopupTransport } from './transport/PopupTransport';\n\ntype ListenerMap = { [T in WalletEvent['type']]?: Set<WalletEventListener<T>> };\n\n/**\n * Public SDK class. v2.0.0. Spec §4.\n *\n * Drives the popup transport: every method that does meaningful work opens\n * (or reuses) a popup at `walletOrigin/embed/*`, sends a `HostToPopup`\n * message, awaits the matching `PopupToHost` response, and updates local\n * state. See spec §5 for the wire protocol.\n */\nexport class EmbedWallet {\n readonly appId: string;\n readonly walletOrigin: string;\n readonly popup: { width: number; height: number };\n readonly appName: string;\n\n private _addresses: Addresses | null = null;\n private _credentialId: string | null = null;\n private _listeners: ListenerMap = {};\n private readonly transport: PopupTransport;\n\n constructor(opts: EmbedWalletOptions) {\n // `walletOrigin` is required for real use — the SDK builds a PopupTransport\n // pinned to it. The `__internal__.transport` test seam supplies its own\n // origin-pinned transport, so walletOrigin may be omitted in that case.\n const injectedTransport = opts.__internal__?.transport;\n if (!injectedTransport && !opts.walletOrigin) {\n throw new Error('EmbedWallet: `walletOrigin` is required (e.g. https://wallet.example.com).');\n }\n this.appId = opts.appId;\n this.walletOrigin = opts.walletOrigin ?? '';\n this.popup = { width: opts.popup?.width ?? 420, height: opts.popup?.height ?? 640 };\n this.appName = opts.appName ?? '';\n this.transport =\n injectedTransport ??\n new PopupTransport({\n walletOrigin: this.walletOrigin,\n });\n }\n\n get isLoggedIn(): boolean {\n return this._addresses !== null;\n }\n get addresses(): Addresses | null {\n return this._addresses;\n }\n get credentialId(): string | null {\n return this._credentialId;\n }\n\n async register(opts: { label?: string } = {}): Promise<LoginResult> {\n return this.helloAndAwaitLogin('register', opts);\n }\n\n async login(): Promise<LoginResult> {\n return this.helloAndAwaitLogin('login');\n }\n\n async logout(): Promise<void> {\n if (!this._addresses) {\n this.transport.close();\n return;\n }\n const id = crypto.randomUUID();\n try {\n await this.transport.request<Extract<PopupToHost, { type: 'wallet:result' }>>({ type: 'wallet:logout', id }, [\n 'wallet:result',\n ]);\n } catch (_err) {\n // Ignore — local state still gets cleared below.\n }\n this._addresses = null;\n this._credentialId = null;\n this.transport.close();\n this.emit('logout', { type: 'logout' });\n }\n\n getSigner(spec: { chain: 'evm' }): EthersSigner;\n getSigner(spec: { chain: 'cere' }): PolkadotSigner;\n getSigner(spec: { chain: 'solana' }): SolanaSigner;\n getSigner(spec: SignerSpec): EthersSigner | PolkadotSigner | SolanaSigner;\n getSigner(spec: SignerSpec): EthersSigner | PolkadotSigner | SolanaSigner {\n this.assertLoggedIn('getSigner');\n const sign: InternalSign = async (chain, payload) => {\n const id = crypto.randomUUID();\n const result = await this.transport.request<Extract<PopupToHost, { type: 'wallet:result' }>>(\n { type: 'wallet:sign', id, chain, payload, requestKind: 'sdk' },\n ['wallet:result'],\n );\n const sig = result.result;\n if (!(sig instanceof Uint8Array)) {\n throw new WalletError('internal', `popup returned non-Uint8Array sign result (got ${typeof sig})`);\n }\n return sig;\n };\n const addresses = this._addresses!;\n switch (spec.chain) {\n case 'evm':\n return new EthersSigner({ address: addresses.evm, sign });\n case 'cere':\n return new PolkadotSigner({ address: addresses.cere, sign });\n case 'solana':\n return new SolanaSigner({ address: addresses.solana, sign });\n default:\n throw new WalletError('validation', `getSigner: unknown chain \"${String((spec as any).chain)}\"`);\n }\n }\n\n /**\n * Expose the wallet as a chain-free `@cef-ai/signer` over the Cere\n * Ed25519 key — the pluggable-signer seam `@cef-ai/account` consumes for DDC\n * and `@cef-ai/chain` adapts for extrinsics.\n *\n * `publicKey` is recovered from the (public) Solana address — no key material\n * leaves the popup's `SessionVault`. `sign(bytes, 'extrinsic', { humanReadable })`\n * routes through the popup's extrinsic-consent screen.\n */\n asSigner(): CefSigner {\n this.assertLoggedIn('asSigner');\n const addresses = this._addresses!;\n const send = async (\n payload: Uint8Array,\n intent: SignIntent | undefined,\n humanReadable: string | undefined,\n ): Promise<Uint8Array> => {\n // `asSigner()` captured the addresses at call time; if the user has since\n // logged out (e.g. cross-tab logout), fail fast here rather than sending a\n // `wallet:sign` the popup would reject with `unauthorized`.\n if (!this.isLoggedIn) {\n throw new WalletError('unauthorized', 'asSigner: wallet is no longer logged in');\n }\n const id = crypto.randomUUID();\n const result = await this.transport.request<Extract<PopupToHost, { type: 'wallet:result' }>>(\n { type: 'wallet:sign', id, chain: 'cere', payload, requestKind: intent ?? 'sdk', humanReadable },\n ['wallet:result'],\n );\n const sig = result.result;\n if (!(sig instanceof Uint8Array)) {\n throw new WalletError('internal', `popup returned non-Uint8Array sign result (got ${typeof sig})`);\n }\n return sig;\n };\n return {\n type: 'ed25519',\n address: addresses.cere,\n publicKey: decodeEd25519Pubkey(addresses.solana),\n isReady: async () => this.isLoggedIn,\n sign: (bytes, intent, opts) => send(bytes, intent, opts?.humanReadable),\n };\n }\n\n async requestDelegation(req: DelegationRequest): Promise<DelegationResult> {\n this.assertLoggedIn('requestDelegation');\n const id = crypto.randomUUID();\n const scope = {\n capabilities: req.capabilities,\n appId: req.appId,\n agentPubkey: req.agentPubkey,\n constraints: req.constraints,\n };\n const result = await this.transport.request<Extract<PopupToHost, { type: 'wallet:result' }>>(\n { type: 'wallet:requestDelegation', id, scope, ttl: req.ttl },\n ['wallet:result'],\n );\n return result.result as DelegationResult;\n }\n\n async findApplications(filter: ApplicationFilter = {}): Promise<ApplicationRecord[]> {\n this.assertLoggedIn('findApplications');\n const id = crypto.randomUUID();\n const result = await this.transport.request<Extract<PopupToHost, { type: 'wallet:result' }>>(\n { type: 'wallet:findApplications', id, appId: filter.appId },\n ['wallet:result'],\n );\n return result.result as ApplicationRecord[];\n }\n\n async saveApplication(body: ApplicationBody): Promise<ApplicationRecord> {\n this.assertLoggedIn('saveApplication');\n const id = crypto.randomUUID();\n const result = await this.transport.request<Extract<PopupToHost, { type: 'wallet:result' }>>(\n { type: 'wallet:saveApplication', id, permissions: body.permissions, email: body.email },\n ['wallet:result'],\n );\n return result.result as ApplicationRecord;\n }\n\n on<T extends WalletEvent['type']>(type: T, listener: WalletEventListener<T>): this {\n const map = this._listeners as Record<string, Set<WalletEventListener<any>>>;\n (map[type] ??= new Set()).add(listener);\n return this;\n }\n\n off<T extends WalletEvent['type']>(type: T, listener: WalletEventListener<T>): this {\n const map = this._listeners as Record<string, Set<WalletEventListener<any>>>;\n map[type]?.delete(listener);\n return this;\n }\n\n /**\n * Tear down the wallet instance. Closes any open popup, removes transport\n * listeners, clears in-memory state. Call from your app's unmount hook.\n *\n * After dispose(), this instance is not reusable — construct a new one.\n */\n dispose(): void {\n this._addresses = null;\n this._credentialId = null;\n this._listeners = {};\n this.transport.destroy();\n }\n\n // ---- private --------------------------------------------------------------\n\n private appContext(): AppContext {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n return { appId: this.appId, name: this.appName, origin };\n }\n\n private async helloAndAwaitLogin(intent: 'register' | 'login', opts: { label?: string } = {}): Promise<LoginResult> {\n const id = crypto.randomUUID();\n const helloMessage: HostToPopup = {\n type: 'wallet:hello',\n id,\n appContext: this.appContext(),\n intent,\n label: opts.label,\n };\n const result = await this.transport.request<Extract<PopupToHost, { type: 'wallet:login:ok' }>>(helloMessage, [\n 'wallet:login:ok',\n ]);\n this._addresses = result.addresses;\n this._credentialId = result.credentialId;\n this.emit('login', { type: 'login', addresses: result.addresses });\n return { addresses: result.addresses, credentialId: result.credentialId };\n }\n\n private emit<T extends WalletEvent['type']>(type: T, ev: Extract<WalletEvent, { type: T }>): void {\n const set = this._listeners[type] as Set<WalletEventListener<T>> | undefined;\n if (!set) return;\n for (const listener of set) {\n try {\n listener(ev);\n } catch {\n // Listener errors are isolated.\n }\n }\n }\n\n private assertLoggedIn(method: string): void {\n if (!this._addresses) {\n throw new WalletError('unauthorized', `${method}: not logged in`);\n }\n }\n}\n","import type { Addresses, Chain } from '@cef-ai/wallet-identity';\nimport type { WalletErrorCode } from '@cef-ai/wallet-api-client';\nimport type { ApplicationBody, ApplicationFilter, DelegationScope } from './types';\n\nexport interface AppContext {\n appId: string;\n name: string;\n origin: string;\n}\n\n/** Spec §5.2. Messages sent from a host page to a wallet popup. */\nexport type HostToPopup =\n | { type: 'wallet:hello'; id: string; appContext: AppContext; intent: 'register' | 'login'; label?: string }\n | { type: 'wallet:requestDelegation'; id: string; scope: DelegationScope; ttl: string }\n | { type: 'wallet:sign'; id: string; chain: Chain; payload: Uint8Array; requestKind: string; humanReadable?: string }\n | ({ type: 'wallet:saveApplication'; id: string } & ApplicationBody)\n | ({ type: 'wallet:findApplications'; id: string } & ApplicationFilter)\n | { type: 'wallet:logout'; id: string };\n\n/**\n * Spec §5.2. Messages sent from a wallet popup back to the host.\n *\n * On `wallet:error`, `message` carries the human-readable detail\n * (what `WalletError.detail` returns), NOT the compound `Error.message`\n * (`\"${code}: ${detail}\"`). The compound is reconstructable from `code + message`\n * on the receiving side. Serialisers in the popup MUST send `err.detail ?? ''`,\n * not `err.message`.\n */\nexport type PopupToHost =\n | { type: 'wallet:ready'; id: string }\n | { type: 'wallet:login:ok'; id: string; addresses: Addresses; credentialId: string }\n | { type: 'wallet:result'; id: string; result: unknown }\n | { type: 'wallet:error'; id: string; code: WalletErrorCode; message: string; traceId?: string };\n\n/** Spec §5.5. Channel name: `scp-wallet-v2`. Wallet-origin tabs only. */\nexport type BroadcastChannelMessage =\n | { type: 'request-session'; requestId: string }\n | {\n type: 'offer-session';\n requestId: string;\n edSeed: Uint8Array;\n secpKey: Uint8Array;\n addresses: Addresses;\n /** absolute Unix epoch ms when session keys expire */ expMs: number;\n }\n | { type: 'logout' };\n\nexport const BROADCAST_CHANNEL_NAME = 'scp-wallet-v2';\n","import { WalletError } from '@cef-ai/wallet-api-client';\nimport type { HostToPopup, PopupToHost } from '../protocol';\nimport { isMatchingOrigin } from './origin';\nimport type { PopupMessageHandler } from './types';\n\nexport interface PopupHostBridgeOptions {\n /** Expected origin of the host page (the page that opened this popup). */\n hostOrigin: string;\n /** The window this bridge runs in. Defaults to `globalThis`. */\n popupWindow?: Window;\n}\n\ntype HandlerMap = {\n [T in HostToPopup['type']]?: PopupMessageHandler<Extract<HostToPopup, { type: T }>>;\n};\n\n/**\n * Popup-side bridge. Spec §5.\n *\n * The wallet SPA constructs one of these at boot, registers handlers via\n * `on(type, fn)`, and calls `start()` to begin listening. Each inbound\n * `HostToPopup` message that matches a registered handler is dispatched;\n * the handler is responsible for calling `bridge.send(...)` to reply.\n *\n * Handlers may throw `WalletError`; the bridge automatically converts the\n * throw into a `wallet:error` response keyed by the inbound message id.\n */\nexport class PopupHostBridge {\n private readonly opts: Required<PopupHostBridgeOptions>;\n private readonly handlers: HandlerMap = {};\n private listener: ((event: MessageEvent) => void) | null = null;\n\n constructor(options: PopupHostBridgeOptions) {\n this.opts = {\n popupWindow: (globalThis as any).window,\n ...options,\n };\n }\n\n /** Register a handler for a specific message type. Replaces any prior handler. */\n on<T extends HostToPopup['type']>(type: T, handler: PopupMessageHandler<Extract<HostToPopup, { type: T }>>): this {\n this.handlers[type] = handler as any;\n return this;\n }\n\n /**\n * Send a `PopupToHost` message back to the opener. The bridge does not\n * remember the host-window reference itself — it reads `globalThis.opener`\n * each call, so it survives popup re-opens.\n */\n send(message: PopupToHost): void {\n const opener: any = (globalThis as any).opener;\n if (!opener || typeof opener.postMessage !== 'function') {\n // No opener — popup was opened standalone or the opener is closed.\n return;\n }\n opener.postMessage(message, this.opts.hostOrigin);\n }\n\n /**\n * Start listening for inbound messages.\n *\n * If `announceReady` is provided, sends a `wallet:ready` message immediately.\n * Use this when the popup wants to signal \"I'm here\" without waiting for the\n * host's first call.\n */\n start(opts: { announceReady?: { id: string } } = {}): void {\n if (this.listener) return;\n this.listener = (event: MessageEvent) => this.onMessage(event);\n this.opts.popupWindow.addEventListener('message', this.listener);\n if (opts.announceReady) {\n this.send({ type: 'wallet:ready', id: opts.announceReady.id });\n }\n }\n\n stop(): void {\n if (!this.listener) return;\n this.opts.popupWindow.removeEventListener('message', this.listener);\n this.listener = null;\n }\n\n // ---- internal -------------------------------------------------------------\n\n private async onMessage(event: MessageEvent): Promise<void> {\n if (!isMatchingOrigin(event.origin, this.opts.hostOrigin)) {\n // Silently drop.\n return;\n }\n const data = event.data as HostToPopup | undefined;\n if (!data || typeof data.type !== 'string' || typeof data.id !== 'string') return;\n\n const handler = (this.handlers as any)[data.type] as PopupMessageHandler<HostToPopup> | undefined;\n if (!handler) {\n // No handler registered — reply with a typed error.\n this.send({\n type: 'wallet:error',\n id: data.id,\n code: 'internal',\n message: `no handler registered for \"${data.type}\"`,\n });\n return;\n }\n\n try {\n await handler(data, { origin: event.origin });\n } catch (err) {\n if (err instanceof WalletError) {\n this.send({\n type: 'wallet:error',\n id: data.id,\n code: err.code,\n message: err.detail ?? '',\n traceId: err.traceId,\n });\n } else {\n this.send({\n type: 'wallet:error',\n id: data.id,\n code: 'internal',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n }\n}\n","import { BROADCAST_CHANNEL_NAME, type BroadcastChannelMessage } from '../protocol';\nimport type { Addresses } from '@cef-ai/wallet-identity';\n\nexport interface BroadcastSession {\n edSeed: Uint8Array;\n secpKey: Uint8Array;\n addresses: Addresses;\n /** Absolute Unix epoch ms when the session expires. */\n expMs: number;\n}\n\nexport interface BroadcastSessionShareOptions {\n /**\n * Returns the local session if this tab has one to offer. Called whenever\n * another tab broadcasts `request-session`.\n */\n getSession: () => BroadcastSession | null;\n /**\n * Called when another tab broadcasts a `logout` message. The local handler\n * should wipe its own session.\n */\n onLogout?: () => void;\n}\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 200;\n\n/**\n * Popup-side cross-tab session sharing. Spec §5.5.\n *\n * - `request()`: broadcast `request-session`, wait up to 200ms for an offer.\n * - `start()`: listen for incoming requests; reply with `offer-session` if we\n * have a non-expired session and `getSession()` returns it.\n * - `broadcastLogout()`: notify peers to wipe their sessions too.\n *\n * Channel name is the spec-locked `scp-wallet-v2`. Only wallet-origin popups\n * join. Host pages do not participate.\n */\nexport class BroadcastSessionShare {\n private readonly channel: BroadcastChannel;\n private readonly opts: BroadcastSessionShareOptions;\n private listening = false;\n\n constructor(opts: BroadcastSessionShareOptions) {\n this.opts = opts;\n this.channel = new BroadcastChannel(BROADCAST_CHANNEL_NAME);\n }\n\n /**\n * Broadcast a `request-session` and wait for an `offer-session` from another\n * tab. Resolves with the offered session, or null if nobody offered before\n * the timeout.\n */\n async request(opts: { timeoutMs?: number } = {}): Promise<BroadcastSession | null> {\n const requestId = crypto.randomUUID();\n const timeoutMs = opts.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n\n return new Promise<BroadcastSession | null>((resolve) => {\n const onMsg = (ev: MessageEvent<BroadcastChannelMessage>) => {\n if (ev.data.type === 'offer-session' && ev.data.requestId === requestId && ev.data.expMs > Date.now()) {\n this.channel.removeEventListener('message', onMsg);\n clearTimeout(timer);\n resolve({\n edSeed: ev.data.edSeed,\n secpKey: ev.data.secpKey,\n addresses: ev.data.addresses,\n expMs: ev.data.expMs,\n });\n }\n };\n this.channel.addEventListener('message', onMsg);\n const timer = setTimeout(() => {\n this.channel.removeEventListener('message', onMsg);\n resolve(null);\n }, timeoutMs);\n\n this.channel.postMessage({ type: 'request-session', requestId } as BroadcastChannelMessage);\n });\n }\n\n /** Begin offering this tab's session in response to requests, and handle logouts. */\n start(): void {\n if (this.listening) return;\n this.listening = true;\n this.channel.addEventListener('message', this.onMessage);\n }\n\n stop(): void {\n this.channel.removeEventListener('message', this.onMessage);\n this.listening = false;\n }\n\n /** Notify peers that the user logged out. Peers wipe their sessions. */\n broadcastLogout(): void {\n this.channel.postMessage({ type: 'logout' } as BroadcastChannelMessage);\n }\n\n /** Free the underlying channel handle. Call from unload handlers. */\n close(): void {\n this.stop();\n this.channel.close();\n }\n\n private onMessage = (ev: MessageEvent<BroadcastChannelMessage>): void => {\n const msg = ev.data;\n if (msg.type === 'request-session') {\n const session = this.opts.getSession();\n if (!session || session.expMs <= Date.now()) return;\n this.channel.postMessage({\n type: 'offer-session',\n requestId: msg.requestId,\n edSeed: session.edSeed,\n secpKey: session.secpKey,\n addresses: session.addresses,\n expMs: session.expMs,\n } as BroadcastChannelMessage);\n return;\n }\n if (msg.type === 'logout') {\n this.opts.onLogout?.();\n return;\n }\n };\n}\n"]}
@@ -0,0 +1,452 @@
1
+ import { Addresses, Chain } from '@cef-ai/wallet-identity';
2
+ import { EthersSigner, PolkadotSigner, SolanaSigner } from '@cef-ai/wallet-signers';
3
+ import { WalletErrorCode } from '@cef-ai/wallet-api-client';
4
+
5
+ /**
6
+ * The `@cef-ai/signer` contract, declared locally.
7
+ *
8
+ * `@cef-ai/signer` is published from the CEF-AI/sdk repo; until it is released
9
+ * we mirror its shape here so `EmbedWallet.asSigner()` can produce a
10
+ * structurally-compatible signer that `@cef-ai/account` consumes. When the
11
+ * package ships, replace this with `import type { Signer, SignIntent } from
12
+ * '@cef-ai/signer'`. The shape MUST stay in sync with that interface.
13
+ */
14
+ type SignerType = 'ed25519' | 'sr25519' | 'ecdsa' | 'ethereum';
15
+ type SignIntent = 'data' | 'token' | 'extrinsic';
16
+ interface CefSigner {
17
+ readonly type: SignerType;
18
+ readonly address: string;
19
+ readonly publicKey: Uint8Array;
20
+ isReady(): Promise<boolean>;
21
+ /**
22
+ * Sign raw bytes. `intent` keys the wallet's consent UI ('extrinsic' raises
23
+ * the extrinsic-consent screen). `opts.humanReadable` is an out-of-band
24
+ * description shown best-effort on that screen — it is NOT part of the
25
+ * minimal `@cef-ai/signer` interface, just an extra the CEF wallet honors.
26
+ */
27
+ sign(bytes: Uint8Array, intent?: SignIntent, opts?: {
28
+ humanReadable?: string;
29
+ }): Promise<Uint8Array>;
30
+ }
31
+
32
+ interface AppContext {
33
+ appId: string;
34
+ name: string;
35
+ origin: string;
36
+ }
37
+ /** Spec §5.2. Messages sent from a host page to a wallet popup. */
38
+ type HostToPopup = {
39
+ type: 'wallet:hello';
40
+ id: string;
41
+ appContext: AppContext;
42
+ intent: 'register' | 'login';
43
+ label?: string;
44
+ } | {
45
+ type: 'wallet:requestDelegation';
46
+ id: string;
47
+ scope: DelegationScope;
48
+ ttl: string;
49
+ } | {
50
+ type: 'wallet:sign';
51
+ id: string;
52
+ chain: Chain;
53
+ payload: Uint8Array;
54
+ requestKind: string;
55
+ humanReadable?: string;
56
+ } | ({
57
+ type: 'wallet:saveApplication';
58
+ id: string;
59
+ } & ApplicationBody) | ({
60
+ type: 'wallet:findApplications';
61
+ id: string;
62
+ } & ApplicationFilter) | {
63
+ type: 'wallet:logout';
64
+ id: string;
65
+ };
66
+ /**
67
+ * Spec §5.2. Messages sent from a wallet popup back to the host.
68
+ *
69
+ * On `wallet:error`, `message` carries the human-readable detail
70
+ * (what `WalletError.detail` returns), NOT the compound `Error.message`
71
+ * (`"${code}: ${detail}"`). The compound is reconstructable from `code + message`
72
+ * on the receiving side. Serialisers in the popup MUST send `err.detail ?? ''`,
73
+ * not `err.message`.
74
+ */
75
+ type PopupToHost = {
76
+ type: 'wallet:ready';
77
+ id: string;
78
+ } | {
79
+ type: 'wallet:login:ok';
80
+ id: string;
81
+ addresses: Addresses;
82
+ credentialId: string;
83
+ } | {
84
+ type: 'wallet:result';
85
+ id: string;
86
+ result: unknown;
87
+ } | {
88
+ type: 'wallet:error';
89
+ id: string;
90
+ code: WalletErrorCode;
91
+ message: string;
92
+ traceId?: string;
93
+ };
94
+ /** Spec §5.5. Channel name: `scp-wallet-v2`. Wallet-origin tabs only. */
95
+ type BroadcastChannelMessage = {
96
+ type: 'request-session';
97
+ requestId: string;
98
+ } | {
99
+ type: 'offer-session';
100
+ requestId: string;
101
+ edSeed: Uint8Array;
102
+ secpKey: Uint8Array;
103
+ addresses: Addresses;
104
+ /** absolute Unix epoch ms when session keys expire */ expMs: number;
105
+ } | {
106
+ type: 'logout';
107
+ };
108
+ declare const BROADCAST_CHANNEL_NAME = "scp-wallet-v2";
109
+
110
+ /**
111
+ * The minimal subset of `Window` that we use for postMessage + lifecycle.
112
+ * Both real browser windows and `MessageChannel`-backed test doubles can
113
+ * satisfy this shape.
114
+ */
115
+ interface PopupHandle {
116
+ postMessage(message: HostToPopup, targetOrigin: string): void;
117
+ close(): void;
118
+ readonly closed: boolean;
119
+ }
120
+ /** Opens a popup window. Defaults to `window.open(url, '_blank', features)`. */
121
+ type PopupOpener = (url: string, features?: string) => PopupHandle | null;
122
+ /**
123
+ * Subscriber for inbound messages on the host side. Both event.origin and
124
+ * event.data are passed through; the transport verifies origin before
125
+ * dispatching.
126
+ */
127
+ type HostMessageListener = (event: {
128
+ data: PopupToHost;
129
+ origin: string;
130
+ }) => void;
131
+ /**
132
+ * Inbound message handler on the popup side. Receives only messages whose
133
+ * origin matched the expected host origin.
134
+ */
135
+ type PopupMessageHandler<T extends HostToPopup = HostToPopup> = (message: T, meta: {
136
+ origin: string;
137
+ }) => Promise<void> | void;
138
+
139
+ interface PopupTransportOptions {
140
+ /** Expected origin of the wallet popup, e.g. 'https://wallet.example.com'. */
141
+ walletOrigin: string;
142
+ /** Defaults to `(url, features) => window.open(url, '_blank', features)`. */
143
+ openPopup?: PopupOpener;
144
+ /** Window object hosting the event listener. Defaults to `globalThis.window`. */
145
+ hostWindow?: Window;
146
+ /** Default per-request timeout. Defaults to 60_000 ms. */
147
+ defaultTimeoutMs?: number;
148
+ }
149
+ /**
150
+ * Host-side popup transport. Spec §5.
151
+ *
152
+ * Use one `PopupTransport` instance per `EmbedWallet`. The instance owns a
153
+ * single popup window at a time, opens it on demand, auto-reopens on the next
154
+ * `request()` after it's been closed, and correlates each in-flight request
155
+ * by its message `id`.
156
+ *
157
+ * Wire handshake: every freshly opened popup must send `wallet:ready` before
158
+ * this transport will post any `HostToPopup` envelope. Without the handshake,
159
+ * `postMessage` may fire before the popup document has executed its `message`
160
+ * listener and the message is dropped. Outbound messages are queued in
161
+ * `outbox` while `popupReady === false`; `wallet:ready` flushes them.
162
+ */
163
+ declare class PopupTransport {
164
+ private readonly opts;
165
+ private popup;
166
+ private pending;
167
+ private listener;
168
+ private popupReady;
169
+ private outbox;
170
+ constructor(options: PopupTransportOptions);
171
+ request<T extends PopupToHost>(message: HostToPopup, expectedTypes: T['type'][], init?: {
172
+ timeoutMs?: number;
173
+ }): Promise<T>;
174
+ /** Close the popup if open. Pending requests will time out normally. */
175
+ close(): void;
176
+ /**
177
+ * Tear down the transport entirely. Closes the popup AND removes the host-
178
+ * window message listener. After `destroy()`, the transport instance cannot
179
+ * be reused — callers should drop the reference.
180
+ *
181
+ * Use `close()` if you only want to close the popup but keep the transport
182
+ * alive for a later re-open.
183
+ */
184
+ destroy(): void;
185
+ private ensureListening;
186
+ private onMessage;
187
+ }
188
+
189
+ interface EmbedWalletOptions {
190
+ appId: string;
191
+ /**
192
+ * Origin where the wallet SPA is deployed, e.g. `https://wallet.example.com`.
193
+ * Required for real use (the SDK opens a popup to `${walletOrigin}/embed/wallet`
194
+ * and pins postMessage to this origin) — there is no default; the constructor
195
+ * throws if it is absent. Optional only when injecting a transport via the
196
+ * `__internal__` test seam, which already carries the origin.
197
+ */
198
+ walletOrigin?: string;
199
+ popup?: {
200
+ width?: number;
201
+ height?: number;
202
+ };
203
+ /** Optional name for the appContext sent via wallet:hello. Defaults to ''. */
204
+ appName?: string;
205
+ /**
206
+ * Test seam. Injects an alternative `PopupTransport` instance. Production
207
+ * callers leave this undefined and the SDK constructs its own transport.
208
+ */
209
+ __internal__?: {
210
+ transport?: PopupTransport;
211
+ };
212
+ }
213
+
214
+ interface LoginResult {
215
+ addresses: Addresses;
216
+ credentialId: string;
217
+ }
218
+ interface DelegationScope {
219
+ capabilities: string[];
220
+ appId?: string;
221
+ agentPubkey?: string;
222
+ constraints?: Record<string, unknown>;
223
+ }
224
+ interface DelegationRequest extends DelegationScope {
225
+ ttl: string;
226
+ }
227
+ interface DelegationResult {
228
+ token: string;
229
+ expiresAt: string;
230
+ issuer: string;
231
+ }
232
+ interface SignerSpec {
233
+ chain: Chain;
234
+ }
235
+ interface ApplicationFilter {
236
+ appId?: string;
237
+ }
238
+ interface ApplicationBody {
239
+ permissions: Record<string, unknown>;
240
+ email?: string;
241
+ }
242
+ /**
243
+ * Per-app record returned by `findApplications` / `saveApplication`. Mirrors
244
+ * the `Application` shape returned by wallet-api; duplicated here so
245
+ * embed-sdk consumers don't have to depend on `@cef-ai/wallet-api-client` for a
246
+ * type.
247
+ */
248
+ interface ApplicationRecord {
249
+ appId: string;
250
+ address: string;
251
+ permissions: Record<string, unknown>;
252
+ email?: string;
253
+ }
254
+ type WalletEvent = {
255
+ type: 'login';
256
+ addresses: Addresses;
257
+ } | {
258
+ type: 'logout';
259
+ } | {
260
+ type: 'error';
261
+ code: WalletErrorCode;
262
+ message: string;
263
+ };
264
+ type WalletEventListener<T extends WalletEvent['type']> = (ev: Extract<WalletEvent, {
265
+ type: T;
266
+ }>) => void;
267
+
268
+ /**
269
+ * Public SDK class. v2.0.0. Spec §4.
270
+ *
271
+ * Drives the popup transport: every method that does meaningful work opens
272
+ * (or reuses) a popup at `walletOrigin/embed/*`, sends a `HostToPopup`
273
+ * message, awaits the matching `PopupToHost` response, and updates local
274
+ * state. See spec §5 for the wire protocol.
275
+ */
276
+ declare class EmbedWallet {
277
+ readonly appId: string;
278
+ readonly walletOrigin: string;
279
+ readonly popup: {
280
+ width: number;
281
+ height: number;
282
+ };
283
+ readonly appName: string;
284
+ private _addresses;
285
+ private _credentialId;
286
+ private _listeners;
287
+ private readonly transport;
288
+ constructor(opts: EmbedWalletOptions);
289
+ get isLoggedIn(): boolean;
290
+ get addresses(): Addresses | null;
291
+ get credentialId(): string | null;
292
+ register(opts?: {
293
+ label?: string;
294
+ }): Promise<LoginResult>;
295
+ login(): Promise<LoginResult>;
296
+ logout(): Promise<void>;
297
+ getSigner(spec: {
298
+ chain: 'evm';
299
+ }): EthersSigner;
300
+ getSigner(spec: {
301
+ chain: 'cere';
302
+ }): PolkadotSigner;
303
+ getSigner(spec: {
304
+ chain: 'solana';
305
+ }): SolanaSigner;
306
+ getSigner(spec: SignerSpec): EthersSigner | PolkadotSigner | SolanaSigner;
307
+ /**
308
+ * Expose the wallet as a chain-free `@cef-ai/signer` over the Cere
309
+ * Ed25519 key — the pluggable-signer seam `@cef-ai/account` consumes for DDC
310
+ * and `@cef-ai/chain` adapts for extrinsics.
311
+ *
312
+ * `publicKey` is recovered from the (public) Solana address — no key material
313
+ * leaves the popup's `SessionVault`. `sign(bytes, 'extrinsic', { humanReadable })`
314
+ * routes through the popup's extrinsic-consent screen.
315
+ */
316
+ asSigner(): CefSigner;
317
+ requestDelegation(req: DelegationRequest): Promise<DelegationResult>;
318
+ findApplications(filter?: ApplicationFilter): Promise<ApplicationRecord[]>;
319
+ saveApplication(body: ApplicationBody): Promise<ApplicationRecord>;
320
+ on<T extends WalletEvent['type']>(type: T, listener: WalletEventListener<T>): this;
321
+ off<T extends WalletEvent['type']>(type: T, listener: WalletEventListener<T>): this;
322
+ /**
323
+ * Tear down the wallet instance. Closes any open popup, removes transport
324
+ * listeners, clears in-memory state. Call from your app's unmount hook.
325
+ *
326
+ * After dispose(), this instance is not reusable — construct a new one.
327
+ */
328
+ dispose(): void;
329
+ private appContext;
330
+ private helloAndAwaitLogin;
331
+ private emit;
332
+ private assertLoggedIn;
333
+ }
334
+
335
+ /**
336
+ * Origin verification helpers used by both ends of the popup transport.
337
+ * Spec §5.3.
338
+ */
339
+ /**
340
+ * Schemes that we accept for origins. Production uses https only; we allow
341
+ * http here so test setups and `localhost:port` work — callers can layer
342
+ * tighter rules (e.g. "only https in production") on top.
343
+ */
344
+ declare const ALLOWED_ORIGIN_SCHEMES: readonly string[];
345
+ /**
346
+ * Strict origin equality check. Returns true iff both inputs are non-empty,
347
+ * URL-parseable, and have matching `origin` (scheme + host + port).
348
+ */
349
+ declare function isMatchingOrigin(a: string | undefined, b: string | undefined): boolean;
350
+
351
+ interface PopupHostBridgeOptions {
352
+ /** Expected origin of the host page (the page that opened this popup). */
353
+ hostOrigin: string;
354
+ /** The window this bridge runs in. Defaults to `globalThis`. */
355
+ popupWindow?: Window;
356
+ }
357
+ /**
358
+ * Popup-side bridge. Spec §5.
359
+ *
360
+ * The wallet SPA constructs one of these at boot, registers handlers via
361
+ * `on(type, fn)`, and calls `start()` to begin listening. Each inbound
362
+ * `HostToPopup` message that matches a registered handler is dispatched;
363
+ * the handler is responsible for calling `bridge.send(...)` to reply.
364
+ *
365
+ * Handlers may throw `WalletError`; the bridge automatically converts the
366
+ * throw into a `wallet:error` response keyed by the inbound message id.
367
+ */
368
+ declare class PopupHostBridge {
369
+ private readonly opts;
370
+ private readonly handlers;
371
+ private listener;
372
+ constructor(options: PopupHostBridgeOptions);
373
+ /** Register a handler for a specific message type. Replaces any prior handler. */
374
+ on<T extends HostToPopup['type']>(type: T, handler: PopupMessageHandler<Extract<HostToPopup, {
375
+ type: T;
376
+ }>>): this;
377
+ /**
378
+ * Send a `PopupToHost` message back to the opener. The bridge does not
379
+ * remember the host-window reference itself — it reads `globalThis.opener`
380
+ * each call, so it survives popup re-opens.
381
+ */
382
+ send(message: PopupToHost): void;
383
+ /**
384
+ * Start listening for inbound messages.
385
+ *
386
+ * If `announceReady` is provided, sends a `wallet:ready` message immediately.
387
+ * Use this when the popup wants to signal "I'm here" without waiting for the
388
+ * host's first call.
389
+ */
390
+ start(opts?: {
391
+ announceReady?: {
392
+ id: string;
393
+ };
394
+ }): void;
395
+ stop(): void;
396
+ private onMessage;
397
+ }
398
+
399
+ interface BroadcastSession {
400
+ edSeed: Uint8Array;
401
+ secpKey: Uint8Array;
402
+ addresses: Addresses;
403
+ /** Absolute Unix epoch ms when the session expires. */
404
+ expMs: number;
405
+ }
406
+ interface BroadcastSessionShareOptions {
407
+ /**
408
+ * Returns the local session if this tab has one to offer. Called whenever
409
+ * another tab broadcasts `request-session`.
410
+ */
411
+ getSession: () => BroadcastSession | null;
412
+ /**
413
+ * Called when another tab broadcasts a `logout` message. The local handler
414
+ * should wipe its own session.
415
+ */
416
+ onLogout?: () => void;
417
+ }
418
+ /**
419
+ * Popup-side cross-tab session sharing. Spec §5.5.
420
+ *
421
+ * - `request()`: broadcast `request-session`, wait up to 200ms for an offer.
422
+ * - `start()`: listen for incoming requests; reply with `offer-session` if we
423
+ * have a non-expired session and `getSession()` returns it.
424
+ * - `broadcastLogout()`: notify peers to wipe their sessions too.
425
+ *
426
+ * Channel name is the spec-locked `scp-wallet-v2`. Only wallet-origin popups
427
+ * join. Host pages do not participate.
428
+ */
429
+ declare class BroadcastSessionShare {
430
+ private readonly channel;
431
+ private readonly opts;
432
+ private listening;
433
+ constructor(opts: BroadcastSessionShareOptions);
434
+ /**
435
+ * Broadcast a `request-session` and wait for an `offer-session` from another
436
+ * tab. Resolves with the offered session, or null if nobody offered before
437
+ * the timeout.
438
+ */
439
+ request(opts?: {
440
+ timeoutMs?: number;
441
+ }): Promise<BroadcastSession | null>;
442
+ /** Begin offering this tab's session in response to requests, and handle logouts. */
443
+ start(): void;
444
+ stop(): void;
445
+ /** Notify peers that the user logged out. Peers wipe their sessions. */
446
+ broadcastLogout(): void;
447
+ /** Free the underlying channel handle. Call from unload handlers. */
448
+ close(): void;
449
+ private onMessage;
450
+ }
451
+
452
+ export { ALLOWED_ORIGIN_SCHEMES, type AppContext, type ApplicationBody, type ApplicationFilter, type ApplicationRecord, BROADCAST_CHANNEL_NAME, type BroadcastChannelMessage, type BroadcastSession, BroadcastSessionShare, type BroadcastSessionShareOptions, type CefSigner, type DelegationRequest, type DelegationResult, type DelegationScope, EmbedWallet, type EmbedWalletOptions, type HostMessageListener, type HostToPopup, type LoginResult, type PopupHandle, PopupHostBridge, type PopupHostBridgeOptions, type PopupMessageHandler, type PopupOpener, type PopupToHost, PopupTransport, type PopupTransportOptions, type SignIntent, type SignerSpec, type SignerType, type WalletEvent, type WalletEventListener, isMatchingOrigin };