@enbox/browser 0.3.44 → 0.3.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/web-features.ts", "../src/drl-url-parser.ts", "../src/ui/connect-modal.ts", "../src/ui/wallet-icon.ts", "../src/dweb-connect-client.ts", "../src/dweb-connect-messages.ts", "../src/ui/qr.ts", "../src/ui/wallet-well-known.ts", "../src/relay-connect-runner.ts", "../src/browser-connect-handler.ts", "../src/dweb-connect-wallet.ts"],
4
- "sourcesContent": ["/**\n * @enbox/browser \u2014 The Enbox browser SDK.\n *\n * For browser-based dapps, this is the only package you need to import.\n * It re-exports the high-level API from `@enbox/api`, the authentication\n * layer from `@enbox/auth`, and provides browser-specific connect handlers.\n *\n * @example Single-import dapp setup\n * ```ts\n * import {\n * Enbox, BrowserConnectHandler,\n * defineProtocol, repository,\n * } from '@enbox/browser';\n *\n * const { enbox, session } = await Enbox.connect({\n * connectHandler: BrowserConnectHandler({ appName: 'My App' }),\n * protocols: [MyProtocol],\n * });\n * ```\n *\n * For non-browser environments (Node.js, CLI, desktop), import from\n * `@enbox/api` and `@enbox/auth` directly instead.\n *\n * @packageDocumentation\n */\n\n// \u2500\u2500\u2500 Re-exports from @enbox/api \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The high-level Enbox API: DWN records, protocols, repositories.\n\nexport {\n Enbox,\n defineProtocol,\n repository,\n} from '@enbox/api';\n\nexport type {\n EnboxAnonymousOptions,\n EnboxConnectOptions,\n EnboxConnectResult,\n EnboxParams,\n EnboxSessionParams,\n} from '@enbox/api';\n\n// \u2500\u2500\u2500 Re-exports from @enbox/auth \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Authentication lifecycle, session management, connect handlers.\n\nexport {\n AuthManager,\n AuthSession,\n normalizeProtocolRequests,\n WalletConnect,\n} from '@enbox/auth/browser';\n\nexport type {\n AuthEvent,\n AuthEventHandler,\n AuthManagerOptions,\n AuthState,\n ConnectHandler,\n ConnectOptions,\n ConnectResult,\n DisconnectOptions,\n HandlerConnectOptions,\n ImportFromPortableOptions,\n VaultConnectOptions,\n Permission,\n PortableIdentity,\n ProtocolRequest,\n RegistrationOptions,\n StorageAdapter,\n SyncOption,\n WalletConnectOptions,\n} from '@enbox/auth/browser';\n\n// \u2500\u2500\u2500 Re-exports from @enbox/connect \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The connect kernel pieces wallet apps need alongside the popup\n// transports: opening/sealing envelopes and the deny token.\n\nexport { CONNECT_DENIED_TOKEN, ConnectProvider } from '@enbox/connect';\nexport type { ConnectApproval, ConnectPermissionRequest, ConnectRequest } from '@enbox/connect';\n\n// \u2500\u2500\u2500 Browser-specific exports \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// DWeb Connect popup transports, wallet selector, DRL polyfills.\n\nexport * from './web-features.js';\nexport { BrowserConnectHandler, DEFAULT_WALLETS } from './browser-connect-handler.js';\nexport type { BrowserConnectHandlerOptions, WalletOption } from './browser-connect-handler.js';\nexport { connectViaPopup, PopupClientTransport, PopupWindowClosedError } from './dweb-connect-client.js';\nexport type { PopupClientTransportOptions, PopupConnectOptions } from './dweb-connect-client.js';\nexport { WalletPostMessageTransport } from './dweb-connect-wallet.js';\nexport type { WalletPostMessageTransportOptions } from './dweb-connect-wallet.js';\nexport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_PATH,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n} from './dweb-connect-messages.js';\nexport type {\n DWebConnectLoadedMessage,\n DWebConnectRequestMessage,\n DWebConnectResponseMessage,\n} from './dweb-connect-messages.js';\nexport { fetchWalletWellKnown, probeWalletWellKnown, WALLET_WELL_KNOWN_PATH } from './ui/wallet-well-known.js';\nexport type { WalletWellKnownDocument } from './ui/wallet-well-known.js';\nexport { discoverWalletConnectServerUrl, runConnectModal } from './ui/connect-modal.js';\nexport type { ConnectMethod, ConnectModalDeps, ConnectModalOptions } from './ui/connect-modal.js';\nexport { MAX_PIN_ATTEMPTS, RelayConnectCancelledError, runRelayConnect } from './relay-connect-runner.js';\nexport type { RelayConnectOptions } from './relay-connect-runner.js';\nexport { encodeQr, qrToSvg } from './ui/qr.js';\nexport type { QrCode, QrSvgOptions } from './ui/qr.js';\n\n// \u2500\u2500\u2500 Convenience re-exports for dapps \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// So that most browser dapps only need `@enbox/browser` (plus\n// `@enbox/protocols` for shared protocol definitions). These surface the\n// symbols dapps most commonly reached into sibling packages for; anything\n// more specialized is still available by importing the underlying package\n// directly.\n\n// Typed record wrapper (from @enbox/api).\nexport { TypedRecord } from '@enbox/api';\n\n// Custom storage adapter + DWN registration provider-auth callback shapes\n// (from @enbox/auth).\nexport { BrowserStorage } from '@enbox/auth/browser';\nexport type { ProviderAuthParams, ProviderAuthResult } from '@enbox/auth/browser';\n\n// DWN interface enum for typing agent requests (from @enbox/agent).\nexport { DwnInterface } from '@enbox/agent';\n\n// Common DWN primitives for record queries, permission scopes, and protocol\n// typing (from @enbox/dwn-sdk-js).\nexport { DateSort, DwnInterfaceName, DwnMethodName } from '@enbox/dwn-sdk-js';\nexport type { ProtocolActionRule, ProtocolDefinition } from '@enbox/dwn-sdk-js';\n", "/*\n This file is run in dual environments to make installation of the Service Worker code easier.\n Be mindful that code placed in any open excution space may be evaluated multiple times in different contexts,\n so take care to gate additions to only activate code in the right env, such as a Service Worker scope or page window.\n*/\n\nimport type { DidMethodResolver } from '@enbox/dids';\n\nimport { DidDht, DidWeb, UniversalResolver } from '@enbox/dids';\n\n/**\n * Result returned by the `onCacheCheck` callback.\n * When returned, it signals that the response for the given DRL should be cached.\n */\nexport type CacheCheckResult = {\n /** Time-to-live for the cached DRL response, in milliseconds. */\n ttl?: number;\n};\n\n/**\n * Callback invoked to determine whether a DRL response should be cached and for how long.\n * Returning a truthy `CacheCheckResult` opts in to caching; returning a falsy value skips it.\n */\nexport type CacheCheckCallback = (\n event: FetchEvent | Event,\n drl: string,\n) => CacheCheckResult | undefined | null | Promise<CacheCheckResult | undefined | null>;\n\n/**\n * Configuration options for {@link activatePolyfills}.\n */\nexport type ActivatePolyfillsOptions = {\n /**\n * Path to the script to register as a Service Worker.\n * Falls back to `document.currentScript.src` or `import.meta.url`.\n *\n * **Required in strict CSP environments** where `new Function()` is blocked and `import.meta`\n * cannot be evaluated dynamically.\n */\n path?: string;\n /** Set to `false` to skip Service Worker installation. Defaults to `true`. */\n serviceWorker?: boolean;\n /** Set to `false` to skip injection of DRL loading-overlay styles. Defaults to `true`. */\n injectStyles?: boolean;\n /** Set to `false` to skip activation of DRL anchor/link click handling. Defaults to `true`. */\n links?: boolean;\n /** Callback to control per-request caching behaviour. */\n onCacheCheck?: CacheCheckCallback;\n /**\n * DID method resolvers to use for DRL resolution. Defaults to `[DidDht, DidWeb]`.\n * Pass a custom array to add or replace DID methods (e.g., `[DidDht, DidWeb, DidJwk]`).\n */\n didResolvers?: DidMethodResolver[];\n};\n\n/**\n * An `HTMLElement` that has a `src` property (e.g., `<img>`, `<video>`, `<audio>`).\n * Extended with `__src__` to stash the original DRL src during context-menu swaps.\n */\ninterface DrlMediaElement extends HTMLElement {\n src: string;\n __src__?: string;\n}\n\nlet didResolver = new UniversalResolver({ didResolvers: [DidDht, DidWeb] });\n\nimport { parseDrlUrl } from './drl-url-parser.js';\nexport { parseDrlUrl } from './drl-url-parser.js';\n\nconst httpToHttpsRegex = /^http:/;\nconst trailingSlashRegex = /\\/$/;\nconst DRL_CACHE_NAME = 'drl';\n\n/** @internal Exported for testing. Resolves DWN service endpoints from a DID. */\nexport async function getDwnEndpoints(did: string): Promise<string[]> {\n const { didDocument } = await didResolver.resolve(did);\n const endpoints = didDocument?.service?.find(\n (service) => service.type === 'DecentralizedWebNode'\n )?.serviceEndpoint;\n if (!endpoints) {return [];}\n return (Array.isArray(endpoints) ? endpoints : [endpoints]).filter(\n (url) => typeof url === 'string' && url.startsWith('http')\n );\n}\n\n/** Returns an open DRL cache, or `undefined` if the Cache API is unavailable. */\nasync function openDrlCache(): Promise<Cache | undefined> {\n if (typeof caches === 'undefined') {return undefined;}\n return caches.open(DRL_CACHE_NAME);\n}\n\n/** @internal Exported for testing. Handles a DRL fetch event. */\nexport async function handleEvent(\n event: FetchEvent, did: string, path: string, options?: ActivatePolyfillsOptions\n): Promise<Response> {\n const drl = event.request.url\n .replace(httpToHttpsRegex, 'https:')\n .replace(trailingSlashRegex, '');\n const responseCache = await openDrlCache();\n const cachedResponse = await responseCache?.match(drl);\n if (cachedResponse) {\n if (!navigator.onLine) {return cachedResponse;}\n const match = await options?.onCacheCheck?.(event, drl);\n if (match) {\n const cacheTime = cachedResponse.headers.get('dwn-cache-time');\n if (\n cacheTime &&\n Date.now() < Number(cacheTime) + (Number(match.ttl) || 0)\n ) {\n return cachedResponse;\n }\n }\n }\n try {\n if (path) {\n return await fetchResource(event, did, drl, path, responseCache, options);\n } else {\n const response = await didResolver.resolve(did);\n return new Response(JSON.stringify(response), {\n status : 200,\n headers : {\n 'Content-Type': 'application/json',\n },\n });\n }\n } catch (error) {\n if (error instanceof Response) {\n return error;\n }\n console.log(`Error in DID URL fetch: ${error}`);\n return new Response('DID URL fetch error', { status: 500 });\n }\n}\n\n/** @internal Exported for testing. Fetches a resource from DWN endpoints. */\nexport async function fetchResource(\n event: FetchEvent, did: string, drl: string, path: string,\n responseCache: Cache | undefined, options?: ActivatePolyfillsOptions\n): Promise<Response> {\n const endpoints = await getDwnEndpoints(did);\n if (!endpoints?.length) {\n throw new Response(\n 'DWeb Node resolution failed: no valid endpoints found.',\n { status: 530 }\n );\n }\n let lastError: Response | undefined;\n for (const endpoint of endpoints) {\n try {\n const url = `${endpoint.replace(trailingSlashRegex, '')}/${did}/${path}`;\n const response = await fetch(url, { headers: event.request.headers });\n if (response.ok) {\n const match = await options?.onCacheCheck?.(event, drl);\n if (match && responseCache) {\n cacheResponse(drl, url, response, responseCache);\n }\n return response;\n }\n console.log(`DWN endpoint error: ${response.status}`);\n lastError = new Response('DWeb Node request failed', {\n status: response.status,\n });\n } catch (error) {\n console.log(`DWN endpoint error: ${error}`);\n lastError = new Response('DWeb Node request failed', {\n status: 500,\n });\n }\n }\n return lastError!;\n}\n\n/** @internal Exported for testing. Caches a DRL response with metadata headers. */\nexport async function cacheResponse(drl: string, url: string, response: Response, cache: Cache): Promise<void> {\n try {\n const clonedResponse = response.clone();\n const headers = new Headers(clonedResponse.headers);\n headers.append('dwn-cache-time', Date.now().toString());\n headers.append('dwn-composed-url', url);\n const modifiedResponse = new Response(clonedResponse.body, { headers });\n await cache.put(drl, modifiedResponse);\n } catch (error) {\n console.log(`Failed to cache DRL response: ${error}`);\n }\n}\n\n/* Service Worker-based features */\n\nasync function installWorker(options: ActivatePolyfillsOptions = {}): Promise<void> {\n try {\n // Check to see if we are in a Service Worker already, if so, proceed\n // You can call the activatePolyfills() function in your own worker, or standalone as a root worker\n if (\n typeof ServiceWorkerGlobalScope !== 'undefined' &&\n self instanceof ServiceWorkerGlobalScope\n ) {\n const workerSelf = self as unknown as ServiceWorkerGlobalScope;\n workerSelf.skipWaiting();\n workerSelf.addEventListener('activate', (event: ExtendableEvent) => {\n // Claim clients to make the service worker take control immediately\n event.waitUntil(workerSelf.clients.claim());\n });\n workerSelf.addEventListener('fetch', (event: FetchEvent) => {\n const parsed = parseDrlUrl(event.request.url);\n if (parsed) {\n event.respondWith(handleEvent(event, parsed[0], parsed[1], options));\n }\n });\n }\n // If the code gets here, it is not a SW env, it is likely DOM, but check to be sure\n else if (globalThis?.navigator?.serviceWorker) {\n const registration = await navigator.serviceWorker.getRegistration('/');\n // You can only have one worker per path, so check to see if one is already registered\n if (!registration) {\n const installUrl: string | undefined =\n options.path ||\n (document?.currentScript as HTMLScriptElement | null)?.src ||\n import.meta.url;\n if (installUrl)\n {navigator.serviceWorker\n .register(installUrl, { type: 'module' })\n .catch((error: unknown) => {\n console.error(\n 'DWeb networking feature installation failed: ',\n error\n );\n });}\n }\n } else {\n throw new Error(\n 'DWeb networking features are not available for install in this environment'\n );\n }\n } catch (error) {\n console.error('Error in installing networking features:', error);\n }\n}\n\n/* DOM Environment Features */\n\nconst loaderStyles = `\n .drl-loading-overlay {\n position: fixed;\n inset: 0;\n display: flex;\n flex-wrap: wrap;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: 22px;\n color: #fff;\n background: rgba(0, 0, 0, 0.75);\n backdrop-filter: blur(15px);\n -webkit-backdrop-filter: blur(15px);\n z-index: 1000000;\n }\n\n .drl-loading-overlay > div {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .drl-loading-spinner {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .drl-loading-spinner div {\n position: relative;\n width: 2em;\n height: 2em;\n margin: 0.1em 0.25em 0 0;\n }\n .drl-loading-spinner div::after,\n .drl-loading-spinner div::before {\n content: ''; \n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 0.1em solid #FFF;\n position: absolute;\n left: 0;\n top: 0;\n opacity: 0;\n animation: drl-loading-spinner 2s linear infinite;\n }\n .drl-loading-spinner div::after {\n animation-delay: 1s;\n }\n\n .drl-loading-overlay span {\n --text-opacity: 2;\n display: flex;\n align-items: center;\n margin: 2em auto 0;\n padding: 0.2em 0.75em 0.25em;\n text-align: center;\n border-radius: 5em;\n background: rgba(255 255 255 / 8%);\n opacity: 0.8;\n transition: opacity 0.3s ease;\n cursor: pointer;\n }\n\n .drl-loading-overlay span:focus {\n opacity: 1;\n }\n\n .drl-loading-overlay span:hover {\n opacity: 1;\n }\n\n .drl-loading-overlay span::before {\n content: '\u2715 ';\n margin: 0 0.4em 0 0;\n color: red;\n font-size: 65%;\n font-weight: bold;\n }\n\n .drl-loading-overlay span::after {\n content: 'stop';\n display: block;\n font-size: 60%;\n line-height: 0;\n color: rgba(255 255 255 / 60%);\n }\n\n .drl-loading-overlay.new-tab-overlay span::after {\n content: 'close';\n }\n \n @keyframes drl-loading-spinner {\n 0% {\n transform: scale(0);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n opacity: 0;\n }\n }\n`;\nconst tabContent = `\n<!DOCTYPE html>\n<html lang='en'>\n<head>\n <meta charset='UTF-8'>\n <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n <title>Loading DRL...</title>\n <style>\n html, body {\n background-color: #151518;\n height: 100%;\n margin: 0;\n padding: 0;\n font-family: Arial, sans-serif;\n text-align: center;\n }\n ${loaderStyles}\n </style>\n</head>\n<body>\n <div class='drl-loading-overlay new-tab-overlay'>\n <div class='drl-loading-spinner'>\n <div></div>\n Loading DRL\n </div>\n <span onclick='window.close()' tabindex='0'></span>\n </div>\n</body>\n</html>\n`;\n\nlet elementsInjected = false;\nlet overlayElement: HTMLDivElement | null = null;\nlet styleElement: HTMLStyleElement | null = null;\n\nfunction injectElements(): void {\n if (elementsInjected) {return;}\n styleElement = document.createElement('style');\n styleElement.innerHTML = `\n ${loaderStyles}\n\n .drl-loading-overlay {\n opacity: 0;\n transition: opacity 0.3s ease;\n pointer-events: none;\n }\n\n :root[drl-link-loading] .drl-loading-overlay {\n opacity: 1;\n pointer-events: all;\n }\n `;\n document.head.append(styleElement);\n\n overlayElement = document.createElement('div');\n overlayElement.classList.add('drl-loading-overlay');\n overlayElement.innerHTML = `\n <div class='drl-loading-spinner'>\n <div></div>\n Loading DRL\n </div> \n <span tabindex='0'></span>\n `;\n overlayElement.lastElementChild!.addEventListener('click', cancelNavigation);\n document.body.prepend(overlayElement);\n elementsInjected = true;\n}\n\nfunction removeElements(): void {\n if (!elementsInjected) {return;}\n styleElement?.remove();\n styleElement = null;\n overlayElement?.remove();\n overlayElement = null;\n elementsInjected = false;\n}\n\nfunction cancelNavigation(): void {\n document.documentElement.removeAttribute('drl-link-loading');\n activeNavigation = null;\n}\n\nlet activeNavigation: string | null = null;\nlet linkFeaturesActive = false;\n\n// Stored references for listener cleanup in deactivatePolyfills()\nlet clickHandler: ((event: MouseEvent) => Promise<void>) | null = null;\nlet pointerdownHandler: ((event: PointerEvent) => Promise<void>) | null = null;\n\nfunction addLinkFeatures(): void {\n if (!linkFeaturesActive) {\n clickHandler = async (event: MouseEvent): Promise<void> => {\n const anchor = (event.target as Element)?.closest('a');\n if (anchor) {\n const href = anchor.href;\n const parsed = parseDrlUrl(href);\n if (parsed) {\n const did = parsed[0];\n const path = parsed[1];\n const openAsTab = anchor.target === '_blank';\n event.preventDefault();\n try {\n let tab: Window | null = null;\n if (openAsTab) {\n tab = window.open('', '_blank');\n if (tab) {tab.document.write(tabContent);}\n } else {\n activeNavigation = path;\n // this is to allow for cached DIDs to instantly load without any flash of loading UI\n setTimeout(\n () =>\n document.documentElement.setAttribute('drl-link-loading', ''),\n 50\n );\n }\n const endpoints = await getDwnEndpoints(did);\n if (!endpoints.length) {\n throw new Error('no valid DWN endpoints found');\n }\n const url = `${endpoints[0].replace(\n trailingSlashRegex,\n ''\n )}/${did}/${path}`;\n if (openAsTab) {\n if (tab && !tab.closed) {tab.location.href = url;}\n } else if (activeNavigation === path) {\n window.location.href = url;\n }\n } catch {\n if (activeNavigation === path) {\n cancelNavigation();\n }\n throw new Error(\n `DID endpoint resolution failed for the DRL: ${href}`\n );\n }\n }\n }\n };\n\n pointerdownHandler = async (event: PointerEvent): Promise<void> => {\n const target = event.composedPath()[0] as DrlMediaElement | undefined;\n if (\n (event.pointerType === 'mouse' && event.button === 2) ||\n (event.pointerType === 'touch' && event.isPrimary)\n ) {\n resetContextMenuTarget();\n if (target?.src && parseDrlUrl(target.src)) {\n contextMenuTarget = target;\n target.__src__ = target.src;\n const drl = target.src\n .replace(httpToHttpsRegex, 'https:')\n .replace(trailingSlashRegex, '');\n const responseCache = await openDrlCache();\n const response = await responseCache?.match(drl);\n if (response) {\n const url = response.headers.get('dwn-composed-url');\n if (url) {target.src = url;}\n }\n target.addEventListener('pointerup', resetContextMenuTarget, {\n once: true,\n });\n }\n } else if (target === contextMenuTarget) {\n resetContextMenuTarget();\n }\n };\n\n document.addEventListener('click', clickHandler);\n document.addEventListener('pointercancel', resetContextMenuTarget);\n document.addEventListener('pointerdown', pointerdownHandler);\n\n linkFeaturesActive = true;\n }\n}\n\nfunction removeLinkFeatures(): void {\n if (!linkFeaturesActive) {return;}\n if (clickHandler) {\n document.removeEventListener('click', clickHandler);\n clickHandler = null;\n }\n if (pointerdownHandler) {\n document.removeEventListener('pointerdown', pointerdownHandler);\n pointerdownHandler = null;\n }\n document.removeEventListener('pointercancel', resetContextMenuTarget);\n resetContextMenuTarget();\n cancelNavigation();\n linkFeaturesActive = false;\n}\n\nlet contextMenuTarget: DrlMediaElement | null = null;\nasync function resetContextMenuTarget(e?: Event): Promise<void> {\n if (e?.type === 'pointerup') {\n await new Promise<void>((r) => requestAnimationFrame(() => r()));\n }\n if (contextMenuTarget) {\n contextMenuTarget.src = contextMenuTarget.__src__!;\n delete contextMenuTarget.__src__;\n contextMenuTarget = null;\n }\n}\n\n/**\n * Activates various polyfills to enable Enbox features in Web environments.\n *\n * @param options - Configuration options to control the activation of polyfills.\n *\n * @example\n * // Activate all polyfills with default options, and cache every DRL for 1 minute\n * activatePolyfills({\n * onCacheCheck(event, route){\n * return {\n * ttl: 60_000\n * }\n * }\n * });\n *\n * @example\n * // Activate polyfills, but without Service Worker activation\n * activatePolyfills({ serviceWorker: false });\n *\n * @example\n * // Use custom DID resolvers\n * activatePolyfills({ didResolvers: [DidDht, DidWeb, DidJwk] });\n */\nexport function activatePolyfills(options: ActivatePolyfillsOptions = {}): void {\n if (options.didResolvers) {\n didResolver = new UniversalResolver({ didResolvers: options.didResolvers });\n }\n if (options.serviceWorker !== false) {\n installWorker(options);\n }\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n if (options.injectStyles !== false) {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', injectElements, {\n once: true,\n });\n } else {injectElements();}\n }\n if (options.links !== false) {addLinkFeatures();}\n }\n}\n\n/**\n * Removes all polyfill event listeners, injected DOM elements, and resets internal state.\n * Call this to fully clean up after {@link activatePolyfills}.\n *\n * Does **not** unregister an installed Service Worker \u2014 use\n * `navigator.serviceWorker.getRegistration('/').then(r => r?.unregister())` for that.\n */\nexport function deactivatePolyfills(): void {\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n removeLinkFeatures();\n removeElements();\n }\n}\n\n/**\n * Deletes the entire DRL response cache.\n * Useful for clearing stale cached DWN responses.\n *\n * @returns `true` if the cache existed and was deleted, `false` otherwise.\n * Returns `false` if the Cache API is unavailable.\n */\nexport async function clearDrlCache(): Promise<boolean> {\n if (typeof caches === 'undefined') {return false;}\n return caches.delete(DRL_CACHE_NAME);\n}\n", "/**\n * Parses a DRL URL (http(s)://dweb/{did}/{path}) without regex quantifiers.\n * Returns `[did, path]` or `null` if the URL does not match the DRL scheme.\n *\n * Extracted to a standalone module so it can be tested under Node.js (bun:test)\n * in addition to the browser-based vitest suite, ensuring SonarCloud's\n * merged coverage report includes these lines.\n */\nexport function parseDrlUrl(url: string): [string, string] | null {\n const idx = url.indexOf('://dweb/');\n if (idx === -1) { return null; }\n const prefix = url.slice(0, idx);\n if (prefix !== 'http' && prefix !== 'https') { return null; }\n const rest = url.slice(idx + 8); // '://dweb/'.length === 8\n if (rest.length === 0) { return null; }\n const slashIdx = rest.indexOf('/');\n if (slashIdx === -1) { return [rest, '']; }\n if (slashIdx === 0) { return null; } // DID segment must be non-empty\n return [rest.slice(0, slashIdx), rest.slice(slashIdx + 1)];\n}\n", "/**\n * Connect modal \u2014 the single surface that owns a whole connect session.\n *\n * One Shadow-DOM dialog whose stage morphs in place through the session:\n * QR (phone path) \u2192 pairing code \u2192 connected, with the in-browser popup\n * path and the wallet catalog folded in as in-place alternates. The modal\n * never chains into a second modal and stays mounted until the session\n * resolves (connected / denied / cancelled).\n *\n * Layout: three zones \u2014\n *\n * 1. **Header** \u2014 requesting app identity + close.\n * 2. **Stage** \u2014 a height-stable region where states crossfade: the QR\n * (or deep link on phones), the pairing-code input, progress, success,\n * and error states.\n * 3. **Footer** \u2014 the alternate-method link and the wallet switcher\n * disclosure (catalog + custom URL \u2014 the entire legacy selector,\n * demoted to an option).\n *\n * The phone path drives the `@enbox/connect` relay transport via\n * {@link runRelayConnect}; the browser path drives the popup transport via\n * the kernel `ConnectClient`. Wallet `connectServerUrl`s are discovered\n * from each wallet's `/.well-known/enbox-connect` document unless\n * overridden.\n *\n * @module\n */\n\nimport type { WalletOption } from '../browser-connect-handler.js';\nimport type { ConnectPermissionRequest, ConnectResult, WalletUriHandoff } from '@enbox/connect';\n\nimport { ConnectClient } from '@enbox/connect';\n\nimport { buildWalletIcon } from './wallet-icon.js';\nimport {\n collectBrowserClientMetadata,\n PopupClientTransport,\n PopupWindowClosedError,\n} from '../dweb-connect-client.js';\nimport { encodeQr, qrToSvg } from './qr.js';\nimport { fetchWalletWellKnown, probeWalletWellKnown } from './wallet-well-known.js';\nimport { RelayConnectCancelledError, runRelayConnect } from '../relay-connect-runner.js';\n\n/** How the user carries out the approval. */\nexport type ConnectMethod = 'phone' | 'browser';\n\n/** localStorage key remembering the last successful method + wallet. */\nconst LAST_CHOICE_STORAGE_KEY = 'enbox:connect:lastChoice';\n\n/** Safety margin subtracted from the relay pointer TTL before re-minting. */\nconst REMINT_SAFETY_MS = 30_000;\n\n/** Minimum delay before an automatic re-mint. */\nconst REMINT_MIN_MS = 10_000;\n\n/** Pairing code length (matches the wallet's generated PIN). */\nconst PIN_LENGTH = 4;\n\n/** Options for {@link runConnectModal}. */\nexport interface ConnectModalOptions {\n /** Wallet catalog shown in the wallet switcher. */\n wallets?: WalletOption[];\n\n /**\n * Explicit wallet URL: hides the catalog switcher and uses this wallet\n * for both methods.\n */\n walletUrl?: string;\n\n /** Preferred method on open; overrides the remembered choice. */\n preferredMethod?: ConnectMethod;\n\n /**\n * Remember the successful method + wallet in localStorage and pre-shape\n * the next session accordingly.\n * @default true\n */\n rememberChoice?: boolean;\n\n /** Display name of the requesting application. */\n appName?: string;\n\n /** Icon URL of the requesting application. */\n appIcon?: string;\n\n /**\n * Relay base URL override for the phone path. When omitted, each wallet's\n * `connectServerUrl` is discovered from its `/.well-known/enbox-connect`\n * document.\n */\n connectServerUrl?: string;\n\n /**\n * Path appended to the wallet origin to form the QR / deep-link target.\n * @default '/connect/app'\n */\n relayWalletPath?: string;\n\n /** Timeout in milliseconds for either method's handshake. */\n timeout?: number;\n\n /** DWN protocols and permission scopes being requested. */\n permissionRequests: ConnectPermissionRequest[];\n\n /** Internal dependency seams (tests). */\n deps?: Partial<ConnectModalDeps>;\n}\n\n/** Injectable collaborators, defaulted to the real implementations. */\nexport interface ConnectModalDeps {\n /** Runs one relay handshake (phone path). */\n runRelay: typeof runRelayConnect;\n\n /** Runs one popup handshake (browser path); must open the popup synchronously. */\n runPopup: (options: {\n walletUrl: string;\n permissionRequests: ConnectPermissionRequest[];\n appName: string;\n appIcon?: string;\n timeoutMs?: number;\n }) => Promise<ConnectResult | undefined>;\n\n /** Resolves a wallet origin to its relay `connectServerUrl` (or undefined). */\n discoverConnectServerUrl: (walletOrigin: string) => Promise<string | undefined>;\n\n /** Validates a pasted custom wallet URL. */\n validateWalletUrl: (origin: string) => Promise<boolean>;\n\n /** Whether to present the deep-link (same-device) variant of the phone path. */\n isMobile: () => boolean;\n\n /** Persistence for the remembered choice. */\n storage: Pick<Storage, 'getItem' | 'setItem' | 'removeItem'> | undefined;\n}\n\n/**\n * Resolves a wallet origin to its relay `connectServerUrl` via the wallet's\n * `/.well-known/enbox-connect` document ({@link fetchWalletWellKnown} \u2014 the\n * same machinery the wallet selector uses for custom-URL validation).\n */\nexport async function discoverWalletConnectServerUrl(walletOrigin: string): Promise<string | undefined> {\n return (await fetchWalletWellKnown(walletOrigin))?.connectServerUrl;\n}\n\n/** Runs one popup handshake without collapsing early-close into a denial. */\nasync function runPopupConnect(options: {\n walletUrl: string;\n permissionRequests: ConnectPermissionRequest[];\n appName: string;\n appIcon?: string;\n timeoutMs?: number;\n}): Promise<ConnectResult | undefined> {\n // The transport constructor calls `window.open` synchronously \u2014 callers\n // must invoke this inside the user-gesture call stack.\n const transport = new PopupClientTransport({\n walletUrl : options.walletUrl,\n timeoutMs : options.timeoutMs,\n });\n const client = new ConnectClient({ transport });\n\n return await client.connect({\n appName : options.appName,\n appIcon : options.appIcon,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n });\n}\n\nfunction defaultIsMobile(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n const coarse = window.matchMedia?.('(pointer: coarse)').matches ?? false;\n return coarse && Math.min(window.innerWidth, window.innerHeight) < 900;\n}\n\nfunction defaultDeps(): ConnectModalDeps {\n return {\n runRelay : runRelayConnect,\n runPopup : runPopupConnect,\n discoverConnectServerUrl : discoverWalletConnectServerUrl,\n validateWalletUrl : probeWalletWellKnown,\n isMobile : defaultIsMobile,\n storage : typeof localStorage === 'undefined' ? undefined : localStorage,\n };\n}\n\n/** Remembered method + wallet from a previous successful session. */\ninterface LastChoice {\n method: ConnectMethod;\n walletUrl: string;\n}\n\nfunction readLastChoice(storage: ConnectModalDeps['storage']): LastChoice | undefined {\n try {\n const raw = storage?.getItem(LAST_CHOICE_STORAGE_KEY);\n if (raw == null) {\n return undefined;\n }\n const parsed = JSON.parse(raw) as Partial<LastChoice>;\n if ((parsed.method === 'phone' || parsed.method === 'browser') && typeof parsed.walletUrl === 'string') {\n return { method: parsed.method, walletUrl: parsed.walletUrl };\n }\n } catch { /* unreadable storage \u2014 behave as first visit */ }\n return undefined;\n}\n\nfunction writeLastChoice(storage: ConnectModalDeps['storage'], choice: LastChoice): void {\n try {\n storage?.setItem(LAST_CHOICE_STORAGE_KEY, JSON.stringify(choice));\n } catch { /* best effort */ }\n}\n\n/** One cancellable relay session. */\ninterface RelaySession {\n cancelled: Promise<never>;\n cancel: () => void;\n active: boolean;\n}\n\nfunction createRelaySession(): RelaySession {\n let cancel!: () => void;\n const session: Partial<RelaySession> = { active: true };\n const cancelled = new Promise<never>((_, reject) => {\n cancel = (): void => {\n if (session.active === true) {\n session.active = false;\n reject(new RelayConnectCancelledError());\n }\n };\n });\n // Mark handled so an unconsumed cancellation never surfaces as unhandled.\n cancelled.catch((): undefined => undefined);\n session.cancelled = cancelled;\n session.cancel = cancel;\n return session as RelaySession;\n}\n\n/**\n * Opens the connect modal and resolves when the session ends.\n *\n * @returns The delegated credentials; `undefined` when the user denied the\n * request in the wallet (or dismissed after a denial).\n * @throws When the user cancels the modal, or the session fails and the\n * user dismisses the error.\n */\nexport function runConnectModal(options: ConnectModalOptions): Promise<ConnectResult | undefined> {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new Error('[@enbox/browser] The connect modal is only available in browser environments.');\n }\n\n const deps: ConnectModalDeps = { ...defaultDeps(), ...options.deps };\n const wallets = options.wallets ?? [];\n const rememberChoice = options.rememberChoice ?? true;\n const appName = options.appName ?? window.location.host;\n const relayWalletPath = options.relayWalletPath ?? '/connect/app';\n const isMobile = deps.isMobile();\n\n const lastChoice = rememberChoice ? readLastChoice(deps.storage) : undefined;\n\n // Wallet resolution order: explicit option \u2192 remembered \u2192 catalog head.\n const lockedWallet = options.walletUrl !== undefined;\n let walletUrl = options.walletUrl\n ?? (lastChoice !== undefined && (lockedWallet || walletInCatalog(wallets, lastChoice.walletUrl)) ? lastChoice.walletUrl : undefined)\n ?? wallets[0]?.url;\n\n // Method resolution order: explicit option \u2192 remembered \u2192 phone.\n let method: ConnectMethod = options.preferredMethod ?? lastChoice?.method ?? 'phone';\n\n return new Promise<ConnectResult | undefined>((resolve, reject) => {\n // \u2500\u2500 Host + shadow root \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const host = document.createElement('div');\n host.id = 'enbox-connect-modal';\n const shadow = host.attachShadow({ mode: 'open' });\n\n const isDark = window.matchMedia?.('(prefers-color-scheme: dark)').matches ?? false;\n const style = document.createElement('style');\n style.textContent = buildStyles(isDark);\n shadow.appendChild(style);\n\n const overlay = document.createElement('div');\n overlay.className = 'overlay';\n const modal = document.createElement('div');\n modal.className = 'modal';\n modal.setAttribute('role', 'dialog');\n modal.setAttribute('aria-modal', 'true');\n modal.setAttribute('aria-label', `Connect to ${appName}`);\n\n // \u2500\u2500 Session state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let settled = false;\n let relaySession: RelaySession | undefined;\n let remintTimer: ReturnType<typeof setTimeout> | undefined;\n let popupBusy = false;\n let pinResolve: ((pin: string) => void) | undefined;\n const discoveryCache = new Map<string, Promise<string | undefined>>();\n\n const cleanup = (): void => {\n relaySession?.cancel();\n clearTimeout(remintTimer);\n document.removeEventListener('keydown', onKeydown);\n try { document.body.removeChild(host); } catch { /* best effort */ }\n };\n\n const settle = (settler: () => void): void => {\n if (settled) { return; }\n settled = true;\n cleanup();\n settler();\n };\n\n const succeed = (result: ConnectResult): void => {\n if (rememberChoice) {\n writeLastChoice(deps.storage, { method, walletUrl: walletUrl ?? '' });\n }\n renderConnected();\n const finish = (): void => settle(() => resolve(result));\n setTimeout(finish, 1_200);\n };\n\n const cancelModal = (): void => settle(() => reject(new Error('[@enbox/browser] Connect cancelled.')));\n\n // \u2500\u2500 Zones \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n modal.appendChild(buildHeader(appName, options.appIcon, cancelModal));\n\n const stage = document.createElement('div');\n stage.className = 'stage';\n stage.setAttribute('aria-live', 'polite');\n modal.appendChild(stage);\n\n const footer = document.createElement('div');\n footer.className = 'footer';\n modal.appendChild(footer);\n\n // \u2500\u2500 Stage renderers (all render in place; nothing navigates) \u2500\u2500\n const setStage = (...nodes: (HTMLElement | SVGElement)[]): void => {\n stage.replaceChildren(...nodes);\n stage.classList.remove('fade-in');\n void stage.offsetWidth; // restart the transition\n stage.classList.add('fade-in');\n };\n\n const renderBusy = (message: string): void => {\n setStage(el('div', 'spinner'), el('p', 'stage-caption', message));\n };\n\n const renderQr = (handoff: WalletUriHandoff): void => {\n if (isMobile) {\n const link = document.createElement('a');\n link.className = 'deep-link';\n link.href = handoff.walletUri;\n link.textContent = 'Continue in your wallet';\n setStage(\n link,\n el('p', 'stage-caption', 'Your wallet opens to approve this connection.'),\n el('p', 'stage-subline', 'Come back here when you\u2019re done.'),\n );\n return;\n }\n\n const qrBox = document.createElement('div');\n qrBox.className = 'qr-box';\n qrBox.replaceChildren(qrToSvg(encodeQr(handoff.walletUri), {\n dark : isDark ? '#e8e8f0' : '#14141f',\n light : 'transparent',\n quietZone : 2,\n }));\n\n setStage(\n qrBox,\n el('p', 'stage-caption', 'Scan with your phone\u2019s camera'),\n el('p', 'stage-subline', 'Your wallet stays on your phone, so you can approve things anywhere.'),\n );\n };\n\n const renderPin = (attempt: number, previousError?: Error): Promise<string> => {\n return new Promise<string>((resolvePin) => {\n pinResolve = resolvePin;\n\n const boxes = document.createElement('div');\n boxes.className = 'pin-row';\n if (previousError !== undefined) {\n boxes.classList.add('shake');\n }\n\n const inputs: HTMLInputElement[] = [];\n for (let i = 0; i < PIN_LENGTH; i++) {\n const input = document.createElement('input');\n input.className = 'pin-input';\n input.type = 'text';\n input.inputMode = 'numeric';\n input.maxLength = 1;\n input.setAttribute('aria-label', `Code digit ${i + 1}`);\n inputs.push(input);\n boxes.appendChild(input);\n }\n\n const submitIfComplete = (): void => {\n const code = inputs.map((i) => i.value).join('');\n if (code.length === PIN_LENGTH && pinResolve !== undefined) {\n const resolveOnce = pinResolve;\n pinResolve = undefined;\n renderBusy('Checking the code\u2026');\n resolveOnce(code);\n }\n };\n\n inputs.forEach((input, index) => {\n input.addEventListener('input', () => {\n input.value = input.value.replace(/\\D/g, '').slice(0, 1);\n if (input.value !== '' && index + 1 < inputs.length) {\n inputs[index + 1].focus();\n }\n submitIfComplete();\n });\n input.addEventListener('keydown', (event) => {\n if (event.key === 'Backspace' && input.value === '' && index > 0) {\n inputs[index - 1].focus();\n }\n });\n input.addEventListener('paste', (event) => {\n const digits = (event.clipboardData?.getData('text') ?? '').replace(/\\D/g, '').slice(0, PIN_LENGTH);\n if (digits.length === 0) { return; }\n event.preventDefault();\n digits.split('').forEach((digit, digitIndex) => {\n if (inputs[digitIndex] !== undefined) {\n inputs[digitIndex].value = digit;\n }\n });\n inputs[Math.min(digits.length, PIN_LENGTH) - 1]?.focus();\n submitIfComplete();\n });\n });\n\n setStage(\n el('p', 'stage-caption', 'Enter the code shown on your phone'),\n boxes,\n ...(previousError !== undefined\n ? [el('p', 'stage-error', 'That code doesn\u2019t match \u2014 check your phone.')]\n : [el('p', 'stage-subline', attempt === 1 ? 'Phone connected.' : '')]),\n );\n\n inputs[0].focus();\n });\n };\n\n const renderConnected = (): void => {\n const check = el('div', 'check');\n check.textContent = '\u2713';\n setStage(check, el('p', 'stage-caption', 'You\u2019re connected.'));\n };\n\n const renderDenied = (): void => {\n setStage(\n el('p', 'stage-caption', 'No problem \u2014 nothing was shared.'),\n stageButton('Start over', () => { void startMethod(); }),\n stageLinkButton('Close', () => settle(() => resolve(undefined))),\n );\n };\n\n const renderError = (message: string, error?: Error): void => {\n setStage(\n el('p', 'stage-caption', message),\n stageButton('Start over', () => { void startMethod(); }),\n stageLinkButton('Close', () => settle(() => reject(error ?? new Error(`[@enbox/browser] ${message}`)))),\n );\n };\n\n const renderPhoneUnavailable = (): void => {\n setStage(\n el('p', 'stage-caption', 'This wallet can\u2019t connect by phone here.'),\n el('p', 'stage-subline', 'You can continue in this browser instead.'),\n stageButton('Use this browser', () => { startPopup(); }),\n );\n };\n\n const renderPopupPrompt = (): void => {\n setStage(\n el('p', 'stage-caption', 'Connect with a wallet in this browser'),\n el('p', 'stage-subline', 'Your wallet opens in a small window to approve this connection.'),\n stageButton('Open wallet window', () => { startPopup(); }),\n );\n };\n\n const renderPopupWaiting = (): void => {\n setStage(\n el('div', 'spinner'),\n el('p', 'stage-caption', 'Finish in the wallet window'),\n el('p', 'stage-subline', 'We\u2019ll wrap up here as soon as you\u2019re done.'),\n );\n };\n\n const renderPopupInterrupted = (blocked: boolean): void => {\n setStage(\n el('p', 'stage-caption', blocked\n ? 'Your browser blocked the wallet window.'\n : 'The wallet window was closed.'),\n stageButton(blocked ? 'Open it now' : 'Reopen window', () => { startPopup(); }),\n ...(isMobile ? [] : [stageLinkButton('Use your phone instead', () => { void switchMethod('phone'); })]),\n );\n };\n\n // \u2500\u2500 Method drivers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const resolveConnectServerUrl = async (origin: string): Promise<string | undefined> => {\n if (options.connectServerUrl !== undefined) {\n return options.connectServerUrl;\n }\n let cached = discoveryCache.get(origin);\n if (cached === undefined) {\n cached = deps.discoverConnectServerUrl(origin);\n discoveryCache.set(origin, cached);\n }\n return cached;\n };\n\n const scheduleRemint = (expiresInSeconds: number): void => {\n clearTimeout(remintTimer);\n const delay = Math.max(REMINT_MIN_MS, expiresInSeconds * 1_000 - REMINT_SAFETY_MS);\n remintTimer = setTimeout(() => {\n // Never re-mint once the wallet has responded (pairing in progress).\n if (!settled && pinResolve === undefined && method === 'phone') {\n void startPhone();\n }\n }, delay);\n };\n\n const startPhone = async (): Promise<void> => {\n relaySession?.cancel();\n clearTimeout(remintTimer);\n\n if (walletUrl === undefined) {\n renderError('No wallet is configured.');\n return;\n }\n\n method = 'phone';\n renderFooter();\n renderBusy('Getting things ready\u2026');\n\n const origin = new URL(walletUrl).origin;\n const connectServerUrl = await resolveConnectServerUrl(origin);\n if (connectServerUrl === undefined) {\n renderPhoneUnavailable();\n return;\n }\n\n const session = createRelaySession();\n relaySession = session;\n\n try {\n const result = await deps.runRelay({\n connectServerUrl,\n walletUri : new URL(relayWalletPath, origin).toString(),\n appName,\n appIcon : options.appIcon,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n timeoutMs : options.timeout,\n cancelled : session.cancelled,\n onWalletUriReady : (handoff): void => {\n if (session.active && !settled) {\n renderQr(handoff);\n scheduleRemint(handoff.expiresIn);\n }\n },\n requestPin: (attempt, previousError): Promise<string> => {\n clearTimeout(remintTimer);\n return renderPin(attempt, previousError);\n },\n });\n\n if (!session.active || settled) { return; }\n\n if (result === undefined) {\n renderDenied();\n } else {\n succeed(result);\n }\n } catch (error) {\n if (!session.active || settled || error instanceof RelayConnectCancelledError) {\n return;\n }\n const failure = error instanceof Error ? error : new Error(String(error));\n renderError(\n /timed out/i.test(failure.message)\n ? 'That took too long, so we stopped for safety.'\n : 'Something went wrong while connecting.',\n failure,\n );\n }\n };\n\n const startPopup = (): void => {\n // Synchronous popup open inside the click's call stack.\n relaySession?.cancel();\n clearTimeout(remintTimer);\n\n if (walletUrl === undefined) {\n renderError('No wallet is configured.');\n return;\n }\n if (popupBusy) { return; }\n\n method = 'browser';\n renderFooter();\n\n let flow: Promise<ConnectResult | undefined>;\n try {\n flow = deps.runPopup({\n walletUrl,\n permissionRequests : options.permissionRequests,\n appName,\n appIcon : options.appIcon,\n timeoutMs : options.timeout,\n });\n } catch (error) {\n const blocked = error instanceof Error && /popup blocked/i.test(error.message);\n renderPopupInterrupted(blocked);\n return;\n }\n\n popupBusy = true;\n renderPopupWaiting();\n\n flow\n .then((result) => {\n if (settled) { return; }\n if (result === undefined) {\n renderDenied();\n } else {\n succeed(result);\n }\n })\n .catch((error: unknown) => {\n if (settled) { return; }\n if (error instanceof PopupWindowClosedError) {\n renderPopupInterrupted(false);\n return;\n }\n const failure = error instanceof Error ? error : new Error(String(error));\n renderError(\n /timed out/i.test(failure.message)\n ? 'That took too long, so we stopped for safety.'\n : 'Something went wrong while connecting.',\n failure,\n );\n })\n .finally(() => { popupBusy = false; });\n };\n\n const startMethod = async (): Promise<void> => {\n if (method === 'browser') {\n // window.open must stay inside a user gesture \u2014 prompt for the click.\n relaySession?.cancel();\n clearTimeout(remintTimer);\n renderFooter();\n renderPopupPrompt();\n } else {\n await startPhone();\n }\n };\n\n const switchMethod = async (next: ConnectMethod): Promise<void> => {\n method = next;\n await startMethod();\n };\n\n // \u2500\u2500 Footer: method link + wallet switcher \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const renderFooter = (): void => {\n footer.replaceChildren();\n\n if (method === 'phone') {\n const alt = document.createElement('button');\n alt.className = 'footer-link method-link';\n alt.textContent = 'No phone handy? Use this browser \u2192';\n // startPopup runs synchronously in this click handler.\n alt.addEventListener('click', () => { startPopup(); });\n footer.appendChild(alt);\n } else if (!isMobile) {\n const alt = document.createElement('button');\n alt.className = 'footer-link method-link';\n alt.textContent = 'Use your phone instead \u2192';\n alt.addEventListener('click', () => { void switchMethod('phone'); });\n footer.appendChild(alt);\n }\n\n if (!lockedWallet && wallets.length > 0) {\n footer.appendChild(buildWalletSwitcher());\n }\n };\n\n const buildWalletSwitcher = (): HTMLElement => {\n const wrap = document.createElement('div');\n wrap.className = 'wallet-switcher';\n\n const current = wallets.find((wallet) => wallet.url === walletUrl);\n const toggle = document.createElement('button');\n toggle.className = 'footer-link wallet-toggle';\n toggle.setAttribute('aria-expanded', 'false');\n toggle.textContent = `Wallet: ${current?.name ?? walletUrl ?? 'Choose'} \u25BE`;\n\n const panel = document.createElement('div');\n panel.className = 'wallet-panel';\n panel.hidden = true;\n\n // Search filter \u2014 only worth the chrome once the catalog grows.\n const rows: Array<{ wallet: (typeof wallets)[number]; el: HTMLButtonElement }> = [];\n const empty = document.createElement('div');\n empty.className = 'wallet-empty';\n empty.textContent = 'No wallets match your search.';\n empty.hidden = true;\n\n if (wallets.length > 5) {\n const search = document.createElement('input');\n search.type = 'search';\n search.className = 'wallet-search';\n search.placeholder = 'Search wallets\u2026';\n search.addEventListener('input', () => {\n const query = search.value.trim().toLowerCase();\n let visible = 0;\n for (const { wallet, el } of rows) {\n const match = query === ''\n || wallet.name.toLowerCase().includes(query)\n || wallet.url.toLowerCase().includes(query);\n el.hidden = !match;\n if (match) { visible += 1; }\n }\n empty.hidden = visible > 0;\n });\n panel.appendChild(search);\n }\n\n for (const wallet of wallets) {\n const row = document.createElement('button');\n row.className = 'wallet-row';\n row.appendChild(buildWalletIcon(wallet));\n const rowName = document.createElement('span');\n rowName.className = 'wallet-row-name';\n rowName.textContent = wallet.name;\n row.appendChild(rowName);\n if (wallet.url === walletUrl) {\n row.classList.add('selected');\n }\n row.addEventListener('click', () => {\n walletUrl = wallet.url;\n renderFooter();\n void startMethod();\n });\n rows.push({ wallet, el: row });\n panel.appendChild(row);\n }\n panel.appendChild(empty);\n\n // Custom wallet URL (the power-user path, demoted to the disclosure).\n const custom = document.createElement('div');\n custom.className = 'wallet-custom';\n const input = document.createElement('input');\n input.className = 'url-input';\n input.type = 'url';\n input.placeholder = 'https://your-wallet.example';\n const go = document.createElement('button');\n go.className = 'url-go';\n go.textContent = 'Use';\n const urlError = document.createElement('div');\n urlError.className = 'url-error';\n urlError.hidden = true;\n\n // When validation fails we let the user override, since the connect\n // handshake is the ultimate gate \u2014 a valid wallet behind strict CORS\n // should not be permanently blocked.\n let allowUnverified = false;\n\n const useWallet = (origin: string): void => {\n walletUrl = origin;\n renderFooter();\n void startMethod();\n };\n\n const submitCustom = async (): Promise<void> => {\n const value = input.value.trim();\n if (value === '') { return; }\n let origin: string;\n try {\n origin = new URL(value.includes('://') ? value : `https://${value}`).origin;\n } catch {\n input.classList.add('invalid');\n return;\n }\n if (allowUnverified) {\n useWallet(origin);\n return;\n }\n go.disabled = true;\n go.textContent = 'Checking\u2026';\n urlError.hidden = true;\n const valid = await deps.validateWalletUrl(origin);\n go.disabled = false;\n if (valid) {\n go.textContent = 'Use';\n useWallet(origin);\n return;\n }\n allowUnverified = true;\n go.textContent = 'Use anyway';\n input.classList.add('invalid');\n urlError.textContent = `Couldn't verify a wallet at ${origin}.`;\n urlError.hidden = false;\n };\n\n input.addEventListener('input', () => {\n allowUnverified = false;\n go.textContent = 'Use';\n input.classList.remove('invalid');\n urlError.hidden = true;\n });\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') { void submitCustom(); }\n });\n go.addEventListener('click', () => { void submitCustom(); });\n custom.appendChild(input);\n custom.appendChild(go);\n panel.appendChild(custom);\n panel.appendChild(urlError);\n\n toggle.addEventListener('click', () => {\n panel.hidden = !panel.hidden;\n toggle.setAttribute('aria-expanded', panel.hidden ? 'false' : 'true');\n });\n\n wrap.appendChild(toggle);\n wrap.appendChild(panel);\n return wrap;\n };\n\n // \u2500\u2500 Global interactions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n overlay.addEventListener('click', (event) => {\n if (event.target === overlay) {\n cancelModal();\n }\n });\n\n const onKeydown = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') {\n cancelModal();\n return;\n }\n if (event.key === 'Tab') {\n trapFocus(shadow, event);\n }\n };\n document.addEventListener('keydown', onKeydown);\n\n overlay.appendChild(modal);\n shadow.appendChild(overlay);\n document.body.appendChild(host);\n\n renderFooter();\n void startMethod();\n });\n}\n\n// \u2500\u2500\u2500 Small DOM helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction walletInCatalog(wallets: WalletOption[], url: string): boolean {\n return wallets.some((wallet) => wallet.url === url);\n}\n\nfunction el(tag: string, className: string, text?: string): HTMLElement {\n const node = document.createElement(tag);\n node.className = className;\n if (text !== undefined) {\n node.textContent = text;\n }\n return node;\n}\n\nfunction stageButton(label: string, onClick: () => void): HTMLButtonElement {\n const button = document.createElement('button');\n button.className = 'stage-btn';\n button.textContent = label;\n button.addEventListener('click', onClick);\n return button;\n}\n\nfunction stageLinkButton(label: string, onClick: () => void): HTMLButtonElement {\n const button = document.createElement('button');\n button.className = 'footer-link';\n button.textContent = label;\n button.addEventListener('click', onClick);\n return button;\n}\n\nfunction buildHeader(appName: string, appIcon: string | undefined, onCancel: () => void): HTMLDivElement {\n const header = document.createElement('div');\n header.className = 'header';\n\n const identity = document.createElement('div');\n identity.className = 'header-identity';\n\n if (appIcon !== undefined) {\n const icon = document.createElement('img');\n icon.className = 'header-icon';\n icon.src = appIcon;\n icon.alt = '';\n icon.width = 24;\n icon.height = 24;\n icon.addEventListener('error', () => icon.remove());\n identity.appendChild(icon);\n }\n\n const title = document.createElement('h2');\n title.textContent = `Connect to ${appName}`;\n identity.appendChild(title);\n\n const closeBtn = document.createElement('button');\n closeBtn.className = 'close-btn';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.textContent = '\\u00d7';\n closeBtn.addEventListener('click', onCancel);\n\n header.appendChild(identity);\n header.appendChild(closeBtn);\n return header;\n}\n\nfunction trapFocus(shadow: ShadowRoot, event: KeyboardEvent): void {\n const focusables = Array.from(\n shadow.querySelectorAll<HTMLElement>('button, input, a[href], [tabindex]:not([tabindex=\"-1\"])'),\n ).filter((node) => !node.hasAttribute('disabled') && node.offsetParent !== null);\n\n if (focusables.length === 0) {\n return;\n }\n\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = shadow.activeElement as HTMLElement | null;\n\n if (event.shiftKey && (active === first || active === null)) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && active === last) {\n event.preventDefault();\n first.focus();\n }\n}\n\n// \u2500\u2500\u2500 Styles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction buildStyles(isDark: boolean): string {\n const bg = isDark ? '#1a1a2e' : '#ffffff';\n const text = isDark ? '#e0e0e0' : '#1a1a2e';\n const muted = isDark ? '#888' : '#666';\n const border = isDark ? '#333' : '#e0e0e0';\n const itemBg = isDark ? '#16213e' : '#f8f9fa';\n const accent = isDark ? '#4a9eff' : '#0066cc';\n const accentSoft = isDark ? 'rgba(74, 158, 255, 0.16)' : 'rgba(0, 102, 204, 0.1)';\n const danger = isDark ? '#ff6b6b' : '#c0392b';\n const success = isDark ? '#43d17c' : '#1e9e5a';\n\n return `\n * { box-sizing: border-box; margin: 0; padding: 0; }\n\n .overlay {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.5);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n animation: fadeIn 0.15s ease-out;\n }\n\n @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }\n @keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }\n @keyframes stageIn { from { opacity: 0; } to { opacity: 1; } }\n @keyframes shake {\n 0%, 100% { transform: translateX(0); }\n 20%, 60% { transform: translateX(-6px); }\n 40%, 80% { transform: translateX(6px); }\n }\n @keyframes spin { to { transform: rotate(360deg); } }\n\n .modal {\n background: ${bg};\n color: ${text};\n border-radius: 16px;\n width: 400px;\n max-width: 92vw;\n max-height: 88vh;\n overflow-y: auto;\n padding: 20px 24px 16px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n animation: slideUp 0.2s ease-out;\n display: flex;\n flex-direction: column;\n }\n\n .header { display: flex; justify-content: space-between; align-items: center; }\n .header-identity { display: flex; align-items: center; gap: 10px; min-width: 0; }\n .header-icon { border-radius: 6px; }\n h2 { font-size: 16px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n .close-btn {\n background: none; border: none; font-size: 24px; cursor: pointer;\n color: ${muted}; padding: 4px 8px; border-radius: 8px; line-height: 1;\n }\n .close-btn:hover { color: ${text}; background: ${itemBg}; }\n\n .stage {\n min-height: 300px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n text-align: center;\n padding: 16px 0;\n }\n .stage.fade-in > * { animation: stageIn 0.15s ease-out; }\n\n .qr-box {\n width: 216px;\n height: 216px;\n padding: 12px;\n border-radius: 12px;\n background: ${isDark ? '#10192e' : '#ffffff'};\n border: 1px solid ${border};\n }\n .qr-box svg { width: 100%; height: 100%; display: block; }\n\n .stage-caption { font-size: 15px; font-weight: 600; }\n .stage-subline { font-size: 13px; color: ${muted}; max-width: 300px; line-height: 1.45; }\n .stage-error { font-size: 13px; color: ${danger}; }\n\n .deep-link {\n display: block;\n width: 100%;\n padding: 14px 16px;\n border-radius: 12px;\n background: ${accent};\n color: #fff;\n font-weight: 600;\n font-size: 15px;\n text-decoration: none;\n }\n\n .pin-row { display: flex; gap: 10px; }\n .pin-row.shake { animation: shake 0.4s ease-in-out; }\n .pin-input {\n width: 48px; height: 56px;\n text-align: center;\n font-size: 24px; font-weight: 600;\n color: ${text};\n background: ${itemBg};\n border: 1px solid ${border};\n border-radius: 10px;\n outline: none;\n }\n .pin-input:focus { border-color: ${accent}; }\n\n .check {\n width: 56px; height: 56px;\n display: flex; align-items: center; justify-content: center;\n border-radius: 50%;\n background: ${success};\n color: #fff;\n font-size: 28px;\n }\n\n .spinner {\n width: 32px; height: 32px;\n border-radius: 50%;\n border: 3px solid ${border};\n border-top-color: ${accent};\n animation: spin 0.8s linear infinite;\n }\n\n .stage-btn {\n padding: 10px 20px;\n border: none;\n border-radius: 10px;\n background: ${accent};\n color: #fff;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n }\n .stage-btn:hover { filter: brightness(1.1); }\n\n .footer {\n border-top: 1px solid ${border};\n padding-top: 10px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n align-items: center;\n }\n\n .footer-link {\n background: none;\n border: none;\n color: ${muted};\n font-size: 13px;\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 8px;\n }\n .footer-link:hover { color: ${text}; background: ${itemBg}; }\n .method-link { color: ${accent}; }\n\n .wallet-switcher { width: 100%; display: flex; flex-direction: column; align-items: center; }\n .wallet-panel { width: 100%; padding: 6px 0; display: flex; flex-direction: column; gap: 4px; }\n .wallet-row {\n width: 100%;\n text-align: left;\n padding: 8px 12px;\n background: ${itemBg};\n border: 1px solid ${border};\n border-radius: 10px;\n color: ${text};\n font-size: 13px;\n cursor: pointer;\n }\n .wallet-row:hover, .wallet-row.selected { border-color: ${accent}; }\n\n .wallet-icon { position: relative; width: 28px; height: 28px; flex-shrink: 0; display: inline-flex; }\n .wallet-badge {\n width: 28px; height: 28px; border-radius: 8px; display: inline-flex;\n align-items: center; justify-content: center; font-size: 13px;\n font-weight: 600; background: ${accentSoft}; color: ${accent};\n }\n .wallet-img { position: absolute; inset: 0; width: 28px; height: 28px; border-radius: 8px; object-fit: cover; }\n .wallet-row-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .wallet-search {\n width: 100%; box-sizing: border-box; padding: 8px 10px; margin-bottom: 4px;\n border-radius: 8px; border: 1px solid ${border}; background: transparent;\n color: inherit; font: inherit;\n }\n .wallet-search:focus { outline: none; border-color: ${accent}; }\n .wallet-empty { padding: 8px 10px; font-size: 12px; opacity: 0.7; }\n .url-error { padding: 4px 2px 0; font-size: 12px; color: ${danger}; }\n .wallet-custom { display: flex; gap: 6px; margin-top: 4px; }\n .url-input {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid ${border};\n border-radius: 10px;\n font-size: 13px;\n background: ${itemBg};\n color: ${text};\n outline: none;\n }\n .url-input:focus { border-color: ${accent}; }\n .url-input.invalid { border-color: ${danger}; }\n .url-go {\n padding: 8px 14px;\n border: none;\n border-radius: 10px;\n background: ${accent};\n color: #fff;\n font-size: 13px;\n cursor: pointer;\n }\n `;\n}\n", "/**\n * Wallet icon builder shared by the connect modal's wallet switcher.\n *\n * Prefers the wallet's own favicon and degrades to a letter badge. We never\n * call a third-party favicon proxy: those 404 for many origins and leak the\n * wallet URL to the proxy.\n *\n * @module\n */\n\nimport type { WalletOption } from '../browser-connect-handler.js';\n\n/** Build a wallet icon element (own favicon with a letter-badge fallback). */\nexport function buildWalletIcon(wallet: WalletOption): HTMLElement {\n const wrap = document.createElement('span');\n wrap.className = 'wallet-icon';\n\n const badge = document.createElement('span');\n badge.className = 'wallet-badge';\n badge.textContent = wallet.name.charAt(0).toUpperCase();\n wrap.appendChild(badge);\n\n const sources = iconCandidates(wallet);\n if (sources.length === 0) {\n return wrap;\n }\n\n const img = document.createElement('img');\n img.className = 'wallet-img';\n img.alt = '';\n img.width = 28;\n img.height = 28;\n\n let index = 0;\n img.addEventListener('error', () => {\n index += 1;\n if (index < sources.length) {\n img.src = sources[index];\n } else {\n img.remove(); // fall back to the letter badge\n }\n });\n\n img.src = sources[index];\n wrap.appendChild(img);\n return wrap;\n}\n\n/** Ordered favicon URLs to try for a wallet, most specific first. */\nfunction iconCandidates(wallet: WalletOption): string[] {\n if (wallet.icon !== undefined) {\n return [wallet.icon];\n }\n\n let origin: string;\n try {\n origin = new URL(wallet.url).origin;\n } catch {\n return [];\n }\n\n return [`${origin}/favicon.svg`, `${origin}/favicon.ico`, `${origin}/favicon.png`];\n}\n", "/**\n * DWeb Connect client \u2014 the dapp side of the popup/postMessage connect flow.\n *\n * {@link PopupClientTransport} implements the `@enbox/connect` kernel's\n * `ConnectTransport` over a wallet popup:\n *\n * 1. The dapp opens `${walletUrl}/dweb-connect` as a popup window.\n * 2. The wallet emits a `loaded` beacon carrying a fresh ephemeral X25519\n * public key and its origin.\n * 3. The kernel seals the signed connect request to that key (ECDH-ES,\n * `apv` bound to the wallet origin) and the transport posts the\n * ciphertext to the popup.\n * 4. The wallet posts back the sealed response JWE (or the deny token),\n * which the kernel opens and value-checks.\n *\n * Only ciphertext crosses the postMessage channel. Every message is checked\n * against the wallet origin derived from the configured wallet URL (never\n * `'*'`), and against the popup window as `event.source`.\n *\n * @module\n */\n\nimport type { Jwk } from '@enbox/crypto';\nimport type {\n ConnectClientMetadata,\n ConnectPermissionRequest,\n ConnectRequestProfile,\n ConnectResult,\n ConnectTransport,\n} from '@enbox/connect';\n\nimport { assertX25519PublicJwk, CONNECT_DENIED_TOKEN, ConnectClient } from '@enbox/connect';\n\nimport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_PATH,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n getTrustedMessage,\n} from './dweb-connect-messages.js';\n\n/** Default budget for the whole popup handshake (beacon + user consent + response). */\nconst DEFAULT_TIMEOUT_MS = 300_000;\n\n/** Interval at which the transport checks whether the user closed the popup. */\nconst CLOSED_POLL_INTERVAL_MS = 500;\n\n/** Window name given to the wallet popup. */\nconst POPUP_WINDOW_NAME = 'enbox-dweb-connect';\n\n/** Window features given to the wallet popup. */\nconst POPUP_WINDOW_FEATURES = 'width=500,height=700,menubar=no,toolbar=no,location=no,status=no';\n\n/** Guards against calling browser-only entry points outside a browser. */\nfunction assertBrowserEnvironment(): void {\n if (typeof window === 'undefined') {\n throw new Error('[@enbox/browser] DWeb Connect is only available in browser environments.');\n }\n}\n\n/**\n * Thrown when the user closes the wallet popup before the wallet finished\n * loading (i.e. before its `loaded` beacon arrived). Callers typically treat\n * this the same as a user denial.\n */\nexport class PopupWindowClosedError extends Error {\n constructor() {\n super('[@enbox/browser] Wallet popup was closed before the wallet finished loading.');\n this.name = 'PopupWindowClosedError';\n }\n}\n\n/** Options for constructing a {@link PopupClientTransport}. */\nexport type PopupClientTransportOptions = {\n /** Base URL of the wallet app (e.g. `https://enbox-wallet.pages.dev`). */\n walletUrl: string;\n\n /**\n * Total budget in milliseconds for the popup handshake. The popup is closed\n * and the handshake rejected when the wallet has not responded in time.\n * @default 300_000 (5 minutes)\n */\n timeoutMs?: number;\n};\n\n/**\n * Popup/postMessage {@link ConnectTransport} for browser dapps.\n *\n * Single-use: construct a new transport per handshake. The **constructor**\n * opens the wallet popup synchronously \u2014 so `window.open` runs inside the user\n * gesture, ahead of the kernel's awaited key generation, and survives strict\n * popup blockers; `requestProfile()` then awaits the wallet's `loaded` beacon;\n * `deliverRequest()` posts the sealed request ciphertext; `awaitResponse()`\n * resolves with the sealed response JWE, or the deny token when the user denies\n * or closes the popup after the handshake was established.\n *\n * Security properties:\n * - `targetOrigin` of every outbound `postMessage` is pinned to the origin\n * derived from `walletUrl` \u2014 never `'*'`.\n * - Inbound messages are dropped unless `event.origin` equals the pinned\n * wallet origin AND `event.source` is the popup window this transport opened.\n * - The beacon's `walletOrigin` field must equal the pinned origin, and its\n * `walletEpk` must be a public-only X25519 JWK; a malformed beacon from the\n * genuine popup fails the handshake closed.\n */\nexport class PopupClientTransport implements ConnectTransport {\n /** {@inheritDoc ConnectTransport.requiresPin} */\n public readonly requiresPin: boolean = false;\n\n private readonly _walletOrigin: string;\n private readonly _timeoutMs: number;\n\n private readonly _popup: Window;\n private _settled = false;\n private _walletEpkReceived = false;\n private _timeoutId?: ReturnType<typeof setTimeout>;\n private _closedPollId?: ReturnType<typeof setInterval>;\n private _messageListener?: (event: MessageEvent) => void;\n\n private readonly _walletEpkPromise: Promise<Jwk>;\n private _resolveWalletEpk?: (walletEpk: Jwk) => void;\n private _rejectWalletEpk?: (error: Error) => void;\n\n private readonly _responsePromise: Promise<string>;\n private _resolveResponse?: (payload: string) => void;\n private _rejectResponse?: (error: Error) => void;\n\n constructor(options: PopupClientTransportOptions) {\n assertBrowserEnvironment();\n\n this._walletOrigin = new URL(options.walletUrl).origin;\n this._timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n // Open the wallet popup SYNCHRONOUSLY, in the user-gesture call stack,\n // before the kernel's awaited `DidJwk.create()` / `X25519.generateKey()`\n // run. Strict popup blockers (Safari) reject a `window.open` issued once\n // the stack has yielded to a prior `await`, so opening it here \u2014 instead of\n // inside the awaited `requestProfile()` \u2014 is what keeps the flow usable.\n const popupUrl = new URL(DWEB_CONNECT_PATH, options.walletUrl).toString();\n const popup = window.open(popupUrl, POPUP_WINDOW_NAME, POPUP_WINDOW_FEATURES);\n if (!popup) {\n throw new Error('[@enbox/browser] Popup blocked. Allow popups for this site to connect to a wallet.');\n }\n this._popup = popup;\n\n this._walletEpkPromise = new Promise<Jwk>((resolve, reject): void => {\n this._resolveWalletEpk = resolve;\n this._rejectWalletEpk = reject;\n });\n\n // Created up-front so a response (or deny) arriving before\n // `awaitResponse()` is called is never dropped. The no-op catch marks\n // early rejections (timeout, popup closed during load) as handled until\n // the kernel attaches its own handlers via `awaitResponse()`.\n this._responsePromise = new Promise<string>((resolve, reject): void => {\n this._resolveResponse = resolve;\n this._rejectResponse = reject;\n });\n this._responsePromise.catch((): undefined => undefined);\n\n // Listen synchronously, before the wallet page can emit its `loaded`\n // beacon, so the beacon is never missed while the kernel awaits key\n // generation ahead of `requestProfile()`.\n this._messageListener = (event: MessageEvent): void => { this.onMessage(event); };\n window.addEventListener('message', this._messageListener);\n\n this._timeoutId = setTimeout((): void => {\n this.fail(new Error('[@enbox/browser] DWeb Connect timed out waiting for wallet response.'));\n }, this._timeoutMs);\n\n this._closedPollId = setInterval((): void => { this.onClosedPoll(); }, CLOSED_POLL_INTERVAL_MS);\n }\n\n /**\n * Awaits the already-open popup's `loaded` beacon, then returns the popup\n * channel profile: ECDH-ES encryption to the beacon's ephemeral key with the\n * pinned wallet origin as the `apv` binding, a `post_message` reply\n * descriptor, and the client-supplied `state` correlator.\n *\n * The popup was opened synchronously at construction, so this method only\n * awaits the beacon \u2014 it never issues the blocker-sensitive `window.open`.\n *\n * @param state - The handshake correlator minted by the {@link ConnectClient}.\n * @throws If the user closes the popup before the beacon arrives\n * ({@link PopupWindowClosedError}), the beacon is malformed, or on\n * timeout.\n */\n public async requestProfile(state: string): Promise<ConnectRequestProfile> {\n const walletEpk = await this._walletEpkPromise;\n\n return {\n encryption : { mode: 'ecdh-es', walletEpk, walletOrigin: this._walletOrigin },\n reply : { mode: 'post_message' },\n state,\n };\n }\n\n /**\n * Posts the sealed request ciphertext to the wallet popup with the\n * `targetOrigin` pinned to the wallet origin.\n */\n public async deliverRequest(jwe: string): Promise<void> {\n this._popup.postMessage({ type: DWEB_CONNECT_REQUEST_MESSAGE_TYPE, jwe }, this._walletOrigin);\n }\n\n /**\n * Awaits the wallet's response ciphertext: the sealed response JWE, or the\n * deny token when the user denies in the wallet or closes the popup.\n * Rejects on timeout.\n */\n public async awaitResponse(): Promise<string> {\n return await this._responsePromise;\n }\n\n private onMessage(event: MessageEvent): void {\n const message = getTrustedMessage(event, this._walletOrigin, this._popup);\n if (message === undefined) { return; }\n\n if (message.type === DWEB_CONNECT_LOADED_MESSAGE_TYPE) {\n this.onLoadedBeacon(message);\n return;\n }\n\n if (message.type === DWEB_CONNECT_RESPONSE_MESSAGE_TYPE) {\n this.onResponseMessage(message);\n }\n }\n\n private onLoadedBeacon(message: Record<string, unknown>): void {\n if (this._settled || this._walletEpkReceived) { return; }\n\n // The beacon passed the origin and source checks, so a malformed payload\n // is a protocol violation by the genuine popup \u2014 fail closed. The X25519\n // public-JWK shape check is delegated to the connect kernel.\n let walletEpk: Jwk;\n try {\n assertX25519PublicJwk(message.walletEpk);\n walletEpk = message.walletEpk;\n } catch {\n this.fail(new Error('[@enbox/browser] Wallet loaded beacon did not carry a valid X25519 public key.'));\n return;\n }\n\n if (message.walletOrigin !== this._walletOrigin) {\n this.fail(new Error('[@enbox/browser] Wallet loaded beacon origin does not match the configured wallet origin.'));\n return;\n }\n\n this._walletEpkReceived = true;\n this._resolveWalletEpk?.(walletEpk);\n }\n\n private onResponseMessage(message: Record<string, unknown>): void {\n if (this._settled) { return; }\n\n if (typeof message.payload !== 'string') {\n this.fail(new Error('[@enbox/browser] Wallet response message did not carry a ciphertext payload.'));\n return;\n }\n\n this._settled = true;\n this.cleanup();\n // No-op on the normal path; unblocks `requestProfile()` if a response\n // somehow arrives before the beacon.\n this._rejectWalletEpk?.(new Error('[@enbox/browser] Wallet responded before the handshake was established.'));\n this._resolveResponse?.(message.payload);\n }\n\n private onClosedPoll(): void {\n if (this._settled || this._popup.closed !== true) { return; }\n\n if (!this._walletEpkReceived) {\n // Closed before the wallet ever loaded \u2014 the handshake cannot proceed.\n this.fail(new PopupWindowClosedError());\n return;\n }\n\n // Closed after the handshake was established \u2014 treat as a user denial.\n this._settled = true;\n this.cleanup();\n this._resolveResponse?.(CONNECT_DENIED_TOKEN);\n }\n\n private fail(error: Error): void {\n if (this._settled) { return; }\n this._settled = true;\n this.cleanup();\n try { this._popup.close(); } catch { /* best effort */ }\n this._rejectWalletEpk?.(error);\n this._rejectResponse?.(error);\n }\n\n private cleanup(): void {\n clearTimeout(this._timeoutId);\n clearInterval(this._closedPollId);\n if (this._messageListener !== undefined) {\n window.removeEventListener('message', this._messageListener);\n this._messageListener = undefined;\n }\n }\n}\n\n/** Options for a one-shot {@link connectViaPopup} flow. */\nexport type PopupConnectOptions = {\n /** Base URL of the wallet app (e.g. `https://enbox-wallet.pages.dev`). */\n walletUrl: string;\n\n /** DWN protocols and permission scopes to request from the wallet. */\n permissionRequests: ConnectPermissionRequest[];\n\n /**\n * Timeout in milliseconds for the popup handshake.\n * @default 300_000 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Display name of the requesting application, shown in the wallet's\n * consent screen. Defaults to the dapp's host.\n */\n appName?: string;\n\n /**\n * Icon URL of the requesting application, shown alongside the app name in\n * the wallet's consent screen.\n */\n appIcon?: string;\n};\n\n/** Collects self-reported environment hints for the wallet's session display. */\nexport function collectBrowserClientMetadata(): ConnectClientMetadata {\n const resolvedOptions = Intl.DateTimeFormat().resolvedOptions();\n const languages = Array.isArray(globalThis.navigator.languages)\n ? globalThis.navigator.languages.filter((language) => typeof language === 'string' && language.length > 0)\n : undefined;\n\n return {\n origin : globalThis.location.origin,\n userAgent : globalThis.navigator.userAgent,\n platform : globalThis.navigator.platform,\n language : globalThis.navigator.language,\n ...(languages && languages.length > 0 ? { languages } : {}),\n ...(resolvedOptions.timeZone ? { timezone: resolvedOptions.timeZone } : {}),\n };\n}\n\n/**\n * Runs one DWeb Connect popup handshake end-to-end: opens the wallet popup,\n * drives the `@enbox/connect` kernel client over a {@link PopupClientTransport},\n * and returns the delegated credentials.\n *\n * @returns The delegate credentials, or `undefined` when the user denied the\n * request or closed the popup.\n * @throws If the popup is blocked, the handshake times out, or the wallet\n * returns an invalid response.\n */\nexport async function connectViaPopup(options: PopupConnectOptions): Promise<ConnectResult | undefined> {\n const transport = new PopupClientTransport({\n walletUrl : options.walletUrl,\n timeoutMs : options.timeout,\n });\n const client = new ConnectClient({ transport });\n\n try {\n return await client.connect({\n appName : options.appName ?? globalThis.location.host,\n appIcon : options.appIcon,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n });\n } catch (error) {\n if (error instanceof PopupWindowClosedError) {\n // The user closed the wallet before it loaded \u2014 same as a denial.\n return undefined;\n }\n throw error;\n }\n}\n", "/**\n * Wire shapes for the DWeb Connect popup/postMessage channel.\n *\n * The dapp and the wallet exchange exactly three message kinds over\n * `window.postMessage`:\n *\n * 1. `loaded` beacon (wallet \u2192 dapp): announces the wallet page is ready and\n * carries a fresh ephemeral X25519 public key plus the wallet's origin.\n * 2. `request` (dapp \u2192 wallet): the sealed connect request JWE \u2014 ciphertext\n * only, encrypted to the beacon key with ECDH-ES and the wallet origin\n * bound into the JWE `apv` header.\n * 3. `response` (wallet \u2192 dapp): the sealed connect response JWE, or the\n * literal deny token \u2014 again ciphertext only.\n *\n * Plaintext never crosses the channel, and both sides pin `targetOrigin`\n * and verify `event.origin` / `event.source` on every message.\n *\n * @module\n */\n\nimport type { Jwk } from '@enbox/crypto';\n\n/** Path of the wallet's DWeb Connect page, opened as a popup by the dapp. */\nexport const DWEB_CONNECT_PATH = '/dweb-connect';\n\n/** Message type of the wallet's `loaded` beacon (wallet \u2192 dapp). */\nexport const DWEB_CONNECT_LOADED_MESSAGE_TYPE = 'enbox-connect-loaded';\n\n/** Message type carrying the sealed connect request JWE (dapp \u2192 wallet). */\nexport const DWEB_CONNECT_REQUEST_MESSAGE_TYPE = 'enbox-connect-request';\n\n/** Message type carrying the sealed connect response JWE or deny token (wallet \u2192 dapp). */\nexport const DWEB_CONNECT_RESPONSE_MESSAGE_TYPE = 'enbox-connect-response';\n\n/**\n * The wallet's readiness beacon. Emitted to `window.opener` once the wallet's\n * DWeb Connect page has generated its per-session ephemeral X25519 key.\n */\nexport type DWebConnectLoadedMessage = {\n type: typeof DWEB_CONNECT_LOADED_MESSAGE_TYPE;\n\n /** Fresh ephemeral X25519 public JWK the dapp seals the request to. */\n walletEpk: Jwk;\n\n /** The wallet's own origin; must match the origin the dapp has pinned. */\n walletOrigin: string;\n};\n\n/** The dapp's sealed connect request, posted to the wallet popup. */\nexport type DWebConnectRequestMessage = {\n type: typeof DWEB_CONNECT_REQUEST_MESSAGE_TYPE;\n\n /** The sealed connect request as a Compact JWE string. */\n jwe: string;\n};\n\n/** The wallet's sealed connect response, posted back to the opener. */\nexport type DWebConnectResponseMessage = {\n type: typeof DWEB_CONNECT_RESPONSE_MESSAGE_TYPE;\n\n /** The sealed connect response JWE, or the literal `CONNECT_DENIED_TOKEN`. */\n payload: string;\n};\n\n/**\n * Applies the shared inbound-message trust filter for the popup channel:\n * pins the message to the expected `event.origin`, pins its `event.source` to\n * the expected window, and requires a non-null object payload.\n *\n * Returns the payload cast to a plain record when every check passes, or\n * `undefined` when the message must be dropped. Both the dapp-side and\n * wallet-side transports early-return on `undefined` before inspecting any\n * message field \u2014 this is the security-critical filter that keeps hostile\n * origins and stray windows off the channel.\n */\nexport function getTrustedMessage(\n event: MessageEvent,\n expectedOrigin: string,\n expectedSource: Window | undefined,\n): Record<string, unknown> | undefined {\n // Origin pinning: only messages from the expected origin count.\n if (event.origin !== expectedOrigin) { return undefined; }\n\n // Source pinning: the message must come from the expected window.\n if (event.source !== expectedSource) { return undefined; }\n\n const data: unknown = event.data;\n if (typeof data !== 'object' || data === null) { return undefined; }\n\n return data as Record<string, unknown>;\n}\n", "/**\n * Minimal QR code encoder \u2014 dependency-free, byte mode, ECC level M,\n * versions 1\u201310 with automatic version selection and standard mask\n * evaluation (ISO/IEC 18004 penalty rules N1\u2013N4).\n *\n * Scope is deliberately narrow: it exists to render wallet-connect URIs in\n * the connect modal without adding a third-party runtime dependency. The\n * encoding pipeline follows the standard exactly \u2014 segment \u2192 codewords \u2192\n * Reed-Solomon blocks \u2192 interleave \u2192 placement \u2192 mask \u2014 and the test suite\n * verifies full module-matrix equality against the `qrcode` npm package\n * (dev-only oracle) across versions and mask patterns.\n *\n * @module\n */\n\n/** An encoded QR symbol: `modules[y][x]` is `true` for dark modules. */\nexport interface QrCode {\n /** Symbol width/height in modules (17 + 4\u00D7version). */\n size: number;\n\n /** Dark/light module matrix, row-major. */\n modules: boolean[][];\n\n /** Symbol version (1\u201310). */\n version: number;\n\n /** Applied mask pattern (0\u20137). */\n mask: number;\n}\n\n/** Error-correction level M codewords per block, indexed by version (1\u201310). */\nconst ECC_PER_BLOCK = [-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26];\n\n/** Error-correction level M block counts, indexed by version (1\u201310). */\nconst NUM_BLOCKS = [-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5];\n\n/** Total codewords in the symbol, indexed by version (1\u201310). */\nconst TOTAL_CODEWORDS = [-1, 26, 44, 70, 100, 134, 172, 196, 242, 292, 346];\n\n/** Format-info error-correction bits for level M (`00` per the standard). */\nconst FORMAT_ECL_M = 0b00;\n\nconst MAX_VERSION = 10;\n\n/** Data codeword capacity for level M at `version`. */\nfunction dataCodewords(version: number): number {\n return TOTAL_CODEWORDS[version] - ECC_PER_BLOCK[version] * NUM_BLOCKS[version];\n}\n\n/**\n * Encodes UTF-8 text as a byte-mode QR symbol at ECC level M.\n *\n * @param text - The payload; encoded as UTF-8 bytes.\n * @param forcedMask - Optional mask override (0\u20137); defaults to the\n * penalty-minimising mask per the standard.\n * @returns The encoded symbol.\n * @throws If the payload does not fit in a version-10 level-M symbol.\n */\nexport function encodeQr(text: string, forcedMask?: number): QrCode {\n const data = new TextEncoder().encode(text);\n\n // \u2500\u2500 Version selection: smallest version that fits the segment. \u2500\u2500\n let version = 0;\n for (let candidate = 1; candidate <= MAX_VERSION; candidate++) {\n const capacityBits = dataCodewords(candidate) * 8;\n const headerBits = 4 + (candidate <= 9 ? 8 : 16);\n if (headerBits + data.length * 8 <= capacityBits) {\n version = candidate;\n break;\n }\n }\n if (version === 0) {\n throw new Error(`[@enbox/browser] QR payload too long (${data.length} bytes exceeds version ${MAX_VERSION}-M capacity).`);\n }\n\n // \u2500\u2500 Segment bits: mode 0100, char count, data, terminator, padding. \u2500\u2500\n const bits: number[] = [];\n const pushBits = (value: number, length: number): void => {\n for (let i = length - 1; i >= 0; i--) {\n bits.push((value >>> i) & 1);\n }\n };\n\n pushBits(0b0100, 4);\n pushBits(data.length, version <= 9 ? 8 : 16);\n for (const byte of data) {\n pushBits(byte, 8);\n }\n\n const capacityBits = dataCodewords(version) * 8;\n pushBits(0, Math.min(4, capacityBits - bits.length)); // terminator\n pushBits(0, (8 - (bits.length % 8)) % 8); // byte align\n\n const padBytes = [0xEC, 0x11];\n for (let i = 0; bits.length < capacityBits; i++) {\n pushBits(padBytes[i % 2], 8);\n }\n\n const codewords = new Uint8Array(capacityBits / 8);\n for (let i = 0; i < bits.length; i++) {\n codewords[i >> 3] |= bits[i] << (7 - (i & 7));\n }\n\n // \u2500\u2500 Reed-Solomon blocks + interleave. \u2500\u2500\n const allCodewords = buildInterleavedCodewords(codewords, version);\n\n // \u2500\u2500 Module placement. \u2500\u2500\n const size = 17 + 4 * version;\n const modules: boolean[][] = Array.from({ length: size }, () => new Array<boolean>(size).fill(false));\n const isFunction: boolean[][] = Array.from({ length: size }, () => new Array<boolean>(size).fill(false));\n\n drawFunctionPatterns(modules, isFunction, version);\n drawCodewords(modules, isFunction, allCodewords);\n\n // \u2500\u2500 Mask selection: apply each mask, score, keep the best. \u2500\u2500\n let mask = forcedMask ?? -1;\n if (mask === -1) {\n let bestPenalty = Infinity;\n for (let candidate = 0; candidate < 8; candidate++) {\n applyMask(modules, isFunction, candidate);\n drawFormatBits(modules, isFunction, candidate);\n const penalty = computePenalty(modules);\n if (penalty < bestPenalty) {\n bestPenalty = penalty;\n mask = candidate;\n }\n applyMask(modules, isFunction, candidate); // undo (XOR is involutive)\n }\n }\n\n applyMask(modules, isFunction, mask);\n drawFormatBits(modules, isFunction, mask);\n\n return { size, modules, version, mask };\n}\n\n/** Splits data codewords into level-M blocks, computes ECC, interleaves. */\nfunction buildInterleavedCodewords(data: Uint8Array, version: number): Uint8Array {\n const numBlocks = NUM_BLOCKS[version];\n const eccLen = ECC_PER_BLOCK[version];\n const totalCodewords = TOTAL_CODEWORDS[version];\n\n const numShortBlocks = numBlocks - (totalCodewords % numBlocks);\n const shortBlockLen = Math.floor(totalCodewords / numBlocks);\n\n const blocks: Uint8Array[] = [];\n const eccBlocks: Uint8Array[] = [];\n const rsDivisor = reedSolomonDivisor(eccLen);\n\n let offset = 0;\n for (let i = 0; i < numBlocks; i++) {\n const dataLen = shortBlockLen - eccLen + (i < numShortBlocks ? 0 : 1);\n const block = data.slice(offset, offset + dataLen);\n offset += dataLen;\n blocks.push(block);\n eccBlocks.push(reedSolomonRemainder(block, rsDivisor));\n }\n\n const result = new Uint8Array(totalCodewords);\n let index = 0;\n const maxDataLen = shortBlockLen - eccLen + 1;\n for (let i = 0; i < maxDataLen; i++) {\n for (let b = 0; b < numBlocks; b++) {\n if (i < blocks[b].length) {\n result[index++] = blocks[b][i];\n }\n }\n }\n for (let i = 0; i < eccLen; i++) {\n for (let b = 0; b < numBlocks; b++) {\n result[index++] = eccBlocks[b][i];\n }\n }\n\n return result;\n}\n\n// \u2500\u2500 GF(256) Reed-Solomon (polynomial 0x11D) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction gfMultiply(x: number, y: number): number {\n let z = 0;\n for (let i = 7; i >= 0; i--) {\n z = (z << 1) ^ ((z >>> 7) * 0x11D);\n z ^= ((y >>> i) & 1) * x;\n }\n return z & 0xFF;\n}\n\n/** Generator polynomial coefficients for `degree` ECC codewords. */\nfunction reedSolomonDivisor(degree: number): Uint8Array {\n const result = new Uint8Array(degree);\n result[degree - 1] = 1;\n\n let root = 1;\n for (let i = 0; i < degree; i++) {\n for (let j = 0; j < degree; j++) {\n result[j] = gfMultiply(result[j], root);\n if (j + 1 < degree) {\n result[j] ^= result[j + 1];\n }\n }\n root = gfMultiply(root, 0x02);\n }\n return result;\n}\n\nfunction reedSolomonRemainder(data: Uint8Array, divisor: Uint8Array): Uint8Array {\n const result = new Uint8Array(divisor.length);\n for (const byte of data) {\n const factor = byte ^ result[0];\n result.copyWithin(0, 1);\n result[result.length - 1] = 0;\n for (let i = 0; i < divisor.length; i++) {\n result[i] ^= gfMultiply(divisor[i], factor);\n }\n }\n return result;\n}\n\n// \u2500\u2500 Function patterns \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Alignment pattern centre coordinates, indexed by version (1\u201310). */\nconst ALIGNMENT_POSITIONS: number[][] = [\n [], [],\n [6, 18], [6, 22], [6, 26], [6, 30], [6, 34],\n [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50],\n];\n\nfunction setFunctionModule(\n modules: boolean[][],\n isFunction: boolean[][],\n x: number,\n y: number,\n dark: boolean,\n): void {\n modules[y][x] = dark;\n isFunction[y][x] = true;\n}\n\nfunction drawFunctionPatterns(modules: boolean[][], isFunction: boolean[][], version: number): void {\n const size = modules.length;\n\n // Timing patterns.\n for (let i = 0; i < size; i++) {\n setFunctionModule(modules, isFunction, 6, i, i % 2 === 0);\n setFunctionModule(modules, isFunction, i, 6, i % 2 === 0);\n }\n\n // Finder patterns (with separators) at three corners.\n drawFinderPattern(modules, isFunction, 3, 3);\n drawFinderPattern(modules, isFunction, size - 4, 3);\n drawFinderPattern(modules, isFunction, 3, size - 4);\n\n // Alignment patterns: all pairs except the three finder corners.\n const positions = ALIGNMENT_POSITIONS[version];\n for (let i = 0; i < positions.length; i++) {\n for (let j = 0; j < positions.length; j++) {\n const skip =\n (i === 0 && j === 0) ||\n (i === 0 && j === positions.length - 1) ||\n (i === positions.length - 1 && j === 0);\n if (!skip) {\n drawAlignmentPattern(modules, isFunction, positions[i], positions[j]);\n }\n }\n }\n\n // Format-info reserved areas (drawn with mask later, but the modules must\n // be marked as function modules before codeword placement).\n drawFormatBits(modules, isFunction, 0);\n\n // Dark module.\n setFunctionModule(modules, isFunction, 8, size - 8, true);\n\n // Version information (versions \u2265 7).\n if (version >= 7) {\n drawVersionBits(modules, isFunction, version);\n }\n}\n\nfunction drawFinderPattern(modules: boolean[][], isFunction: boolean[][], cx: number, cy: number): void {\n const size = modules.length;\n for (let dy = -4; dy <= 4; dy++) {\n for (let dx = -4; dx <= 4; dx++) {\n const x = cx + dx;\n const y = cy + dy;\n if (x < 0 || x >= size || y < 0 || y >= size) {\n continue;\n }\n const distance = Math.max(Math.abs(dx), Math.abs(dy));\n setFunctionModule(modules, isFunction, x, y, distance !== 2 && distance !== 4);\n }\n }\n}\n\nfunction drawAlignmentPattern(modules: boolean[][], isFunction: boolean[][], cx: number, cy: number): void {\n for (let dy = -2; dy <= 2; dy++) {\n for (let dx = -2; dx <= 2; dx++) {\n setFunctionModule(modules, isFunction, cx + dx, cy + dy, Math.max(Math.abs(dx), Math.abs(dy)) !== 1);\n }\n }\n}\n\n/** 15-bit format info: 5 data bits BCH(15,5)-expanded, XORed with 0x5412. */\nfunction drawFormatBits(modules: boolean[][], isFunction: boolean[][], mask: number): void {\n const size = modules.length;\n\n const data = (FORMAT_ECL_M << 3) | mask;\n let rem = data;\n for (let i = 0; i < 10; i++) {\n rem = (rem << 1) ^ ((rem >>> 9) * 0x537);\n }\n const bits = ((data << 10) | rem) ^ 0x5412;\n\n // Around the top-left finder.\n for (let i = 0; i <= 5; i++) {\n setFunctionModule(modules, isFunction, 8, i, ((bits >>> i) & 1) !== 0);\n }\n setFunctionModule(modules, isFunction, 8, 7, ((bits >>> 6) & 1) !== 0);\n setFunctionModule(modules, isFunction, 8, 8, ((bits >>> 7) & 1) !== 0);\n setFunctionModule(modules, isFunction, 7, 8, ((bits >>> 8) & 1) !== 0);\n for (let i = 9; i < 15; i++) {\n setFunctionModule(modules, isFunction, 14 - i, 8, ((bits >>> i) & 1) !== 0);\n }\n\n // Second copy: below the top-right finder and beside the bottom-left one.\n for (let i = 0; i < 8; i++) {\n setFunctionModule(modules, isFunction, size - 1 - i, 8, ((bits >>> i) & 1) !== 0);\n }\n for (let i = 8; i < 15; i++) {\n setFunctionModule(modules, isFunction, 8, size - 15 + i, ((bits >>> i) & 1) !== 0);\n }\n}\n\n/** 18-bit version info (versions \u2265 7): 6 data bits + BCH(18,6) remainder. */\nfunction drawVersionBits(modules: boolean[][], isFunction: boolean[][], version: number): void {\n const size = modules.length;\n\n let rem = version;\n for (let i = 0; i < 12; i++) {\n rem = (rem << 1) ^ ((rem >>> 11) * 0x1F25);\n }\n const bits = (version << 12) | rem;\n\n for (let i = 0; i < 18; i++) {\n const bit = ((bits >>> i) & 1) !== 0;\n const a = size - 11 + (i % 3);\n const b = Math.floor(i / 3);\n setFunctionModule(modules, isFunction, a, b, bit);\n setFunctionModule(modules, isFunction, b, a, bit);\n }\n}\n\n/** Zig-zag codeword placement over non-function modules. */\nfunction drawCodewords(modules: boolean[][], isFunction: boolean[][], codewords: Uint8Array): void {\n const size = modules.length;\n let bitIndex = 0;\n\n for (let right = size - 1; right >= 1; right -= 2) {\n if (right === 6) {\n right = 5;\n }\n for (let vertical = 0; vertical < size; vertical++) {\n for (let j = 0; j < 2; j++) {\n const x = right - j;\n const upward = ((right + 1) & 2) === 0;\n const y = upward ? size - 1 - vertical : vertical;\n if (!isFunction[y][x] && bitIndex < codewords.length * 8) {\n modules[y][x] = ((codewords[bitIndex >> 3] >>> (7 - (bitIndex & 7))) & 1) !== 0;\n bitIndex++;\n }\n }\n }\n }\n}\n\n/** XORs the mask pattern over non-function modules (involutive). */\nfunction applyMask(modules: boolean[][], isFunction: boolean[][], mask: number): void {\n const size = modules.length;\n for (let y = 0; y < size; y++) {\n for (let x = 0; x < size; x++) {\n if (isFunction[y][x]) {\n continue;\n }\n let invert: boolean;\n switch (mask) {\n case 0: invert = (x + y) % 2 === 0; break;\n case 1: invert = y % 2 === 0; break;\n case 2: invert = x % 3 === 0; break;\n case 3: invert = (x + y) % 3 === 0; break;\n case 4: invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0; break;\n case 5: invert = ((x * y) % 2) + ((x * y) % 3) === 0; break;\n case 6: invert = (((x * y) % 2) + ((x * y) % 3)) % 2 === 0; break;\n default: invert = (((x + y) % 2) + ((x * y) % 3)) % 2 === 0; break;\n }\n if (invert) {\n modules[y][x] = !modules[y][x];\n }\n }\n }\n}\n\n// \u2500\u2500 Mask penalty scoring (rules N1\u2013N4) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction computePenalty(modules: boolean[][]): number {\n const size = modules.length;\n let penalty = 0;\n\n // N1: runs of \u22655 same-colour modules in a row/column.\n for (let y = 0; y < size; y++) {\n let runColor = false;\n let runLength = 0;\n for (let x = 0; x < size; x++) {\n if (x === 0 || modules[y][x] !== runColor) {\n runColor = modules[y][x];\n runLength = 1;\n } else {\n runLength++;\n if (runLength === 5) {\n penalty += 3;\n } else if (runLength > 5) {\n penalty += 1;\n }\n }\n }\n }\n for (let x = 0; x < size; x++) {\n let runColor = false;\n let runLength = 0;\n for (let y = 0; y < size; y++) {\n if (y === 0 || modules[y][x] !== runColor) {\n runColor = modules[y][x];\n runLength = 1;\n } else {\n runLength++;\n if (runLength === 5) {\n penalty += 3;\n } else if (runLength > 5) {\n penalty += 1;\n }\n }\n }\n }\n\n // N2: 2\u00D72 blocks of the same colour.\n for (let y = 0; y < size - 1; y++) {\n for (let x = 0; x < size - 1; x++) {\n const c = modules[y][x];\n if (c === modules[y][x + 1] && c === modules[y + 1][x] && c === modules[y + 1][x + 1]) {\n penalty += 3;\n }\n }\n }\n\n // N3: finder-like 1:1:3:1:1 patterns with 4-module light flank.\n const hasFinderPattern = (line: boolean[], start: number): number => {\n const core = [true, false, true, true, true, false, true];\n const matchesCore = core.every((value, index) => line[start + index] === value);\n if (!matchesCore) {\n return 0;\n }\n const lightBefore = start >= 4 && line.slice(start - 4, start).every((v) => !v);\n const lightAfter = start + 11 <= line.length && line.slice(start + 7, start + 11).every((v) => !v);\n return (lightBefore ? 40 : 0) + (lightAfter ? 40 : 0);\n };\n\n for (let y = 0; y < size; y++) {\n const row = modules[y];\n const column = modules.map((r) => r[y]);\n for (let x = 0; x + 7 <= size; x++) {\n penalty += hasFinderPattern(row, x);\n penalty += hasFinderPattern(column, x);\n }\n }\n\n // N4: dark-module proportion deviation from 50%, in 5% steps.\n let dark = 0;\n for (const row of modules) {\n for (const module of row) {\n if (module) {\n dark++;\n }\n }\n }\n const total = size * size;\n const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;\n penalty += k * 10;\n\n return penalty;\n}\n\n// \u2500\u2500 SVG rendering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Options for {@link qrToSvg}. */\nexport interface QrSvgOptions {\n /** Dark module colour. @default '#000000' */\n dark?: string;\n\n /** Light/background colour; `'transparent'` is allowed. @default '#ffffff' */\n light?: string;\n\n /** Quiet-zone width in modules on each side. @default 2 */\n quietZone?: number;\n}\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Renders an encoded symbol as a crisp, scalable `<svg>` element. One\n * `<path>` carries all dark modules so the output stays compact.\n *\n * Built with `createElementNS`/`setAttribute` rather than markup strings so\n * caller-supplied colours can never be interpreted as HTML (CodeQL\n * js/html-constructed-from-input). Append the returned element directly;\n * never serialize it back through `innerHTML`.\n */\nexport function qrToSvg(qr: QrCode, options: QrSvgOptions = {}): SVGSVGElement {\n const dark = options.dark ?? '#000000';\n const light = options.light ?? '#ffffff';\n const quietZone = options.quietZone ?? 2;\n const dimension = qr.size + quietZone * 2;\n\n let path = '';\n for (let y = 0; y < qr.size; y++) {\n for (let x = 0; x < qr.size; x++) {\n if (qr.modules[y][x]) {\n path += `M${x + quietZone} ${y + quietZone}h1v1h-1z`;\n }\n }\n }\n\n const svg = document.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('viewBox', `0 0 ${dimension} ${dimension}`);\n svg.setAttribute('shape-rendering', 'crispEdges');\n svg.setAttribute('role', 'img');\n\n const rect = document.createElementNS(SVG_NS, 'rect');\n rect.setAttribute('width', String(dimension));\n rect.setAttribute('height', String(dimension));\n rect.setAttribute('fill', light);\n svg.appendChild(rect);\n\n const modules = document.createElementNS(SVG_NS, 'path');\n modules.setAttribute('d', path);\n modules.setAttribute('fill', dark);\n svg.appendChild(modules);\n\n return svg;\n}\n", "/**\n * Wallet discovery via the `/.well-known/enbox-connect` document.\n *\n * Shared by the connect modal (relay discovery + custom-URL validation)\n * and exported for dapps rolling their own wallet selection UI.\n *\n * @module\n */\n\n/** Path of the wallet's connect discovery document, relative to its origin. */\nexport const WALLET_WELL_KNOWN_PATH = '/.well-known/enbox-connect';\n\n/** Timeout applied to the well-known validation fetch. */\nconst WELL_KNOWN_FETCH_TIMEOUT_MS = 6_000;\n\n/** The wallet's `/.well-known/enbox-connect` discovery document. */\nexport interface WalletWellKnownDocument {\n /** Base URL of the relay that brokers this wallet's remote connects. */\n connectServerUrl: string;\n}\n\n/**\n * Fetch a wallet's `/.well-known/enbox-connect` discovery document.\n *\n * Resolves the parsed document when it is reachable and names a\n * `connectServerUrl`; resolves `undefined` for unreachable origins, non-2xx\n * responses, CORS failures, and malformed documents.\n */\nexport async function fetchWalletWellKnown(origin: string): Promise<WalletWellKnownDocument | undefined> {\n try {\n const wellKnownUrl = new URL(WALLET_WELL_KNOWN_PATH, origin).toString();\n const response = await fetch(wellKnownUrl, { signal: AbortSignal.timeout(WELL_KNOWN_FETCH_TIMEOUT_MS) });\n if (!response.ok) {\n return undefined;\n }\n\n const payload = await response.json() as { connectServerUrl?: unknown } | null;\n if (typeof payload?.connectServerUrl !== 'string') {\n return undefined;\n }\n return { connectServerUrl: payload.connectServerUrl };\n } catch {\n return undefined;\n }\n}\n\n/**\n * Fetch a wallet's `/.well-known/enbox-connect` discovery document to confirm\n * the origin hosts an Enbox-compatible wallet.\n *\n * Resolves `true` only when the document is reachable and names a\n * `connectServerUrl`. Unreachable origins, non-2xx responses, CORS failures,\n * and malformed documents resolve `false`.\n */\nexport async function probeWalletWellKnown(origin: string): Promise<boolean> {\n return (await fetchWalletWellKnown(origin)) !== undefined;\n}\n", "/**\n * Relay connect runner \u2014 the dapp side of the QR/deep-link connect flow,\n * with interactive PIN retry.\n *\n * This mirrors the `@enbox/connect` kernel `ConnectClient` step-for-step and\n * is composed entirely from the kernel's exported primitives (`sealRequest`,\n * `openResponse`, `RelayClientTransport`); no cryptography is reimplemented\n * here. It exists as a separate orchestrator for one reason the kernel\n * client cannot express today: **PIN retry against the delivered response**.\n * `ConnectClient` collects the PIN once and opens the response once, so a\n * mistyped code fails the whole handshake \u2014 the wallet user would have to\n * scan and approve again. The connect modal instead keeps the sealed\n * response and re-runs `openResponse` per attempt, which is safe because\n * opening is a pure decrypt-and-verify step.\n *\n * If the kernel later grows a PIN-attempts seam, this module collapses into\n * `ConnectClient` usage.\n *\n * @module\n */\n\nimport type { Jwk } from '@enbox/crypto';\nimport type {\n ConnectClientMetadata,\n ConnectPermissionRequest,\n ConnectRequest,\n ConnectResult,\n WalletUriHandoff,\n} from '@enbox/connect';\n\nimport { DidJwk } from '@enbox/dids';\nimport { X25519 } from '@enbox/crypto';\nimport {\n CONNECT_DENIED_TOKEN,\n openResponse,\n randomToken,\n RelayClientTransport,\n sealRequest,\n} from '@enbox/connect';\n\n/** Maximum interactive PIN attempts before the handshake fails. */\nexport const MAX_PIN_ATTEMPTS = 6;\n\n/** Thrown internally when a relay handshake is cancelled by the UI. */\nexport class RelayConnectCancelledError extends Error {\n constructor() {\n super('[@enbox/browser] Relay connect cancelled.');\n this.name = 'RelayConnectCancelledError';\n }\n}\n\n/** Options for {@link runRelayConnect}. */\nexport interface RelayConnectOptions {\n /** Relay base URL (the wallet's `connectServerUrl`). */\n connectServerUrl: string;\n\n /** Wallet URI the request pointer is attached to (QR / deep-link target). */\n walletUri: string;\n\n /** The user-friendly name of the app, shown in the wallet consent UI. */\n appName: string;\n\n /** Optional icon URL for the app, shown in the wallet consent UI. */\n appIcon?: string;\n\n /** Optional client/environment metadata for wallet session display. */\n clientMetadata?: ConnectClientMetadata;\n\n /** DWN protocols and permission scopes being requested. */\n permissionRequests: ConnectPermissionRequest[];\n\n /** Total milliseconds to poll the relay for a wallet response. */\n timeoutMs?: number;\n\n /** Milliseconds between relay polling attempts. */\n pollIntervalMs?: number;\n\n /**\n * Receives the wallet URI handoff (with the request pointer TTL) as soon\n * as the request is delivered \u2014 render it as a QR code or deep link.\n */\n onWalletUriReady: (handoff: WalletUriHandoff) => void;\n\n /**\n * Collects one PIN attempt from the user. Called again (with the attempt\n * number, 1-based, and the previous failure) after a wrong code, up to\n * {@link MAX_PIN_ATTEMPTS} times.\n */\n requestPin: (attempt: number, previousError?: Error) => Promise<string>;\n\n /**\n * Cancellation signal: when it settles, polling stops and the handshake\n * rejects with {@link RelayConnectCancelledError}.\n */\n cancelled?: Promise<never> | undefined;\n\n /** Transport factory override (tests). */\n createTransport?: (options: {\n connectServerUrl: string;\n walletUri: string;\n timeoutMs?: number;\n pollIntervalMs?: number;\n }) => Pick<RelayClientTransport, 'requestProfile' | 'deliverRequest' | 'awaitResponse' | 'requiresPin'>;\n}\n\n/**\n * Runs one relay-mediated connect handshake end-to-end and returns the\n * delegated credentials, or `undefined` when the user denied in the wallet.\n */\nexport async function runRelayConnect(options: RelayConnectOptions): Promise<ConnectResult | undefined> {\n const createTransport = options.createTransport\n ?? ((transportOptions): RelayClientTransport => new RelayClientTransport(transportOptions));\n\n const transport = createTransport({\n connectServerUrl : options.connectServerUrl,\n walletUri : options.walletUri,\n timeoutMs : options.timeoutMs,\n pollIntervalMs : options.pollIntervalMs,\n });\n\n // Ephemeral client DID for request signing and response addressing, and a\n // fresh X25519 pair the wallet seals the response to \u2014 same shape as the\n // kernel `ConnectClient`.\n const clientDid = await DidJwk.create();\n const responsePrivateKey = await X25519.generateKey();\n const responsePublicKey: Jwk = { kty: 'OKP', crv: 'X25519', x: responsePrivateKey.x };\n\n const nonce = randomToken();\n const state = randomToken();\n\n const profile = await transport.requestProfile(state);\n\n const request: ConnectRequest = {\n clientDid : clientDid.uri,\n appName : options.appName,\n appIcon : options.appIcon,\n clientMetadata : options.clientMetadata,\n permissionRequests : options.permissionRequests,\n supportedDidMethods : ['did:dht', 'did:jwk'],\n nonce,\n state,\n responseKey : responsePublicKey,\n reply : profile.reply,\n };\n\n const requestJwe = await sealRequest({ request, signer: clientDid, encryption: profile.encryption });\n\n const handoff = await transport.deliverRequest(requestJwe);\n if (handoff !== undefined) {\n options.onWalletUriReady(handoff);\n }\n\n const race = options.cancelled === undefined\n ? transport.awaitResponse()\n : Promise.race([transport.awaitResponse(), options.cancelled]);\n\n const responseCiphertext = await race;\n if (responseCiphertext === CONNECT_DENIED_TOKEN) {\n return undefined;\n }\n\n // Interactive PIN loop: opening is a pure decrypt-and-verify step, so a\n // wrong code costs one more attempt, not a whole new wallet approval.\n // Errors raised by the kernel's value checks carry a 'Connect:' prefix and\n // indicate a protocol violation, not a mistyped code \u2014 those fail closed.\n let lastError: Error | undefined;\n for (let attempt = 1; attempt <= MAX_PIN_ATTEMPTS; attempt++) {\n const pin = await (options.cancelled === undefined\n ? options.requestPin(attempt, lastError)\n : Promise.race([options.requestPin(attempt, lastError), options.cancelled]));\n\n try {\n const response = await openResponse({\n jwe : responseCiphertext,\n recipientPrivateKey : responsePrivateKey,\n expected : { clientDid: clientDid.uri, nonce, state },\n pin,\n });\n\n if (response.delegatePortableDid === undefined) {\n throw new Error('Connect: wallet response omitted `delegatePortableDid`.');\n }\n\n return {\n delegatePortableDid : response.delegatePortableDid,\n delegateGrants : response.delegateGrants,\n connectedDid : response.providerDid,\n sessionRevocations : response.sessionRevocations,\n };\n } catch (error) {\n const failure = error instanceof Error ? error : new Error(String(error));\n if (failure.message.startsWith('Connect:')) {\n // Structural/value-check failure \u2014 retrying the PIN cannot help.\n throw failure;\n }\n lastError = failure;\n }\n }\n\n throw new Error(`[@enbox/browser] The pairing code did not match after ${MAX_PIN_ATTEMPTS} attempts.`);\n}\n", "/**\n * Browser connect handler for `@enbox/auth`.\n *\n * Implements the {@link ConnectHandler} interface using browser-native\n * DWeb Connect (popup + postMessage) with a wallet selector modal.\n *\n * @module\n */\n\nimport type { ConnectPermissionRequest } from '@enbox/connect';\nimport type { ConnectHandler, ConnectResult } from '@enbox/auth';\n\nimport { runConnectModal } from './ui/connect-modal.js';\n\nimport type { ConnectMethod } from './ui/connect-modal.js';\n\n/** A wallet entry shown in the wallet selector modal. */\nexport interface WalletOption {\n /** Display name (e.g. \"Enbox\"). */\n name: string;\n\n /** Base URL of the wallet app (e.g. \"https://enbox-wallet.pages.dev\"). */\n url: string;\n\n /** Optional icon URL. If omitted, the wallet's favicon is used. */\n icon?: string;\n\n /** Short description shown below the wallet name in the selector. */\n description?: string;\n}\n\n/** Default wallets shown in the selector when no overrides are provided. */\nexport const DEFAULT_WALLETS: WalletOption[] = [\n {\n name : 'Enbox',\n url : 'https://enbox-wallet.pages.dev',\n description : 'Manage your digital identity and data',\n },\n {\n name : 'Prism',\n url : 'https://prism-wallet.pages.dev',\n description : 'A clear view into your digital identity',\n },\n {\n name : 'Matcha',\n url : 'https://matcha-wallet.pages.dev',\n description : 'A fresh approach to digital identity',\n },\n {\n name : 'Onyx',\n url : 'https://onyx-wallet.pages.dev',\n description : 'A refined home for your digital identity',\n },\n];\n\n/** Options for creating a BrowserConnectHandler. */\nexport interface BrowserConnectHandlerOptions {\n /**\n * Known wallets shown in the wallet selector modal.\n * If omitted, {@link DEFAULT_WALLETS} is used.\n */\n wallets?: WalletOption[];\n\n /**\n * Explicit wallet URL. If provided, the wallet selector is skipped\n * and this URL is used directly.\n */\n walletUrl?: string;\n\n /**\n * Timeout in milliseconds for the wallet popup flow.\n * @default 300_000 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Display name of the requesting application.\n * Shown in the wallet's permission consent screen.\n */\n appName?: string;\n\n /**\n * Icon URL of the requesting application.\n * Shown alongside the app name in the wallet's consent screen.\n * Defaults to `${window.location.origin}/favicon.ico` if omitted.\n */\n appIcon?: string;\n\n /**\n * Preferred connect method on open: `'phone'` (QR / deep link via the\n * relay) or `'browser'` (wallet popup on this device). Overrides the\n * remembered choice.\n * @default 'phone'\n */\n preferredMethod?: ConnectMethod;\n\n /**\n * Remember the successful method + wallet in localStorage and pre-shape\n * the next connect session accordingly.\n * @default true\n */\n rememberChoice?: boolean;\n\n /**\n * Relay base URL override for the phone path. When omitted, each wallet's\n * `connectServerUrl` is discovered from its `/.well-known/enbox-connect`\n * document.\n */\n connectServerUrl?: string;\n\n /**\n * Path appended to the wallet origin to form the phone path's QR /\n * deep-link target.\n * @default '/connect/app'\n */\n relayWalletPath?: string;\n}\n\n/**\n * Create a browser-native connect handler over the connect modal.\n *\n * The modal owns the whole session on one surface: the phone path (a QR /\n * deep link over the relay, with pairing-code entry) is the default, the\n * in-browser wallet popup is the alternate, and the wallet catalog plus\n * custom-URL entry live in a disclosure. It resolves with the delegate\n * credentials on success and `undefined` when the user denies.\n *\n * @example\n * ```ts\n * import { AuthManager, BrowserConnectHandler } from '@enbox/browser';\n *\n * const auth = await AuthManager.create({\n * connectHandler: BrowserConnectHandler({\n * appName: 'My Dapp',\n * }),\n * });\n *\n * const session = await auth.connect({ protocols: [NotesProtocol] });\n * ```\n */\nexport function BrowserConnectHandler(\n options: BrowserConnectHandlerOptions = {},\n): ConnectHandler {\n const {\n wallets = DEFAULT_WALLETS,\n walletUrl,\n timeout,\n appName,\n appIcon,\n preferredMethod,\n rememberChoice,\n connectServerUrl,\n relayWalletPath,\n } = options;\n\n return {\n async requestAccess(params: {\n permissionRequests: ConnectPermissionRequest[];\n }): Promise<ConnectResult | undefined> {\n return runConnectModal({\n wallets,\n walletUrl,\n preferredMethod,\n rememberChoice,\n appName,\n appIcon : appIcon ?? `${window.location.origin}/favicon.ico`,\n connectServerUrl,\n relayWalletPath,\n timeout,\n permissionRequests : params.permissionRequests,\n });\n },\n };\n}\n", "/**\n * DWeb Connect wallet transport \u2014 the wallet side of the popup/postMessage\n * connect flow, exported for wallet apps (e.g. the Enbox web wallet).\n *\n * A wallet's `/dweb-connect` page creates one transport per session:\n *\n * 1. `create()` generates a fresh ephemeral X25519 key pair and emits the\n * `loaded` beacon (public key + wallet origin) to the opener window with a\n * pinned `targetOrigin`.\n * 2. `awaitRequest()` receives the sealed request ciphertext and opens it via\n * the `@enbox/connect` kernel (`ConnectProvider.openRequest`), which\n * value-checks the `apv` origin binding against this wallet's origin.\n * 3. After the consent ceremony, the wallet posts the sealed response JWE via\n * `sendResponse()` \u2014 or the deny token via `deny()` \u2014 back to the opener,\n * again with a pinned `targetOrigin`.\n *\n * The dapp origin is never assumed: it is taken from an explicit option or\n * derived from `document.referrer`, and `create()` fails when neither is\n * available. `'*'` is never used as a `targetOrigin`.\n *\n * @module\n */\n\nimport type { ConnectRequest } from '@enbox/connect';\nimport type { Jwk } from '@enbox/crypto';\n\nimport { X25519 } from '@enbox/crypto';\nimport { CONNECT_DENIED_TOKEN, ConnectProvider } from '@enbox/connect';\n\nimport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n getTrustedMessage,\n} from './dweb-connect-messages.js';\n\n/** Default budget for awaiting the dapp's sealed request. */\nconst DEFAULT_REQUEST_TIMEOUT_MS = 300_000;\n\n/** Options for creating a {@link WalletPostMessageTransport}. */\nexport type WalletPostMessageTransportOptions = {\n /**\n * Origin of the dapp that opened this wallet popup. When omitted, it is\n * derived from `document.referrer`; creation fails when neither is\n * available \u2014 the transport never falls back to `'*'`.\n */\n dappOrigin?: string;\n\n /**\n * The dapp window to exchange messages with.\n * @default window.opener\n */\n dappWindow?: Window;\n\n /**\n * Budget in milliseconds for awaiting the dapp's sealed request.\n * @default 300_000 (5 minutes)\n */\n timeoutMs?: number;\n};\n\n/**\n * Wallet-side postMessage transport for the DWeb Connect popup flow.\n *\n * Security properties:\n * - `targetOrigin` of every outbound `postMessage` (beacon and response) is\n * pinned to the dapp origin \u2014 never `'*'`.\n * - Inbound messages are dropped unless `event.origin` equals the pinned dapp\n * origin AND `event.source` is the dapp window.\n * - The ephemeral X25519 private key never leaves the transport; the request\n * JWE is opened by the kernel with the `apv` header value-checked against\n * this wallet's own origin.\n */\nexport class WalletPostMessageTransport {\n private readonly _dappOrigin: string;\n private readonly _dappWindow: Window;\n private readonly _recipientPrivateKey: Jwk;\n\n private _requestReceived = false;\n private _timeoutId?: ReturnType<typeof setTimeout>;\n private _messageListener?: (event: MessageEvent) => void;\n\n private readonly _requestPromise: Promise<ConnectRequest>;\n private _resolveRequest?: (request: ConnectRequest) => void;\n private _rejectRequest?: (error: Error) => void;\n\n private constructor(params: { dappOrigin: string; dappWindow: Window; recipientPrivateKey: Jwk; timeoutMs: number }) {\n this._dappOrigin = params.dappOrigin;\n this._dappWindow = params.dappWindow;\n this._recipientPrivateKey = params.recipientPrivateKey;\n\n this._requestPromise = new Promise<ConnectRequest>((resolve, reject): void => {\n this._resolveRequest = resolve;\n this._rejectRequest = reject;\n });\n // Mark early rejections (timeout before `awaitRequest()` is called) as\n // handled until the wallet attaches its own handlers.\n this._requestPromise.catch((): undefined => undefined);\n\n this._messageListener = (event: MessageEvent): void => { this.onMessage(event); };\n window.addEventListener('message', this._messageListener);\n\n this._timeoutId = setTimeout((): void => {\n this.close();\n this._rejectRequest?.(new Error('[@enbox/browser] Timed out waiting for the connect request from the dapp.'));\n }, params.timeoutMs);\n }\n\n /**\n * Creates the transport for one connect session: resolves and pins the dapp\n * origin, generates a fresh ephemeral X25519 key pair, starts listening for\n * the sealed request, and emits the `loaded` beacon to the dapp window.\n *\n * @throws If not in a browser, if no dapp window is available, or if the\n * dapp origin can neither be supplied nor derived from the referrer.\n */\n public static async create(options: WalletPostMessageTransportOptions = {}): Promise<WalletPostMessageTransport> {\n if (typeof window === 'undefined') {\n throw new Error('[@enbox/browser] WalletPostMessageTransport is only available in browser environments.');\n }\n\n const dappWindow = options.dappWindow ?? window.opener as Window | null;\n if (!dappWindow) {\n throw new Error('[@enbox/browser] No opener window: the DWeb Connect page must be opened as a popup by the dapp.');\n }\n\n const dappOrigin = resolveDappOrigin(options.dappOrigin);\n\n const recipientPrivateKey = await X25519.generateKey();\n const walletEpk: Jwk = { kty: 'OKP', crv: 'X25519', x: recipientPrivateKey.x };\n\n const transport = new WalletPostMessageTransport({\n dappOrigin,\n dappWindow,\n recipientPrivateKey,\n timeoutMs: options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n });\n\n // The listener is registered, so the beacon cannot race the request.\n dappWindow.postMessage({\n type : DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n walletEpk,\n walletOrigin : globalThis.location.origin,\n }, dappOrigin);\n\n return transport;\n }\n\n /** The pinned origin of the dapp this transport exchanges messages with. */\n public get dappOrigin(): string {\n return this._dappOrigin;\n }\n\n /**\n * Awaits the dapp's sealed request and opens it via the kernel: ECDH-ES\n * decryption with this session's ephemeral key, `apv` value-checked against\n * this wallet's origin, JWT signature verification, and payload shape\n * assertion. Rejects on timeout, on an unopenable request, or when the\n * request does not use the `post_message` reply mode.\n */\n public async awaitRequest(): Promise<ConnectRequest> {\n return await this._requestPromise;\n }\n\n /**\n * Posts the sealed response JWE (or the deny token) back to the dapp window\n * with the `targetOrigin` pinned to the dapp origin, then closes the\n * transport.\n *\n * @param idToken - The sealed response JWE, or the literal deny token.\n */\n public sendResponse(idToken: string): void {\n this._dappWindow.postMessage({\n type : DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n payload : idToken,\n }, this._dappOrigin);\n this.close();\n }\n\n /** Posts the deny token back to the dapp \u2014 the user rejected the request. */\n public deny(): void {\n this.sendResponse(CONNECT_DENIED_TOKEN);\n }\n\n /** Stops listening and releases the session's timers. Idempotent. */\n public close(): void {\n clearTimeout(this._timeoutId);\n if (this._messageListener !== undefined) {\n window.removeEventListener('message', this._messageListener);\n this._messageListener = undefined;\n }\n }\n\n private onMessage(event: MessageEvent): void {\n const message = getTrustedMessage(event, this._dappOrigin, this._dappWindow);\n if (message === undefined) { return; }\n\n if (message.type !== DWEB_CONNECT_REQUEST_MESSAGE_TYPE || this._requestReceived) { return; }\n this._requestReceived = true;\n\n if (typeof message.jwe !== 'string') {\n this.settleRequest(new Error('[@enbox/browser] Connect request message did not carry a ciphertext payload.'));\n return;\n }\n\n void this.openRequest(message.jwe);\n }\n\n private async openRequest(jwe: string): Promise<void> {\n try {\n const request = await ConnectProvider.openRequest({\n jwe,\n decryption: {\n mode : 'ecdh-es',\n recipientPrivateKey : this._recipientPrivateKey,\n walletOrigin : globalThis.location.origin,\n },\n });\n\n if (request.reply.mode !== 'post_message') {\n this.settleRequest(new Error('[@enbox/browser] Connect request over the popup channel must use the `post_message` reply mode.'));\n return;\n }\n\n this.settleRequest(request);\n } catch (error) {\n this.settleRequest(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private settleRequest(outcome: ConnectRequest | Error): void {\n clearTimeout(this._timeoutId);\n if (outcome instanceof Error) {\n this.close();\n this._rejectRequest?.(outcome);\n return;\n }\n this._resolveRequest?.(outcome);\n }\n}\n\n/**\n * Resolves the dapp origin to pin: the explicit option when provided,\n * otherwise the origin of `document.referrer`. Never falls back to `'*'`.\n */\nfunction resolveDappOrigin(explicitOrigin: string | undefined): string {\n if (explicitOrigin !== undefined) {\n return new URL(explicitOrigin).origin;\n }\n\n if (document.referrer) {\n return new URL(document.referrer).origin;\n }\n\n throw new Error(\n '[@enbox/browser] Unable to determine the dapp origin: no `dappOrigin` option was provided and `document.referrer` is empty.'\n );\n}\n"],
5
- "mappings": "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",
6
- "names": ["Enbox", "defineProtocol", "repository", "AuthManager", "AuthSession", "normalizeProtocolRequests", "WalletConnect", "CONNECT_DENIED_TOKEN", "ConnectProvider", "DidDht", "DidWeb", "UniversalResolver", "parseDrlUrl", "url", "idx", "prefix", "rest", "slashIdx", "didResolver", "UniversalResolver", "DidDht", "DidWeb", "httpToHttpsRegex", "trailingSlashRegex", "DRL_CACHE_NAME", "getDwnEndpoints", "did", "didDocument", "endpoints", "service", "url", "openDrlCache", "handleEvent", "event", "path", "options", "drl", "responseCache", "cachedResponse", "match", "cacheTime", "fetchResource", "response", "error", "lastError", "endpoint", "cacheResponse", "cache", "clonedResponse", "headers", "modifiedResponse", "installWorker", "workerSelf", "parsed", "parseDrlUrl", "installUrl", "loaderStyles", "tabContent", "elementsInjected", "overlayElement", "styleElement", "injectElements", "cancelNavigation", "removeElements", "activeNavigation", "linkFeaturesActive", "clickHandler", "pointerdownHandler", "addLinkFeatures", "anchor", "href", "openAsTab", "tab", "target", "resetContextMenuTarget", "contextMenuTarget", "removeLinkFeatures", "r", "activatePolyfills", "deactivatePolyfills", "clearDrlCache", "ConnectClient", "buildWalletIcon", "wallet", "wrap", "badge", "sources", "iconCandidates", "img", "index", "origin", "assertX25519PublicJwk", "CONNECT_DENIED_TOKEN", "ConnectClient", "DWEB_CONNECT_PATH", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "getTrustedMessage", "event", "expectedOrigin", "expectedSource", "data", "DEFAULT_TIMEOUT_MS", "CLOSED_POLL_INTERVAL_MS", "POPUP_WINDOW_NAME", "POPUP_WINDOW_FEATURES", "assertBrowserEnvironment", "PopupWindowClosedError", "PopupClientTransport", "options", "popupUrl", "DWEB_CONNECT_PATH", "popup", "resolve", "reject", "event", "state", "jwe", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "message", "getTrustedMessage", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "walletEpk", "assertX25519PublicJwk", "CONNECT_DENIED_TOKEN", "error", "collectBrowserClientMetadata", "resolvedOptions", "languages", "language", "connectViaPopup", "transport", "client", "ConnectClient", "ECC_PER_BLOCK", "NUM_BLOCKS", "TOTAL_CODEWORDS", "FORMAT_ECL_M", "MAX_VERSION", "dataCodewords", "version", "encodeQr", "text", "forcedMask", "data", "candidate", "capacityBits", "bits", "pushBits", "value", "length", "i", "byte", "padBytes", "codewords", "allCodewords", "buildInterleavedCodewords", "size", "modules", "isFunction", "drawFunctionPatterns", "drawCodewords", "mask", "bestPenalty", "applyMask", "drawFormatBits", "penalty", "computePenalty", "numBlocks", "eccLen", "totalCodewords", "numShortBlocks", "shortBlockLen", "blocks", "eccBlocks", "rsDivisor", "reedSolomonDivisor", "offset", "dataLen", "block", "reedSolomonRemainder", "result", "index", "maxDataLen", "b", "gfMultiply", "x", "y", "z", "degree", "root", "j", "divisor", "factor", "ALIGNMENT_POSITIONS", "setFunctionModule", "dark", "drawFinderPattern", "positions", "drawAlignmentPattern", "drawVersionBits", "cx", "cy", "dy", "dx", "distance", "rem", "bit", "a", "bitIndex", "right", "vertical", "invert", "runColor", "runLength", "c", "hasFinderPattern", "line", "start", "lightBefore", "v", "lightAfter", "row", "column", "r", "module", "total", "k", "SVG_NS", "qrToSvg", "qr", "options", "light", "quietZone", "dimension", "path", "svg", "rect", "WALLET_WELL_KNOWN_PATH", "fetchWalletWellKnown", "origin", "wellKnownUrl", "WALLET_WELL_KNOWN_PATH", "response", "payload", "probeWalletWellKnown", "DidJwk", "X25519", "CONNECT_DENIED_TOKEN", "openResponse", "randomToken", "RelayClientTransport", "sealRequest", "MAX_PIN_ATTEMPTS", "RelayConnectCancelledError", "runRelayConnect", "options", "transport", "transportOptions", "clientDid", "responsePrivateKey", "responsePublicKey", "nonce", "state", "profile", "request", "requestJwe", "handoff", "responseCiphertext", "lastError", "attempt", "pin", "response", "error", "failure", "LAST_CHOICE_STORAGE_KEY", "REMINT_SAFETY_MS", "REMINT_MIN_MS", "PIN_LENGTH", "discoverWalletConnectServerUrl", "walletOrigin", "fetchWalletWellKnown", "runPopupConnect", "options", "transport", "PopupClientTransport", "ConnectClient", "collectBrowserClientMetadata", "defaultIsMobile", "defaultDeps", "runRelayConnect", "probeWalletWellKnown", "readLastChoice", "storage", "raw", "parsed", "writeLastChoice", "choice", "createRelaySession", "cancel", "session", "cancelled", "_", "reject", "RelayConnectCancelledError", "runConnectModal", "deps", "wallets", "rememberChoice", "appName", "relayWalletPath", "isMobile", "lastChoice", "lockedWallet", "walletUrl", "walletInCatalog", "method", "resolve", "host", "shadow", "isDark", "style", "buildStyles", "overlay", "modal", "settled", "relaySession", "remintTimer", "popupBusy", "pinResolve", "discoveryCache", "cleanup", "onKeydown", "settle", "settler", "succeed", "result", "renderConnected", "cancelModal", "buildHeader", "stage", "footer", "setStage", "nodes", "renderBusy", "message", "el", "renderQr", "handoff", "link", "qrBox", "qrToSvg", "encodeQr", "renderPin", "attempt", "previousError", "resolvePin", "boxes", "inputs", "i", "input", "submitIfComplete", "code", "resolveOnce", "index", "event", "digits", "digit", "digitIndex", "check", "renderDenied", "stageButton", "startMethod", "stageLinkButton", "renderError", "error", "renderPhoneUnavailable", "startPopup", "renderPopupPrompt", "renderPopupWaiting", "renderPopupInterrupted", "blocked", "switchMethod", "resolveConnectServerUrl", "origin", "cached", "scheduleRemint", "expiresInSeconds", "delay", "startPhone", "renderFooter", "connectServerUrl", "failure", "flow", "PopupWindowClosedError", "next", "alt", "buildWalletSwitcher", "wrap", "current", "wallet", "toggle", "panel", "rows", "empty", "search", "query", "visible", "match", "row", "buildWalletIcon", "rowName", "custom", "go", "urlError", "allowUnverified", "useWallet", "submitCustom", "value", "valid", "e", "trapFocus", "url", "tag", "className", "text", "node", "label", "onClick", "button", "appIcon", "onCancel", "header", "identity", "icon", "title", "closeBtn", "focusables", "first", "last", "active", "bg", "muted", "border", "itemBg", "accent", "accentSoft", "danger", "DEFAULT_WALLETS", "BrowserConnectHandler", "options", "wallets", "walletUrl", "timeout", "appName", "appIcon", "preferredMethod", "rememberChoice", "connectServerUrl", "relayWalletPath", "params", "runConnectModal", "X25519", "CONNECT_DENIED_TOKEN", "ConnectProvider", "DEFAULT_REQUEST_TIMEOUT_MS", "WalletPostMessageTransport", "_WalletPostMessageTransport", "params", "resolve", "reject", "event", "options", "dappWindow", "dappOrigin", "resolveDappOrigin", "recipientPrivateKey", "X25519", "walletEpk", "transport", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "idToken", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "CONNECT_DENIED_TOKEN", "message", "getTrustedMessage", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "jwe", "request", "ConnectProvider", "error", "outcome", "explicitOrigin", "TypedRecord", "BrowserStorage", "DwnInterface", "DateSort", "DwnInterfaceName", "DwnMethodName"]
4
+ "sourcesContent": ["/**\n * @enbox/browser \u2014 The Enbox browser SDK.\n *\n * For browser-based dapps, this is the only package you need to import.\n * It re-exports the high-level API from `@enbox/api`, the authentication\n * layer from `@enbox/auth`, and provides browser-specific connect handlers.\n *\n * @example Single-import dapp setup\n * ```ts\n * import {\n * Enbox, BrowserConnectHandler,\n * defineProtocol, repository,\n * } from '@enbox/browser';\n *\n * const { enbox, session } = await Enbox.connect({\n * connectHandler: BrowserConnectHandler({ appName: 'My App' }),\n * protocols: [MyProtocol],\n * });\n * ```\n *\n * For non-browser environments (Node.js, CLI, desktop), import from\n * `@enbox/api` and `@enbox/auth` directly instead.\n *\n * @packageDocumentation\n */\n\n// \u2500\u2500\u2500 Re-exports from @enbox/api \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The high-level Enbox API: DWN records, protocols, repositories.\n\nexport {\n Enbox,\n defineProtocol,\n repository,\n} from '@enbox/api';\n\nexport type {\n EnboxAnonymousOptions,\n EnboxConnectOptions,\n EnboxConnectResult,\n EnboxParams,\n EnboxSessionParams,\n} from '@enbox/api';\n\n// \u2500\u2500\u2500 Re-exports from @enbox/auth \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Authentication lifecycle, session management, connect handlers.\n\nexport {\n AuthManager,\n AuthSession,\n normalizeProtocolRequests,\n WalletConnect,\n} from '@enbox/auth/browser';\n\nexport type {\n AuthEvent,\n AuthEventHandler,\n AuthManagerOptions,\n AuthState,\n ConnectHandler,\n ConnectOptions,\n ConnectResult,\n DisconnectOptions,\n HandlerConnectOptions,\n ImportFromPortableOptions,\n VaultConnectOptions,\n Permission,\n PortableIdentity,\n ProtocolRequest,\n RegistrationOptions,\n StorageAdapter,\n SyncOption,\n WalletConnectOptions,\n} from '@enbox/auth/browser';\n\n// \u2500\u2500\u2500 Re-exports from @enbox/connect \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The connect kernel pieces wallet apps need alongside the popup\n// transports: opening/sealing envelopes and the deny token.\n\nexport { CONNECT_DENIED_TOKEN, ConnectProvider } from '@enbox/connect';\nexport type { ConnectApproval, ConnectPermissionRequest, ConnectRequest } from '@enbox/connect';\n\n// \u2500\u2500\u2500 Browser-specific exports \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// DWeb Connect popup transports, wallet selector, DRL polyfills.\n\nexport * from './web-features.js';\nexport { BrowserConnectHandler, DEFAULT_WALLETS } from './browser-connect-handler.js';\nexport type { BrowserConnectHandlerOptions, WalletOption } from './browser-connect-handler.js';\nexport { connectViaPopup, PopupClientTransport, PopupWindowClosedError } from './dweb-connect-client.js';\nexport type { PopupClientTransportOptions, PopupConnectOptions } from './dweb-connect-client.js';\nexport { WalletPostMessageTransport } from './dweb-connect-wallet.js';\nexport type { WalletPostMessageTransportOptions } from './dweb-connect-wallet.js';\nexport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_PATH,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n} from './dweb-connect-messages.js';\nexport type {\n DWebConnectLoadedMessage,\n DWebConnectRequestMessage,\n DWebConnectResponseMessage,\n} from './dweb-connect-messages.js';\nexport { fetchWalletWellKnown, probeWalletWellKnown, WALLET_WELL_KNOWN_PATH } from './ui/wallet-well-known.js';\nexport type { WalletWellKnownDocument } from './ui/wallet-well-known.js';\nexport { discoverWalletConnectServerUrl, runConnectModal } from './ui/connect-modal.js';\nexport type { ConnectMethod, ConnectModalDeps, ConnectModalOptions } from './ui/connect-modal.js';\nexport { MAX_PIN_ATTEMPTS, RelayConnectCancelledError, runRelayConnect } from './relay-connect-runner.js';\nexport type { RelayConnectOptions } from './relay-connect-runner.js';\nexport { encodeQr, qrToSvg } from './ui/qr.js';\nexport type { QrCode, QrSvgOptions } from './ui/qr.js';\n\n// \u2500\u2500\u2500 Convenience re-exports for dapps \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// So that most browser dapps only need `@enbox/browser` (plus\n// `@enbox/protocols` for shared protocol definitions). These surface the\n// symbols dapps most commonly reached into sibling packages for; anything\n// more specialized is still available by importing the underlying package\n// directly.\n\n// Typed record wrapper (from @enbox/api).\nexport { TypedRecord } from '@enbox/api';\n\n// Custom storage adapter + DWN registration provider-auth callback shapes\n// (from @enbox/auth).\nexport { BrowserStorage } from '@enbox/auth/browser';\nexport type { ProviderAuthParams, ProviderAuthResult } from '@enbox/auth/browser';\n\n// DWN interface enum for typing agent requests (from @enbox/agent).\nexport { DwnInterface } from '@enbox/agent';\n\n// Common DWN primitives for record queries, permission scopes, and protocol\n// typing (from @enbox/dwn-sdk-js).\nexport { DateSort, DwnInterfaceName, DwnMethodName } from '@enbox/dwn-sdk-js';\nexport type { ProtocolActionRule, ProtocolDefinition } from '@enbox/dwn-sdk-js';\n", "/*\n This file is run in dual environments to make installation of the Service Worker code easier.\n Be mindful that code placed in any open excution space may be evaluated multiple times in different contexts,\n so take care to gate additions to only activate code in the right env, such as a Service Worker scope or page window.\n*/\n\nimport type { DidMethodResolver } from '@enbox/dids';\n\nimport { DidDht, DidWeb, UniversalResolver } from '@enbox/dids';\n\n/**\n * Result returned by the `onCacheCheck` callback.\n * When returned, it signals that the response for the given DRL should be cached.\n */\nexport type CacheCheckResult = {\n /** Time-to-live for the cached DRL response, in milliseconds. */\n ttl?: number;\n};\n\n/**\n * Callback invoked to determine whether a DRL response should be cached and for how long.\n * Returning a truthy `CacheCheckResult` opts in to caching; returning a falsy value skips it.\n */\nexport type CacheCheckCallback = (\n event: FetchEvent | Event,\n drl: string,\n) => CacheCheckResult | undefined | null | Promise<CacheCheckResult | undefined | null>;\n\n/**\n * Configuration options for {@link activatePolyfills}.\n */\nexport type ActivatePolyfillsOptions = {\n /**\n * Path to the script to register as a Service Worker.\n * Falls back to `document.currentScript.src` or `import.meta.url`.\n *\n * **Required in strict CSP environments** where `new Function()` is blocked and `import.meta`\n * cannot be evaluated dynamically.\n */\n path?: string;\n /** Set to `false` to skip Service Worker installation. Defaults to `true`. */\n serviceWorker?: boolean;\n /** Set to `false` to skip injection of DRL loading-overlay styles. Defaults to `true`. */\n injectStyles?: boolean;\n /** Set to `false` to skip activation of DRL anchor/link click handling. Defaults to `true`. */\n links?: boolean;\n /** Callback to control per-request caching behaviour. */\n onCacheCheck?: CacheCheckCallback;\n /**\n * DID method resolvers to use for DRL resolution. Defaults to `[DidDht, DidWeb]`.\n * Pass a custom array to add or replace DID methods (e.g., `[DidDht, DidWeb, DidJwk]`).\n */\n didResolvers?: DidMethodResolver[];\n};\n\n/**\n * An `HTMLElement` that has a `src` property (e.g., `<img>`, `<video>`, `<audio>`).\n * Extended with `__src__` to stash the original DRL src during context-menu swaps.\n */\ninterface DrlMediaElement extends HTMLElement {\n src: string;\n __src__?: string;\n}\n\nlet didResolver = new UniversalResolver({ didResolvers: [DidDht, DidWeb] });\n\nimport { parseDrlUrl } from './drl-url-parser.js';\nexport { parseDrlUrl } from './drl-url-parser.js';\n\nconst httpToHttpsRegex = /^http:/;\nconst trailingSlashRegex = /\\/$/;\nconst DRL_CACHE_NAME = 'drl';\n\n/** @internal Exported for testing. Resolves DWN service endpoints from a DID. */\nexport async function getDwnEndpoints(did: string): Promise<string[]> {\n const { didDocument } = await didResolver.resolve(did);\n const endpoints = didDocument?.service?.find(\n (service) => service.type === 'DecentralizedWebNode'\n )?.serviceEndpoint;\n if (!endpoints) {return [];}\n return (Array.isArray(endpoints) ? endpoints : [endpoints]).filter(\n (url) => typeof url === 'string' && url.startsWith('http')\n );\n}\n\n/** Returns an open DRL cache, or `undefined` if the Cache API is unavailable. */\nasync function openDrlCache(): Promise<Cache | undefined> {\n if (typeof caches === 'undefined') {return undefined;}\n return caches.open(DRL_CACHE_NAME);\n}\n\n/** @internal Exported for testing. Handles a DRL fetch event. */\nexport async function handleEvent(\n event: FetchEvent, did: string, path: string, options?: ActivatePolyfillsOptions\n): Promise<Response> {\n const drl = event.request.url\n .replace(httpToHttpsRegex, 'https:')\n .replace(trailingSlashRegex, '');\n const responseCache = await openDrlCache();\n const cachedResponse = await responseCache?.match(drl);\n if (cachedResponse) {\n if (!navigator.onLine) {return cachedResponse;}\n const match = await options?.onCacheCheck?.(event, drl);\n if (match) {\n const cacheTime = cachedResponse.headers.get('dwn-cache-time');\n if (\n cacheTime &&\n Date.now() < Number(cacheTime) + (Number(match.ttl) || 0)\n ) {\n return cachedResponse;\n }\n }\n }\n try {\n if (path) {\n return await fetchResource(event, did, drl, path, responseCache, options);\n } else {\n const response = await didResolver.resolve(did);\n return new Response(JSON.stringify(response), {\n status : 200,\n headers : {\n 'Content-Type': 'application/json',\n },\n });\n }\n } catch (error) {\n if (error instanceof Response) {\n return error;\n }\n console.log(`Error in DID URL fetch: ${error}`);\n return new Response('DID URL fetch error', { status: 500 });\n }\n}\n\n/** @internal Exported for testing. Fetches a resource from DWN endpoints. */\nexport async function fetchResource(\n event: FetchEvent, did: string, drl: string, path: string,\n responseCache: Cache | undefined, options?: ActivatePolyfillsOptions\n): Promise<Response> {\n const endpoints = await getDwnEndpoints(did);\n if (!endpoints?.length) {\n throw new Response(\n 'DWeb Node resolution failed: no valid endpoints found.',\n { status: 530 }\n );\n }\n let lastError: Response | undefined;\n for (const endpoint of endpoints) {\n try {\n const url = `${endpoint.replace(trailingSlashRegex, '')}/${did}/${path}`;\n const response = await fetch(url, { headers: event.request.headers });\n if (response.ok) {\n const match = await options?.onCacheCheck?.(event, drl);\n if (match && responseCache) {\n cacheResponse(drl, url, response, responseCache);\n }\n return response;\n }\n console.log(`DWN endpoint error: ${response.status}`);\n lastError = new Response('DWeb Node request failed', {\n status: response.status,\n });\n } catch (error) {\n console.log(`DWN endpoint error: ${error}`);\n lastError = new Response('DWeb Node request failed', {\n status: 500,\n });\n }\n }\n return lastError!;\n}\n\n/** @internal Exported for testing. Caches a DRL response with metadata headers. */\nexport async function cacheResponse(drl: string, url: string, response: Response, cache: Cache): Promise<void> {\n try {\n const clonedResponse = response.clone();\n const headers = new Headers(clonedResponse.headers);\n headers.append('dwn-cache-time', Date.now().toString());\n headers.append('dwn-composed-url', url);\n const modifiedResponse = new Response(clonedResponse.body, { headers });\n await cache.put(drl, modifiedResponse);\n } catch (error) {\n console.log(`Failed to cache DRL response: ${error}`);\n }\n}\n\n/* Service Worker-based features */\n\nasync function installWorker(options: ActivatePolyfillsOptions = {}): Promise<void> {\n try {\n // Check to see if we are in a Service Worker already, if so, proceed\n // You can call the activatePolyfills() function in your own worker, or standalone as a root worker\n if (\n typeof ServiceWorkerGlobalScope !== 'undefined' &&\n self instanceof ServiceWorkerGlobalScope\n ) {\n const workerSelf = self as unknown as ServiceWorkerGlobalScope;\n workerSelf.skipWaiting();\n workerSelf.addEventListener('activate', (event: ExtendableEvent) => {\n // Claim clients to make the service worker take control immediately\n event.waitUntil(workerSelf.clients.claim());\n });\n workerSelf.addEventListener('fetch', (event: FetchEvent) => {\n const parsed = parseDrlUrl(event.request.url);\n if (parsed) {\n event.respondWith(handleEvent(event, parsed[0], parsed[1], options));\n }\n });\n }\n // If the code gets here, it is not a SW env, it is likely DOM, but check to be sure\n else if (globalThis?.navigator?.serviceWorker) {\n const registration = await navigator.serviceWorker.getRegistration('/');\n // You can only have one worker per path, so check to see if one is already registered\n if (!registration) {\n const installUrl: string | undefined =\n options.path ||\n (document?.currentScript as HTMLScriptElement | null)?.src ||\n import.meta.url;\n if (installUrl)\n {navigator.serviceWorker\n .register(installUrl, { type: 'module' })\n .catch((error: unknown) => {\n console.error(\n 'DWeb networking feature installation failed: ',\n error\n );\n });}\n }\n } else {\n throw new Error(\n 'DWeb networking features are not available for install in this environment'\n );\n }\n } catch (error) {\n console.error('Error in installing networking features:', error);\n }\n}\n\n/* DOM Environment Features */\n\nconst loaderStyles = `\n .drl-loading-overlay {\n position: fixed;\n inset: 0;\n display: flex;\n flex-wrap: wrap;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: 22px;\n color: #fff;\n background: rgba(0, 0, 0, 0.75);\n backdrop-filter: blur(15px);\n -webkit-backdrop-filter: blur(15px);\n z-index: 1000000;\n }\n\n .drl-loading-overlay > div {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .drl-loading-spinner {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .drl-loading-spinner div {\n position: relative;\n width: 2em;\n height: 2em;\n margin: 0.1em 0.25em 0 0;\n }\n .drl-loading-spinner div::after,\n .drl-loading-spinner div::before {\n content: ''; \n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 0.1em solid #FFF;\n position: absolute;\n left: 0;\n top: 0;\n opacity: 0;\n animation: drl-loading-spinner 2s linear infinite;\n }\n .drl-loading-spinner div::after {\n animation-delay: 1s;\n }\n\n .drl-loading-overlay span {\n --text-opacity: 2;\n display: flex;\n align-items: center;\n margin: 2em auto 0;\n padding: 0.2em 0.75em 0.25em;\n text-align: center;\n border-radius: 5em;\n background: rgba(255 255 255 / 8%);\n opacity: 0.8;\n transition: opacity 0.3s ease;\n cursor: pointer;\n }\n\n .drl-loading-overlay span:focus {\n opacity: 1;\n }\n\n .drl-loading-overlay span:hover {\n opacity: 1;\n }\n\n .drl-loading-overlay span::before {\n content: '\u2715 ';\n margin: 0 0.4em 0 0;\n color: red;\n font-size: 65%;\n font-weight: bold;\n }\n\n .drl-loading-overlay span::after {\n content: 'stop';\n display: block;\n font-size: 60%;\n line-height: 0;\n color: rgba(255 255 255 / 60%);\n }\n\n .drl-loading-overlay.new-tab-overlay span::after {\n content: 'close';\n }\n \n @keyframes drl-loading-spinner {\n 0% {\n transform: scale(0);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n opacity: 0;\n }\n }\n`;\nconst tabContent = `\n<!DOCTYPE html>\n<html lang='en'>\n<head>\n <meta charset='UTF-8'>\n <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n <title>Loading DRL...</title>\n <style>\n html, body {\n background-color: #151518;\n height: 100%;\n margin: 0;\n padding: 0;\n font-family: Arial, sans-serif;\n text-align: center;\n }\n ${loaderStyles}\n </style>\n</head>\n<body>\n <div class='drl-loading-overlay new-tab-overlay'>\n <div class='drl-loading-spinner'>\n <div></div>\n Loading DRL\n </div>\n <span onclick='window.close()' tabindex='0'></span>\n </div>\n</body>\n</html>\n`;\n\nlet elementsInjected = false;\nlet overlayElement: HTMLDivElement | null = null;\nlet styleElement: HTMLStyleElement | null = null;\n\nfunction injectElements(): void {\n if (elementsInjected) {return;}\n styleElement = document.createElement('style');\n styleElement.innerHTML = `\n ${loaderStyles}\n\n .drl-loading-overlay {\n opacity: 0;\n transition: opacity 0.3s ease;\n pointer-events: none;\n }\n\n :root[drl-link-loading] .drl-loading-overlay {\n opacity: 1;\n pointer-events: all;\n }\n `;\n document.head.append(styleElement);\n\n overlayElement = document.createElement('div');\n overlayElement.classList.add('drl-loading-overlay');\n overlayElement.innerHTML = `\n <div class='drl-loading-spinner'>\n <div></div>\n Loading DRL\n </div> \n <span tabindex='0'></span>\n `;\n overlayElement.lastElementChild!.addEventListener('click', cancelNavigation);\n document.body.prepend(overlayElement);\n elementsInjected = true;\n}\n\nfunction removeElements(): void {\n if (!elementsInjected) {return;}\n styleElement?.remove();\n styleElement = null;\n overlayElement?.remove();\n overlayElement = null;\n elementsInjected = false;\n}\n\nfunction cancelNavigation(): void {\n document.documentElement.removeAttribute('drl-link-loading');\n activeNavigation = null;\n}\n\nlet activeNavigation: string | null = null;\nlet linkFeaturesActive = false;\n\n// Stored references for listener cleanup in deactivatePolyfills()\nlet clickHandler: ((event: MouseEvent) => Promise<void>) | null = null;\nlet pointerdownHandler: ((event: PointerEvent) => Promise<void>) | null = null;\n\nfunction addLinkFeatures(): void {\n if (!linkFeaturesActive) {\n clickHandler = async (event: MouseEvent): Promise<void> => {\n const anchor = (event.target as Element)?.closest('a');\n if (anchor) {\n const href = anchor.href;\n const parsed = parseDrlUrl(href);\n if (parsed) {\n const did = parsed[0];\n const path = parsed[1];\n const openAsTab = anchor.target === '_blank';\n event.preventDefault();\n try {\n let tab: Window | null = null;\n if (openAsTab) {\n tab = window.open('', '_blank');\n if (tab) {tab.document.write(tabContent);}\n } else {\n activeNavigation = path;\n // this is to allow for cached DIDs to instantly load without any flash of loading UI\n setTimeout(\n () =>\n document.documentElement.setAttribute('drl-link-loading', ''),\n 50\n );\n }\n const endpoints = await getDwnEndpoints(did);\n if (!endpoints.length) {\n throw new Error('no valid DWN endpoints found');\n }\n const url = `${endpoints[0].replace(\n trailingSlashRegex,\n ''\n )}/${did}/${path}`;\n if (openAsTab) {\n if (tab && !tab.closed) {tab.location.href = url;}\n } else if (activeNavigation === path) {\n window.location.href = url;\n }\n } catch {\n if (activeNavigation === path) {\n cancelNavigation();\n }\n throw new Error(\n `DID endpoint resolution failed for the DRL: ${href}`\n );\n }\n }\n }\n };\n\n pointerdownHandler = async (event: PointerEvent): Promise<void> => {\n const target = event.composedPath()[0] as DrlMediaElement | undefined;\n if (\n (event.pointerType === 'mouse' && event.button === 2) ||\n (event.pointerType === 'touch' && event.isPrimary)\n ) {\n resetContextMenuTarget();\n if (target?.src && parseDrlUrl(target.src)) {\n contextMenuTarget = target;\n target.__src__ = target.src;\n const drl = target.src\n .replace(httpToHttpsRegex, 'https:')\n .replace(trailingSlashRegex, '');\n const responseCache = await openDrlCache();\n const response = await responseCache?.match(drl);\n if (response) {\n const url = response.headers.get('dwn-composed-url');\n if (url) {target.src = url;}\n }\n target.addEventListener('pointerup', resetContextMenuTarget, {\n once: true,\n });\n }\n } else if (target === contextMenuTarget) {\n resetContextMenuTarget();\n }\n };\n\n document.addEventListener('click', clickHandler);\n document.addEventListener('pointercancel', resetContextMenuTarget);\n document.addEventListener('pointerdown', pointerdownHandler);\n\n linkFeaturesActive = true;\n }\n}\n\nfunction removeLinkFeatures(): void {\n if (!linkFeaturesActive) {return;}\n if (clickHandler) {\n document.removeEventListener('click', clickHandler);\n clickHandler = null;\n }\n if (pointerdownHandler) {\n document.removeEventListener('pointerdown', pointerdownHandler);\n pointerdownHandler = null;\n }\n document.removeEventListener('pointercancel', resetContextMenuTarget);\n resetContextMenuTarget();\n cancelNavigation();\n linkFeaturesActive = false;\n}\n\nlet contextMenuTarget: DrlMediaElement | null = null;\nasync function resetContextMenuTarget(e?: Event): Promise<void> {\n if (e?.type === 'pointerup') {\n await new Promise<void>((r) => requestAnimationFrame(() => r()));\n }\n if (contextMenuTarget) {\n contextMenuTarget.src = contextMenuTarget.__src__!;\n delete contextMenuTarget.__src__;\n contextMenuTarget = null;\n }\n}\n\n/**\n * Activates various polyfills to enable Enbox features in Web environments.\n *\n * @param options - Configuration options to control the activation of polyfills.\n *\n * @example\n * // Activate all polyfills with default options, and cache every DRL for 1 minute\n * activatePolyfills({\n * onCacheCheck(event, route){\n * return {\n * ttl: 60_000\n * }\n * }\n * });\n *\n * @example\n * // Activate polyfills, but without Service Worker activation\n * activatePolyfills({ serviceWorker: false });\n *\n * @example\n * // Use custom DID resolvers\n * activatePolyfills({ didResolvers: [DidDht, DidWeb, DidJwk] });\n */\nexport function activatePolyfills(options: ActivatePolyfillsOptions = {}): void {\n if (options.didResolvers) {\n didResolver = new UniversalResolver({ didResolvers: options.didResolvers });\n }\n if (options.serviceWorker !== false) {\n installWorker(options);\n }\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n if (options.injectStyles !== false) {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', injectElements, {\n once: true,\n });\n } else {injectElements();}\n }\n if (options.links !== false) {addLinkFeatures();}\n }\n}\n\n/**\n * Removes all polyfill event listeners, injected DOM elements, and resets internal state.\n * Call this to fully clean up after {@link activatePolyfills}.\n *\n * Does **not** unregister an installed Service Worker \u2014 use\n * `navigator.serviceWorker.getRegistration('/').then(r => r?.unregister())` for that.\n */\nexport function deactivatePolyfills(): void {\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n removeLinkFeatures();\n removeElements();\n }\n}\n\n/**\n * Deletes the entire DRL response cache.\n * Useful for clearing stale cached DWN responses.\n *\n * @returns `true` if the cache existed and was deleted, `false` otherwise.\n * Returns `false` if the Cache API is unavailable.\n */\nexport async function clearDrlCache(): Promise<boolean> {\n if (typeof caches === 'undefined') {return false;}\n return caches.delete(DRL_CACHE_NAME);\n}\n", "/**\n * Parses a DRL URL (http(s)://dweb/{did}/{path}) without regex quantifiers.\n * Returns `[did, path]` or `null` if the URL does not match the DRL scheme.\n *\n * Extracted to a standalone module so it can be tested under Node.js (bun:test)\n * in addition to the browser-based vitest suite, ensuring SonarCloud's\n * merged coverage report includes these lines.\n */\nexport function parseDrlUrl(url: string): [string, string] | null {\n const idx = url.indexOf('://dweb/');\n if (idx === -1) { return null; }\n const prefix = url.slice(0, idx);\n if (prefix !== 'http' && prefix !== 'https') { return null; }\n const rest = url.slice(idx + 8); // '://dweb/'.length === 8\n if (rest.length === 0) { return null; }\n const slashIdx = rest.indexOf('/');\n if (slashIdx === -1) { return [rest, '']; }\n if (slashIdx === 0) { return null; } // DID segment must be non-empty\n return [rest.slice(0, slashIdx), rest.slice(slashIdx + 1)];\n}\n", "/**\n * Connect modal \u2014 the single surface that owns a whole connect session.\n *\n * One Shadow-DOM dialog whose stage morphs in place through the session:\n * QR (phone path) \u2192 pairing code \u2192 connected, with the in-browser popup\n * path and the wallet catalog folded in as in-place alternates. The modal\n * never chains into a second modal and stays mounted until the session\n * resolves (connected / denied / cancelled).\n *\n * Layout: three zones \u2014\n *\n * 1. **Header** \u2014 requesting app identity + close.\n * 2. **Stage** \u2014 a height-stable region where states crossfade: the QR\n * (or deep link on phones), the pairing-code input, progress, success,\n * and error states.\n * 3. **Footer** \u2014 the alternate-method link and the wallet switcher\n * disclosure (catalog + custom URL \u2014 the entire legacy selector,\n * demoted to an option).\n *\n * The phone path drives the `@enbox/connect` relay transport via\n * {@link runRelayConnect}; the browser path drives the popup transport via\n * the kernel `ConnectClient`. Wallet `connectServerUrl`s are discovered\n * from each wallet's `/.well-known/enbox-connect` document unless\n * overridden.\n *\n * @module\n */\n\nimport type { WalletOption } from '../browser-connect-handler.js';\nimport type { ConnectPermissionRequest, ConnectResult, WalletUriHandoff } from '@enbox/connect';\n\nimport { ConnectClient } from '@enbox/connect';\n\nimport { buildWalletIcon } from './wallet-icon.js';\nimport {\n collectBrowserClientMetadata,\n PopupClientTransport,\n PopupWindowClosedError,\n} from '../dweb-connect-client.js';\nimport { encodeQr, qrToSvg } from './qr.js';\nimport { fetchWalletWellKnown, probeWalletWellKnown } from './wallet-well-known.js';\nimport { RelayConnectCancelledError, runRelayConnect } from '../relay-connect-runner.js';\n\n/** How the user carries out the approval. */\nexport type ConnectMethod = 'phone' | 'browser';\n\n/** localStorage key remembering the last successful method + wallet. */\nconst LAST_CHOICE_STORAGE_KEY = 'enbox:connect:lastChoice';\n\n/** Safety margin subtracted from the relay pointer TTL before re-minting. */\nconst REMINT_SAFETY_MS = 30_000;\n\n/** Minimum delay before an automatic re-mint. */\nconst REMINT_MIN_MS = 10_000;\n\n/** Pairing code length (matches the wallet's generated PIN). */\nconst PIN_LENGTH = 4;\n\n/** Options for {@link runConnectModal}. */\nexport interface ConnectModalOptions {\n /** Wallet catalog shown in the wallet switcher. */\n wallets?: WalletOption[];\n\n /**\n * Explicit wallet URL: hides the catalog switcher and uses this wallet\n * for both methods.\n */\n walletUrl?: string;\n\n /** Preferred method on open; overrides the remembered choice. */\n preferredMethod?: ConnectMethod;\n\n /**\n * Remember the successful method + wallet in localStorage and pre-shape\n * the next session accordingly.\n * @default true\n */\n rememberChoice?: boolean;\n\n /** Display name of the requesting application. */\n appName?: string;\n\n /** Icon URL of the requesting application. */\n appIcon?: string;\n\n /**\n * Relay base URL override for the phone path. When omitted, each wallet's\n * `connectServerUrl` is discovered from its `/.well-known/enbox-connect`\n * document.\n */\n connectServerUrl?: string;\n\n /**\n * Path appended to the wallet origin to form the QR / deep-link target.\n * @default '/connect/app'\n */\n relayWalletPath?: string;\n\n /** Timeout in milliseconds for either method's handshake. */\n timeout?: number;\n\n /** DWN protocols and permission scopes being requested. */\n permissionRequests: ConnectPermissionRequest[];\n\n /** Internal dependency seams (tests). */\n deps?: Partial<ConnectModalDeps>;\n}\n\n/** Injectable collaborators, defaulted to the real implementations. */\nexport interface ConnectModalDeps {\n /** Runs one relay handshake (phone path). */\n runRelay: typeof runRelayConnect;\n\n /** Runs one popup handshake (browser path); must open the popup synchronously. */\n runPopup: (options: {\n walletUrl: string;\n permissionRequests: ConnectPermissionRequest[];\n appName: string;\n appIcon?: string;\n timeoutMs?: number;\n }) => Promise<ConnectResult | undefined>;\n\n /** Resolves a wallet origin to its relay `connectServerUrl` (or undefined). */\n discoverConnectServerUrl: (walletOrigin: string) => Promise<string | undefined>;\n\n /** Validates a pasted custom wallet URL. */\n validateWalletUrl: (origin: string) => Promise<boolean>;\n\n /** Whether to present the deep-link (same-device) variant of the phone path. */\n isMobile: () => boolean;\n\n /** Persistence for the remembered choice. */\n storage: Pick<Storage, 'getItem' | 'setItem' | 'removeItem'> | undefined;\n}\n\n/**\n * Resolves a wallet origin to its relay `connectServerUrl` via the wallet's\n * `/.well-known/enbox-connect` document ({@link fetchWalletWellKnown} \u2014 the\n * same machinery the wallet selector uses for custom-URL validation).\n */\nexport async function discoverWalletConnectServerUrl(walletOrigin: string): Promise<string | undefined> {\n return (await fetchWalletWellKnown(walletOrigin))?.connectServerUrl;\n}\n\n/** Runs one popup handshake without collapsing early-close into a denial. */\nasync function runPopupConnect(options: {\n walletUrl: string;\n permissionRequests: ConnectPermissionRequest[];\n appName: string;\n appIcon?: string;\n timeoutMs?: number;\n}): Promise<ConnectResult | undefined> {\n // The transport constructor calls `window.open` synchronously \u2014 callers\n // must invoke this inside the user-gesture call stack.\n const transport = new PopupClientTransport({\n walletUrl : options.walletUrl,\n timeoutMs : options.timeoutMs,\n });\n const client = new ConnectClient({ transport });\n\n return await client.connect({\n appName : options.appName,\n appIcon : options.appIcon,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n });\n}\n\nfunction defaultIsMobile(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n const coarse = window.matchMedia?.('(pointer: coarse)').matches ?? false;\n return coarse && Math.min(window.innerWidth, window.innerHeight) < 900;\n}\n\nfunction defaultDeps(): ConnectModalDeps {\n return {\n runRelay : runRelayConnect,\n runPopup : runPopupConnect,\n discoverConnectServerUrl : discoverWalletConnectServerUrl,\n validateWalletUrl : probeWalletWellKnown,\n isMobile : defaultIsMobile,\n storage : typeof localStorage === 'undefined' ? undefined : localStorage,\n };\n}\n\n/** Remembered method + wallet from a previous successful session. */\ninterface LastChoice {\n method: ConnectMethod;\n walletUrl: string;\n}\n\nfunction readLastChoice(storage: ConnectModalDeps['storage']): LastChoice | undefined {\n try {\n const raw = storage?.getItem(LAST_CHOICE_STORAGE_KEY);\n if (raw == null) {\n return undefined;\n }\n const parsed = JSON.parse(raw) as Partial<LastChoice>;\n if ((parsed.method === 'phone' || parsed.method === 'browser') && typeof parsed.walletUrl === 'string') {\n return { method: parsed.method, walletUrl: parsed.walletUrl };\n }\n } catch { /* unreadable storage \u2014 behave as first visit */ }\n return undefined;\n}\n\nfunction writeLastChoice(storage: ConnectModalDeps['storage'], choice: LastChoice): void {\n try {\n storage?.setItem(LAST_CHOICE_STORAGE_KEY, JSON.stringify(choice));\n } catch { /* best effort */ }\n}\n\n/** One cancellable relay session. */\ninterface RelaySession {\n cancelled: Promise<never>;\n cancel: () => void;\n active: boolean;\n}\n\nfunction createRelaySession(): RelaySession {\n let cancel!: () => void;\n const session: Partial<RelaySession> = { active: true };\n const cancelled = new Promise<never>((_, reject) => {\n cancel = (): void => {\n if (session.active === true) {\n session.active = false;\n reject(new RelayConnectCancelledError());\n }\n };\n });\n // Mark handled so an unconsumed cancellation never surfaces as unhandled.\n cancelled.catch((): undefined => undefined);\n session.cancelled = cancelled;\n session.cancel = cancel;\n return session as RelaySession;\n}\n\n/**\n * Opens the connect modal and resolves when the session ends.\n *\n * @returns The delegated credentials; `undefined` when the user denied the\n * request in the wallet (or dismissed after a denial).\n * @throws When the user cancels the modal, or the session fails and the\n * user dismisses the error.\n */\nexport function runConnectModal(options: ConnectModalOptions): Promise<ConnectResult | undefined> {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new Error('[@enbox/browser] The connect modal is only available in browser environments.');\n }\n\n const deps: ConnectModalDeps = { ...defaultDeps(), ...options.deps };\n const wallets = options.wallets ?? [];\n const rememberChoice = options.rememberChoice ?? true;\n const appName = options.appName ?? window.location.host;\n const relayWalletPath = options.relayWalletPath ?? '/connect/app';\n const isMobile = deps.isMobile();\n\n const lastChoice = rememberChoice ? readLastChoice(deps.storage) : undefined;\n\n // Wallet resolution order: explicit option \u2192 remembered \u2192 catalog head.\n const lockedWallet = options.walletUrl !== undefined;\n let walletUrl = options.walletUrl\n ?? (lastChoice !== undefined && (lockedWallet || walletInCatalog(wallets, lastChoice.walletUrl)) ? lastChoice.walletUrl : undefined)\n ?? wallets[0]?.url;\n\n // Method resolution order: explicit option \u2192 remembered \u2192 phone.\n let method: ConnectMethod = options.preferredMethod ?? lastChoice?.method ?? 'phone';\n\n return new Promise<ConnectResult | undefined>((resolve, reject) => {\n // \u2500\u2500 Host + shadow root \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const host = document.createElement('div');\n host.id = 'enbox-connect-modal';\n const shadow = host.attachShadow({ mode: 'open' });\n\n const isDark = window.matchMedia?.('(prefers-color-scheme: dark)').matches ?? false;\n const style = document.createElement('style');\n style.textContent = buildStyles(isDark);\n shadow.appendChild(style);\n\n const overlay = document.createElement('div');\n overlay.className = 'overlay';\n const modal = document.createElement('div');\n modal.className = 'modal';\n modal.setAttribute('role', 'dialog');\n modal.setAttribute('aria-modal', 'true');\n modal.setAttribute('aria-label', `Connect to ${appName}`);\n\n // \u2500\u2500 Session state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let settled = false;\n let relaySession: RelaySession | undefined;\n let remintTimer: ReturnType<typeof setTimeout> | undefined;\n let popupBusy = false;\n let pinResolve: ((pin: string) => void) | undefined;\n const discoveryCache = new Map<string, Promise<string | undefined>>();\n\n const cleanup = (): void => {\n relaySession?.cancel();\n clearTimeout(remintTimer);\n document.removeEventListener('keydown', onKeydown);\n try { document.body.removeChild(host); } catch { /* best effort */ }\n };\n\n const settle = (settler: () => void): void => {\n if (settled) { return; }\n settled = true;\n cleanup();\n settler();\n };\n\n const succeed = (result: ConnectResult): void => {\n if (rememberChoice) {\n writeLastChoice(deps.storage, { method, walletUrl: walletUrl ?? '' });\n }\n renderConnected();\n const finish = (): void => settle(() => resolve(result));\n setTimeout(finish, 1_200);\n };\n\n const cancelModal = (): void => settle(() => reject(new Error('[@enbox/browser] Connect cancelled.')));\n\n // \u2500\u2500 Zones \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n modal.appendChild(buildHeader(appName, options.appIcon, cancelModal));\n\n const stage = document.createElement('div');\n stage.className = 'stage';\n stage.setAttribute('aria-live', 'polite');\n modal.appendChild(stage);\n\n const footer = document.createElement('div');\n footer.className = 'footer';\n modal.appendChild(footer);\n\n // \u2500\u2500 Stage renderers (all render in place; nothing navigates) \u2500\u2500\n const setStage = (...nodes: (HTMLElement | SVGElement)[]): void => {\n stage.replaceChildren(...nodes);\n stage.classList.remove('fade-in');\n void stage.offsetWidth; // restart the transition\n stage.classList.add('fade-in');\n };\n\n const renderBusy = (message: string): void => {\n setStage(el('div', 'spinner'), el('p', 'stage-caption', message));\n };\n\n const renderQr = (handoff: WalletUriHandoff): void => {\n if (isMobile) {\n const link = document.createElement('a');\n link.className = 'deep-link';\n link.href = handoff.walletUri;\n link.textContent = 'Continue in your wallet';\n setStage(\n link,\n el('p', 'stage-caption', 'Your wallet opens to approve this connection.'),\n el('p', 'stage-subline', 'Come back here when you\u2019re done.'),\n );\n return;\n }\n\n const qrBox = document.createElement('div');\n qrBox.className = 'qr-box';\n qrBox.replaceChildren(qrToSvg(encodeQr(handoff.walletUri), {\n dark : isDark ? '#e8e8f0' : '#14141f',\n light : 'transparent',\n quietZone : 2,\n }));\n\n setStage(\n qrBox,\n el('p', 'stage-caption', 'Scan with your phone\u2019s camera'),\n el('p', 'stage-subline', 'Your wallet stays on your phone, so you can approve things anywhere.'),\n );\n };\n\n const renderClaimed = (): void => {\n const pulse = document.createElement('div');\n pulse.className = 'claimed-pulse';\n setStage(\n pulse,\n el('p', 'stage-caption', 'Phone connected \u2014 finish there'),\n el('p', 'stage-subline', 'Approve the request on your phone, then come back here.'),\n );\n };\n\n const renderPin = (attempt: number, previousError?: Error): Promise<string> => {\n return new Promise<string>((resolvePin) => {\n pinResolve = resolvePin;\n\n const boxes = document.createElement('div');\n boxes.className = 'pin-row';\n if (previousError !== undefined) {\n boxes.classList.add('shake');\n }\n\n const inputs: HTMLInputElement[] = [];\n for (let i = 0; i < PIN_LENGTH; i++) {\n const input = document.createElement('input');\n input.className = 'pin-input';\n input.type = 'text';\n input.inputMode = 'numeric';\n input.maxLength = 1;\n input.setAttribute('aria-label', `Code digit ${i + 1}`);\n inputs.push(input);\n boxes.appendChild(input);\n }\n\n const submitIfComplete = (): void => {\n const code = inputs.map((i) => i.value).join('');\n if (code.length === PIN_LENGTH && pinResolve !== undefined) {\n const resolveOnce = pinResolve;\n pinResolve = undefined;\n renderBusy('Checking the code\u2026');\n resolveOnce(code);\n }\n };\n\n inputs.forEach((input, index) => {\n input.addEventListener('input', () => {\n input.value = input.value.replace(/\\D/g, '').slice(0, 1);\n if (input.value !== '' && index + 1 < inputs.length) {\n inputs[index + 1].focus();\n }\n submitIfComplete();\n });\n input.addEventListener('keydown', (event) => {\n if (event.key === 'Backspace' && input.value === '' && index > 0) {\n inputs[index - 1].focus();\n }\n });\n input.addEventListener('paste', (event) => {\n const digits = (event.clipboardData?.getData('text') ?? '').replace(/\\D/g, '').slice(0, PIN_LENGTH);\n if (digits.length === 0) { return; }\n event.preventDefault();\n digits.split('').forEach((digit, digitIndex) => {\n if (inputs[digitIndex] !== undefined) {\n inputs[digitIndex].value = digit;\n }\n });\n inputs[Math.min(digits.length, PIN_LENGTH) - 1]?.focus();\n submitIfComplete();\n });\n });\n\n setStage(\n el('p', 'stage-caption', 'Enter the code shown on your phone'),\n boxes,\n ...(previousError !== undefined\n ? [el('p', 'stage-error', 'That code doesn\u2019t match \u2014 check your phone.')]\n : [el('p', 'stage-subline', attempt === 1 ? 'Phone connected.' : '')]),\n );\n\n inputs[0].focus();\n });\n };\n\n const renderConnected = (): void => {\n const check = el('div', 'check');\n check.textContent = '\u2713';\n setStage(check, el('p', 'stage-caption', 'You\u2019re connected.'));\n };\n\n const renderDenied = (): void => {\n setStage(\n el('p', 'stage-caption', 'No problem \u2014 nothing was shared.'),\n stageButton('Start over', () => { void startMethod(); }),\n stageLinkButton('Close', () => settle(() => resolve(undefined))),\n );\n };\n\n const renderError = (message: string, error?: Error): void => {\n setStage(\n el('p', 'stage-caption', message),\n stageButton('Start over', () => { void startMethod(); }),\n stageLinkButton('Close', () => settle(() => reject(error ?? new Error(`[@enbox/browser] ${message}`)))),\n );\n };\n\n const renderPhoneUnavailable = (): void => {\n setStage(\n el('p', 'stage-caption', 'This wallet can\u2019t connect by phone here.'),\n el('p', 'stage-subline', 'You can continue in this browser instead.'),\n stageButton('Use this browser', () => { startPopup(); }),\n );\n };\n\n const renderPopupPrompt = (): void => {\n setStage(\n el('p', 'stage-caption', 'Connect with a wallet in this browser'),\n el('p', 'stage-subline', 'Your wallet opens in a small window to approve this connection.'),\n stageButton('Open wallet window', () => { startPopup(); }),\n );\n };\n\n const renderPopupWaiting = (): void => {\n setStage(\n el('div', 'spinner'),\n el('p', 'stage-caption', 'Finish in the wallet window'),\n el('p', 'stage-subline', 'We\u2019ll wrap up here as soon as you\u2019re done.'),\n );\n };\n\n const renderPopupInterrupted = (blocked: boolean): void => {\n setStage(\n el('p', 'stage-caption', blocked\n ? 'Your browser blocked the wallet window.'\n : 'The wallet window was closed.'),\n stageButton(blocked ? 'Open it now' : 'Reopen window', () => { startPopup(); }),\n ...(isMobile ? [] : [stageLinkButton('Use your phone instead', () => { void switchMethod('phone'); })]),\n );\n };\n\n // \u2500\u2500 Method drivers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const resolveConnectServerUrl = async (origin: string): Promise<string | undefined> => {\n if (options.connectServerUrl !== undefined) {\n return options.connectServerUrl;\n }\n let cached = discoveryCache.get(origin);\n if (cached === undefined) {\n cached = deps.discoverConnectServerUrl(origin);\n discoveryCache.set(origin, cached);\n }\n return cached;\n };\n\n const scheduleRemint = (expiresInSeconds: number): void => {\n clearTimeout(remintTimer);\n const delay = Math.max(REMINT_MIN_MS, expiresInSeconds * 1_000 - REMINT_SAFETY_MS);\n remintTimer = setTimeout(() => {\n // Never re-mint once the wallet has responded (pairing in progress).\n if (!settled && pinResolve === undefined && method === 'phone') {\n void startPhone();\n }\n }, delay);\n };\n\n const startPhone = async (): Promise<void> => {\n relaySession?.cancel();\n clearTimeout(remintTimer);\n\n if (walletUrl === undefined) {\n renderError('No wallet is configured.');\n return;\n }\n\n method = 'phone';\n renderFooter();\n renderBusy('Getting things ready\u2026');\n\n const origin = new URL(walletUrl).origin;\n const connectServerUrl = await resolveConnectServerUrl(origin);\n if (connectServerUrl === undefined) {\n renderPhoneUnavailable();\n return;\n }\n\n const session = createRelaySession();\n relaySession = session;\n\n try {\n const result = await deps.runRelay({\n connectServerUrl,\n walletUri : new URL(relayWalletPath, origin).toString(),\n appName,\n appIcon : options.appIcon,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n timeoutMs : options.timeout,\n cancelled : session.cancelled,\n onWalletUriReady : (handoff): void => {\n if (session.active && !settled) {\n renderQr(handoff);\n scheduleRemint(handoff.expiresIn);\n }\n },\n onClaimed: (): void => {\n if (session.active && !settled) {\n // The phone has the request \u2014 stop re-minting (a new pointer\n // would orphan the approval in progress) and show progress.\n clearTimeout(remintTimer);\n renderClaimed();\n }\n },\n requestPin: (attempt, previousError): Promise<string> => {\n clearTimeout(remintTimer);\n return renderPin(attempt, previousError);\n },\n });\n\n if (!session.active || settled) { return; }\n\n if (result === undefined) {\n renderDenied();\n } else {\n succeed(result);\n }\n } catch (error) {\n if (!session.active || settled || error instanceof RelayConnectCancelledError) {\n return;\n }\n const failure = error instanceof Error ? error : new Error(String(error));\n renderError(\n /timed out/i.test(failure.message)\n ? 'That took too long, so we stopped for safety.'\n : 'Something went wrong while connecting.',\n failure,\n );\n }\n };\n\n const startPopup = (): void => {\n // Synchronous popup open inside the click's call stack.\n relaySession?.cancel();\n clearTimeout(remintTimer);\n\n if (walletUrl === undefined) {\n renderError('No wallet is configured.');\n return;\n }\n if (popupBusy) { return; }\n\n method = 'browser';\n renderFooter();\n\n let flow: Promise<ConnectResult | undefined>;\n try {\n flow = deps.runPopup({\n walletUrl,\n permissionRequests : options.permissionRequests,\n appName,\n appIcon : options.appIcon,\n timeoutMs : options.timeout,\n });\n } catch (error) {\n const blocked = error instanceof Error && /popup blocked/i.test(error.message);\n renderPopupInterrupted(blocked);\n return;\n }\n\n popupBusy = true;\n renderPopupWaiting();\n\n flow\n .then((result) => {\n if (settled) { return; }\n if (result === undefined) {\n renderDenied();\n } else {\n succeed(result);\n }\n })\n .catch((error: unknown) => {\n if (settled) { return; }\n if (error instanceof PopupWindowClosedError) {\n renderPopupInterrupted(false);\n return;\n }\n const failure = error instanceof Error ? error : new Error(String(error));\n renderError(\n /timed out/i.test(failure.message)\n ? 'That took too long, so we stopped for safety.'\n : 'Something went wrong while connecting.',\n failure,\n );\n })\n .finally(() => { popupBusy = false; });\n };\n\n const startMethod = async (): Promise<void> => {\n if (method === 'browser') {\n // window.open must stay inside a user gesture \u2014 prompt for the click.\n relaySession?.cancel();\n clearTimeout(remintTimer);\n renderFooter();\n renderPopupPrompt();\n } else {\n await startPhone();\n }\n };\n\n const switchMethod = async (next: ConnectMethod): Promise<void> => {\n method = next;\n await startMethod();\n };\n\n // \u2500\u2500 Footer: method link + wallet switcher \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const renderFooter = (): void => {\n footer.replaceChildren();\n\n if (method === 'phone') {\n const alt = document.createElement('button');\n alt.className = 'footer-link method-link';\n alt.textContent = 'No phone handy? Use this browser \u2192';\n // startPopup runs synchronously in this click handler.\n alt.addEventListener('click', () => { startPopup(); });\n footer.appendChild(alt);\n } else if (!isMobile) {\n const alt = document.createElement('button');\n alt.className = 'footer-link method-link';\n alt.textContent = 'Use your phone instead \u2192';\n alt.addEventListener('click', () => { void switchMethod('phone'); });\n footer.appendChild(alt);\n }\n\n if (!lockedWallet && wallets.length > 0) {\n footer.appendChild(buildWalletSwitcher());\n }\n };\n\n const buildWalletSwitcher = (): HTMLElement => {\n const wrap = document.createElement('div');\n wrap.className = 'wallet-switcher';\n\n const current = wallets.find((wallet) => wallet.url === walletUrl);\n const toggle = document.createElement('button');\n toggle.className = 'footer-link wallet-toggle';\n toggle.setAttribute('aria-expanded', 'false');\n toggle.textContent = `Wallet: ${current?.name ?? walletUrl ?? 'Choose'} \u25BE`;\n\n const panel = document.createElement('div');\n panel.className = 'wallet-panel';\n panel.hidden = true;\n\n // Search filter \u2014 only worth the chrome once the catalog grows.\n const rows: Array<{ wallet: (typeof wallets)[number]; el: HTMLButtonElement }> = [];\n const empty = document.createElement('div');\n empty.className = 'wallet-empty';\n empty.textContent = 'No wallets match your search.';\n empty.hidden = true;\n\n if (wallets.length > 5) {\n const search = document.createElement('input');\n search.type = 'search';\n search.className = 'wallet-search';\n search.placeholder = 'Search wallets\u2026';\n search.addEventListener('input', () => {\n const query = search.value.trim().toLowerCase();\n let visible = 0;\n for (const { wallet, el } of rows) {\n const match = query === ''\n || wallet.name.toLowerCase().includes(query)\n || wallet.url.toLowerCase().includes(query);\n el.hidden = !match;\n if (match) { visible += 1; }\n }\n empty.hidden = visible > 0;\n });\n panel.appendChild(search);\n }\n\n for (const wallet of wallets) {\n const row = document.createElement('button');\n row.className = 'wallet-row';\n row.appendChild(buildWalletIcon(wallet));\n const rowName = document.createElement('span');\n rowName.className = 'wallet-row-name';\n rowName.textContent = wallet.name;\n row.appendChild(rowName);\n if (wallet.url === walletUrl) {\n row.classList.add('selected');\n }\n row.addEventListener('click', () => {\n walletUrl = wallet.url;\n renderFooter();\n void startMethod();\n });\n rows.push({ wallet, el: row });\n panel.appendChild(row);\n }\n panel.appendChild(empty);\n\n // Custom wallet URL (the power-user path, demoted to the disclosure).\n const custom = document.createElement('div');\n custom.className = 'wallet-custom';\n const input = document.createElement('input');\n input.className = 'url-input';\n input.type = 'url';\n input.placeholder = 'https://your-wallet.example';\n const go = document.createElement('button');\n go.className = 'url-go';\n go.textContent = 'Use';\n const urlError = document.createElement('div');\n urlError.className = 'url-error';\n urlError.hidden = true;\n\n // When validation fails we let the user override, since the connect\n // handshake is the ultimate gate \u2014 a valid wallet behind strict CORS\n // should not be permanently blocked.\n let allowUnverified = false;\n\n const useWallet = (origin: string): void => {\n walletUrl = origin;\n renderFooter();\n void startMethod();\n };\n\n const submitCustom = async (): Promise<void> => {\n const value = input.value.trim();\n if (value === '') { return; }\n let origin: string;\n try {\n origin = new URL(value.includes('://') ? value : `https://${value}`).origin;\n } catch {\n input.classList.add('invalid');\n return;\n }\n if (allowUnverified) {\n useWallet(origin);\n return;\n }\n go.disabled = true;\n go.textContent = 'Checking\u2026';\n urlError.hidden = true;\n const valid = await deps.validateWalletUrl(origin);\n go.disabled = false;\n if (valid) {\n go.textContent = 'Use';\n useWallet(origin);\n return;\n }\n allowUnverified = true;\n go.textContent = 'Use anyway';\n input.classList.add('invalid');\n urlError.textContent = `Couldn't verify a wallet at ${origin}.`;\n urlError.hidden = false;\n };\n\n input.addEventListener('input', () => {\n allowUnverified = false;\n go.textContent = 'Use';\n input.classList.remove('invalid');\n urlError.hidden = true;\n });\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') { void submitCustom(); }\n });\n go.addEventListener('click', () => { void submitCustom(); });\n custom.appendChild(input);\n custom.appendChild(go);\n panel.appendChild(custom);\n panel.appendChild(urlError);\n\n toggle.addEventListener('click', () => {\n panel.hidden = !panel.hidden;\n toggle.setAttribute('aria-expanded', panel.hidden ? 'false' : 'true');\n });\n\n wrap.appendChild(toggle);\n wrap.appendChild(panel);\n return wrap;\n };\n\n // \u2500\u2500 Global interactions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n overlay.addEventListener('click', (event) => {\n if (event.target === overlay) {\n cancelModal();\n }\n });\n\n const onKeydown = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') {\n cancelModal();\n return;\n }\n if (event.key === 'Tab') {\n trapFocus(shadow, event);\n }\n };\n document.addEventListener('keydown', onKeydown);\n\n overlay.appendChild(modal);\n shadow.appendChild(overlay);\n document.body.appendChild(host);\n\n renderFooter();\n void startMethod();\n });\n}\n\n// \u2500\u2500\u2500 Small DOM helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction walletInCatalog(wallets: WalletOption[], url: string): boolean {\n return wallets.some((wallet) => wallet.url === url);\n}\n\nfunction el(tag: string, className: string, text?: string): HTMLElement {\n const node = document.createElement(tag);\n node.className = className;\n if (text !== undefined) {\n node.textContent = text;\n }\n return node;\n}\n\nfunction stageButton(label: string, onClick: () => void): HTMLButtonElement {\n const button = document.createElement('button');\n button.className = 'stage-btn';\n button.textContent = label;\n button.addEventListener('click', onClick);\n return button;\n}\n\nfunction stageLinkButton(label: string, onClick: () => void): HTMLButtonElement {\n const button = document.createElement('button');\n button.className = 'footer-link';\n button.textContent = label;\n button.addEventListener('click', onClick);\n return button;\n}\n\nfunction buildHeader(appName: string, appIcon: string | undefined, onCancel: () => void): HTMLDivElement {\n const header = document.createElement('div');\n header.className = 'header';\n\n const identity = document.createElement('div');\n identity.className = 'header-identity';\n\n if (appIcon !== undefined) {\n const icon = document.createElement('img');\n icon.className = 'header-icon';\n icon.src = appIcon;\n icon.alt = '';\n icon.width = 24;\n icon.height = 24;\n icon.addEventListener('error', () => icon.remove());\n identity.appendChild(icon);\n }\n\n const title = document.createElement('h2');\n title.textContent = `Connect to ${appName}`;\n identity.appendChild(title);\n\n const closeBtn = document.createElement('button');\n closeBtn.className = 'close-btn';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.textContent = '\\u00d7';\n closeBtn.addEventListener('click', onCancel);\n\n header.appendChild(identity);\n header.appendChild(closeBtn);\n return header;\n}\n\nfunction trapFocus(shadow: ShadowRoot, event: KeyboardEvent): void {\n const focusables = Array.from(\n shadow.querySelectorAll<HTMLElement>('button, input, a[href], [tabindex]:not([tabindex=\"-1\"])'),\n ).filter((node) => !node.hasAttribute('disabled') && node.offsetParent !== null);\n\n if (focusables.length === 0) {\n return;\n }\n\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = shadow.activeElement as HTMLElement | null;\n\n if (event.shiftKey && (active === first || active === null)) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && active === last) {\n event.preventDefault();\n first.focus();\n }\n}\n\n// \u2500\u2500\u2500 Styles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction buildStyles(isDark: boolean): string {\n const bg = isDark ? '#1a1a2e' : '#ffffff';\n const text = isDark ? '#e0e0e0' : '#1a1a2e';\n const muted = isDark ? '#888' : '#666';\n const border = isDark ? '#333' : '#e0e0e0';\n const itemBg = isDark ? '#16213e' : '#f8f9fa';\n const accent = isDark ? '#4a9eff' : '#0066cc';\n const accentSoft = isDark ? 'rgba(74, 158, 255, 0.16)' : 'rgba(0, 102, 204, 0.1)';\n const danger = isDark ? '#ff6b6b' : '#c0392b';\n const success = isDark ? '#43d17c' : '#1e9e5a';\n\n return `\n * { box-sizing: border-box; margin: 0; padding: 0; }\n\n .overlay {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.5);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n animation: fadeIn 0.15s ease-out;\n }\n\n @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }\n @keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }\n @keyframes stageIn { from { opacity: 0; } to { opacity: 1; } }\n @keyframes shake {\n 0%, 100% { transform: translateX(0); }\n 20%, 60% { transform: translateX(-6px); }\n 40%, 80% { transform: translateX(6px); }\n }\n @keyframes spin { to { transform: rotate(360deg); } }\n\n .modal {\n background: ${bg};\n color: ${text};\n border-radius: 16px;\n width: 400px;\n max-width: 92vw;\n max-height: 88vh;\n overflow-y: auto;\n padding: 20px 24px 16px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n animation: slideUp 0.2s ease-out;\n display: flex;\n flex-direction: column;\n }\n\n .header { display: flex; justify-content: space-between; align-items: center; }\n .header-identity { display: flex; align-items: center; gap: 10px; min-width: 0; }\n .header-icon { border-radius: 6px; }\n h2 { font-size: 16px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n .close-btn {\n background: none; border: none; font-size: 24px; cursor: pointer;\n color: ${muted}; padding: 4px 8px; border-radius: 8px; line-height: 1;\n }\n .close-btn:hover { color: ${text}; background: ${itemBg}; }\n\n .stage {\n min-height: 300px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n text-align: center;\n padding: 16px 0;\n }\n .stage.fade-in > * { animation: stageIn 0.15s ease-out; }\n\n .qr-box {\n width: 216px;\n height: 216px;\n padding: 12px;\n border-radius: 12px;\n background: ${isDark ? '#10192e' : '#ffffff'}\n .claimed-pulse {\n width: 64px; height: 64px; border-radius: 50%;\n background: ${accentSoft}; position: relative;\n }\n .claimed-pulse::after {\n content: ''; position: absolute; inset: 18px; border-radius: 50%;\n background: ${accent};\n animation: enbox-claimed-pulse 1.6s ease-in-out infinite;\n }\n @keyframes enbox-claimed-pulse {\n 0%, 100% { transform: scale(0.85); opacity: 0.7; }\n 50% { transform: scale(1); opacity: 1; }\n }\n @media (prefers-reduced-motion: reduce) {\n .claimed-pulse::after { animation: none; }\n };\n border: 1px solid ${border};\n }\n .qr-box svg { width: 100%; height: 100%; display: block; }\n\n .stage-caption { font-size: 15px; font-weight: 600; }\n .stage-subline { font-size: 13px; color: ${muted}; max-width: 300px; line-height: 1.45; }\n .stage-error { font-size: 13px; color: ${danger}; }\n\n .deep-link {\n display: block;\n width: 100%;\n padding: 14px 16px;\n border-radius: 12px;\n background: ${accent};\n color: #fff;\n font-weight: 600;\n font-size: 15px;\n text-decoration: none;\n }\n\n .pin-row { display: flex; gap: 10px; }\n .pin-row.shake { animation: shake 0.4s ease-in-out; }\n .pin-input {\n width: 48px; height: 56px;\n text-align: center;\n font-size: 24px; font-weight: 600;\n color: ${text};\n background: ${itemBg};\n border: 1px solid ${border};\n border-radius: 10px;\n outline: none;\n }\n .pin-input:focus { border-color: ${accent}; }\n\n .check {\n width: 56px; height: 56px;\n display: flex; align-items: center; justify-content: center;\n border-radius: 50%;\n background: ${success};\n color: #fff;\n font-size: 28px;\n }\n\n .spinner {\n width: 32px; height: 32px;\n border-radius: 50%;\n border: 3px solid ${border};\n border-top-color: ${accent};\n animation: spin 0.8s linear infinite;\n }\n\n .stage-btn {\n padding: 10px 20px;\n border: none;\n border-radius: 10px;\n background: ${accent};\n color: #fff;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n }\n .stage-btn:hover { filter: brightness(1.1); }\n\n .footer {\n border-top: 1px solid ${border};\n padding-top: 10px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n align-items: center;\n }\n\n .footer-link {\n background: none;\n border: none;\n color: ${muted};\n font-size: 13px;\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 8px;\n }\n .footer-link:hover { color: ${text}; background: ${itemBg}; }\n .method-link { color: ${accent}; }\n\n .wallet-switcher { width: 100%; display: flex; flex-direction: column; align-items: center; }\n .wallet-panel { width: 100%; padding: 6px 0; display: flex; flex-direction: column; gap: 4px; }\n .wallet-row {\n width: 100%;\n text-align: left;\n padding: 8px 12px;\n background: ${itemBg};\n border: 1px solid ${border};\n border-radius: 10px;\n color: ${text};\n font-size: 13px;\n cursor: pointer;\n }\n .wallet-row:hover, .wallet-row.selected { border-color: ${accent}; }\n\n .wallet-icon { position: relative; width: 28px; height: 28px; flex-shrink: 0; display: inline-flex; }\n .wallet-badge {\n width: 28px; height: 28px; border-radius: 8px; display: inline-flex;\n align-items: center; justify-content: center; font-size: 13px;\n font-weight: 600; background: ${accentSoft}; color: ${accent};\n }\n .wallet-img { position: absolute; inset: 0; width: 28px; height: 28px; border-radius: 8px; object-fit: cover; }\n .wallet-row-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .wallet-search {\n width: 100%; box-sizing: border-box; padding: 8px 10px; margin-bottom: 4px;\n border-radius: 8px; border: 1px solid ${border}; background: transparent;\n color: inherit; font: inherit;\n }\n .wallet-search:focus { outline: none; border-color: ${accent}; }\n .wallet-empty { padding: 8px 10px; font-size: 12px; opacity: 0.7; }\n .url-error { padding: 4px 2px 0; font-size: 12px; color: ${danger}; }\n .wallet-custom { display: flex; gap: 6px; margin-top: 4px; }\n .url-input {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid ${border};\n border-radius: 10px;\n font-size: 13px;\n background: ${itemBg};\n color: ${text};\n outline: none;\n }\n .url-input:focus { border-color: ${accent}; }\n .url-input.invalid { border-color: ${danger}; }\n .url-go {\n padding: 8px 14px;\n border: none;\n border-radius: 10px;\n background: ${accent};\n color: #fff;\n font-size: 13px;\n cursor: pointer;\n }\n `;\n}\n", "/**\n * Wallet icon builder shared by the connect modal's wallet switcher.\n *\n * Prefers the wallet's own favicon and degrades to a letter badge. We never\n * call a third-party favicon proxy: those 404 for many origins and leak the\n * wallet URL to the proxy.\n *\n * @module\n */\n\nimport type { WalletOption } from '../browser-connect-handler.js';\n\n/** Build a wallet icon element (own favicon with a letter-badge fallback). */\nexport function buildWalletIcon(wallet: WalletOption): HTMLElement {\n const wrap = document.createElement('span');\n wrap.className = 'wallet-icon';\n\n const badge = document.createElement('span');\n badge.className = 'wallet-badge';\n badge.textContent = wallet.name.charAt(0).toUpperCase();\n wrap.appendChild(badge);\n\n const sources = iconCandidates(wallet);\n if (sources.length === 0) {\n return wrap;\n }\n\n const img = document.createElement('img');\n img.className = 'wallet-img';\n img.alt = '';\n img.width = 28;\n img.height = 28;\n\n let index = 0;\n img.addEventListener('error', () => {\n index += 1;\n if (index < sources.length) {\n img.src = sources[index];\n } else {\n img.remove(); // fall back to the letter badge\n }\n });\n\n img.src = sources[index];\n wrap.appendChild(img);\n return wrap;\n}\n\n/** Ordered favicon URLs to try for a wallet, most specific first. */\nfunction iconCandidates(wallet: WalletOption): string[] {\n if (wallet.icon !== undefined) {\n return [wallet.icon];\n }\n\n let origin: string;\n try {\n origin = new URL(wallet.url).origin;\n } catch {\n return [];\n }\n\n return [`${origin}/favicon.svg`, `${origin}/favicon.ico`, `${origin}/favicon.png`];\n}\n", "/**\n * DWeb Connect client \u2014 the dapp side of the popup/postMessage connect flow.\n *\n * {@link PopupClientTransport} implements the `@enbox/connect` kernel's\n * `ConnectTransport` over a wallet popup:\n *\n * 1. The dapp opens `${walletUrl}/dweb-connect` as a popup window.\n * 2. The wallet emits a `loaded` beacon carrying a fresh ephemeral X25519\n * public key and its origin.\n * 3. The kernel seals the signed connect request to that key (ECDH-ES,\n * `apv` bound to the wallet origin) and the transport posts the\n * ciphertext to the popup.\n * 4. The wallet posts back the sealed response JWE (or the deny token),\n * which the kernel opens and value-checks.\n *\n * Only ciphertext crosses the postMessage channel. Every message is checked\n * against the wallet origin derived from the configured wallet URL (never\n * `'*'`), and against the popup window as `event.source`.\n *\n * @module\n */\n\nimport type { Jwk } from '@enbox/crypto';\nimport type {\n ConnectClientMetadata,\n ConnectPermissionRequest,\n ConnectRequestProfile,\n ConnectResult,\n ConnectTransport,\n} from '@enbox/connect';\n\nimport { assertX25519PublicJwk, CONNECT_DENIED_TOKEN, ConnectClient } from '@enbox/connect';\n\nimport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_PATH,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n getTrustedMessage,\n} from './dweb-connect-messages.js';\n\n/** Default budget for the whole popup handshake (beacon + user consent + response). */\nconst DEFAULT_TIMEOUT_MS = 300_000;\n\n/** Interval at which the transport checks whether the user closed the popup. */\nconst CLOSED_POLL_INTERVAL_MS = 500;\n\n/** Window name given to the wallet popup. */\nconst POPUP_WINDOW_NAME = 'enbox-dweb-connect';\n\n/** Window features given to the wallet popup. */\nconst POPUP_WINDOW_FEATURES = 'width=500,height=700,menubar=no,toolbar=no,location=no,status=no';\n\n/** Guards against calling browser-only entry points outside a browser. */\nfunction assertBrowserEnvironment(): void {\n if (typeof window === 'undefined') {\n throw new Error('[@enbox/browser] DWeb Connect is only available in browser environments.');\n }\n}\n\n/**\n * Thrown when the user closes the wallet popup before the wallet finished\n * loading (i.e. before its `loaded` beacon arrived). Callers typically treat\n * this the same as a user denial.\n */\nexport class PopupWindowClosedError extends Error {\n constructor() {\n super('[@enbox/browser] Wallet popup was closed before the wallet finished loading.');\n this.name = 'PopupWindowClosedError';\n }\n}\n\n/** Options for constructing a {@link PopupClientTransport}. */\nexport type PopupClientTransportOptions = {\n /** Base URL of the wallet app (e.g. `https://enbox-wallet.pages.dev`). */\n walletUrl: string;\n\n /**\n * Total budget in milliseconds for the popup handshake. The popup is closed\n * and the handshake rejected when the wallet has not responded in time.\n * @default 300_000 (5 minutes)\n */\n timeoutMs?: number;\n};\n\n/**\n * Popup/postMessage {@link ConnectTransport} for browser dapps.\n *\n * Single-use: construct a new transport per handshake. The **constructor**\n * opens the wallet popup synchronously \u2014 so `window.open` runs inside the user\n * gesture, ahead of the kernel's awaited key generation, and survives strict\n * popup blockers; `requestProfile()` then awaits the wallet's `loaded` beacon;\n * `deliverRequest()` posts the sealed request ciphertext; `awaitResponse()`\n * resolves with the sealed response JWE, or the deny token when the user denies\n * or closes the popup after the handshake was established.\n *\n * Security properties:\n * - `targetOrigin` of every outbound `postMessage` is pinned to the origin\n * derived from `walletUrl` \u2014 never `'*'`.\n * - Inbound messages are dropped unless `event.origin` equals the pinned\n * wallet origin AND `event.source` is the popup window this transport opened.\n * - The beacon's `walletOrigin` field must equal the pinned origin, and its\n * `walletEpk` must be a public-only X25519 JWK; a malformed beacon from the\n * genuine popup fails the handshake closed.\n */\nexport class PopupClientTransport implements ConnectTransport {\n /** {@inheritDoc ConnectTransport.requiresPin} */\n public readonly requiresPin: boolean = false;\n\n private readonly _walletOrigin: string;\n private readonly _timeoutMs: number;\n\n private readonly _popup: Window;\n private _settled = false;\n private _walletEpkReceived = false;\n private _timeoutId?: ReturnType<typeof setTimeout>;\n private _closedPollId?: ReturnType<typeof setInterval>;\n private _messageListener?: (event: MessageEvent) => void;\n\n private readonly _walletEpkPromise: Promise<Jwk>;\n private _resolveWalletEpk?: (walletEpk: Jwk) => void;\n private _rejectWalletEpk?: (error: Error) => void;\n\n private readonly _responsePromise: Promise<string>;\n private _resolveResponse?: (payload: string) => void;\n private _rejectResponse?: (error: Error) => void;\n\n constructor(options: PopupClientTransportOptions) {\n assertBrowserEnvironment();\n\n this._walletOrigin = new URL(options.walletUrl).origin;\n this._timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n // Open the wallet popup SYNCHRONOUSLY, in the user-gesture call stack,\n // before the kernel's awaited `DidJwk.create()` / `X25519.generateKey()`\n // run. Strict popup blockers (Safari) reject a `window.open` issued once\n // the stack has yielded to a prior `await`, so opening it here \u2014 instead of\n // inside the awaited `requestProfile()` \u2014 is what keeps the flow usable.\n const popupUrl = new URL(DWEB_CONNECT_PATH, options.walletUrl).toString();\n const popup = window.open(popupUrl, POPUP_WINDOW_NAME, POPUP_WINDOW_FEATURES);\n if (!popup) {\n throw new Error('[@enbox/browser] Popup blocked. Allow popups for this site to connect to a wallet.');\n }\n this._popup = popup;\n\n this._walletEpkPromise = new Promise<Jwk>((resolve, reject): void => {\n this._resolveWalletEpk = resolve;\n this._rejectWalletEpk = reject;\n });\n\n // Created up-front so a response (or deny) arriving before\n // `awaitResponse()` is called is never dropped. The no-op catch marks\n // early rejections (timeout, popup closed during load) as handled until\n // the kernel attaches its own handlers via `awaitResponse()`.\n this._responsePromise = new Promise<string>((resolve, reject): void => {\n this._resolveResponse = resolve;\n this._rejectResponse = reject;\n });\n this._responsePromise.catch((): undefined => undefined);\n\n // Listen synchronously, before the wallet page can emit its `loaded`\n // beacon, so the beacon is never missed while the kernel awaits key\n // generation ahead of `requestProfile()`.\n this._messageListener = (event: MessageEvent): void => { this.onMessage(event); };\n window.addEventListener('message', this._messageListener);\n\n this._timeoutId = setTimeout((): void => {\n this.fail(new Error('[@enbox/browser] DWeb Connect timed out waiting for wallet response.'));\n }, this._timeoutMs);\n\n this._closedPollId = setInterval((): void => { this.onClosedPoll(); }, CLOSED_POLL_INTERVAL_MS);\n }\n\n /**\n * Awaits the already-open popup's `loaded` beacon, then returns the popup\n * channel profile: ECDH-ES encryption to the beacon's ephemeral key with the\n * pinned wallet origin as the `apv` binding, a `post_message` reply\n * descriptor, and the client-supplied `state` correlator.\n *\n * The popup was opened synchronously at construction, so this method only\n * awaits the beacon \u2014 it never issues the blocker-sensitive `window.open`.\n *\n * @param state - The handshake correlator minted by the {@link ConnectClient}.\n * @throws If the user closes the popup before the beacon arrives\n * ({@link PopupWindowClosedError}), the beacon is malformed, or on\n * timeout.\n */\n public async requestProfile(state: string): Promise<ConnectRequestProfile> {\n const walletEpk = await this._walletEpkPromise;\n\n return {\n encryption : { mode: 'ecdh-es', walletEpk, walletOrigin: this._walletOrigin },\n reply : { mode: 'post_message' },\n state,\n };\n }\n\n /**\n * Posts the sealed request ciphertext to the wallet popup with the\n * `targetOrigin` pinned to the wallet origin.\n */\n public async deliverRequest(jwe: string): Promise<void> {\n this._popup.postMessage({ type: DWEB_CONNECT_REQUEST_MESSAGE_TYPE, jwe }, this._walletOrigin);\n }\n\n /**\n * Awaits the wallet's response ciphertext: the sealed response JWE, or the\n * deny token when the user denies in the wallet or closes the popup.\n * Rejects on timeout.\n */\n public async awaitResponse(): Promise<string> {\n return await this._responsePromise;\n }\n\n private onMessage(event: MessageEvent): void {\n const message = getTrustedMessage(event, this._walletOrigin, this._popup);\n if (message === undefined) { return; }\n\n if (message.type === DWEB_CONNECT_LOADED_MESSAGE_TYPE) {\n this.onLoadedBeacon(message);\n return;\n }\n\n if (message.type === DWEB_CONNECT_RESPONSE_MESSAGE_TYPE) {\n this.onResponseMessage(message);\n }\n }\n\n private onLoadedBeacon(message: Record<string, unknown>): void {\n if (this._settled || this._walletEpkReceived) { return; }\n\n // The beacon passed the origin and source checks, so a malformed payload\n // is a protocol violation by the genuine popup \u2014 fail closed. The X25519\n // public-JWK shape check is delegated to the connect kernel.\n let walletEpk: Jwk;\n try {\n assertX25519PublicJwk(message.walletEpk);\n walletEpk = message.walletEpk;\n } catch {\n this.fail(new Error('[@enbox/browser] Wallet loaded beacon did not carry a valid X25519 public key.'));\n return;\n }\n\n if (message.walletOrigin !== this._walletOrigin) {\n this.fail(new Error('[@enbox/browser] Wallet loaded beacon origin does not match the configured wallet origin.'));\n return;\n }\n\n this._walletEpkReceived = true;\n this._resolveWalletEpk?.(walletEpk);\n }\n\n private onResponseMessage(message: Record<string, unknown>): void {\n if (this._settled) { return; }\n\n if (typeof message.payload !== 'string') {\n this.fail(new Error('[@enbox/browser] Wallet response message did not carry a ciphertext payload.'));\n return;\n }\n\n this._settled = true;\n this.cleanup();\n // No-op on the normal path; unblocks `requestProfile()` if a response\n // somehow arrives before the beacon.\n this._rejectWalletEpk?.(new Error('[@enbox/browser] Wallet responded before the handshake was established.'));\n this._resolveResponse?.(message.payload);\n }\n\n private onClosedPoll(): void {\n if (this._settled || this._popup.closed !== true) { return; }\n\n if (!this._walletEpkReceived) {\n // Closed before the wallet ever loaded \u2014 the handshake cannot proceed.\n this.fail(new PopupWindowClosedError());\n return;\n }\n\n // Closed after the handshake was established \u2014 treat as a user denial.\n this._settled = true;\n this.cleanup();\n this._resolveResponse?.(CONNECT_DENIED_TOKEN);\n }\n\n private fail(error: Error): void {\n if (this._settled) { return; }\n this._settled = true;\n this.cleanup();\n try { this._popup.close(); } catch { /* best effort */ }\n this._rejectWalletEpk?.(error);\n this._rejectResponse?.(error);\n }\n\n private cleanup(): void {\n clearTimeout(this._timeoutId);\n clearInterval(this._closedPollId);\n if (this._messageListener !== undefined) {\n window.removeEventListener('message', this._messageListener);\n this._messageListener = undefined;\n }\n }\n}\n\n/** Options for a one-shot {@link connectViaPopup} flow. */\nexport type PopupConnectOptions = {\n /** Base URL of the wallet app (e.g. `https://enbox-wallet.pages.dev`). */\n walletUrl: string;\n\n /** DWN protocols and permission scopes to request from the wallet. */\n permissionRequests: ConnectPermissionRequest[];\n\n /**\n * Timeout in milliseconds for the popup handshake.\n * @default 300_000 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Display name of the requesting application, shown in the wallet's\n * consent screen. Defaults to the dapp's host.\n */\n appName?: string;\n\n /**\n * Icon URL of the requesting application, shown alongside the app name in\n * the wallet's consent screen.\n */\n appIcon?: string;\n};\n\n/** Collects self-reported environment hints for the wallet's session display. */\nexport function collectBrowserClientMetadata(): ConnectClientMetadata {\n const resolvedOptions = Intl.DateTimeFormat().resolvedOptions();\n const languages = Array.isArray(globalThis.navigator.languages)\n ? globalThis.navigator.languages.filter((language) => typeof language === 'string' && language.length > 0)\n : undefined;\n\n return {\n origin : globalThis.location.origin,\n userAgent : globalThis.navigator.userAgent,\n platform : globalThis.navigator.platform,\n language : globalThis.navigator.language,\n ...(languages && languages.length > 0 ? { languages } : {}),\n ...(resolvedOptions.timeZone ? { timezone: resolvedOptions.timeZone } : {}),\n };\n}\n\n/**\n * Runs one DWeb Connect popup handshake end-to-end: opens the wallet popup,\n * drives the `@enbox/connect` kernel client over a {@link PopupClientTransport},\n * and returns the delegated credentials.\n *\n * @returns The delegate credentials, or `undefined` when the user denied the\n * request or closed the popup.\n * @throws If the popup is blocked, the handshake times out, or the wallet\n * returns an invalid response.\n */\nexport async function connectViaPopup(options: PopupConnectOptions): Promise<ConnectResult | undefined> {\n const transport = new PopupClientTransport({\n walletUrl : options.walletUrl,\n timeoutMs : options.timeout,\n });\n const client = new ConnectClient({ transport });\n\n try {\n return await client.connect({\n appName : options.appName ?? globalThis.location.host,\n appIcon : options.appIcon,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n });\n } catch (error) {\n if (error instanceof PopupWindowClosedError) {\n // The user closed the wallet before it loaded \u2014 same as a denial.\n return undefined;\n }\n throw error;\n }\n}\n", "/**\n * Wire shapes for the DWeb Connect popup/postMessage channel.\n *\n * The dapp and the wallet exchange exactly three message kinds over\n * `window.postMessage`:\n *\n * 1. `loaded` beacon (wallet \u2192 dapp): announces the wallet page is ready and\n * carries a fresh ephemeral X25519 public key plus the wallet's origin.\n * 2. `request` (dapp \u2192 wallet): the sealed connect request JWE \u2014 ciphertext\n * only, encrypted to the beacon key with ECDH-ES and the wallet origin\n * bound into the JWE `apv` header.\n * 3. `response` (wallet \u2192 dapp): the sealed connect response JWE, or the\n * literal deny token \u2014 again ciphertext only.\n *\n * Plaintext never crosses the channel, and both sides pin `targetOrigin`\n * and verify `event.origin` / `event.source` on every message.\n *\n * @module\n */\n\nimport type { Jwk } from '@enbox/crypto';\n\n/** Path of the wallet's DWeb Connect page, opened as a popup by the dapp. */\nexport const DWEB_CONNECT_PATH = '/dweb-connect';\n\n/** Message type of the wallet's `loaded` beacon (wallet \u2192 dapp). */\nexport const DWEB_CONNECT_LOADED_MESSAGE_TYPE = 'enbox-connect-loaded';\n\n/** Message type carrying the sealed connect request JWE (dapp \u2192 wallet). */\nexport const DWEB_CONNECT_REQUEST_MESSAGE_TYPE = 'enbox-connect-request';\n\n/** Message type carrying the sealed connect response JWE or deny token (wallet \u2192 dapp). */\nexport const DWEB_CONNECT_RESPONSE_MESSAGE_TYPE = 'enbox-connect-response';\n\n/**\n * The wallet's readiness beacon. Emitted to `window.opener` once the wallet's\n * DWeb Connect page has generated its per-session ephemeral X25519 key.\n */\nexport type DWebConnectLoadedMessage = {\n type: typeof DWEB_CONNECT_LOADED_MESSAGE_TYPE;\n\n /** Fresh ephemeral X25519 public JWK the dapp seals the request to. */\n walletEpk: Jwk;\n\n /** The wallet's own origin; must match the origin the dapp has pinned. */\n walletOrigin: string;\n};\n\n/** The dapp's sealed connect request, posted to the wallet popup. */\nexport type DWebConnectRequestMessage = {\n type: typeof DWEB_CONNECT_REQUEST_MESSAGE_TYPE;\n\n /** The sealed connect request as a Compact JWE string. */\n jwe: string;\n};\n\n/** The wallet's sealed connect response, posted back to the opener. */\nexport type DWebConnectResponseMessage = {\n type: typeof DWEB_CONNECT_RESPONSE_MESSAGE_TYPE;\n\n /** The sealed connect response JWE, or the literal `CONNECT_DENIED_TOKEN`. */\n payload: string;\n};\n\n/**\n * Applies the shared inbound-message trust filter for the popup channel:\n * pins the message to the expected `event.origin`, pins its `event.source` to\n * the expected window, and requires a non-null object payload.\n *\n * Returns the payload cast to a plain record when every check passes, or\n * `undefined` when the message must be dropped. Both the dapp-side and\n * wallet-side transports early-return on `undefined` before inspecting any\n * message field \u2014 this is the security-critical filter that keeps hostile\n * origins and stray windows off the channel.\n */\nexport function getTrustedMessage(\n event: MessageEvent,\n expectedOrigin: string,\n expectedSource: Window | undefined,\n): Record<string, unknown> | undefined {\n // Origin pinning: only messages from the expected origin count.\n if (event.origin !== expectedOrigin) { return undefined; }\n\n // Source pinning: the message must come from the expected window.\n if (event.source !== expectedSource) { return undefined; }\n\n const data: unknown = event.data;\n if (typeof data !== 'object' || data === null) { return undefined; }\n\n return data as Record<string, unknown>;\n}\n", "/**\n * Minimal QR code encoder \u2014 dependency-free, byte mode, ECC level M,\n * versions 1\u201310 with automatic version selection and standard mask\n * evaluation (ISO/IEC 18004 penalty rules N1\u2013N4).\n *\n * Scope is deliberately narrow: it exists to render wallet-connect URIs in\n * the connect modal without adding a third-party runtime dependency. The\n * encoding pipeline follows the standard exactly \u2014 segment \u2192 codewords \u2192\n * Reed-Solomon blocks \u2192 interleave \u2192 placement \u2192 mask \u2014 and the test suite\n * verifies full module-matrix equality against the `qrcode` npm package\n * (dev-only oracle) across versions and mask patterns.\n *\n * @module\n */\n\n/** An encoded QR symbol: `modules[y][x]` is `true` for dark modules. */\nexport interface QrCode {\n /** Symbol width/height in modules (17 + 4\u00D7version). */\n size: number;\n\n /** Dark/light module matrix, row-major. */\n modules: boolean[][];\n\n /** Symbol version (1\u201310). */\n version: number;\n\n /** Applied mask pattern (0\u20137). */\n mask: number;\n}\n\n/** Error-correction level M codewords per block, indexed by version (1\u201310). */\nconst ECC_PER_BLOCK = [-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26];\n\n/** Error-correction level M block counts, indexed by version (1\u201310). */\nconst NUM_BLOCKS = [-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5];\n\n/** Total codewords in the symbol, indexed by version (1\u201310). */\nconst TOTAL_CODEWORDS = [-1, 26, 44, 70, 100, 134, 172, 196, 242, 292, 346];\n\n/** Format-info error-correction bits for level M (`00` per the standard). */\nconst FORMAT_ECL_M = 0b00;\n\nconst MAX_VERSION = 10;\n\n/** Data codeword capacity for level M at `version`. */\nfunction dataCodewords(version: number): number {\n return TOTAL_CODEWORDS[version] - ECC_PER_BLOCK[version] * NUM_BLOCKS[version];\n}\n\n/**\n * Encodes UTF-8 text as a byte-mode QR symbol at ECC level M.\n *\n * @param text - The payload; encoded as UTF-8 bytes.\n * @param forcedMask - Optional mask override (0\u20137); defaults to the\n * penalty-minimising mask per the standard.\n * @returns The encoded symbol.\n * @throws If the payload does not fit in a version-10 level-M symbol.\n */\nexport function encodeQr(text: string, forcedMask?: number): QrCode {\n const data = new TextEncoder().encode(text);\n\n // \u2500\u2500 Version selection: smallest version that fits the segment. \u2500\u2500\n let version = 0;\n for (let candidate = 1; candidate <= MAX_VERSION; candidate++) {\n const capacityBits = dataCodewords(candidate) * 8;\n const headerBits = 4 + (candidate <= 9 ? 8 : 16);\n if (headerBits + data.length * 8 <= capacityBits) {\n version = candidate;\n break;\n }\n }\n if (version === 0) {\n throw new Error(`[@enbox/browser] QR payload too long (${data.length} bytes exceeds version ${MAX_VERSION}-M capacity).`);\n }\n\n // \u2500\u2500 Segment bits: mode 0100, char count, data, terminator, padding. \u2500\u2500\n const bits: number[] = [];\n const pushBits = (value: number, length: number): void => {\n for (let i = length - 1; i >= 0; i--) {\n bits.push((value >>> i) & 1);\n }\n };\n\n pushBits(0b0100, 4);\n pushBits(data.length, version <= 9 ? 8 : 16);\n for (const byte of data) {\n pushBits(byte, 8);\n }\n\n const capacityBits = dataCodewords(version) * 8;\n pushBits(0, Math.min(4, capacityBits - bits.length)); // terminator\n pushBits(0, (8 - (bits.length % 8)) % 8); // byte align\n\n const padBytes = [0xEC, 0x11];\n for (let i = 0; bits.length < capacityBits; i++) {\n pushBits(padBytes[i % 2], 8);\n }\n\n const codewords = new Uint8Array(capacityBits / 8);\n for (let i = 0; i < bits.length; i++) {\n codewords[i >> 3] |= bits[i] << (7 - (i & 7));\n }\n\n // \u2500\u2500 Reed-Solomon blocks + interleave. \u2500\u2500\n const allCodewords = buildInterleavedCodewords(codewords, version);\n\n // \u2500\u2500 Module placement. \u2500\u2500\n const size = 17 + 4 * version;\n const modules: boolean[][] = Array.from({ length: size }, () => new Array<boolean>(size).fill(false));\n const isFunction: boolean[][] = Array.from({ length: size }, () => new Array<boolean>(size).fill(false));\n\n drawFunctionPatterns(modules, isFunction, version);\n drawCodewords(modules, isFunction, allCodewords);\n\n // \u2500\u2500 Mask selection: apply each mask, score, keep the best. \u2500\u2500\n let mask = forcedMask ?? -1;\n if (mask === -1) {\n let bestPenalty = Infinity;\n for (let candidate = 0; candidate < 8; candidate++) {\n applyMask(modules, isFunction, candidate);\n drawFormatBits(modules, isFunction, candidate);\n const penalty = computePenalty(modules);\n if (penalty < bestPenalty) {\n bestPenalty = penalty;\n mask = candidate;\n }\n applyMask(modules, isFunction, candidate); // undo (XOR is involutive)\n }\n }\n\n applyMask(modules, isFunction, mask);\n drawFormatBits(modules, isFunction, mask);\n\n return { size, modules, version, mask };\n}\n\n/** Splits data codewords into level-M blocks, computes ECC, interleaves. */\nfunction buildInterleavedCodewords(data: Uint8Array, version: number): Uint8Array {\n const numBlocks = NUM_BLOCKS[version];\n const eccLen = ECC_PER_BLOCK[version];\n const totalCodewords = TOTAL_CODEWORDS[version];\n\n const numShortBlocks = numBlocks - (totalCodewords % numBlocks);\n const shortBlockLen = Math.floor(totalCodewords / numBlocks);\n\n const blocks: Uint8Array[] = [];\n const eccBlocks: Uint8Array[] = [];\n const rsDivisor = reedSolomonDivisor(eccLen);\n\n let offset = 0;\n for (let i = 0; i < numBlocks; i++) {\n const dataLen = shortBlockLen - eccLen + (i < numShortBlocks ? 0 : 1);\n const block = data.slice(offset, offset + dataLen);\n offset += dataLen;\n blocks.push(block);\n eccBlocks.push(reedSolomonRemainder(block, rsDivisor));\n }\n\n const result = new Uint8Array(totalCodewords);\n let index = 0;\n const maxDataLen = shortBlockLen - eccLen + 1;\n for (let i = 0; i < maxDataLen; i++) {\n for (let b = 0; b < numBlocks; b++) {\n if (i < blocks[b].length) {\n result[index++] = blocks[b][i];\n }\n }\n }\n for (let i = 0; i < eccLen; i++) {\n for (let b = 0; b < numBlocks; b++) {\n result[index++] = eccBlocks[b][i];\n }\n }\n\n return result;\n}\n\n// \u2500\u2500 GF(256) Reed-Solomon (polynomial 0x11D) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction gfMultiply(x: number, y: number): number {\n let z = 0;\n for (let i = 7; i >= 0; i--) {\n z = (z << 1) ^ ((z >>> 7) * 0x11D);\n z ^= ((y >>> i) & 1) * x;\n }\n return z & 0xFF;\n}\n\n/** Generator polynomial coefficients for `degree` ECC codewords. */\nfunction reedSolomonDivisor(degree: number): Uint8Array {\n const result = new Uint8Array(degree);\n result[degree - 1] = 1;\n\n let root = 1;\n for (let i = 0; i < degree; i++) {\n for (let j = 0; j < degree; j++) {\n result[j] = gfMultiply(result[j], root);\n if (j + 1 < degree) {\n result[j] ^= result[j + 1];\n }\n }\n root = gfMultiply(root, 0x02);\n }\n return result;\n}\n\nfunction reedSolomonRemainder(data: Uint8Array, divisor: Uint8Array): Uint8Array {\n const result = new Uint8Array(divisor.length);\n for (const byte of data) {\n const factor = byte ^ result[0];\n result.copyWithin(0, 1);\n result[result.length - 1] = 0;\n for (let i = 0; i < divisor.length; i++) {\n result[i] ^= gfMultiply(divisor[i], factor);\n }\n }\n return result;\n}\n\n// \u2500\u2500 Function patterns \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Alignment pattern centre coordinates, indexed by version (1\u201310). */\nconst ALIGNMENT_POSITIONS: number[][] = [\n [], [],\n [6, 18], [6, 22], [6, 26], [6, 30], [6, 34],\n [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50],\n];\n\nfunction setFunctionModule(\n modules: boolean[][],\n isFunction: boolean[][],\n x: number,\n y: number,\n dark: boolean,\n): void {\n modules[y][x] = dark;\n isFunction[y][x] = true;\n}\n\nfunction drawFunctionPatterns(modules: boolean[][], isFunction: boolean[][], version: number): void {\n const size = modules.length;\n\n // Timing patterns.\n for (let i = 0; i < size; i++) {\n setFunctionModule(modules, isFunction, 6, i, i % 2 === 0);\n setFunctionModule(modules, isFunction, i, 6, i % 2 === 0);\n }\n\n // Finder patterns (with separators) at three corners.\n drawFinderPattern(modules, isFunction, 3, 3);\n drawFinderPattern(modules, isFunction, size - 4, 3);\n drawFinderPattern(modules, isFunction, 3, size - 4);\n\n // Alignment patterns: all pairs except the three finder corners.\n const positions = ALIGNMENT_POSITIONS[version];\n for (let i = 0; i < positions.length; i++) {\n for (let j = 0; j < positions.length; j++) {\n const skip =\n (i === 0 && j === 0) ||\n (i === 0 && j === positions.length - 1) ||\n (i === positions.length - 1 && j === 0);\n if (!skip) {\n drawAlignmentPattern(modules, isFunction, positions[i], positions[j]);\n }\n }\n }\n\n // Format-info reserved areas (drawn with mask later, but the modules must\n // be marked as function modules before codeword placement).\n drawFormatBits(modules, isFunction, 0);\n\n // Dark module.\n setFunctionModule(modules, isFunction, 8, size - 8, true);\n\n // Version information (versions \u2265 7).\n if (version >= 7) {\n drawVersionBits(modules, isFunction, version);\n }\n}\n\nfunction drawFinderPattern(modules: boolean[][], isFunction: boolean[][], cx: number, cy: number): void {\n const size = modules.length;\n for (let dy = -4; dy <= 4; dy++) {\n for (let dx = -4; dx <= 4; dx++) {\n const x = cx + dx;\n const y = cy + dy;\n if (x < 0 || x >= size || y < 0 || y >= size) {\n continue;\n }\n const distance = Math.max(Math.abs(dx), Math.abs(dy));\n setFunctionModule(modules, isFunction, x, y, distance !== 2 && distance !== 4);\n }\n }\n}\n\nfunction drawAlignmentPattern(modules: boolean[][], isFunction: boolean[][], cx: number, cy: number): void {\n for (let dy = -2; dy <= 2; dy++) {\n for (let dx = -2; dx <= 2; dx++) {\n setFunctionModule(modules, isFunction, cx + dx, cy + dy, Math.max(Math.abs(dx), Math.abs(dy)) !== 1);\n }\n }\n}\n\n/** 15-bit format info: 5 data bits BCH(15,5)-expanded, XORed with 0x5412. */\nfunction drawFormatBits(modules: boolean[][], isFunction: boolean[][], mask: number): void {\n const size = modules.length;\n\n const data = (FORMAT_ECL_M << 3) | mask;\n let rem = data;\n for (let i = 0; i < 10; i++) {\n rem = (rem << 1) ^ ((rem >>> 9) * 0x537);\n }\n const bits = ((data << 10) | rem) ^ 0x5412;\n\n // Around the top-left finder.\n for (let i = 0; i <= 5; i++) {\n setFunctionModule(modules, isFunction, 8, i, ((bits >>> i) & 1) !== 0);\n }\n setFunctionModule(modules, isFunction, 8, 7, ((bits >>> 6) & 1) !== 0);\n setFunctionModule(modules, isFunction, 8, 8, ((bits >>> 7) & 1) !== 0);\n setFunctionModule(modules, isFunction, 7, 8, ((bits >>> 8) & 1) !== 0);\n for (let i = 9; i < 15; i++) {\n setFunctionModule(modules, isFunction, 14 - i, 8, ((bits >>> i) & 1) !== 0);\n }\n\n // Second copy: below the top-right finder and beside the bottom-left one.\n for (let i = 0; i < 8; i++) {\n setFunctionModule(modules, isFunction, size - 1 - i, 8, ((bits >>> i) & 1) !== 0);\n }\n for (let i = 8; i < 15; i++) {\n setFunctionModule(modules, isFunction, 8, size - 15 + i, ((bits >>> i) & 1) !== 0);\n }\n}\n\n/** 18-bit version info (versions \u2265 7): 6 data bits + BCH(18,6) remainder. */\nfunction drawVersionBits(modules: boolean[][], isFunction: boolean[][], version: number): void {\n const size = modules.length;\n\n let rem = version;\n for (let i = 0; i < 12; i++) {\n rem = (rem << 1) ^ ((rem >>> 11) * 0x1F25);\n }\n const bits = (version << 12) | rem;\n\n for (let i = 0; i < 18; i++) {\n const bit = ((bits >>> i) & 1) !== 0;\n const a = size - 11 + (i % 3);\n const b = Math.floor(i / 3);\n setFunctionModule(modules, isFunction, a, b, bit);\n setFunctionModule(modules, isFunction, b, a, bit);\n }\n}\n\n/** Zig-zag codeword placement over non-function modules. */\nfunction drawCodewords(modules: boolean[][], isFunction: boolean[][], codewords: Uint8Array): void {\n const size = modules.length;\n let bitIndex = 0;\n\n for (let right = size - 1; right >= 1; right -= 2) {\n if (right === 6) {\n right = 5;\n }\n for (let vertical = 0; vertical < size; vertical++) {\n for (let j = 0; j < 2; j++) {\n const x = right - j;\n const upward = ((right + 1) & 2) === 0;\n const y = upward ? size - 1 - vertical : vertical;\n if (!isFunction[y][x] && bitIndex < codewords.length * 8) {\n modules[y][x] = ((codewords[bitIndex >> 3] >>> (7 - (bitIndex & 7))) & 1) !== 0;\n bitIndex++;\n }\n }\n }\n }\n}\n\n/** XORs the mask pattern over non-function modules (involutive). */\nfunction applyMask(modules: boolean[][], isFunction: boolean[][], mask: number): void {\n const size = modules.length;\n for (let y = 0; y < size; y++) {\n for (let x = 0; x < size; x++) {\n if (isFunction[y][x]) {\n continue;\n }\n let invert: boolean;\n switch (mask) {\n case 0: invert = (x + y) % 2 === 0; break;\n case 1: invert = y % 2 === 0; break;\n case 2: invert = x % 3 === 0; break;\n case 3: invert = (x + y) % 3 === 0; break;\n case 4: invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0; break;\n case 5: invert = ((x * y) % 2) + ((x * y) % 3) === 0; break;\n case 6: invert = (((x * y) % 2) + ((x * y) % 3)) % 2 === 0; break;\n default: invert = (((x + y) % 2) + ((x * y) % 3)) % 2 === 0; break;\n }\n if (invert) {\n modules[y][x] = !modules[y][x];\n }\n }\n }\n}\n\n// \u2500\u2500 Mask penalty scoring (rules N1\u2013N4) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction computePenalty(modules: boolean[][]): number {\n const size = modules.length;\n let penalty = 0;\n\n // N1: runs of \u22655 same-colour modules in a row/column.\n for (let y = 0; y < size; y++) {\n let runColor = false;\n let runLength = 0;\n for (let x = 0; x < size; x++) {\n if (x === 0 || modules[y][x] !== runColor) {\n runColor = modules[y][x];\n runLength = 1;\n } else {\n runLength++;\n if (runLength === 5) {\n penalty += 3;\n } else if (runLength > 5) {\n penalty += 1;\n }\n }\n }\n }\n for (let x = 0; x < size; x++) {\n let runColor = false;\n let runLength = 0;\n for (let y = 0; y < size; y++) {\n if (y === 0 || modules[y][x] !== runColor) {\n runColor = modules[y][x];\n runLength = 1;\n } else {\n runLength++;\n if (runLength === 5) {\n penalty += 3;\n } else if (runLength > 5) {\n penalty += 1;\n }\n }\n }\n }\n\n // N2: 2\u00D72 blocks of the same colour.\n for (let y = 0; y < size - 1; y++) {\n for (let x = 0; x < size - 1; x++) {\n const c = modules[y][x];\n if (c === modules[y][x + 1] && c === modules[y + 1][x] && c === modules[y + 1][x + 1]) {\n penalty += 3;\n }\n }\n }\n\n // N3: finder-like 1:1:3:1:1 patterns with 4-module light flank.\n const hasFinderPattern = (line: boolean[], start: number): number => {\n const core = [true, false, true, true, true, false, true];\n const matchesCore = core.every((value, index) => line[start + index] === value);\n if (!matchesCore) {\n return 0;\n }\n const lightBefore = start >= 4 && line.slice(start - 4, start).every((v) => !v);\n const lightAfter = start + 11 <= line.length && line.slice(start + 7, start + 11).every((v) => !v);\n return (lightBefore ? 40 : 0) + (lightAfter ? 40 : 0);\n };\n\n for (let y = 0; y < size; y++) {\n const row = modules[y];\n const column = modules.map((r) => r[y]);\n for (let x = 0; x + 7 <= size; x++) {\n penalty += hasFinderPattern(row, x);\n penalty += hasFinderPattern(column, x);\n }\n }\n\n // N4: dark-module proportion deviation from 50%, in 5% steps.\n let dark = 0;\n for (const row of modules) {\n for (const module of row) {\n if (module) {\n dark++;\n }\n }\n }\n const total = size * size;\n const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;\n penalty += k * 10;\n\n return penalty;\n}\n\n// \u2500\u2500 SVG rendering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Options for {@link qrToSvg}. */\nexport interface QrSvgOptions {\n /** Dark module colour. @default '#000000' */\n dark?: string;\n\n /** Light/background colour; `'transparent'` is allowed. @default '#ffffff' */\n light?: string;\n\n /** Quiet-zone width in modules on each side. @default 2 */\n quietZone?: number;\n}\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Renders an encoded symbol as a crisp, scalable `<svg>` element. One\n * `<path>` carries all dark modules so the output stays compact.\n *\n * Built with `createElementNS`/`setAttribute` rather than markup strings so\n * caller-supplied colours can never be interpreted as HTML (CodeQL\n * js/html-constructed-from-input). Append the returned element directly;\n * never serialize it back through `innerHTML`.\n */\nexport function qrToSvg(qr: QrCode, options: QrSvgOptions = {}): SVGSVGElement {\n const dark = options.dark ?? '#000000';\n const light = options.light ?? '#ffffff';\n const quietZone = options.quietZone ?? 2;\n const dimension = qr.size + quietZone * 2;\n\n let path = '';\n for (let y = 0; y < qr.size; y++) {\n for (let x = 0; x < qr.size; x++) {\n if (qr.modules[y][x]) {\n path += `M${x + quietZone} ${y + quietZone}h1v1h-1z`;\n }\n }\n }\n\n const svg = document.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('viewBox', `0 0 ${dimension} ${dimension}`);\n svg.setAttribute('shape-rendering', 'crispEdges');\n svg.setAttribute('role', 'img');\n\n const rect = document.createElementNS(SVG_NS, 'rect');\n rect.setAttribute('width', String(dimension));\n rect.setAttribute('height', String(dimension));\n rect.setAttribute('fill', light);\n svg.appendChild(rect);\n\n const modules = document.createElementNS(SVG_NS, 'path');\n modules.setAttribute('d', path);\n modules.setAttribute('fill', dark);\n svg.appendChild(modules);\n\n return svg;\n}\n", "/**\n * Wallet discovery via the `/.well-known/enbox-connect` document.\n *\n * Shared by the connect modal (relay discovery + custom-URL validation)\n * and exported for dapps rolling their own wallet selection UI.\n *\n * @module\n */\n\n/** Path of the wallet's connect discovery document, relative to its origin. */\nexport const WALLET_WELL_KNOWN_PATH = '/.well-known/enbox-connect';\n\n/** Timeout applied to the well-known validation fetch. */\nconst WELL_KNOWN_FETCH_TIMEOUT_MS = 6_000;\n\n/** The wallet's `/.well-known/enbox-connect` discovery document. */\nexport interface WalletWellKnownDocument {\n /** Base URL of the relay that brokers this wallet's remote connects. */\n connectServerUrl: string;\n}\n\n/**\n * Fetch a wallet's `/.well-known/enbox-connect` discovery document.\n *\n * Resolves the parsed document when it is reachable and names a\n * `connectServerUrl`; resolves `undefined` for unreachable origins, non-2xx\n * responses, CORS failures, and malformed documents.\n */\nexport async function fetchWalletWellKnown(origin: string): Promise<WalletWellKnownDocument | undefined> {\n try {\n const wellKnownUrl = new URL(WALLET_WELL_KNOWN_PATH, origin).toString();\n const response = await fetch(wellKnownUrl, { signal: AbortSignal.timeout(WELL_KNOWN_FETCH_TIMEOUT_MS) });\n if (!response.ok) {\n return undefined;\n }\n\n const payload = await response.json() as { connectServerUrl?: unknown } | null;\n if (typeof payload?.connectServerUrl !== 'string') {\n return undefined;\n }\n return { connectServerUrl: payload.connectServerUrl };\n } catch {\n return undefined;\n }\n}\n\n/**\n * Fetch a wallet's `/.well-known/enbox-connect` discovery document to confirm\n * the origin hosts an Enbox-compatible wallet.\n *\n * Resolves `true` only when the document is reachable and names a\n * `connectServerUrl`. Unreachable origins, non-2xx responses, CORS failures,\n * and malformed documents resolve `false`.\n */\nexport async function probeWalletWellKnown(origin: string): Promise<boolean> {\n return (await fetchWalletWellKnown(origin)) !== undefined;\n}\n", "/**\n * Relay connect runner \u2014 the dapp side of the QR/deep-link connect flow,\n * with interactive PIN retry.\n *\n * This mirrors the `@enbox/connect` kernel `ConnectClient` step-for-step and\n * is composed entirely from the kernel's exported primitives (`sealRequest`,\n * `openResponse`, `RelayClientTransport`); no cryptography is reimplemented\n * here. It exists as a separate orchestrator for one reason the kernel\n * client cannot express today: **PIN retry against the delivered response**.\n * `ConnectClient` collects the PIN once and opens the response once, so a\n * mistyped code fails the whole handshake \u2014 the wallet user would have to\n * scan and approve again. The connect modal instead keeps the sealed\n * response and re-runs `openResponse` per attempt, which is safe because\n * opening is a pure decrypt-and-verify step.\n *\n * If the kernel later grows a PIN-attempts seam, this module collapses into\n * `ConnectClient` usage.\n *\n * @module\n */\n\nimport type { Jwk } from '@enbox/crypto';\nimport type {\n ConnectClientMetadata,\n ConnectPermissionRequest,\n ConnectRequest,\n ConnectResult,\n WalletUriHandoff,\n} from '@enbox/connect';\n\nimport { DidJwk } from '@enbox/dids';\nimport { X25519 } from '@enbox/crypto';\nimport {\n CONNECT_DENIED_TOKEN,\n openResponse,\n randomToken,\n RelayClientTransport,\n sealRequest,\n} from '@enbox/connect';\n\n/** Maximum interactive PIN attempts before the handshake fails. */\nexport const MAX_PIN_ATTEMPTS = 6;\n\n/** Thrown internally when a relay handshake is cancelled by the UI. */\nexport class RelayConnectCancelledError extends Error {\n constructor() {\n super('[@enbox/browser] Relay connect cancelled.');\n this.name = 'RelayConnectCancelledError';\n }\n}\n\n/** Options for {@link runRelayConnect}. */\nexport interface RelayConnectOptions {\n /** Relay base URL (the wallet's `connectServerUrl`). */\n connectServerUrl: string;\n\n /** Wallet URI the request pointer is attached to (QR / deep-link target). */\n walletUri: string;\n\n /** The user-friendly name of the app, shown in the wallet consent UI. */\n appName: string;\n\n /** Optional icon URL for the app, shown in the wallet consent UI. */\n appIcon?: string;\n\n /** Optional client/environment metadata for wallet session display. */\n clientMetadata?: ConnectClientMetadata;\n\n /** DWN protocols and permission scopes being requested. */\n permissionRequests: ConnectPermissionRequest[];\n\n /** Total milliseconds to poll the relay for a wallet response. */\n timeoutMs?: number;\n\n /** Milliseconds between relay polling attempts. */\n pollIntervalMs?: number;\n\n /**\n * Receives the wallet URI handoff (with the request pointer TTL) as soon\n * as the request is delivered \u2014 render it as a QR code or deep link.\n */\n onWalletUriReady: (handoff: WalletUriHandoff) => void;\n\n /**\n * Collects one PIN attempt from the user. Called again (with the attempt\n * number, 1-based, and the previous failure) after a wrong code, up to\n * {@link MAX_PIN_ATTEMPTS} times.\n */\n requestPin: (attempt: number, previousError?: Error) => Promise<string>;\n\n /**\n * Cancellation signal: when it settles, polling stops and the handshake\n * rejects with {@link RelayConnectCancelledError}.\n */\n cancelled?: Promise<never> | undefined;\n\n /**\n * Invoked once when the relay reports the wallet has claimed (fetched)\n * the pushed request \u2014 the app can show \"phone connected\" progress.\n */\n onClaimed?: () => void;\n\n /** Transport factory override (tests). */\n createTransport?: (options: {\n connectServerUrl: string;\n walletUri: string;\n timeoutMs?: number;\n pollIntervalMs?: number;\n onClaimed?: () => void;\n }) => Pick<RelayClientTransport, 'requestProfile' | 'deliverRequest' | 'awaitResponse' | 'requiresPin'>;\n}\n\n/**\n * Runs one relay-mediated connect handshake end-to-end and returns the\n * delegated credentials, or `undefined` when the user denied in the wallet.\n */\nexport async function runRelayConnect(options: RelayConnectOptions): Promise<ConnectResult | undefined> {\n const createTransport = options.createTransport\n ?? ((transportOptions): RelayClientTransport => new RelayClientTransport(transportOptions));\n\n const transport = createTransport({\n connectServerUrl : options.connectServerUrl,\n walletUri : options.walletUri,\n timeoutMs : options.timeoutMs,\n pollIntervalMs : options.pollIntervalMs,\n onClaimed : options.onClaimed,\n });\n\n // Ephemeral client DID for request signing and response addressing, and a\n // fresh X25519 pair the wallet seals the response to \u2014 same shape as the\n // kernel `ConnectClient`.\n const clientDid = await DidJwk.create();\n const responsePrivateKey = await X25519.generateKey();\n const responsePublicKey: Jwk = { kty: 'OKP', crv: 'X25519', x: responsePrivateKey.x };\n\n const nonce = randomToken();\n const state = randomToken();\n\n const profile = await transport.requestProfile(state);\n\n const request: ConnectRequest = {\n clientDid : clientDid.uri,\n appName : options.appName,\n appIcon : options.appIcon,\n clientMetadata : options.clientMetadata,\n permissionRequests : options.permissionRequests,\n supportedDidMethods : ['did:dht', 'did:jwk'],\n nonce,\n state,\n responseKey : responsePublicKey,\n reply : profile.reply,\n };\n\n const requestJwe = await sealRequest({ request, signer: clientDid, encryption: profile.encryption });\n\n const handoff = await transport.deliverRequest(requestJwe);\n if (handoff !== undefined) {\n options.onWalletUriReady(handoff);\n }\n\n const race = options.cancelled === undefined\n ? transport.awaitResponse()\n : Promise.race([transport.awaitResponse(), options.cancelled]);\n\n const responseCiphertext = await race;\n if (responseCiphertext === CONNECT_DENIED_TOKEN) {\n return undefined;\n }\n\n // Interactive PIN loop: opening is a pure decrypt-and-verify step, so a\n // wrong code costs one more attempt, not a whole new wallet approval.\n // Errors raised by the kernel's value checks carry a 'Connect:' prefix and\n // indicate a protocol violation, not a mistyped code \u2014 those fail closed.\n let lastError: Error | undefined;\n for (let attempt = 1; attempt <= MAX_PIN_ATTEMPTS; attempt++) {\n const pin = await (options.cancelled === undefined\n ? options.requestPin(attempt, lastError)\n : Promise.race([options.requestPin(attempt, lastError), options.cancelled]));\n\n try {\n const response = await openResponse({\n jwe : responseCiphertext,\n recipientPrivateKey : responsePrivateKey,\n expected : { clientDid: clientDid.uri, nonce, state },\n pin,\n });\n\n if (response.delegatePortableDid === undefined) {\n throw new Error('Connect: wallet response omitted `delegatePortableDid`.');\n }\n\n return {\n delegatePortableDid : response.delegatePortableDid,\n delegateGrants : response.delegateGrants,\n connectedDid : response.providerDid,\n sessionRevocations : response.sessionRevocations,\n };\n } catch (error) {\n const failure = error instanceof Error ? error : new Error(String(error));\n if (failure.message.startsWith('Connect:')) {\n // Structural/value-check failure \u2014 retrying the PIN cannot help.\n throw failure;\n }\n lastError = failure;\n }\n }\n\n throw new Error(`[@enbox/browser] The pairing code did not match after ${MAX_PIN_ATTEMPTS} attempts.`);\n}\n", "/**\n * Browser connect handler for `@enbox/auth`.\n *\n * Implements the {@link ConnectHandler} interface using browser-native\n * DWeb Connect (popup + postMessage) with a wallet selector modal.\n *\n * @module\n */\n\nimport type { ConnectPermissionRequest } from '@enbox/connect';\nimport type { ConnectHandler, ConnectResult } from '@enbox/auth';\n\nimport { runConnectModal } from './ui/connect-modal.js';\n\nimport type { ConnectMethod } from './ui/connect-modal.js';\n\n/** A wallet entry shown in the wallet selector modal. */\nexport interface WalletOption {\n /** Display name (e.g. \"Enbox\"). */\n name: string;\n\n /** Base URL of the wallet app (e.g. \"https://enbox-wallet.pages.dev\"). */\n url: string;\n\n /** Optional icon URL. If omitted, the wallet's favicon is used. */\n icon?: string;\n\n /** Short description shown below the wallet name in the selector. */\n description?: string;\n}\n\n/** Default wallets shown in the selector when no overrides are provided. */\nexport const DEFAULT_WALLETS: WalletOption[] = [\n {\n name : 'Enbox',\n url : 'https://enbox-wallet.pages.dev',\n description : 'Manage your digital identity and data',\n },\n {\n name : 'Prism',\n url : 'https://prism-wallet.pages.dev',\n description : 'A clear view into your digital identity',\n },\n {\n name : 'Matcha',\n url : 'https://matcha-wallet.pages.dev',\n description : 'A fresh approach to digital identity',\n },\n {\n name : 'Onyx',\n url : 'https://onyx-wallet.pages.dev',\n description : 'A refined home for your digital identity',\n },\n];\n\n/** Options for creating a BrowserConnectHandler. */\nexport interface BrowserConnectHandlerOptions {\n /**\n * Known wallets shown in the wallet selector modal.\n * If omitted, {@link DEFAULT_WALLETS} is used.\n */\n wallets?: WalletOption[];\n\n /**\n * Explicit wallet URL. If provided, the wallet selector is skipped\n * and this URL is used directly.\n */\n walletUrl?: string;\n\n /**\n * Timeout in milliseconds for the wallet popup flow.\n * @default 300_000 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Display name of the requesting application.\n * Shown in the wallet's permission consent screen.\n */\n appName?: string;\n\n /**\n * Icon URL of the requesting application.\n * Shown alongside the app name in the wallet's consent screen.\n * Defaults to `${window.location.origin}/favicon.ico` if omitted.\n */\n appIcon?: string;\n\n /**\n * Preferred connect method on open: `'phone'` (QR / deep link via the\n * relay) or `'browser'` (wallet popup on this device). Overrides the\n * remembered choice.\n * @default 'phone'\n */\n preferredMethod?: ConnectMethod;\n\n /**\n * Remember the successful method + wallet in localStorage and pre-shape\n * the next connect session accordingly.\n * @default true\n */\n rememberChoice?: boolean;\n\n /**\n * Relay base URL override for the phone path. When omitted, each wallet's\n * `connectServerUrl` is discovered from its `/.well-known/enbox-connect`\n * document.\n */\n connectServerUrl?: string;\n\n /**\n * Path appended to the wallet origin to form the phone path's QR /\n * deep-link target.\n * @default '/connect/app'\n */\n relayWalletPath?: string;\n}\n\n/**\n * Create a browser-native connect handler over the connect modal.\n *\n * The modal owns the whole session on one surface: the phone path (a QR /\n * deep link over the relay, with pairing-code entry) is the default, the\n * in-browser wallet popup is the alternate, and the wallet catalog plus\n * custom-URL entry live in a disclosure. It resolves with the delegate\n * credentials on success and `undefined` when the user denies.\n *\n * @example\n * ```ts\n * import { AuthManager, BrowserConnectHandler } from '@enbox/browser';\n *\n * const auth = await AuthManager.create({\n * connectHandler: BrowserConnectHandler({\n * appName: 'My Dapp',\n * }),\n * });\n *\n * const session = await auth.connect({ protocols: [NotesProtocol] });\n * ```\n */\nexport function BrowserConnectHandler(\n options: BrowserConnectHandlerOptions = {},\n): ConnectHandler {\n const {\n wallets = DEFAULT_WALLETS,\n walletUrl,\n timeout,\n appName,\n appIcon,\n preferredMethod,\n rememberChoice,\n connectServerUrl,\n relayWalletPath,\n } = options;\n\n return {\n async requestAccess(params: {\n permissionRequests: ConnectPermissionRequest[];\n }): Promise<ConnectResult | undefined> {\n return runConnectModal({\n wallets,\n walletUrl,\n preferredMethod,\n rememberChoice,\n appName,\n appIcon : appIcon ?? `${window.location.origin}/favicon.ico`,\n connectServerUrl,\n relayWalletPath,\n timeout,\n permissionRequests : params.permissionRequests,\n });\n },\n };\n}\n", "/**\n * DWeb Connect wallet transport \u2014 the wallet side of the popup/postMessage\n * connect flow, exported for wallet apps (e.g. the Enbox web wallet).\n *\n * A wallet's `/dweb-connect` page creates one transport per session:\n *\n * 1. `create()` generates a fresh ephemeral X25519 key pair and emits the\n * `loaded` beacon (public key + wallet origin) to the opener window with a\n * pinned `targetOrigin`.\n * 2. `awaitRequest()` receives the sealed request ciphertext and opens it via\n * the `@enbox/connect` kernel (`ConnectProvider.openRequest`), which\n * value-checks the `apv` origin binding against this wallet's origin.\n * 3. After the consent ceremony, the wallet posts the sealed response JWE via\n * `sendResponse()` \u2014 or the deny token via `deny()` \u2014 back to the opener,\n * again with a pinned `targetOrigin`.\n *\n * The dapp origin is never assumed: it is taken from an explicit option or\n * derived from `document.referrer`, and `create()` fails when neither is\n * available. `'*'` is never used as a `targetOrigin`.\n *\n * @module\n */\n\nimport type { ConnectRequest } from '@enbox/connect';\nimport type { Jwk } from '@enbox/crypto';\n\nimport { X25519 } from '@enbox/crypto';\nimport { CONNECT_DENIED_TOKEN, ConnectProvider } from '@enbox/connect';\n\nimport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n getTrustedMessage,\n} from './dweb-connect-messages.js';\n\n/** Default budget for awaiting the dapp's sealed request. */\nconst DEFAULT_REQUEST_TIMEOUT_MS = 300_000;\n\n/** Options for creating a {@link WalletPostMessageTransport}. */\nexport type WalletPostMessageTransportOptions = {\n /**\n * Origin of the dapp that opened this wallet popup. When omitted, it is\n * derived from `document.referrer`; creation fails when neither is\n * available \u2014 the transport never falls back to `'*'`.\n */\n dappOrigin?: string;\n\n /**\n * The dapp window to exchange messages with.\n * @default window.opener\n */\n dappWindow?: Window;\n\n /**\n * Budget in milliseconds for awaiting the dapp's sealed request.\n * @default 300_000 (5 minutes)\n */\n timeoutMs?: number;\n};\n\n/**\n * Wallet-side postMessage transport for the DWeb Connect popup flow.\n *\n * Security properties:\n * - `targetOrigin` of every outbound `postMessage` (beacon and response) is\n * pinned to the dapp origin \u2014 never `'*'`.\n * - Inbound messages are dropped unless `event.origin` equals the pinned dapp\n * origin AND `event.source` is the dapp window.\n * - The ephemeral X25519 private key never leaves the transport; the request\n * JWE is opened by the kernel with the `apv` header value-checked against\n * this wallet's own origin.\n */\nexport class WalletPostMessageTransport {\n private readonly _dappOrigin: string;\n private readonly _dappWindow: Window;\n private readonly _recipientPrivateKey: Jwk;\n\n private _requestReceived = false;\n private _timeoutId?: ReturnType<typeof setTimeout>;\n private _messageListener?: (event: MessageEvent) => void;\n\n private readonly _requestPromise: Promise<ConnectRequest>;\n private _resolveRequest?: (request: ConnectRequest) => void;\n private _rejectRequest?: (error: Error) => void;\n\n private constructor(params: { dappOrigin: string; dappWindow: Window; recipientPrivateKey: Jwk; timeoutMs: number }) {\n this._dappOrigin = params.dappOrigin;\n this._dappWindow = params.dappWindow;\n this._recipientPrivateKey = params.recipientPrivateKey;\n\n this._requestPromise = new Promise<ConnectRequest>((resolve, reject): void => {\n this._resolveRequest = resolve;\n this._rejectRequest = reject;\n });\n // Mark early rejections (timeout before `awaitRequest()` is called) as\n // handled until the wallet attaches its own handlers.\n this._requestPromise.catch((): undefined => undefined);\n\n this._messageListener = (event: MessageEvent): void => { this.onMessage(event); };\n window.addEventListener('message', this._messageListener);\n\n this._timeoutId = setTimeout((): void => {\n this.close();\n this._rejectRequest?.(new Error('[@enbox/browser] Timed out waiting for the connect request from the dapp.'));\n }, params.timeoutMs);\n }\n\n /**\n * Creates the transport for one connect session: resolves and pins the dapp\n * origin, generates a fresh ephemeral X25519 key pair, starts listening for\n * the sealed request, and emits the `loaded` beacon to the dapp window.\n *\n * @throws If not in a browser, if no dapp window is available, or if the\n * dapp origin can neither be supplied nor derived from the referrer.\n */\n public static async create(options: WalletPostMessageTransportOptions = {}): Promise<WalletPostMessageTransport> {\n if (typeof window === 'undefined') {\n throw new Error('[@enbox/browser] WalletPostMessageTransport is only available in browser environments.');\n }\n\n const dappWindow = options.dappWindow ?? window.opener as Window | null;\n if (!dappWindow) {\n throw new Error('[@enbox/browser] No opener window: the DWeb Connect page must be opened as a popup by the dapp.');\n }\n\n const dappOrigin = resolveDappOrigin(options.dappOrigin);\n\n const recipientPrivateKey = await X25519.generateKey();\n const walletEpk: Jwk = { kty: 'OKP', crv: 'X25519', x: recipientPrivateKey.x };\n\n const transport = new WalletPostMessageTransport({\n dappOrigin,\n dappWindow,\n recipientPrivateKey,\n timeoutMs: options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n });\n\n // The listener is registered, so the beacon cannot race the request.\n dappWindow.postMessage({\n type : DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n walletEpk,\n walletOrigin : globalThis.location.origin,\n }, dappOrigin);\n\n return transport;\n }\n\n /** The pinned origin of the dapp this transport exchanges messages with. */\n public get dappOrigin(): string {\n return this._dappOrigin;\n }\n\n /**\n * Awaits the dapp's sealed request and opens it via the kernel: ECDH-ES\n * decryption with this session's ephemeral key, `apv` value-checked against\n * this wallet's origin, JWT signature verification, and payload shape\n * assertion. Rejects on timeout, on an unopenable request, or when the\n * request does not use the `post_message` reply mode.\n */\n public async awaitRequest(): Promise<ConnectRequest> {\n return await this._requestPromise;\n }\n\n /**\n * Posts the sealed response JWE (or the deny token) back to the dapp window\n * with the `targetOrigin` pinned to the dapp origin, then closes the\n * transport.\n *\n * @param idToken - The sealed response JWE, or the literal deny token.\n */\n public sendResponse(idToken: string): void {\n this._dappWindow.postMessage({\n type : DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n payload : idToken,\n }, this._dappOrigin);\n this.close();\n }\n\n /** Posts the deny token back to the dapp \u2014 the user rejected the request. */\n public deny(): void {\n this.sendResponse(CONNECT_DENIED_TOKEN);\n }\n\n /** Stops listening and releases the session's timers. Idempotent. */\n public close(): void {\n clearTimeout(this._timeoutId);\n if (this._messageListener !== undefined) {\n window.removeEventListener('message', this._messageListener);\n this._messageListener = undefined;\n }\n }\n\n private onMessage(event: MessageEvent): void {\n const message = getTrustedMessage(event, this._dappOrigin, this._dappWindow);\n if (message === undefined) { return; }\n\n if (message.type !== DWEB_CONNECT_REQUEST_MESSAGE_TYPE || this._requestReceived) { return; }\n this._requestReceived = true;\n\n if (typeof message.jwe !== 'string') {\n this.settleRequest(new Error('[@enbox/browser] Connect request message did not carry a ciphertext payload.'));\n return;\n }\n\n void this.openRequest(message.jwe);\n }\n\n private async openRequest(jwe: string): Promise<void> {\n try {\n const request = await ConnectProvider.openRequest({\n jwe,\n decryption: {\n mode : 'ecdh-es',\n recipientPrivateKey : this._recipientPrivateKey,\n walletOrigin : globalThis.location.origin,\n },\n });\n\n if (request.reply.mode !== 'post_message') {\n this.settleRequest(new Error('[@enbox/browser] Connect request over the popup channel must use the `post_message` reply mode.'));\n return;\n }\n\n this.settleRequest(request);\n } catch (error) {\n this.settleRequest(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private settleRequest(outcome: ConnectRequest | Error): void {\n clearTimeout(this._timeoutId);\n if (outcome instanceof Error) {\n this.close();\n this._rejectRequest?.(outcome);\n return;\n }\n this._resolveRequest?.(outcome);\n }\n}\n\n/**\n * Resolves the dapp origin to pin: the explicit option when provided,\n * otherwise the origin of `document.referrer`. Never falls back to `'*'`.\n */\nfunction resolveDappOrigin(explicitOrigin: string | undefined): string {\n if (explicitOrigin !== undefined) {\n return new URL(explicitOrigin).origin;\n }\n\n if (document.referrer) {\n return new URL(document.referrer).origin;\n }\n\n throw new Error(\n '[@enbox/browser] Unable to determine the dapp origin: no `dappOrigin` option was provided and `document.referrer` is empty.'\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["Enbox", "defineProtocol", "repository", "AuthManager", "AuthSession", "normalizeProtocolRequests", "WalletConnect", "CONNECT_DENIED_TOKEN", "ConnectProvider", "DidDht", "DidWeb", "UniversalResolver", "parseDrlUrl", "url", "idx", "prefix", "rest", "slashIdx", "didResolver", "UniversalResolver", "DidDht", "DidWeb", "httpToHttpsRegex", "trailingSlashRegex", "DRL_CACHE_NAME", "getDwnEndpoints", "did", "didDocument", "endpoints", "service", "url", "openDrlCache", "handleEvent", "event", "path", "options", "drl", "responseCache", "cachedResponse", "match", "cacheTime", "fetchResource", "response", "error", "lastError", "endpoint", "cacheResponse", "cache", "clonedResponse", "headers", "modifiedResponse", "installWorker", "workerSelf", "parsed", "parseDrlUrl", "installUrl", "loaderStyles", "tabContent", "elementsInjected", "overlayElement", "styleElement", "injectElements", "cancelNavigation", "removeElements", "activeNavigation", "linkFeaturesActive", "clickHandler", "pointerdownHandler", "addLinkFeatures", "anchor", "href", "openAsTab", "tab", "target", "resetContextMenuTarget", "contextMenuTarget", "removeLinkFeatures", "r", "activatePolyfills", "deactivatePolyfills", "clearDrlCache", "ConnectClient", "buildWalletIcon", "wallet", "wrap", "badge", "sources", "iconCandidates", "img", "index", "origin", "assertX25519PublicJwk", "CONNECT_DENIED_TOKEN", "ConnectClient", "DWEB_CONNECT_PATH", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "getTrustedMessage", "event", "expectedOrigin", "expectedSource", "data", "DEFAULT_TIMEOUT_MS", "CLOSED_POLL_INTERVAL_MS", "POPUP_WINDOW_NAME", "POPUP_WINDOW_FEATURES", "assertBrowserEnvironment", "PopupWindowClosedError", "PopupClientTransport", "options", "popupUrl", "DWEB_CONNECT_PATH", "popup", "resolve", "reject", "event", "state", "jwe", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "message", "getTrustedMessage", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "walletEpk", "assertX25519PublicJwk", "CONNECT_DENIED_TOKEN", "error", "collectBrowserClientMetadata", "resolvedOptions", "languages", "language", "connectViaPopup", "transport", "client", "ConnectClient", "ECC_PER_BLOCK", "NUM_BLOCKS", "TOTAL_CODEWORDS", "FORMAT_ECL_M", "MAX_VERSION", "dataCodewords", "version", "encodeQr", "text", "forcedMask", "data", "candidate", "capacityBits", "bits", "pushBits", "value", "length", "i", "byte", "padBytes", "codewords", "allCodewords", "buildInterleavedCodewords", "size", "modules", "isFunction", "drawFunctionPatterns", "drawCodewords", "mask", "bestPenalty", "applyMask", "drawFormatBits", "penalty", "computePenalty", "numBlocks", "eccLen", "totalCodewords", "numShortBlocks", "shortBlockLen", "blocks", "eccBlocks", "rsDivisor", "reedSolomonDivisor", "offset", "dataLen", "block", "reedSolomonRemainder", "result", "index", "maxDataLen", "b", "gfMultiply", "x", "y", "z", "degree", "root", "j", "divisor", "factor", "ALIGNMENT_POSITIONS", "setFunctionModule", "dark", "drawFinderPattern", "positions", "drawAlignmentPattern", "drawVersionBits", "cx", "cy", "dy", "dx", "distance", "rem", "bit", "a", "bitIndex", "right", "vertical", "invert", "runColor", "runLength", "c", "hasFinderPattern", "line", "start", "lightBefore", "v", "lightAfter", "row", "column", "r", "module", "total", "k", "SVG_NS", "qrToSvg", "qr", "options", "light", "quietZone", "dimension", "path", "svg", "rect", "WALLET_WELL_KNOWN_PATH", "fetchWalletWellKnown", "origin", "wellKnownUrl", "WALLET_WELL_KNOWN_PATH", "response", "payload", "probeWalletWellKnown", "DidJwk", "X25519", "CONNECT_DENIED_TOKEN", "openResponse", "randomToken", "RelayClientTransport", "sealRequest", "MAX_PIN_ATTEMPTS", "RelayConnectCancelledError", "runRelayConnect", "options", "transport", "transportOptions", "clientDid", "responsePrivateKey", "responsePublicKey", "nonce", "state", "profile", "request", "requestJwe", "handoff", "responseCiphertext", "lastError", "attempt", "pin", "response", "error", "failure", "LAST_CHOICE_STORAGE_KEY", "REMINT_SAFETY_MS", "REMINT_MIN_MS", "PIN_LENGTH", "discoverWalletConnectServerUrl", "walletOrigin", "fetchWalletWellKnown", "runPopupConnect", "options", "transport", "PopupClientTransport", "ConnectClient", "collectBrowserClientMetadata", "defaultIsMobile", "defaultDeps", "runRelayConnect", "probeWalletWellKnown", "readLastChoice", "storage", "raw", "parsed", "writeLastChoice", "choice", "createRelaySession", "cancel", "session", "cancelled", "_", "reject", "RelayConnectCancelledError", "runConnectModal", "deps", "wallets", "rememberChoice", "appName", "relayWalletPath", "isMobile", "lastChoice", "lockedWallet", "walletUrl", "walletInCatalog", "method", "resolve", "host", "shadow", "isDark", "style", "buildStyles", "overlay", "modal", "settled", "relaySession", "remintTimer", "popupBusy", "pinResolve", "discoveryCache", "cleanup", "onKeydown", "settle", "settler", "succeed", "result", "renderConnected", "cancelModal", "buildHeader", "stage", "footer", "setStage", "nodes", "renderBusy", "message", "el", "renderQr", "handoff", "link", "qrBox", "qrToSvg", "encodeQr", "renderClaimed", "pulse", "renderPin", "attempt", "previousError", "resolvePin", "boxes", "inputs", "i", "input", "submitIfComplete", "code", "resolveOnce", "index", "event", "digits", "digit", "digitIndex", "check", "renderDenied", "stageButton", "startMethod", "stageLinkButton", "renderError", "error", "renderPhoneUnavailable", "startPopup", "renderPopupPrompt", "renderPopupWaiting", "renderPopupInterrupted", "blocked", "switchMethod", "resolveConnectServerUrl", "origin", "cached", "scheduleRemint", "expiresInSeconds", "delay", "startPhone", "renderFooter", "connectServerUrl", "failure", "flow", "PopupWindowClosedError", "next", "alt", "buildWalletSwitcher", "wrap", "current", "wallet", "toggle", "panel", "rows", "empty", "search", "query", "visible", "match", "row", "buildWalletIcon", "rowName", "custom", "go", "urlError", "allowUnverified", "useWallet", "submitCustom", "value", "valid", "e", "trapFocus", "url", "tag", "className", "text", "node", "label", "onClick", "button", "appIcon", "onCancel", "header", "identity", "icon", "title", "closeBtn", "focusables", "first", "last", "active", "bg", "muted", "border", "itemBg", "accent", "accentSoft", "danger", "DEFAULT_WALLETS", "BrowserConnectHandler", "options", "wallets", "walletUrl", "timeout", "appName", "appIcon", "preferredMethod", "rememberChoice", "connectServerUrl", "relayWalletPath", "params", "runConnectModal", "X25519", "CONNECT_DENIED_TOKEN", "ConnectProvider", "DEFAULT_REQUEST_TIMEOUT_MS", "WalletPostMessageTransport", "_WalletPostMessageTransport", "params", "resolve", "reject", "event", "options", "dappWindow", "dappOrigin", "resolveDappOrigin", "recipientPrivateKey", "X25519", "walletEpk", "transport", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "idToken", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "CONNECT_DENIED_TOKEN", "message", "getTrustedMessage", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "jwe", "request", "ConnectProvider", "error", "outcome", "explicitOrigin", "TypedRecord", "BrowserStorage", "DwnInterface", "DateSort", "DwnInterfaceName", "DwnMethodName"]
7
7
  }