@enbox/browser 0.3.76 → 0.3.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.mjs +5 -5
- package/dist/browser.mjs.map +3 -3
- package/dist/esm/dweb-connect-wallet.js +72 -27
- package/dist/esm/dweb-connect-wallet.js.map +1 -1
- package/dist/types/dweb-connect-wallet.d.ts +8 -1
- package/dist/types/dweb-connect-wallet.d.ts.map +1 -1
- package/package.json +13 -13
- package/src/dweb-connect-wallet.ts +66 -26
package/dist/browser.mjs.map
CHANGED
|
@@ -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/handled-deferred.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", "../src/object-url-reference.ts", "../src/blob-url-pool.ts", "../src/file-envelope-url-store.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 * BrowserConnectHandler, createConnectionStore,\n * defineApplicationManifest,\n * } from '@enbox/browser';\n * import { MyProtocol } from './my-protocol.js';\n *\n * const store = createConnectionStore({\n * application : defineApplicationManifest({ protocols: [MyProtocol] }),\n * connectHandler : BrowserConnectHandler({ appName: 'My App' }),\n * });\n * const snapshot = await store.connect();\n * if (snapshot.phase !== 'connected') throw snapshot.error ?? new Error('Connection failed.');\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 and protocols.\n\nexport * 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 * 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, 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_ACK_MESSAGE_TYPE,\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 DWebConnectAckMessage,\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, ConnectModalPalette, ConnectModalTheme } 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';\nexport { createBlobUrlPool } from './blob-url-pool.js';\nexport type { BlobUrlLease, BlobUrlPool } from './blob-url-pool.js';\nexport { createFileEnvelopeUrlStore } from './file-envelope-url-store.js';\nexport type {\n FileEnvelopeUrlLease,\n FileEnvelopeUrlStore,\n FileEnvelopeUrlStoreOptions,\n} from './file-envelope-url-store.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// Public-profile read/cache layer (from @enbox/protocols): fetch other\n// users' published profiles (displayName + avatar/hero) from their DWNs\n// with caching, retries, negative caching, and refcounted subscriptions.\n// Works over a connected records surface and over `Enbox.anonymous()`.\nexport { createProfileReader, isRetryableProfileReadStatus } from '@enbox/protocols';\nexport type {\n ProfileEntryStatus,\n ProfileFieldSnapshot,\n ProfileFieldStatus,\n ProfileImages,\n ProfileReader,\n ProfileReaderFailure,\n ProfileReaderImagesMode,\n ProfileReaderOptions,\n ProfileReaderRecordsSurface,\n ProfileReaderSource,\n ProfileReaderTimers,\n ProfileSnapshot,\n ProfileWatchListener,\n PublicProfile,\n} from '@enbox/protocols';\n\n// DWN interface enum for typing agent requests (from @enbox/agent).\nexport { DwnInterface } from '@enbox/agent';\n\n// Low-level sync-status types for advanced agent consumers. Dapps using a\n// ConnectionStore receive current advertised rows through `snapshot.sync.remotes`\n// and can call `store.retryRemote(remoteEndpoint)` without wiring agent events.\nexport type {\n DeadLetterEntry,\n RemoteSyncState,\n RemoteSyncStatus,\n SyncConnectivityState,\n SyncEngine,\n SyncEvent,\n SyncEventListener,\n SyncHealthSummary,\n SyncIdentityStatus,\n} 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, DidResolverCacheMemory, DidWeb, resolveDwnEndpointStatus, 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({\n didResolvers : [DidDht, DidWeb],\n cache : new DidResolverCacheMemory(),\n});\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 result = await resolveDwnEndpointStatus(did, didResolver);\n return result.status === 'ready' ? result.endpoints : [];\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\n/**\n * Opens the tab/loading-overlay target for a DRL anchor click, then resolves\n * and navigates to the DRL's first working DWN endpoint. Extracted from the\n * click handler so the handler itself stays a shallow guard-clause dispatch\n * (Sonar S3776).\n */\nasync function navigateToDrl(did: string, path: string, openAsTab: boolean): Promise<void> {\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}\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 return;\n }\n const href = anchor.href;\n const parsed = parseDrlUrl(href);\n if (!parsed) {\n return;\n }\n const did = parsed[0];\n const path = parsed[1];\n const openAsTab = anchor.target === '_blank';\n event.preventDefault();\n try {\n await navigateToDrl(did, path, openAsTab);\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 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({\n didResolvers : options.didResolvers,\n cache : new DidResolverCacheMemory(),\n });\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 / deep-link handoff (phone path) \u2192 pairing code \u2192 connected, with the\n * in-browser popup path and the wallet catalog folded in as in-place\n * alternates. The modal never chains into a second modal and stays mounted\n * until the session 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\n * clickable QR (joined by a Continue deep-link button on phones; both\n * open the wallet in a new tab so this session stays alive underneath),\n * the pairing-code input, progress, success, and error states.\n * 3. **Footer** \u2014 the wallet identity row (\"Connecting with\" + the selected\n * wallet and the next catalog wallets as tiles), a More tile that expands\n * the remaining wallets as a matching grid (search + custom URL) in\n * place \u2014 a wallet is never shown twice \u2014 and the alternate-method link.\n *\n * Theming: the stylesheet is static and reads `--ec-*` design tokens.\n * Light/dark follows the visitor's system via `prefers-color-scheme` and\n * updates live; the embedding app can force an appearance or override\n * palette tokens through {@link ConnectModalOptions.theme}. Overrides are\n * applied as inline custom properties \u2014 never interpolated into the\n * stylesheet \u2014 so a hostile string can't escape its declaration. The QR\n * card alone is theme-invariant (dark modules on white scan most\n * reliably).\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 { PortableDid } from '@enbox/dids';\nimport type { WalletOption } from '../browser-connect-handler.js';\nimport type { ConnectPermissionRequest, ConnectRequestType, 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/** localStorage key remembering the exact wallet route for each delegate/profile pair. */\nconst SESSION_CHOICES_STORAGE_KEY = 'enbox:connect:sessionChoices';\n\n/** Bounds local reconnect provenance retained by one dapp origin. */\nconst MAX_SESSION_CHOICES = 20;\n\n/**\n * Safety margin subtracted from the relay pointer TTL before re-minting.\n *\n * The pointer is single-use and its TTL starts at mint time, but the wallet\n * only dereferences it after the user scans \u2014 and, on a locked wallet, after\n * they finish the unlock ceremony. A scanned code must therefore carry\n * enough remaining life to absorb that whole window, so re-mint well before\n * the deadline rather than just ahead of it.\n */\nconst REMINT_SAFETY_MS = 120_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/** Catalog size beyond which the wallet switcher shows its search bar. */\nconst WALLET_SEARCH_THRESHOLD = 4; // one full row of tiles\n\n/** Wallet tiles shown in the collapsed identity row (plus the More tile). */\nconst WALLET_ROW_SIZE = 3;\n\n/** Palette overrides for one appearance's design tokens. */\nexport interface ConnectModalPalette {\n /** Modal surface. */\n background?: string;\n\n /** Inset surfaces: tiles, inputs, hover fills. */\n surface?: string;\n\n /** Primary text. */\n text?: string;\n\n /** Secondary text. */\n textMuted?: string;\n\n /** Hairline borders and dividers. */\n border?: string;\n\n /** Brand accent: buttons, links, focus rings, selection. */\n accent?: string;\n\n /** Text/icon color on accent surfaces. */\n accentContrast?: string;\n\n /** Error text and invalid-input borders. */\n danger?: string;\n\n /** Success surfaces (the connected check). */\n success?: string;\n}\n\n/** Optional color scheme provided by the embedding app. */\nexport interface ConnectModalTheme {\n /**\n * Follow the visitor's system appearance (`'auto'`, live-updating) or\n * force one.\n * @default 'auto'\n */\n appearance?: 'auto' | 'light' | 'dark';\n\n /** Brand accent applied in both appearances (per-scheme palettes win). */\n accent?: string;\n\n /** Text/icon color on accent surfaces, in both appearances. */\n accentContrast?: string;\n\n /** Token overrides applied while the light appearance is active. */\n light?: ConnectModalPalette;\n\n /** Token overrides applied while the dark appearance is active. */\n dark?: ConnectModalPalette;\n}\n\n/** Design-token custom property behind each palette key. */\nconst PALETTE_TOKENS: Record<keyof ConnectModalPalette, string> = {\n background : '--ec-bg',\n surface : '--ec-surface',\n text : '--ec-text',\n textMuted : '--ec-muted',\n border : '--ec-border',\n accent : '--ec-accent',\n accentContrast : '--ec-accent-contrast',\n danger : '--ec-danger',\n success : '--ec-success',\n};\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 /** User-facing mode. Absent means a normal connect. */\n mode?: ConnectRequestType;\n\n /** Existing delegate credentials reused by a refresh request. */\n delegatePortableDid?: PortableDid;\n\n /** Preferred method on open; overrides the remembered choice. */\n preferredMethod?: ConnectMethod;\n\n /**\n * Remember the successful method + wallet in localStorage. Refreshes reuse\n * the route saved for their delegate DID; new connections use the latest\n * successful route as a convenience.\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 * Stable application identifier hint available to the wallet during approval.\n * Defaults to the browser's canonical origin.\n */\n applicationId?: string;\n\n /** Wallet profile DID that a refresh must renew. */\n expectedProviderDid?: 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 /**\n * Color scheme. By default the modal follows the visitor's system\n * light/dark appearance; apps can force an appearance and/or override\n * palette tokens per scheme to match their brand.\n */\n theme?: ConnectModalTheme;\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: typeof runPopupConnect;\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 applicationId?: string;\n timeoutMs?: number;\n delegatePortableDid?: PortableDid;\n requestType?: ConnectRequestType;\n expectedProviderDid?: string;\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 applicationId : options.applicationId,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n delegatePortableDid : options.delegatePortableDid,\n requestType : options.requestType,\n expectedProviderDid : options.expectedProviderDid,\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\n/** Stable reconnect provenance for one delegated app session. */\ninterface SessionChoice extends LastChoice {\n delegateDid: string;\n providerDid: 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') && isValidRememberedWalletUrl(parsed.walletUrl)) {\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\nfunction isSessionChoice(value: unknown): value is SessionChoice {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const choice = value as Partial<SessionChoice>;\n return (choice.method === 'phone' || choice.method === 'browser')\n && isValidRememberedWalletUrl(choice.walletUrl)\n && typeof choice.delegateDid === 'string'\n && choice.delegateDid.length > 0\n && typeof choice.providerDid === 'string'\n && choice.providerDid.length > 0;\n}\n\nfunction readSessionChoices(storage: ConnectModalDeps['storage']): SessionChoice[] {\n try {\n const raw = storage?.getItem(SESSION_CHOICES_STORAGE_KEY);\n if (raw === null || raw === undefined) {\n return [];\n }\n const parsed = JSON.parse(raw) as unknown;\n return Array.isArray(parsed) ? parsed.filter(isSessionChoice).slice(-MAX_SESSION_CHOICES) : [];\n } catch {\n return [];\n }\n}\n\nfunction readSessionChoice(\n storage: ConnectModalDeps['storage'],\n delegateDid: string | undefined,\n expectedProviderDid: string | undefined,\n): SessionChoice | undefined {\n if (delegateDid === undefined) {\n return undefined;\n }\n const choices = readSessionChoices(storage);\n for (let index = choices.length - 1; index >= 0; index--) {\n const choice = choices[index];\n if (choice.delegateDid === delegateDid\n && (expectedProviderDid === undefined || choice.providerDid === expectedProviderDid)) {\n return choice;\n }\n }\n return undefined;\n}\n\nfunction writeSessionChoice(storage: ConnectModalDeps['storage'], choice: SessionChoice): void {\n try {\n const choices = readSessionChoices(storage).filter(entry =>\n entry.delegateDid !== choice.delegateDid || entry.providerDid !== choice.providerDid\n );\n choices.push(choice);\n storage?.setItem(SESSION_CHOICES_STORAGE_KEY, JSON.stringify(choices.slice(-MAX_SESSION_CHOICES)));\n } catch { /* best effort */ }\n}\n\nfunction removeSessionChoice(\n storage: ConnectModalDeps['storage'],\n delegateDid: string,\n providerDid: string,\n): void {\n try {\n const choices = readSessionChoices(storage).filter(choice =>\n choice.delegateDid !== delegateDid || choice.providerDid !== providerDid\n );\n if (choices.length === 0) {\n storage?.removeItem(SESSION_CHOICES_STORAGE_KEY);\n } else {\n storage?.setItem(SESSION_CHOICES_STORAGE_KEY, JSON.stringify(choices));\n }\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 * Wraps `settler` so the returned thunk runs it through `settle()`. Defined\n * at module scope \u2014 not as an inline closure inside each render function \u2014\n * so the returned closure is lexically nested one level (inside this\n * function), not several levels inside `runConnectModal()`'s own render\n * closures (Sonar S2004). `settle` and `settler` are threaded through\n * unchanged, so behavior is identical to writing `() => settle(settler)`\n * inline.\n */\nfunction settleWith(settle: (settler: () => void) => void, settler: () => void): () => void {\n return () => settle(settler);\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 if (options.mode === 'refresh' && options.delegatePortableDid === undefined) {\n throw new Error('Connect: refresh requests require an existing `delegatePortableDid`.');\n }\n\n const deps: ConnectModalDeps = { ...defaultDeps(), ...options.deps };\n const wallets = dedupeWalletsByUrl(options.wallets ?? []);\n const rememberChoice = options.rememberChoice ?? true;\n const appName = options.appName ?? window.location.host;\n const applicationId = options.applicationId ?? window.location.origin;\n const isMobile = deps.isMobile();\n const refreshing = options.mode === 'refresh';\n\n const lastChoice = rememberChoice ? readLastChoice(deps.storage) : undefined;\n let savedRoute = rememberChoice && refreshing\n ? readSessionChoice(\n deps.storage,\n options.delegatePortableDid?.uri,\n options.expectedProviderDid,\n )\n : undefined;\n const expectedProviderDid = options.expectedProviderDid ?? savedRoute?.providerDid;\n const relayWalletPath = options.relayWalletPath ?? '/connect/app';\n const savedRouteEscapeLabel = options.walletUrl === undefined\n ? 'Choose another wallet or method'\n : 'Choose another method';\n\n // Refresh routes resolve by delegate first; general preferences remain a\n // best-effort fallback for sessions created before route-aware storage.\n const rememberedWalletUrl = lastChoice !== undefined\n && (refreshing || walletInCatalog(wallets, lastChoice.walletUrl))\n ? lastChoice.walletUrl\n : undefined;\n let walletUrl = savedRoute?.walletUrl\n ?? options.walletUrl\n ?? rememberedWalletUrl\n ?? wallets[0]?.url;\n\n // An exact refresh route wins over generic handler and global preferences.\n let method: ConnectMethod = savedRoute?.method ?? 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 style = document.createElement('style');\n style.textContent = MODAL_STYLES;\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 const title = refreshing ? `Reconnect to ${appName}` : `Connect to ${appName}`;\n modal.setAttribute('aria-label', title);\n\n // \u2500\u2500 Theme \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 // System light/dark is pure CSS (`prefers-color-scheme`), so it tracks\n // the visitor live. A forced appearance pins the token block instead.\n const theme = options.theme ?? {};\n const appearance = theme.appearance ?? 'auto';\n if (appearance !== 'auto') {\n modal.dataset.appearance = appearance;\n }\n\n // Dapp palette overrides land as inline custom properties: setProperty\n // parses each value as a lone declaration, so a hostile string cannot\n // escape into the stylesheet.\n const systemDark = window.matchMedia?.('(prefers-color-scheme: dark)');\n const hasPaletteOverrides = theme.accent !== undefined || theme.accentContrast !== undefined\n || theme.light !== undefined || theme.dark !== undefined;\n const applyPaletteTokens = (): void => {\n const systemScheme = systemDark?.matches === true ? 'dark' : 'light';\n const scheme = appearance === 'auto' ? systemScheme : appearance;\n const palette: ConnectModalPalette = {\n accent : theme.accent,\n accentContrast : theme.accentContrast,\n ...theme[scheme],\n };\n for (const key of Object.keys(PALETTE_TOKENS) as Array<keyof ConnectModalPalette>) {\n const value = palette[key];\n if (typeof value === 'string' && value.trim() !== '') {\n modal.style.setProperty(PALETTE_TOKENS[key], value);\n } else {\n modal.style.removeProperty(PALETTE_TOKENS[key]);\n }\n }\n };\n const onSchemeChange = (): void => applyPaletteTokens();\n if (hasPaletteOverrides) {\n applyPaletteTokens();\n if (appearance === 'auto') {\n systemDark?.addEventListener?.('change', onSchemeChange);\n }\n }\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 remintAt: number | undefined;\n let popupBusy = false;\n let pinResolve: ((pin: string) => void) | undefined;\n // Proxy pinResolve reads/clears for buildPinInputs (module scope), whose\n // per-input closures would otherwise be nested inside renderPin()'s own\n // executor chain too deeply (Sonar S2004).\n const getPinResolve = (): ((pin: string) => void) | undefined => pinResolve;\n const clearPinResolve = (): void => { pinResolve = undefined; };\n const discoveryCache = new Map<string, Promise<string | undefined>>();\n\n // Collapsed identity row: the selected wallet plus the next catalog\n // wallets, never repeating one. Slots stay stable across in-row\n // switches (only the highlight moves); the row recomposes only when a\n // wallet from outside it \u2014 grid pick or custom URL \u2014 becomes selected,\n // which puts that wallet in the first slot.\n let rowWallets: WalletOption[] = [];\n\n /** The catalog entry for `url`, or a synthesized option for custom URLs. */\n const walletByUrl = (url: string): WalletOption =>\n wallets.find((wallet) => wallet.url === url) ?? { name: hostnameOf(url) ?? url, url };\n\n const composeWalletRow = (): void => {\n if (walletUrl === undefined) {\n rowWallets = wallets.slice(0, WALLET_ROW_SIZE);\n return;\n }\n if (rowWallets.some((wallet) => wallet.url === walletUrl)) {\n return;\n }\n const selected = walletByUrl(walletUrl);\n rowWallets = [selected, ...wallets.filter((wallet) => wallet.url !== selected.url)].slice(0, WALLET_ROW_SIZE);\n };\n\n const selectWallet = (url: string): void => {\n walletUrl = url;\n renderFooter();\n void startMethod();\n };\n\n const cleanup = (): void => {\n relaySession?.cancel();\n clearRemint();\n document.removeEventListener('keydown', onKeydown);\n document.removeEventListener('visibilitychange', onVisibilityReturn);\n systemDark?.removeEventListener?.('change', onSchemeChange);\n try { host.remove(); } 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 && walletUrl !== undefined) {\n writeLastChoice(deps.storage, { method, walletUrl });\n writeSessionChoice(deps.storage, {\n delegateDid : result.delegatePortableDid.uri,\n providerDid : result.connectedDid,\n method,\n walletUrl,\n });\n }\n renderConnected();\n setTimeout(settleWith(settle, () => resolve(result)), 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(title, 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 /**\n * Schedules the \"finish in the wallet\" morph after a handoff link is\n * followed. Deferred one tick so the anchor's default new-tab navigation\n * completes before the anchor is replaced, and guarded so a session that\n * moved on meanwhile (re-mint, wallet response, settle) is never\n * overwritten.\n */\n const morphToAway = (walletName: string): void => {\n const session = relaySession;\n setTimeout((): void => {\n if (settled || session !== relaySession || session?.active !== true || pinResolve !== undefined) {\n return;\n }\n renderAway(walletName);\n }, 0);\n };\n\n /**\n * Builds one same-device handoff anchor for the wallet URI. The wallet\n * opens in a new tab so this modal \u2014 and the relay session under it \u2014\n * stays alive, with the pairing-code entry waiting when the user\n * switches back. `noopener` keeps the wallet tab from reaching back into\n * this one.\n */\n const buildHandoffLink = (handoff: WalletUriHandoff, walletName: string, className: string): HTMLAnchorElement => {\n const link = document.createElement('a');\n link.className = className;\n link.href = handoff.walletUri;\n link.target = '_blank';\n link.rel = 'noopener noreferrer';\n link.addEventListener('click', () => { morphToAway(walletName); });\n return link;\n };\n\n const renderQr = (handoff: WalletUriHandoff): void => {\n const wallet = walletUrl !== undefined ? walletByUrl(walletUrl) : undefined;\n const walletName = wallet?.name ?? 'your wallet';\n\n // The QR card is itself a handoff link on every device: opening it on\n // this device runs the exact handshake the camera path runs on another\n // one, and scanning it keeps working either way.\n const qrLink = buildHandoffLink(handoff, walletName, 'qr-box qr-link');\n qrLink.setAttribute('aria-label', `Open ${walletName} on this device`);\n // Fixed colors on the white card: dark-on-light QRs scan reliably in\n // both appearances (inverted codes trip up some camera apps).\n qrLink.replaceChildren(qrToSvg(encodeQr(handoff.walletUri), {\n dark : '#14141f',\n light : 'transparent',\n quietZone : 2,\n }));\n\n // The selected wallet's mark sits at the QR centre \u2014 the \"this is the\n // wallet you're connecting to\" cue. The 44px plate over the ~180px\n // symbol occludes ~5% of modules, well inside ECC level M's 15%\n // recovery budget (the compact variant scales the plate down to\n // match).\n if (wallet !== undefined) {\n const logo = el('div', 'qr-logo');\n logo.appendChild(buildWalletIcon(wallet));\n qrLink.appendChild(logo);\n }\n\n if (isMobile) {\n const link = buildHandoffLink(handoff, walletName, 'deep-link');\n if (wallet !== undefined) {\n link.appendChild(buildWalletIcon(wallet));\n }\n link.appendChild(el('span', 'deep-link-label', `Continue in ${walletName}`));\n\n qrLink.classList.add('compact');\n setStage(\n link,\n el('p', 'stage-subline', `${walletName} opens in a new tab \u2014 approve there, then come back for your code.`),\n el('div', 'stage-divider', 'or scan with another phone'),\n qrLink,\n );\n return;\n }\n\n setStage(\n qrLink,\n el('p', 'stage-caption', 'Scan with your phone\u2019s camera'),\n el('p', 'stage-subline', `${walletName} stays on your phone \u2014 or click the code to open it here.`),\n );\n };\n\n /**\n * Shown once a handoff link is followed on this device: the approval is\n * happening in the wallet tab, this one waits for the code. \"Start over\"\n * mints a fresh pointer \u2014 the right recovery, because the pointer the\n * wallet tab carried away is single-use.\n */\n const renderAway = (walletName: string): void => {\n setStage(\n el('div', 'spinner'),\n el('p', 'stage-caption', `Finish in ${walletName}`),\n el('p', 'stage-subline', isMobile\n ? `Approve the connection in the ${walletName} tab, then come back here for your code.`\n : 'Approve the connection in the tab that just opened, then come back here for your code.'),\n stageLinkButton('Start over', () => { void startPhone(); }),\n );\n };\n\n const renderClaimed = (): void => {\n const walletName = walletUrl !== undefined ? walletByUrl(walletUrl).name : 'your wallet';\n const pulse = document.createElement('div');\n pulse.className = 'claimed-pulse';\n setStage(\n pulse,\n el('p', 'stage-caption', `Request received \u2014 approve in ${walletName}`),\n el('p', 'stage-subline', 'Once you approve, you\u2019ll get a code to enter here.'),\n );\n };\n\n const renderPin = (attempt: number, previousError?: Error): Promise<string> => {\n return new Promise<string>((resolvePin) => {\n pinResolve = resolvePin;\n const walletName = walletUrl !== undefined ? walletByUrl(walletUrl).name : 'your wallet';\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 = buildPinInputs(boxes, getPinResolve, clearPinResolve, renderBusy);\n\n setStage(\n el('p', 'stage-caption', `Enter the code shown in ${walletName}`),\n boxes,\n ...(previousError !== undefined\n ? [el('p', 'stage-error', `That code doesn\u2019t match \u2014 check ${walletName}.`)]\n : [el('p', 'stage-subline', attempt === 1 ? 'This confirms you\u2019re the one approving.' : '')]),\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', settleWith(settle, () => resolve(undefined))),\n );\n };\n\n const escapeSavedRoute = (): void => {\n if (savedRoute === undefined) {\n return;\n }\n\n relaySession?.cancel();\n relaySession = undefined;\n clearRemint();\n removeSessionChoice(deps.storage, savedRoute.delegateDid, savedRoute.providerDid);\n savedRoute = undefined;\n if (options.walletUrl !== undefined) {\n walletUrl = options.walletUrl;\n }\n renderFooter();\n setStage(\n el('p', 'stage-caption', 'Choose another way to reconnect.'),\n el('p', 'stage-subline', 'We\u2019ll still require the same wallet profile used for this session.'),\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 ...(savedRoute !== undefined\n ? [stageLinkButton(savedRouteEscapeLabel, escapeSavedRoute)]\n : []),\n stageLinkButton('Close', settleWith(settle, () => reject(error ?? new Error(`[@enbox/browser] ${message}`)))),\n );\n };\n\n const renderPhoneUnavailable = (): void => {\n if (savedRoute !== undefined) {\n setStage(\n el('p', 'stage-caption', 'Your saved wallet connection is unavailable right now.'),\n el('p', 'stage-subline', 'Try again in a moment to reconnect the same session.'),\n stageButton('Try again', () => { void startPhone(); }),\n stageLinkButton(savedRouteEscapeLabel, escapeSavedRoute),\n );\n return;\n }\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 // The popup surface is a small window on desktop but a new tab on\n // phones \u2014 the copy names whichever the visitor will actually see.\n const popupSurface = isMobile ? 'tab' : 'window';\n\n const renderPopupPrompt = (): void => {\n const walletName = walletUrl !== undefined ? walletByUrl(walletUrl).name : 'your wallet';\n const exactReconnect = savedRoute !== undefined;\n const connectDescription = isMobile\n ? 'Your wallet opens in a new tab to approve this connection \u2014 no code needed.'\n : 'Your wallet opens in a small window to approve this connection.';\n const description = exactReconnect\n ? `We\u2019ll open the same ${walletName} profile used for this session.`\n : connectDescription;\n const connectButtonLabel = isMobile ? 'Open wallet' : 'Open wallet window';\n const buttonLabel = exactReconnect\n ? `Open ${walletName} ${popupSurface}`\n : connectButtonLabel;\n setStage(\n el('p', 'stage-caption', exactReconnect\n ? `Reconnect with ${walletName}`\n : 'Connect with a wallet in this browser'),\n el('p', 'stage-subline', description),\n stageButton(buttonLabel, () => { startPopup(); }),\n );\n };\n\n const renderPopupWaiting = (): void => {\n setStage(\n el('div', 'spinner'),\n el('p', 'stage-caption', `Finish in the wallet ${popupSurface}`),\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 ${popupSurface}.`\n : `The wallet ${popupSurface} was closed.`),\n stageButton(blocked ? 'Open it now' : `Reopen ${popupSurface}`, () => { startPopup(); }),\n ...(savedRoute !== undefined\n ? [stageLinkButton(savedRouteEscapeLabel, escapeSavedRoute)]\n : [stageLinkButton(isMobile ? 'Use a code instead' : 'Use your phone instead', () => { void switchMethod('phone'); })]),\n );\n };\n\n const renderPopupFailure = (error: unknown): void => {\n if (settled) { return; }\n\n const failure = error instanceof Error ? error : new Error(String(error));\n const popupBlocked = /popup blocked/i.test(failure.message);\n if (error instanceof PopupWindowClosedError || popupBlocked) {\n renderPopupInterrupted(popupBlocked);\n return;\n }\n\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 // \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 clearRemint = (): void => {\n clearTimeout(remintTimer);\n remintAt = undefined;\n };\n\n const remintNow = (): void => {\n // Never re-mint once the wallet has responded (pairing in progress).\n if (!settled && pinResolve === undefined && method === 'phone') {\n void startPhone();\n }\n };\n\n const scheduleRemint = (expiresInSeconds: number): void => {\n clearRemint();\n const delay = Math.max(REMINT_MIN_MS, expiresInSeconds * 1_000 - REMINT_SAFETY_MS);\n // The deadline is kept alongside the timer: background tabs (mobile\n // especially) throttle or freeze timers, so the visibility handler\n // re-checks it when the user returns.\n remintAt = Date.now() + delay;\n remintTimer = setTimeout(remintNow, delay);\n };\n\n const startPhone = async (): Promise<void> => {\n relaySession?.cancel();\n clearRemint();\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 applicationId,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n delegatePortableDid : options.delegatePortableDid,\n requestType : options.mode,\n expectedProviderDid,\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 wallet has the request \u2014 stop re-minting (a new pointer\n // would orphan the approval in progress) and show progress.\n clearRemint();\n renderClaimed();\n }\n },\n requestPin: (attempt, previousError): Promise<string> => {\n clearRemint();\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 = async (): Promise<void> => {\n // Synchronous popup open inside the click's call stack.\n relaySession?.cancel();\n clearRemint();\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 popupBusy = true;\n renderPopupWaiting();\n\n // `runPopup(...)` is invoked synchronously (its `window.open` runs before the\n // first `await`), preserving the user-gesture popup open. Awaiting it inside the\n // try means both a synchronous throw (a custom transport) and an async rejection\n // are handled here \u2014 no unhandled promise sits inside the try (Sonar S4822).\n try {\n const result = await deps.runPopup({\n walletUrl,\n permissionRequests : options.permissionRequests,\n appName,\n appIcon : options.appIcon,\n applicationId,\n timeoutMs : options.timeout,\n delegatePortableDid : options.delegatePortableDid,\n requestType : options.mode,\n expectedProviderDid,\n });\n if (settled) { return; }\n if (result === undefined) {\n renderDenied();\n } else {\n succeed(result);\n }\n } catch (error) {\n renderPopupFailure(error);\n } finally {\n popupBusy = false;\n }\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 clearRemint();\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: identity row (+ catalog panel), method link below \u2500\u2500\n const renderFooter = (): void => {\n footer.replaceChildren();\n\n if (savedRoute === undefined && options.walletUrl === undefined) {\n composeWalletRow();\n const switcher = buildWalletSwitcher();\n if (switcher.label !== undefined) {\n footer.appendChild(switcher.label);\n }\n footer.appendChild(switcher.row);\n footer.appendChild(switcher.panel);\n }\n\n const row = document.createElement('div');\n row.className = 'footer-row';\n\n if (method === 'phone' && savedRoute === undefined) {\n const alt = document.createElement('button');\n alt.className = 'footer-link method-link';\n // On a phone both methods open the wallet on this device \u2014 what the\n // popup channel actually buys the visitor is skipping the code.\n alt.textContent = isMobile ? 'Or connect without a code \u2192' : 'No phone? Use this browser \u2192';\n // startPopup runs synchronously in this click handler.\n alt.addEventListener('click', () => { startPopup(); });\n row.appendChild(alt);\n } else if (method === 'browser' && savedRoute === undefined) {\n const alt = document.createElement('button');\n alt.className = 'footer-link method-link';\n alt.textContent = isMobile ? 'Use a code instead \u2192' : 'Use your phone instead \u2192';\n alt.addEventListener('click', () => { void switchMethod('phone'); });\n row.appendChild(alt);\n }\n\n if (row.childElementCount > 0) {\n footer.appendChild(row);\n }\n };\n\n const buildWalletSwitcher = (): { label?: HTMLElement; row: HTMLDivElement; panel: HTMLDivElement } => {\n // Identity row: selected wallet + the next catalog wallets, then the\n // More tile expanding the full catalog in place.\n const row = document.createElement('div');\n row.className = 'wallet-row';\n row.setAttribute('role', 'radiogroup');\n row.setAttribute('aria-label', 'Wallet');\n\n for (const wallet of rowWallets) {\n const tile = document.createElement('button');\n tile.className = 'row-tile';\n tile.title = wallet.description ?? wallet.name;\n tile.setAttribute('role', 'radio');\n const isSelected = wallet.url === walletUrl;\n tile.setAttribute('aria-checked', isSelected ? 'true' : 'false');\n if (isSelected) {\n tile.classList.add('selected');\n }\n tile.appendChild(buildWalletIcon(wallet));\n tile.appendChild(el('span', 'row-tile-name', wallet.name));\n tile.addEventListener('click', () => {\n if (wallet.url !== walletUrl) {\n selectWallet(wallet.url);\n }\n });\n row.appendChild(tile);\n }\n\n const panel = document.createElement('div');\n panel.className = 'wallet-panel';\n panel.hidden = true;\n\n // The panel grid holds only the wallets NOT already visible in the\n // row, so expanding never shows the same wallet twice.\n const gridWallets = wallets.filter((wallet) => !walletInCatalog(rowWallets, wallet.url));\n\n const more = document.createElement('button');\n more.className = 'row-tile more-tile';\n more.title = 'All wallets';\n more.setAttribute('aria-expanded', 'false');\n more.appendChild(el('span', 'more-count', gridWallets.length > 0 ? `+${gridWallets.length}` : '\u22EF'));\n more.appendChild(el('span', 'row-tile-name', 'More'));\n more.addEventListener('click', () => {\n panel.hidden = !panel.hidden;\n more.setAttribute('aria-expanded', panel.hidden ? 'false' : 'true');\n if (!panel.hidden) {\n updateScrollHint();\n }\n });\n row.appendChild(more);\n\n const label = rowWallets.length > 0 ? el('div', 'wallet-row-label', 'Connecting with') : undefined;\n\n // Search filter \u2014 appears once the grid outgrows one row of tiles.\n const tiles: Array<{ wallet: (typeof wallets)[number]; el: HTMLButtonElement }> = [];\n const empty = document.createElement('div');\n empty.className = 'wallet-empty';\n empty.textContent = 'No other wallets match your search.';\n empty.hidden = true;\n\n if (gridWallets.length > WALLET_SEARCH_THRESHOLD) {\n const search = document.createElement('input');\n search.type = 'search';\n search.className = 'wallet-search';\n search.placeholder = 'Search wallets\u2026';\n search.setAttribute('aria-label', 'Search wallets');\n search.addEventListener('input', () => {\n const query = search.value.trim().toLowerCase();\n let visible = 0;\n for (const { wallet, el: tile } of tiles) {\n const match = query === ''\n || wallet.name.toLowerCase().includes(query)\n || wallet.url.toLowerCase().includes(query);\n tile.hidden = !match;\n if (match) { visible += 1; }\n }\n empty.hidden = visible > 0;\n updateScrollHint();\n });\n panel.appendChild(search);\n }\n\n // Tiles matching the identity row, four per row; past three rows the\n // grid scrolls in place, with a bottom fade hinting at more below.\n const scrollWrap = document.createElement('div');\n scrollWrap.className = 'wallet-scroll-wrap';\n scrollWrap.hidden = gridWallets.length === 0;\n const scroll = document.createElement('div');\n scroll.className = 'wallet-scroll';\n const grid = document.createElement('div');\n grid.className = 'wallet-grid';\n\n const updateScrollHint = (): void => {\n const overflowing = scroll.scrollHeight - scroll.clientHeight > 1;\n const atEnd = scroll.scrollTop + scroll.clientHeight >= scroll.scrollHeight - 1;\n scrollWrap.classList.toggle('scroll-hint', overflowing && !atEnd);\n };\n scroll.addEventListener('scroll', updateScrollHint);\n\n for (const wallet of gridWallets) {\n const tile = document.createElement('button');\n tile.className = 'wallet-tile';\n tile.title = wallet.description ?? wallet.name;\n tile.appendChild(buildWalletIcon(wallet));\n const tileName = document.createElement('span');\n tileName.className = 'wallet-tile-name';\n tileName.textContent = wallet.name;\n tile.appendChild(tileName);\n tile.addEventListener('click', () => {\n selectWallet(wallet.url);\n });\n tiles.push({ wallet, el: tile });\n grid.appendChild(tile);\n }\n scroll.appendChild(grid);\n scroll.appendChild(empty);\n scrollWrap.appendChild(scroll);\n panel.appendChild(scrollWrap);\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 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 selectWallet(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 selectWallet(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 return { label, row, panel };\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 // The visitor typically comes back from the wallet tab mid-session.\n const onVisibilityReturn = (): void => {\n if (document.visibilityState !== 'visible' || settled) {\n return;\n }\n\n // Background tabs throttle (or freeze) timers, so a re-mint that came\n // due while the user was away fires now instead of never.\n if (remintAt !== undefined && Date.now() >= remintAt) {\n remintNow();\n return;\n }\n\n // Returning with the code in hand: put the caret in the first empty\n // pairing-code box so they can type it straight away.\n if (pinResolve !== undefined) {\n const inputs = Array.from(shadow.querySelectorAll<HTMLInputElement>('.pin-input'));\n inputs.find((input) => input.value === '')?.focus();\n }\n };\n document.addEventListener('visibilitychange', onVisibilityReturn);\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 isValidRememberedWalletUrl(value: unknown): value is string {\n if (typeof value !== 'string' || value.trim() === '') {\n return false;\n }\n\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/** Drops catalog entries that repeat an earlier wallet's URL. */\nfunction dedupeWalletsByUrl(wallets: WalletOption[]): WalletOption[] {\n return wallets.filter((wallet, index) => wallets.findIndex((candidate) => candidate.url === wallet.url) === index);\n}\n\n/** Compact display form of a wallet URL for the switcher toggle. */\nfunction hostnameOf(url: string | undefined): string | undefined {\n if (url === undefined) {\n return undefined;\n }\n try {\n return new URL(url).hostname;\n } catch {\n return url;\n }\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(titleText: 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 = titleText;\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\n/**\n * Builds the PIN-entry boxes, wires their input/keydown/paste behavior, and\n * returns the input elements in order. Module-level \u2014 `renderPin()`'s own\n * `new Promise` executor already nests two levels deep inside\n * `runConnectModal()`, so a per-input closure defined there would sit too\n * deep for Sonar's S2004 nesting-depth check.\n *\n * `getPinResolve`/`clearPinResolve` proxy the `pinResolve` state kept in\n * `runConnectModal()`'s closure: a completed code needs it read once, then\n * cleared \u2014 in that order, before the busy state renders and the pending\n * promise resolves \u2014 exactly as it was inline.\n */\nfunction buildPinInputs(\n boxes: HTMLDivElement,\n getPinResolve: () => ((pin: string) => void) | undefined,\n clearPinResolve: () => void,\n renderBusy: (message: string) => void,\n): HTMLInputElement[] {\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 const pinResolve = getPinResolve();\n if (code.length === PIN_LENGTH && pinResolve !== undefined) {\n const resolveOnce = pinResolve;\n clearPinResolve();\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 return inputs;\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//\n// One static sheet; every color reads a `--ec-*` token. Light values sit on\n// `.modal`, dark values apply under `prefers-color-scheme` (so the system\n// appearance tracks live) and under a forced `data-appearance`. Dapp\n// palette overrides land as inline custom properties, which outrank all of\n// these \u2014 nothing user-provided is ever concatenated into this string.\n\n/** Light-appearance design tokens. */\nconst LIGHT_TOKENS = `\n --ec-bg: #ffffff;\n --ec-surface: #f5f6f8;\n --ec-text: #17171f;\n --ec-muted: #63636e;\n --ec-border: #e3e4e9;\n --ec-accent: #0a62d0;\n --ec-accent-contrast: #ffffff;\n --ec-danger: #c0392b;\n --ec-success: #1e9e5a;`;\n\n/** Dark-appearance design tokens. */\nconst DARK_TOKENS = `\n --ec-bg: #181822;\n --ec-surface: #23232f;\n --ec-text: #e9e9f0;\n --ec-muted: #9a9aa6;\n --ec-border: #33333f;\n --ec-accent: #58a6ff;\n --ec-accent-contrast: #0b1526;\n --ec-danger: #ff7a7a;\n --ec-success: #43d17c;`;\n\nconst MODAL_STYLES = `\n * { box-sizing: border-box; margin: 0; padding: 0; }\n\n /* Keep the hidden attribute authoritative: author display values (e.g.\n the panel's flex) would otherwise override the UA's [hidden] rule and\n leave \"collapsed\" sections permanently expanded. */\n [hidden] { display: none !important; }\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 padding: 16px;\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 @keyframes claimedPulse {\n 0%, 100% { transform: scale(0.85); opacity: 0.7; }\n 50% { transform: scale(1); opacity: 1; }\n }\n\n .modal {${LIGHT_TOKENS}\n --ec-accent-soft: color-mix(in srgb, var(--ec-accent) 14%, transparent);\n background: var(--ec-bg);\n color: var(--ec-text);\n border-radius: 16px;\n width: 400px;\n max-width: 100%;\n max-height: calc(100vh - 32px);\n overflow-y: auto;\n padding: 16px 20px 12px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);\n animation: slideUp 0.2s ease-out;\n display: flex;\n flex-direction: column;\n }\n @media (prefers-color-scheme: dark) {\n .modal {${DARK_TOKENS}\n }\n }\n .modal[data-appearance='light'] {${LIGHT_TOKENS}\n }\n .modal[data-appearance='dark'] {${DARK_TOKENS}\n }\n\n button, input { font-family: inherit; }\n button:focus-visible, a:focus-visible {\n outline: 2px solid var(--ec-accent);\n outline-offset: 2px;\n }\n\n .header { display: flex; justify-content: space-between; align-items: center; gap: 8px; }\n .header-identity { display: flex; align-items: center; gap: 10px; min-width: 0; }\n .header-icon { border-radius: 6px; flex-shrink: 0; }\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: var(--ec-muted); padding: 4px 8px; border-radius: 8px; line-height: 1;\n flex-shrink: 0;\n }\n .close-btn:hover { color: var(--ec-text); background: var(--ec-surface); }\n\n .stage {\n min-height: 240px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n text-align: center;\n padding: 12px 0 10px;\n }\n .stage.fade-in > * { animation: stageIn 0.15s ease-out; }\n\n .qr-box {\n position: relative;\n width: 200px;\n height: 200px;\n padding: 10px;\n border-radius: 12px;\n background: #ffffff;\n border: 1px solid #e3e4e9;\n }\n .qr-box svg { width: 100%; height: 100%; display: block; }\n\n /* Selected wallet's mark on the QR centre. Like the card, the plate is\n theme-invariant white so the logo sits on a scannable ground. */\n .qr-logo {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 44px;\n height: 44px;\n border-radius: 10px;\n background: #ffffff;\n border: 1px solid #e3e4e9;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .qr-logo .wallet-icon { width: 30px; height: 30px; }\n .qr-logo .wallet-badge { border-radius: 8px; font-size: 15px; }\n\n /* The QR card doubles as the same-device handoff link. */\n a.qr-box { display: block; cursor: pointer; }\n .qr-box.qr-link:hover {\n border-color: var(--ec-accent);\n box-shadow: 0 0 0 3px var(--ec-accent-soft);\n }\n .qr-box.compact { width: 160px; height: 160px; }\n .qr-box.compact .qr-logo { width: 36px; height: 36px; }\n .qr-box.compact .qr-logo .wallet-icon { width: 24px; height: 24px; }\n\n .stage-divider {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n color: var(--ec-muted);\n font-size: 12px;\n }\n .stage-divider::before, .stage-divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: var(--ec-border);\n }\n\n .claimed-pulse {\n width: 64px; height: 64px; border-radius: 50%;\n background: var(--ec-accent-soft); position: relative;\n }\n .claimed-pulse::after {\n content: ''; position: absolute; inset: 18px; border-radius: 50%;\n background: var(--ec-accent);\n animation: claimedPulse 1.6s ease-in-out infinite;\n }\n\n .stage-caption { font-size: 15px; font-weight: 600; }\n .stage-subline { font-size: 13px; color: var(--ec-muted); max-width: 300px; line-height: 1.45; }\n .stage-error { font-size: 13px; color: var(--ec-danger); }\n\n .deep-link {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n width: 100%;\n padding: 13px 16px;\n border-radius: 12px;\n background: var(--ec-accent);\n color: var(--ec-accent-contrast);\n font-weight: 600;\n font-size: 15px;\n text-decoration: none;\n }\n .deep-link .wallet-icon { width: 24px; height: 24px; }\n .deep-link .wallet-badge {\n border-radius: 6px;\n font-size: 12px;\n background: var(--ec-accent-contrast);\n }\n .deep-link .wallet-img { border-radius: 6px; }\n\n .pin-row { display: flex; gap: 10px; }\n .pin-row.shake { animation: shake 0.4s ease-in-out; }\n .pin-input {\n width: 46px; height: 54px;\n text-align: center;\n font-size: 24px; font-weight: 600;\n color: var(--ec-text);\n background: var(--ec-surface);\n border: 1px solid var(--ec-border);\n border-radius: 10px;\n outline: none;\n }\n .pin-input:focus { border-color: var(--ec-accent); }\n\n .check {\n width: 56px; height: 56px;\n display: flex; align-items: center; justify-content: center;\n border-radius: 50%;\n background: var(--ec-success);\n color: #ffffff;\n font-size: 28px;\n }\n\n .spinner {\n width: 32px; height: 32px;\n border-radius: 50%;\n border: 3px solid var(--ec-border);\n border-top-color: var(--ec-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: var(--ec-accent);\n color: var(--ec-accent-contrast);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n }\n .stage-btn:hover { filter: brightness(1.08); }\n\n .footer {\n border-top: 1px solid var(--ec-border);\n padding-top: 8px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .footer-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-wrap: wrap;\n gap: 2px 8px;\n }\n .footer-row > * { min-width: 0; }\n .footer-row > :only-child { margin-inline: auto; }\n\n .footer-link {\n background: none;\n border: none;\n color: var(--ec-muted);\n font-size: 13px;\n cursor: pointer;\n padding: 5px 8px;\n border-radius: 8px;\n }\n .footer-link:hover { color: var(--ec-text); background: var(--ec-surface); }\n .method-link { color: var(--ec-accent); }\n\n .wallet-row-label { font-size: 12px; color: var(--ec-muted); padding: 2px 2px 0; }\n\n .wallet-row {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 8px;\n }\n .row-tile, .wallet-tile {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px 6px;\n min-width: 0;\n background: var(--ec-surface);\n border: 1px solid var(--ec-border);\n border-radius: 12px;\n color: var(--ec-text);\n font-size: 11px;\n cursor: pointer;\n }\n .row-tile:hover, .wallet-tile:hover { border-color: var(--ec-accent); }\n .row-tile.selected {\n border-color: var(--ec-accent);\n background: var(--ec-accent-soft);\n box-shadow: inset 0 0 0 1px var(--ec-accent);\n }\n .row-tile.selected .row-tile-name { font-weight: 600; }\n .row-tile .wallet-icon, .wallet-tile .wallet-icon { width: 28px; height: 28px; }\n .row-tile-name, .wallet-tile-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n .more-tile { color: var(--ec-muted); }\n .more-tile:hover { color: var(--ec-text); }\n .more-tile[aria-expanded='true'] { border-color: var(--ec-accent); }\n .more-count {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 600;\n background: var(--ec-accent-soft);\n color: var(--ec-accent);\n }\n\n .wallet-panel { width: 100%; padding: 4px 0 2px; display: flex; flex-direction: column; gap: 8px; }\n .wallet-search {\n width: 100%; padding: 8px 12px;\n border-radius: 10px; border: 1px solid var(--ec-border); background: transparent;\n color: inherit; font: inherit; font-size: 13px;\n }\n .wallet-search:focus { outline: none; border-color: var(--ec-accent); }\n\n /* Cap the grid at three rows of tiles; past that it scrolls in place,\n and the wrapper's bottom fade hints that more wallets are below. */\n .wallet-scroll-wrap { position: relative; }\n .wallet-scroll { max-height: 220px; overflow-y: auto; }\n .wallet-scroll-wrap.scroll-hint::after {\n content: '';\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n height: 28px;\n background: linear-gradient(to bottom, transparent, var(--ec-bg));\n pointer-events: none;\n }\n .wallet-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 8px;\n }\n\n .wallet-icon { position: relative; width: 28px; height: 28px; flex-shrink: 0; display: inline-flex; }\n .wallet-badge {\n width: 100%; height: 100%; border-radius: 8px; display: inline-flex;\n align-items: center; justify-content: center; font-size: 13px;\n font-weight: 600; background: var(--ec-accent-soft); color: var(--ec-accent);\n }\n .wallet-img { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 8px; object-fit: cover; }\n\n .wallet-empty { padding: 10px 4px; font-size: 12px; color: var(--ec-muted); text-align: center; }\n\n .wallet-custom { display: flex; gap: 6px; }\n .url-input {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid var(--ec-border);\n border-radius: 10px;\n font-size: 13px;\n background: var(--ec-surface);\n color: var(--ec-text);\n outline: none;\n }\n .url-input:focus { border-color: var(--ec-accent); }\n .url-input.invalid { border-color: var(--ec-danger); }\n .url-go {\n padding: 8px 14px;\n border: none;\n border-radius: 10px;\n background: var(--ec-accent);\n color: var(--ec-accent-contrast);\n font-size: 13px;\n cursor: pointer;\n }\n .url-error { font-size: 12px; color: var(--ec-danger); }\n\n @media (prefers-reduced-motion: reduce) {\n .overlay, .modal, .stage.fade-in > *, .pin-row.shake { animation: none; }\n .claimed-pulse::after { animation: none; }\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 { createHandledDeferred } from './handled-deferred.js';\nimport {\n DWEB_CONNECT_ACK_MESSAGE_TYPE,\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/**\n * Grace period after the popup is seen closed for an already-posted response\n * to finish delivery before the close is treated as a denial.\n */\nconst CLOSED_RESPONSE_GRACE_MS = 1_500;\n\n/** Window name given to the wallet popup. */\nconst POPUP_WINDOW_NAME = 'enbox-dweb-connect';\n\n/** Outer size of the wallet popup window. */\nconst POPUP_WIDTH = 500;\nconst POPUP_HEIGHT = 700;\n\n/**\n * Builds the wallet popup's window features, centring it over the opener\n * window \u2014 without `left`/`top` browsers park the popup wherever they like\n * (usually offset into a corner). Falls back to centring on the screen when\n * the opener's metrics are unavailable, and lets the browser clamp\n * off-screen coordinates. Mobile browsers ignore the features entirely and\n * open a tab.\n */\nfunction popupWindowFeatures(): string {\n const base = `width=${POPUP_WIDTH},height=${POPUP_HEIGHT},menubar=no,toolbar=no,location=no,status=no`;\n\n // `screenX`/`outerWidth` describe the opener window; `screen.avail*`\n // describe its monitor \u2014 so the popup lands on the same display.\n const openerWidth = window.outerWidth > 0 ? window.outerWidth : (window.screen?.availWidth ?? 0);\n const openerHeight = window.outerHeight > 0 ? window.outerHeight : (window.screen?.availHeight ?? 0);\n if (openerWidth === 0 || openerHeight === 0) {\n return base;\n }\n\n const left = Math.max(0, Math.round((window.screenX ?? 0) + (openerWidth - POPUP_WIDTH) / 2));\n const top = Math.max(0, Math.round((window.screenY ?? 0) + (openerHeight - POPUP_HEIGHT) / 2));\n return `${base},left=${left},top=${top}`;\n}\n\n/** Guards against calling browser-only entry points outside a browser. */\nfunction assertBrowserEnvironment(): void {\n if (typeof window === 'undefined') {\n throw new TypeError('[@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 readonly _timeoutId?: ReturnType<typeof setTimeout>;\n private readonly _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 readonly _resolveResponse: (payload: string) => void;\n private readonly _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, popupWindowFeatures());\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. Early rejections\n // (timeout, popup closed during load) are pre-marked as handled until\n // the kernel attaches its own handlers via `awaitResponse()`.\n const response = createHandledDeferred<string>();\n this._responsePromise = response.promise;\n this._resolveResponse = response.resolve;\n this._rejectResponse = response.reject;\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 /**\n * {@inheritDoc ConnectTransport.confirmComplete}\n *\n * Posts the payload-less ack to the wallet popup (pinned `targetOrigin`)\n * so a wallet still holding its \"finishing up\" screen can flip to a\n * confirmed \"connected\" state before closing itself. A popup the user\n * already closed is skipped silently.\n */\n public async confirmComplete(): Promise<void> {\n if (this._popup.closed === true) { return; }\n this._popup.postMessage({ type: DWEB_CONNECT_ACK_MESSAGE_TYPE }, this._walletOrigin);\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. A wallet that posts its\n // response and immediately closes itself can lose the race between that\n // final message and this poll \u2014 especially when this page was\n // backgrounded (mobile tabs) and both signals arrive together on\n // resume \u2014 so give a queued response a grace window before treating the\n // close as a user denial.\n clearInterval(this._closedPollId);\n setTimeout((): void => {\n if (this._settled) { return; }\n this._settled = true;\n this.cleanup();\n this._resolveResponse(CONNECT_DENIED_TOKEN);\n }, CLOSED_RESPONSE_GRACE_MS);\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 * Internal deferred-promise helper for the DWeb Connect transports.\n *\n * @module\n */\n\n/** A promise paired with its `resolve`/`reject` settlers. */\nexport type HandledDeferred<T> = {\n /** The deferred promise. Rejections are pre-marked as handled. */\n promise: Promise<T>;\n\n /** Resolves {@link HandledDeferred.promise}. */\n resolve: (value: T) => void;\n\n /** Rejects {@link HandledDeferred.promise}. */\n reject: (error: Error) => void;\n};\n\n/**\n * Creates a promise alongside its `resolve`/`reject` settlers, with rejections\n * pre-marked as handled \u2014 so a rejection that settles the promise before any\n * consumer attaches handlers (e.g. a timeout firing first) never surfaces as\n * an unhandled rejection.\n */\nexport function createHandledDeferred<T>(): HandledDeferred<T> {\n let resolve!: (value: T) => void;\n let reject!: (error: Error) => void;\n\n // The executor runs synchronously, so `resolve`/`reject` are assigned\n // before the function returns.\n const promise = new Promise<T>((res, rej): void => {\n resolve = res;\n reject = rej;\n });\n promise.catch((): undefined => undefined);\n\n return { promise, resolve, reject };\n}\n", "/**\n * Wire shapes for the DWeb Connect popup/postMessage channel.\n *\n * The dapp and the wallet exchange exactly four 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 * 4. `ack` (dapp \u2192 wallet): payload-less completion signal \u2014 the dapp opened\n * the response successfully, so the wallet can flip to a confirmed\n * \"connected\" state before closing itself. Optional and observational;\n * wallets unaware of it simply ignore the message.\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/** Message type of the dapp's completion acknowledgement (dapp \u2192 wallet). */\nexport const DWEB_CONNECT_ACK_MESSAGE_TYPE = 'enbox-connect-ack';\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 * The dapp's completion acknowledgement: it opened the wallet's response\n * successfully. Carries no payload by design.\n */\nexport type DWebConnectAckMessage = {\n type: typeof DWEB_CONNECT_ACK_MESSAGE_TYPE;\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 const version = selectVersion(data.length);\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 const codewords = buildDataCodewords(data, version);\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 mask = selectBestMask(modules, isFunction);\n }\n\n applyMask(modules, isFunction, mask);\n drawFormatBits(modules, isFunction, mask);\n\n return { size, modules, version, mask };\n}\n\n/**\n * Smallest version (1\u2013{@link MAX_VERSION}) whose level-M byte-mode capacity\n * fits a `dataLength`-byte payload plus its mode/char-count header; `0` if\n * none fits.\n */\nfunction selectVersion(dataLength: number): number {\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 + dataLength * 8 <= capacityBits) {\n return candidate;\n }\n }\n return 0;\n}\n\n/**\n * Builds the packed data codewords for `data` at `version`: mode indicator,\n * char count, byte data, terminator, byte-alignment padding, and the\n * alternating pad-byte fill up to the version's level-M data capacity.\n */\nfunction buildDataCodewords(data: Uint8Array, version: number): Uint8Array {\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 let padIndex = 0;\n while (bits.length < capacityBits) {\n pushBits(padBytes[padIndex], 8);\n padIndex ^= 1; // alternate the two pad bytes\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 return codewords;\n}\n\n/** Applies each of the 8 mask patterns, scores it, and returns the lowest-penalty mask index. */\nfunction selectBestMask(modules: boolean[][], isFunction: boolean[][]): number {\n let bestMask = 0;\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 bestMask = candidate;\n }\n applyMask(modules, isFunction, candidate); // undo (XOR is involutive)\n }\n return bestMask;\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 // Visit columns in right-to-left pairs, shifting one column left of the\n // vertical timing column (index 6) so it is skipped \u2014 without mutating the\n // loop counter (Sonar S2310). `size` is always odd, so `right` is always\n // even and `right - 1` maps 6\u21925, 4\u21923, 2\u21921, matching the original traversal.\n const rightCol = right <= 6 ? right - 1 : right;\n bitIndex = placeColumnPairBits(modules, isFunction, codewords, rightCol, size, bitIndex);\n }\n}\n\n/**\n * Places codeword bits into the zig-zag column pair (`rightCol`,\n * `rightCol - 1`) top-to-bottom or bottom-to-top per {@link zigZagCoordinate},\n * starting at `bitIndex`; returns the updated bit index.\n */\nfunction placeColumnPairBits(\n modules: boolean[][],\n isFunction: boolean[][],\n codewords: Uint8Array,\n rightCol: number,\n size: number,\n bitIndex: number,\n): number {\n for (let vertical = 0; vertical < size; vertical++) {\n for (let j = 0; j < 2; j++) {\n const { x, y } = zigZagCoordinate(rightCol, vertical, j, size);\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 return bitIndex;\n}\n\n/** Module coordinate for column-pair `rightCol`, row `vertical`, sub-column `j` (0 = right, 1 = left). */\nfunction zigZagCoordinate(rightCol: number, vertical: number, j: number, size: number): { x: number; y: number } {\n const x = rightCol - j;\n const upward = ((rightCol + 1) & 2) === 0;\n const y = upward ? size - 1 - vertical : vertical;\n return { x, y };\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\n/** N1: runs of \u22655 same-colour modules in a row/column. */\nfunction penaltyAdjacentRuns(modules: boolean[][], size: number): number {\n let penalty = 0;\n\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 return penalty;\n}\n\n/** N2: 2\u00D72 blocks of the same colour. */\nfunction penaltyBlocks(modules: boolean[][], size: number): number {\n let penalty = 0;\n\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 return penalty;\n}\n\n/** Checks `line` for a 1:1:3:1:1 finder-like core starting at `start`, scoring a 4-module light flank on either side. */\nfunction 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/** N3: finder-like 1:1:3:1:1 patterns with 4-module light flank. */\nfunction penaltyFinderPatterns(modules: boolean[][], size: number): number {\n let penalty = 0;\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 return penalty;\n}\n\n/** N4: dark-module proportion deviation from 50%, in 5% steps. */\nfunction penaltyDarkRatio(modules: boolean[][], size: number): number {\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 return k * 10;\n}\n\nfunction computePenalty(modules: boolean[][]): number {\n const size = modules.length;\n let penalty = 0;\n\n penalty += penaltyAdjacentRuns(modules, size);\n penalty += penaltyBlocks(modules, size);\n penalty += penaltyFinderPatterns(modules, size);\n penalty += penaltyDarkRatio(modules, size);\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 { PortableDid } from '@enbox/dids';\nimport type {\n ConnectClientMetadata,\n ConnectPermissionRequest,\n ConnectRequest,\n ConnectRequestType,\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 resolveDelegatePortableDid,\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 /** Stable application identifier hint available to the wallet during approval. */\n applicationId?: 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 /** Existing delegate credentials reused by a refresh request. */\n delegatePortableDid?: PortableDid;\n\n /** User-facing request purpose. Absent means a normal connect. */\n requestType?: ConnectRequestType;\n\n /** Wallet profile DID that a refresh must renew. */\n expectedProviderDid?: string;\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>;\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 signal?: AbortSignal;\n }) => Pick<RelayClientTransport, 'requestProfile' | 'deliverRequest' | 'awaitResponse' | 'requiresPin'>\n & Partial<Pick<RelayClientTransport, 'confirmComplete'>>;\n}\n\n/**\n * Sleep used between relay polls that ends early when the page returns to\n * the foreground. Browsers throttle \u2014 and mobile browsers freeze \u2014 timers in\n * background tabs, so a plain interval sleep can leave the user staring at a\n * stale stage after approving in the wallet tab; cutting the sleep short on\n * `visibilitychange` makes the next poll (and with it the pairing-code\n * prompt) land the moment they switch back. Falls back to a plain sleep\n * outside DOM environments.\n */\nexport function visibilityAwareSleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n if (typeof document === 'undefined') {\n setTimeout(resolve, ms);\n return;\n }\n\n const finish = (): void => {\n clearTimeout(timer);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n resolve();\n };\n const onVisibilityChange = (): void => {\n if (document.visibilityState === 'visible') {\n finish();\n }\n };\n const timer = setTimeout(finish, ms);\n document.addEventListener('visibilitychange', onVisibilityChange);\n });\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 if (options.requestType === 'refresh' && options.delegatePortableDid === undefined) {\n throw new Error('Connect: refresh requests require an existing `delegatePortableDid`.');\n }\n\n const createTransport = options.createTransport\n ?? ((transportOptions): RelayClientTransport => new RelayClientTransport({\n ...transportOptions,\n sleep: visibilityAwareSleep,\n }));\n\n const cancellationController = options.cancelled === undefined ? undefined : new AbortController();\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 signal : cancellationController?.signal,\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 applicationId : options.applicationId,\n clientMetadata : options.clientMetadata,\n permissionRequests : options.permissionRequests,\n delegateDid : options.delegatePortableDid?.uri,\n requestType : options.requestType,\n expectedProviderDid : options.expectedProviderDid,\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 let responseCiphertext: string;\n try {\n responseCiphertext = await race;\n } catch (error) {\n cancellationController?.abort();\n throw error;\n }\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 const outcome = await attemptPinOpen({\n responseCiphertext,\n responsePrivateKey,\n clientDid : clientDid.uri,\n nonce,\n state,\n pin,\n expectedProviderDid : options.expectedProviderDid,\n delegatePortableDid : options.delegatePortableDid,\n confirmComplete : transport.confirmComplete?.bind(transport),\n });\n if (outcome.matched) {\n return outcome.result;\n }\n lastError = outcome.error;\n }\n\n throw new Error(`[@enbox/browser] The pairing code did not match after ${MAX_PIN_ATTEMPTS} attempts.`);\n}\n\n/** One PIN attempt's outcome: either the delegated credentials, or a retryable failure. */\ntype PinAttemptOutcome =\n | { matched: true; result: ConnectResult }\n | { matched: false; error: Error };\n\n/**\n * Opens `responseCiphertext` with one PIN attempt and, on success, resolves\n * the delegated credentials and fires the best-effort completion signal.\n * Kernel value-check failures (`'Connect:'`-prefixed) are structural, not a\n * mistyped code, so they rethrow instead of reporting a mismatch \u2014 the\n * retry loop in {@link runRelayConnect} treats that as fatal.\n */\nasync function attemptPinOpen(params: {\n responseCiphertext: string;\n responsePrivateKey: Jwk;\n clientDid: string;\n nonce: string;\n state: string;\n pin: string;\n expectedProviderDid: string | undefined;\n delegatePortableDid: PortableDid | undefined;\n confirmComplete: (() => Promise<void>) | undefined;\n}): Promise<PinAttemptOutcome> {\n try {\n const response = await openResponse({\n jwe : params.responseCiphertext,\n recipientPrivateKey : params.responsePrivateKey,\n expected : {\n clientDid : params.clientDid,\n nonce : params.nonce,\n state : params.state,\n providerDid : params.expectedProviderDid,\n },\n pin: params.pin,\n });\n\n const delegatePortableDid = resolveDelegatePortableDid({\n localDelegatePortableDid: params.delegatePortableDid,\n response,\n });\n\n // Best-effort completion signal so the wallet can flip its pairing\n // screen to a confirmed \"connected\" state instead of leaving the user\n // to dismiss it blind. Fire-and-forget \u2014 mirrors the kernel client.\n params.confirmComplete?.().catch((): undefined => undefined);\n\n return {\n matched : true,\n result : {\n delegatePortableDid,\n delegateGrants : response.delegateGrants,\n connectedDid : response.providerDid,\n sessionRevocations : response.sessionRevocations,\n },\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 return { matched: false, error: failure };\n }\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 { PortableDid } from '@enbox/dids';\nimport type { ConnectHandler, ConnectResult } from '@enbox/auth';\nimport type { ConnectPermissionRequest, ConnectRequestType } from '@enbox/connect';\n\nimport { runConnectModal } from './ui/connect-modal.js';\n\nimport type { ConnectMethod, ConnectModalTheme } 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 : 'Sumi',\n url : 'https://sumi-wallet.pages.dev',\n description : 'A refined home for your digital identity',\n },\n {\n name : 'Taffy',\n url : 'https://taffy-wallet.pages.dev',\n description : 'A playful take on your digital identity',\n },\n {\n name : 'Astoria',\n url : 'https://astoria-wallet.pages.dev',\n description : 'A grand home for your digital identity',\n },\n {\n name : 'Quay',\n url : 'https://quay-id.pages.dev',\n description : 'A safe harbor for your digital identity',\n },\n {\n name : 'Quoin',\n url : 'https://quoin-id.pages.dev',\n description : 'A cornerstone 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 * Stable application identifier hint available to the wallet during approval.\n * Defaults to the browser's canonical origin.\n */\n applicationId?: 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. Refreshes reuse\n * the route saved for their delegate DID; new connections use the latest\n * successful route as a convenience.\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 * Color scheme for the connect modal. By default it follows the\n * visitor's system light/dark appearance; apps can force an appearance\n * and/or override palette tokens (accent, surfaces, text) per scheme to\n * match their brand.\n */\n theme?: ConnectModalTheme;\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 applicationId,\n preferredMethod,\n rememberChoice,\n connectServerUrl,\n relayWalletPath,\n theme,\n } = options;\n\n return {\n async requestAccess(params: {\n permissionRequests: ConnectPermissionRequest[];\n delegatePortableDid?: PortableDid;\n requestType?: ConnectRequestType;\n expectedProviderDid?: string;\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 applicationId,\n connectServerUrl,\n relayWalletPath,\n timeout,\n theme,\n mode : params.requestType,\n delegatePortableDid : params.delegatePortableDid,\n expectedProviderDid : params.expectedProviderDid,\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`. `sendResponseAwaitingAck()` does the\n * same but stays alive briefly for the dapp's completion ack, so the\n * wallet can show a confirmed \"connected\" state before closing itself.\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 { createHandledDeferred } from './handled-deferred.js';\nimport {\n DWEB_CONNECT_ACK_MESSAGE_TYPE,\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/** Default budget for awaiting the dapp's completion ack after a response. */\nconst DEFAULT_ACK_TIMEOUT_MS = 5_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 readonly _timeoutId?: ReturnType<typeof setTimeout>;\n private _messageListener?: (event: MessageEvent) => void;\n private _resolveAck?: (acked: boolean) => void;\n\n private readonly _requestPromise: Promise<ConnectRequest>;\n private readonly _resolveRequest: (request: ConnectRequest) => void;\n private readonly _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 // Early rejections (timeout before `awaitRequest()` is called) are\n // pre-marked as handled until the wallet attaches its own handlers.\n const request = createHandledDeferred<ConnectRequest>();\n this._requestPromise = request.promise;\n this._resolveRequest = request.resolve;\n this._rejectRequest = request.reject;\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 TypeError('[@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 /**\n * Posts the sealed response JWE back to the dapp like\n * {@link sendResponse}, then keeps the channel open briefly for the dapp's\n * completion ack \u2014 the signal that it opened the response successfully \u2014\n * before closing the transport.\n *\n * Lets the wallet's connect page show a confirmed \"connected\" state (and\n * close itself with confidence) instead of asking the user to dismiss the\n * screen blind. Dapps predating the ack simply never send one, so the\n * wallet should keep a manual dismiss affordance for the `false` case.\n *\n * @param idToken - The sealed response JWE.\n * @param options - The awaiting options.\n * @param options.timeoutMs - Ack budget in milliseconds; defaults to 5 s.\n * @returns Whether the dapp acknowledged completion within the budget.\n */\n public async sendResponseAwaitingAck(idToken: string, options: { timeoutMs?: number } = {}): Promise<boolean> {\n const ackPromise = new Promise<boolean>((resolve): void => {\n this._resolveAck = resolve;\n });\n\n this._dappWindow.postMessage({\n type : DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n payload : idToken,\n }, this._dappOrigin);\n\n const ackTimeoutId = setTimeout((): void => {\n this._resolveAck?.(false);\n }, options.timeoutMs ?? DEFAULT_ACK_TIMEOUT_MS);\n\n const acked = await ackPromise;\n clearTimeout(ackTimeoutId);\n this._resolveAck = undefined;\n this.close();\n return acked;\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_ACK_MESSAGE_TYPE) {\n this._resolveAck?.(true);\n return;\n }\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", "export type ObjectUrlLease = Readonly<{\n url: string;\n /** Release immediately, cancelling any deferred release. Idempotent. */\n release(): void;\n /** Release after a grace period. The first deferred release wins. */\n releaseAfter(delayMs: number): void;\n}>;\n\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n\nfunction assertReleaseDelay(delayMs: number): void {\n if (!Number.isSafeInteger(delayMs) || delayMs < 0 || delayMs > MAX_TIMER_DELAY_MS) {\n throw new TypeError(`delayMs must be an integer between 0 and ${MAX_TIMER_DELAY_MS}.`);\n }\n}\n\n/** Private reference-counted ownership for one object URL. */\nexport class ObjectUrlReference {\n public readonly url: string;\n private _isRevoked = false;\n private _references = 0;\n private readonly _releaseTimers = new Set<ReturnType<typeof setTimeout>>();\n\n public constructor(blob: Blob, private readonly _onEmpty: (reference: ObjectUrlReference) => void) {\n this.url = globalThis.URL.createObjectURL(blob);\n }\n\n public get references(): number {\n return this._references;\n }\n\n public acquire(): ObjectUrlLease {\n if (this._isRevoked) {\n throw new Error('Object URL has been revoked.');\n }\n\n this._references += 1;\n let released = false;\n let releaseTimer: ReturnType<typeof setTimeout> | undefined;\n const release = (): void => {\n if (released) {\n return;\n }\n released = true;\n if (releaseTimer !== undefined) {\n clearTimeout(releaseTimer);\n this._releaseTimers.delete(releaseTimer);\n }\n if (this._isRevoked) {\n return;\n }\n this._references -= 1;\n if (this._references === 0) {\n this._onEmpty(this);\n }\n };\n return Object.freeze({\n url : this.url,\n release,\n releaseAfter : (delayMs: number): void => {\n assertReleaseDelay(delayMs);\n if (released || this._isRevoked || releaseTimer !== undefined) {\n return;\n }\n releaseTimer = setTimeout(release, delayMs);\n this._releaseTimers.add(releaseTimer);\n },\n });\n }\n\n public revoke(): void {\n if (!this._isRevoked) {\n this._isRevoked = true;\n for (const timer of this._releaseTimers) {\n clearTimeout(timer);\n }\n this._releaseTimers.clear();\n this._references = 0;\n globalThis.URL.revokeObjectURL(this.url);\n }\n }\n}\n", "import type { ObjectUrlLease } from './object-url-reference.js';\n\nimport { ObjectUrlReference } from './object-url-reference.js';\n\n/**\n * A reference-counted lease for a browser object URL.\n *\n * When replacing a URL already rendered by the DOM, `releaseAfter()` provides\n * a grace period without passing the lease through the component tree.\n */\nexport type BlobUrlLease = ObjectUrlLease;\n\n/** Owns object URLs for Blob identities until their last lease is released. */\nexport interface BlobUrlPool {\n acquire(blob: Blob): BlobUrlLease;\n dispose(): void;\n}\n\nclass DefaultBlobUrlPool implements BlobUrlPool {\n private readonly _references = new Map<Blob, ObjectUrlReference>();\n private _isDisposed = false;\n\n public acquire(blob: Blob): BlobUrlLease {\n if (this._isDisposed) {\n throw new Error('BlobUrlPool is disposed.');\n }\n\n let reference = this._references.get(blob);\n if (reference === undefined) {\n reference = new ObjectUrlReference(blob, (released): void => {\n this._references.delete(blob);\n released.revoke();\n });\n this._references.set(blob, reference);\n }\n return reference.acquire();\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n this._isDisposed = true;\n for (const reference of this._references.values()) {\n reference.revoke();\n }\n this._references.clear();\n }\n}\n\n/** Create a terminally disposable, reference-counted object URL pool. */\nexport function createBlobUrlPool(): BlobUrlPool {\n return new DefaultBlobUrlPool();\n}\n", "import type { FileEnvelopeData } from '@enbox/api';\n\nimport type { BlobUrlLease } from './blob-url-pool.js';\n\nimport { ObjectUrlReference } from './object-url-reference.js';\n\nconst DEFAULT_MAX_BYTES = 128 * 1024 * 1024;\nconst DEFAULT_MAX_ENTRIES = 50;\n\ntype CacheEntry = {\n bytes: number;\n filename: string;\n key: string;\n mimeType: string;\n url: ObjectUrlReference;\n};\n\ntype PendingRead = {\n controller: AbortController;\n generation: number;\n promise: Promise<CacheEntry | undefined>;\n};\n\n/** A cached file envelope represented by a leased browser object URL. */\nexport type FileEnvelopeUrlLease = BlobUrlLease & Readonly<{\n filename: string;\n mimeType: string;\n}>;\n\nexport type FileEnvelopeUrlStoreOptions<Request> = Readonly<{\n /** Select the stable cache key for a read request. */\n key(request: Request): string;\n /** Read and decode the file. The signal aborts invalidated work. */\n read(request: Request, signal: AbortSignal): Promise<FileEnvelopeData | undefined>;\n /** Choose the Blob exposed by the URL, retaining MIME/render policy in the caller. */\n blobForUrl(value: FileEnvelopeData): Blob;\n /** Maximum cached entries (default 50). Soft while every eviction candidate is leased. */\n maxEntries?: number;\n /** Maximum cached Blob bytes (default 128 MiB). Soft while every eviction candidate is leased. */\n maxBytes?: number;\n}>;\n\n/** A keyed, bounded object URL cache for decoded file envelopes. */\nexport interface FileEnvelopeUrlStore<Request> {\n acquire(request: Request): Promise<FileEnvelopeUrlLease | undefined>;\n acquireCached(request: Request): FileEnvelopeUrlLease | undefined;\n clear(): void;\n dispose(): void;\n invalidate(request: Request): void;\n}\n\nfunction assertLimit(value: number, name: string): void {\n if (value !== Infinity && (!Number.isSafeInteger(value) || value < 0)) {\n throw new TypeError(`${name} must be a non-negative safe integer or Infinity.`);\n }\n}\n\nfunction throwAborted(controller: AbortController): never {\n controller.abort();\n throw controller.signal.reason;\n}\n\nclass DefaultFileEnvelopeUrlStore<Request> implements FileEnvelopeUrlStore<Request> {\n private readonly _cache = new Map<string, CacheEntry>();\n private readonly _entries = new Set<CacheEntry>();\n private readonly _maxBytes: number;\n private readonly _maxEntries: number;\n private readonly _pending = new Map<string, PendingRead>();\n private _bytes = 0;\n private _generation = 0;\n private _isDisposed = false;\n\n public constructor(private readonly _options: FileEnvelopeUrlStoreOptions<Request>) {\n this._maxBytes = _options.maxBytes ?? DEFAULT_MAX_BYTES;\n this._maxEntries = _options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n assertLimit(this._maxBytes, 'maxBytes');\n assertLimit(this._maxEntries, 'maxEntries');\n }\n\n public async acquire(request: Request): Promise<FileEnvelopeUrlLease | undefined> {\n this._assertActive();\n const key = this._options.key(request);\n const cached = this._cache.get(key);\n if (cached !== undefined) {\n return this._acquire(cached);\n }\n\n const pending = this._pending.get(key) ?? this._startRead(request, key);\n const entry = await pending.promise;\n if (this._isDisposed || pending.generation !== this._generation) {\n return throwAborted(pending.controller);\n }\n if (entry === undefined) {\n return undefined;\n }\n if (this._cache.get(key) !== entry) {\n return throwAborted(pending.controller);\n }\n return this._acquire(entry);\n }\n\n public acquireCached(request: Request): FileEnvelopeUrlLease | undefined {\n this._assertActive();\n const entry = this._cache.get(this._options.key(request));\n return entry === undefined ? undefined : this._acquire(entry);\n }\n\n public invalidate(request: Request): void {\n this._assertActive();\n const key = this._options.key(request);\n const pending = this._pending.get(key);\n pending?.controller.abort();\n this._pending.delete(key);\n const entry = this._cache.get(key);\n if (entry !== undefined) {\n this._remove(entry);\n }\n }\n\n public clear(): void {\n this._assertActive();\n this._reset(false);\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n this._isDisposed = true;\n this._reset(true);\n }\n\n private _abortReads(): void {\n for (const pending of this._pending.values()) {\n pending.controller.abort();\n }\n this._pending.clear();\n }\n\n private _acquire(entry: CacheEntry): FileEnvelopeUrlLease {\n this._cache.delete(entry.key);\n this._cache.set(entry.key, entry);\n const lease = entry.url.acquire();\n this._evict();\n return Object.freeze({\n filename : entry.filename,\n mimeType : entry.mimeType,\n release : lease.release,\n releaseAfter : lease.releaseAfter,\n url : lease.url,\n });\n }\n\n private _assertActive(): void {\n if (this._isDisposed) {\n throw new Error('FileEnvelopeUrlStore is disposed.');\n }\n }\n\n private _assertCurrent(key: string, controller: AbortController, generation: number): void {\n if (\n this._isDisposed\n || controller.signal.aborted\n || this._generation !== generation\n || this._pending.get(key)?.controller !== controller\n ) {\n throwAborted(controller);\n }\n }\n\n private _evict(): void {\n while (this._cache.size > this._maxEntries || this._bytes > this._maxBytes) {\n const entry = [...this._cache.values()].find((candidate): boolean => candidate.url.references === 0);\n if (entry === undefined) {\n return;\n }\n this._remove(entry);\n }\n }\n\n private async _load(request: Request, key: string, controller: AbortController, generation: number): Promise<CacheEntry | undefined> {\n const value = await this._options.read(request, controller.signal);\n this._assertCurrent(key, controller, generation);\n if (value === undefined) {\n return undefined;\n }\n\n const blob = this._options.blobForUrl(value);\n this._assertCurrent(key, controller, generation);\n const url = new ObjectUrlReference(blob, (): void => this._released(entry));\n const entry: CacheEntry = {\n bytes : blob.size,\n filename : value.filename,\n key,\n mimeType : value.mimeType,\n url,\n };\n this._cache.set(key, entry);\n this._bytes += entry.bytes;\n this._entries.add(entry);\n return entry;\n }\n\n private _released(entry: CacheEntry): void {\n if (this._cache.get(entry.key) !== entry) {\n this._revoke(entry);\n } else {\n this._evict();\n }\n }\n\n private _remove(entry: CacheEntry): void {\n if (this._cache.get(entry.key) !== entry) {\n return;\n }\n this._cache.delete(entry.key);\n this._bytes -= entry.bytes;\n if (entry.url.references === 0) {\n this._revoke(entry);\n }\n }\n\n private _reset(revokeActive: boolean): void {\n this._generation += 1;\n this._abortReads();\n this._cache.clear();\n this._bytes = 0;\n for (const entry of this._entries) {\n if (revokeActive || entry.url.references === 0) {\n this._revoke(entry);\n }\n }\n }\n\n private _revoke(entry: CacheEntry): void {\n entry.url.revoke();\n this._entries.delete(entry);\n }\n\n private _startRead(request: Request, key: string): PendingRead {\n const controller = new AbortController();\n const generation = this._generation;\n const promise = this._load(request, key, controller, generation).finally((): void => {\n if (this._pending.get(key)?.controller === controller) {\n this._pending.delete(key);\n }\n });\n const pending = { controller, generation, promise };\n this._pending.set(key, pending);\n return pending;\n }\n}\n\n/** Create a bounded file-envelope URL store with deduplicated reads. */\nexport function createFileEnvelopeUrlStore<Request>(\n options: FileEnvelopeUrlStoreOptions<Request>,\n): FileEnvelopeUrlStore<Request> {\n return new DefaultFileEnvelopeUrlStore(options);\n}\n"],
|
|
5
|
-
"mappings": "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EbC,EAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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",
|
|
6
|
-
"names": ["CONNECT_DENIED_TOKEN", "ConnectProvider", "DidDht", "DidResolverCacheMemory", "DidWeb", "resolveDwnEndpointStatus", "UniversalResolver", "parseDrlUrl", "url", "idx", "prefix", "rest", "slashIdx", "didResolver", "UniversalResolver", "DidDht", "DidWeb", "DidResolverCacheMemory", "httpToHttpsRegex", "trailingSlashRegex", "DRL_CACHE_NAME", "getDwnEndpoints", "did", "result", "resolveDwnEndpointStatus", "openDrlCache", "handleEvent", "event", "path", "options", "drl", "responseCache", "cachedResponse", "match", "cacheTime", "fetchResource", "response", "error", "endpoints", "lastError", "endpoint", "url", "cacheResponse", "cache", "clonedResponse", "headers", "modifiedResponse", "installWorker", "workerSelf", "parsed", "parseDrlUrl", "installUrl", "loaderStyles", "tabContent", "elementsInjected", "overlayElement", "styleElement", "injectElements", "cancelNavigation", "removeElements", "activeNavigation", "navigateToDrl", "openAsTab", "tab", "linkFeaturesActive", "clickHandler", "pointerdownHandler", "addLinkFeatures", "anchor", "href", "target", "resetContextMenuTarget", "contextMenuTarget", "removeLinkFeatures", "e", "r", "activatePolyfills", "deactivatePolyfills", "clearDrlCache", "ConnectClient", "buildWalletIcon", "wallet", "wrap", "badge", "sources", "iconCandidates", "img", "index", "origin", "assertX25519PublicJwk", "CONNECT_DENIED_TOKEN", "ConnectClient", "createHandledDeferred", "resolve", "reject", "promise", "res", "rej", "DWEB_CONNECT_PATH", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "DWEB_CONNECT_ACK_MESSAGE_TYPE", "getTrustedMessage", "event", "expectedOrigin", "expectedSource", "data", "DEFAULT_TIMEOUT_MS", "CLOSED_POLL_INTERVAL_MS", "CLOSED_RESPONSE_GRACE_MS", "POPUP_WINDOW_NAME", "POPUP_WIDTH", "POPUP_HEIGHT", "popupWindowFeatures", "base", "openerWidth", "openerHeight", "left", "top", "assertBrowserEnvironment", "PopupWindowClosedError", "PopupClientTransport", "options", "popupUrl", "DWEB_CONNECT_PATH", "popup", "resolve", "reject", "response", "createHandledDeferred", "event", "state", "jwe", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "DWEB_CONNECT_ACK_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", "selectVersion", "codewords", "buildDataCodewords", "allCodewords", "buildInterleavedCodewords", "size", "modules", "isFunction", "drawFunctionPatterns", "drawCodewords", "mask", "selectBestMask", "applyMask", "drawFormatBits", "dataLength", "candidate", "capacityBits", "bits", "pushBits", "value", "length", "i", "byte", "padBytes", "padIndex", "bestMask", "bestPenalty", "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", "rightCol", "placeColumnPairBits", "vertical", "zigZagCoordinate", "invert", "penaltyAdjacentRuns", "runColor", "runLength", "penaltyBlocks", "c", "hasFinderPattern", "line", "start", "lightBefore", "v", "lightAfter", "penaltyFinderPatterns", "row", "column", "r", "penaltyDarkRatio", "module", "total", "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", "resolveDelegatePortableDid", "sealRequest", "MAX_PIN_ATTEMPTS", "RelayConnectCancelledError", "visibilityAwareSleep", "ms", "resolve", "finish", "timer", "onVisibilityChange", "runRelayConnect", "options", "createTransport", "transportOptions", "cancellationController", "transport", "clientDid", "responsePrivateKey", "responsePublicKey", "nonce", "state", "profile", "request", "requestJwe", "handoff", "race", "responseCiphertext", "error", "lastError", "attempt", "pin", "outcome", "attemptPinOpen", "params", "response", "delegatePortableDid", "failure", "LAST_CHOICE_STORAGE_KEY", "SESSION_CHOICES_STORAGE_KEY", "MAX_SESSION_CHOICES", "REMINT_SAFETY_MS", "REMINT_MIN_MS", "PIN_LENGTH", "WALLET_SEARCH_THRESHOLD", "WALLET_ROW_SIZE", "PALETTE_TOKENS", "discoverWalletConnectServerUrl", "walletOrigin", "fetchWalletWellKnown", "runPopupConnect", "options", "transport", "PopupClientTransport", "ConnectClient", "collectBrowserClientMetadata", "defaultIsMobile", "defaultDeps", "runRelayConnect", "probeWalletWellKnown", "readLastChoice", "storage", "raw", "parsed", "isValidRememberedWalletUrl", "writeLastChoice", "choice", "isSessionChoice", "value", "readSessionChoices", "readSessionChoice", "delegateDid", "expectedProviderDid", "choices", "index", "writeSessionChoice", "entry", "removeSessionChoice", "providerDid", "createRelaySession", "cancel", "session", "cancelled", "_", "reject", "RelayConnectCancelledError", "settleWith", "settle", "settler", "runConnectModal", "deps", "wallets", "dedupeWalletsByUrl", "rememberChoice", "appName", "applicationId", "isMobile", "refreshing", "lastChoice", "savedRoute", "relayWalletPath", "savedRouteEscapeLabel", "rememberedWalletUrl", "walletInCatalog", "walletUrl", "method", "resolve", "host", "shadow", "style", "MODAL_STYLES", "overlay", "modal", "title", "theme", "appearance", "systemDark", "hasPaletteOverrides", "applyPaletteTokens", "systemScheme", "scheme", "palette", "key", "onSchemeChange", "settled", "relaySession", "remintTimer", "remintAt", "popupBusy", "pinResolve", "getPinResolve", "clearPinResolve", "discoveryCache", "rowWallets", "walletByUrl", "url", "wallet", "hostnameOf", "composeWalletRow", "selected", "selectWallet", "renderFooter", "startMethod", "cleanup", "clearRemint", "onKeydown", "onVisibilityReturn", "succeed", "result", "renderConnected", "cancelModal", "buildHeader", "stage", "footer", "setStage", "nodes", "renderBusy", "message", "el", "morphToAway", "walletName", "renderAway", "buildHandoffLink", "handoff", "className", "link", "renderQr", "qrLink", "qrToSvg", "encodeQr", "logo", "buildWalletIcon", "stageLinkButton", "startPhone", "renderClaimed", "pulse", "renderPin", "attempt", "previousError", "resolvePin", "boxes", "inputs", "buildPinInputs", "check", "renderDenied", "stageButton", "escapeSavedRoute", "renderError", "error", "renderPhoneUnavailable", "startPopup", "popupSurface", "renderPopupPrompt", "exactReconnect", "description", "buttonLabel", "renderPopupWaiting", "renderPopupInterrupted", "blocked", "switchMethod", "renderPopupFailure", "failure", "popupBlocked", "PopupWindowClosedError", "resolveConnectServerUrl", "origin", "cached", "remintNow", "scheduleRemint", "expiresInSeconds", "delay", "connectServerUrl", "next", "switcher", "buildWalletSwitcher", "row", "alt", "tile", "isSelected", "panel", "gridWallets", "more", "updateScrollHint", "label", "tiles", "empty", "search", "query", "visible", "match", "scrollWrap", "scroll", "grid", "overflowing", "atEnd", "tileName", "custom", "input", "go", "urlError", "allowUnverified", "submitCustom", "valid", "e", "event", "trapFocus", "candidate", "tag", "text", "node", "onClick", "button", "titleText", "appIcon", "onCancel", "header", "identity", "icon", "closeBtn", "i", "submitIfComplete", "code", "resolveOnce", "digits", "digit", "digitIndex", "focusables", "first", "last", "active", "LIGHT_TOKENS", "DARK_TOKENS", "DEFAULT_WALLETS", "BrowserConnectHandler", "options", "wallets", "walletUrl", "timeout", "appName", "appIcon", "applicationId", "preferredMethod", "rememberChoice", "connectServerUrl", "relayWalletPath", "theme", "params", "runConnectModal", "X25519", "CONNECT_DENIED_TOKEN", "ConnectProvider", "DEFAULT_REQUEST_TIMEOUT_MS", "DEFAULT_ACK_TIMEOUT_MS", "WalletPostMessageTransport", "_WalletPostMessageTransport", "params", "request", "createHandledDeferred", "event", "options", "dappWindow", "dappOrigin", "resolveDappOrigin", "recipientPrivateKey", "X25519", "walletEpk", "transport", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "
|
|
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 * BrowserConnectHandler, createConnectionStore,\n * defineApplicationManifest,\n * } from '@enbox/browser';\n * import { MyProtocol } from './my-protocol.js';\n *\n * const store = createConnectionStore({\n * application : defineApplicationManifest({ protocols: [MyProtocol] }),\n * connectHandler : BrowserConnectHandler({ appName: 'My App' }),\n * });\n * const snapshot = await store.connect();\n * if (snapshot.phase !== 'connected') throw snapshot.error ?? new Error('Connection failed.');\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 and protocols.\n\nexport * 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 * 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, 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_ACK_MESSAGE_TYPE,\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 DWebConnectAckMessage,\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, ConnectModalPalette, ConnectModalTheme } 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';\nexport { createBlobUrlPool } from './blob-url-pool.js';\nexport type { BlobUrlLease, BlobUrlPool } from './blob-url-pool.js';\nexport { createFileEnvelopeUrlStore } from './file-envelope-url-store.js';\nexport type {\n FileEnvelopeUrlLease,\n FileEnvelopeUrlStore,\n FileEnvelopeUrlStoreOptions,\n} from './file-envelope-url-store.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// Public-profile read/cache layer (from @enbox/protocols): fetch other\n// users' published profiles (displayName + avatar/hero) from their DWNs\n// with caching, retries, negative caching, and refcounted subscriptions.\n// Works over a connected records surface and over `Enbox.anonymous()`.\nexport { createProfileReader, isRetryableProfileReadStatus } from '@enbox/protocols';\nexport type {\n ProfileEntryStatus,\n ProfileFieldSnapshot,\n ProfileFieldStatus,\n ProfileImages,\n ProfileReader,\n ProfileReaderFailure,\n ProfileReaderImagesMode,\n ProfileReaderOptions,\n ProfileReaderRecordsSurface,\n ProfileReaderSource,\n ProfileReaderTimers,\n ProfileSnapshot,\n ProfileWatchListener,\n PublicProfile,\n} from '@enbox/protocols';\n\n// DWN interface enum for typing agent requests (from @enbox/agent).\nexport { DwnInterface } from '@enbox/agent';\n\n// Low-level sync-status types for advanced agent consumers. Dapps using a\n// ConnectionStore receive current advertised rows through `snapshot.sync.remotes`\n// and can call `store.retryRemote(remoteEndpoint)` without wiring agent events.\nexport type {\n DeadLetterEntry,\n RemoteSyncState,\n RemoteSyncStatus,\n SyncConnectivityState,\n SyncEngine,\n SyncEvent,\n SyncEventListener,\n SyncHealthSummary,\n SyncIdentityStatus,\n} 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, DidResolverCacheMemory, DidWeb, resolveDwnEndpointStatus, 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({\n didResolvers : [DidDht, DidWeb],\n cache : new DidResolverCacheMemory(),\n});\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 result = await resolveDwnEndpointStatus(did, didResolver);\n return result.status === 'ready' ? result.endpoints : [];\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\n/**\n * Opens the tab/loading-overlay target for a DRL anchor click, then resolves\n * and navigates to the DRL's first working DWN endpoint. Extracted from the\n * click handler so the handler itself stays a shallow guard-clause dispatch\n * (Sonar S3776).\n */\nasync function navigateToDrl(did: string, path: string, openAsTab: boolean): Promise<void> {\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}\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 return;\n }\n const href = anchor.href;\n const parsed = parseDrlUrl(href);\n if (!parsed) {\n return;\n }\n const did = parsed[0];\n const path = parsed[1];\n const openAsTab = anchor.target === '_blank';\n event.preventDefault();\n try {\n await navigateToDrl(did, path, openAsTab);\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 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({\n didResolvers : options.didResolvers,\n cache : new DidResolverCacheMemory(),\n });\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 / deep-link handoff (phone path) \u2192 pairing code \u2192 connected, with the\n * in-browser popup path and the wallet catalog folded in as in-place\n * alternates. The modal never chains into a second modal and stays mounted\n * until the session 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\n * clickable QR (joined by a Continue deep-link button on phones; both\n * open the wallet in a new tab so this session stays alive underneath),\n * the pairing-code input, progress, success, and error states.\n * 3. **Footer** \u2014 the wallet identity row (\"Connecting with\" + the selected\n * wallet and the next catalog wallets as tiles), a More tile that expands\n * the remaining wallets as a matching grid (search + custom URL) in\n * place \u2014 a wallet is never shown twice \u2014 and the alternate-method link.\n *\n * Theming: the stylesheet is static and reads `--ec-*` design tokens.\n * Light/dark follows the visitor's system via `prefers-color-scheme` and\n * updates live; the embedding app can force an appearance or override\n * palette tokens through {@link ConnectModalOptions.theme}. Overrides are\n * applied as inline custom properties \u2014 never interpolated into the\n * stylesheet \u2014 so a hostile string can't escape its declaration. The QR\n * card alone is theme-invariant (dark modules on white scan most\n * reliably).\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 { PortableDid } from '@enbox/dids';\nimport type { WalletOption } from '../browser-connect-handler.js';\nimport type { ConnectPermissionRequest, ConnectRequestType, 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/** localStorage key remembering the exact wallet route for each delegate/profile pair. */\nconst SESSION_CHOICES_STORAGE_KEY = 'enbox:connect:sessionChoices';\n\n/** Bounds local reconnect provenance retained by one dapp origin. */\nconst MAX_SESSION_CHOICES = 20;\n\n/**\n * Safety margin subtracted from the relay pointer TTL before re-minting.\n *\n * The pointer is single-use and its TTL starts at mint time, but the wallet\n * only dereferences it after the user scans \u2014 and, on a locked wallet, after\n * they finish the unlock ceremony. A scanned code must therefore carry\n * enough remaining life to absorb that whole window, so re-mint well before\n * the deadline rather than just ahead of it.\n */\nconst REMINT_SAFETY_MS = 120_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/** Catalog size beyond which the wallet switcher shows its search bar. */\nconst WALLET_SEARCH_THRESHOLD = 4; // one full row of tiles\n\n/** Wallet tiles shown in the collapsed identity row (plus the More tile). */\nconst WALLET_ROW_SIZE = 3;\n\n/** Palette overrides for one appearance's design tokens. */\nexport interface ConnectModalPalette {\n /** Modal surface. */\n background?: string;\n\n /** Inset surfaces: tiles, inputs, hover fills. */\n surface?: string;\n\n /** Primary text. */\n text?: string;\n\n /** Secondary text. */\n textMuted?: string;\n\n /** Hairline borders and dividers. */\n border?: string;\n\n /** Brand accent: buttons, links, focus rings, selection. */\n accent?: string;\n\n /** Text/icon color on accent surfaces. */\n accentContrast?: string;\n\n /** Error text and invalid-input borders. */\n danger?: string;\n\n /** Success surfaces (the connected check). */\n success?: string;\n}\n\n/** Optional color scheme provided by the embedding app. */\nexport interface ConnectModalTheme {\n /**\n * Follow the visitor's system appearance (`'auto'`, live-updating) or\n * force one.\n * @default 'auto'\n */\n appearance?: 'auto' | 'light' | 'dark';\n\n /** Brand accent applied in both appearances (per-scheme palettes win). */\n accent?: string;\n\n /** Text/icon color on accent surfaces, in both appearances. */\n accentContrast?: string;\n\n /** Token overrides applied while the light appearance is active. */\n light?: ConnectModalPalette;\n\n /** Token overrides applied while the dark appearance is active. */\n dark?: ConnectModalPalette;\n}\n\n/** Design-token custom property behind each palette key. */\nconst PALETTE_TOKENS: Record<keyof ConnectModalPalette, string> = {\n background : '--ec-bg',\n surface : '--ec-surface',\n text : '--ec-text',\n textMuted : '--ec-muted',\n border : '--ec-border',\n accent : '--ec-accent',\n accentContrast : '--ec-accent-contrast',\n danger : '--ec-danger',\n success : '--ec-success',\n};\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 /** User-facing mode. Absent means a normal connect. */\n mode?: ConnectRequestType;\n\n /** Existing delegate credentials reused by a refresh request. */\n delegatePortableDid?: PortableDid;\n\n /** Preferred method on open; overrides the remembered choice. */\n preferredMethod?: ConnectMethod;\n\n /**\n * Remember the successful method + wallet in localStorage. Refreshes reuse\n * the route saved for their delegate DID; new connections use the latest\n * successful route as a convenience.\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 * Stable application identifier hint available to the wallet during approval.\n * Defaults to the browser's canonical origin.\n */\n applicationId?: string;\n\n /** Wallet profile DID that a refresh must renew. */\n expectedProviderDid?: 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 /**\n * Color scheme. By default the modal follows the visitor's system\n * light/dark appearance; apps can force an appearance and/or override\n * palette tokens per scheme to match their brand.\n */\n theme?: ConnectModalTheme;\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: typeof runPopupConnect;\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 applicationId?: string;\n timeoutMs?: number;\n delegatePortableDid?: PortableDid;\n requestType?: ConnectRequestType;\n expectedProviderDid?: string;\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 applicationId : options.applicationId,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n delegatePortableDid : options.delegatePortableDid,\n requestType : options.requestType,\n expectedProviderDid : options.expectedProviderDid,\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\n/** Stable reconnect provenance for one delegated app session. */\ninterface SessionChoice extends LastChoice {\n delegateDid: string;\n providerDid: 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') && isValidRememberedWalletUrl(parsed.walletUrl)) {\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\nfunction isSessionChoice(value: unknown): value is SessionChoice {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const choice = value as Partial<SessionChoice>;\n return (choice.method === 'phone' || choice.method === 'browser')\n && isValidRememberedWalletUrl(choice.walletUrl)\n && typeof choice.delegateDid === 'string'\n && choice.delegateDid.length > 0\n && typeof choice.providerDid === 'string'\n && choice.providerDid.length > 0;\n}\n\nfunction readSessionChoices(storage: ConnectModalDeps['storage']): SessionChoice[] {\n try {\n const raw = storage?.getItem(SESSION_CHOICES_STORAGE_KEY);\n if (raw === null || raw === undefined) {\n return [];\n }\n const parsed = JSON.parse(raw) as unknown;\n return Array.isArray(parsed) ? parsed.filter(isSessionChoice).slice(-MAX_SESSION_CHOICES) : [];\n } catch {\n return [];\n }\n}\n\nfunction readSessionChoice(\n storage: ConnectModalDeps['storage'],\n delegateDid: string | undefined,\n expectedProviderDid: string | undefined,\n): SessionChoice | undefined {\n if (delegateDid === undefined) {\n return undefined;\n }\n const choices = readSessionChoices(storage);\n for (let index = choices.length - 1; index >= 0; index--) {\n const choice = choices[index];\n if (choice.delegateDid === delegateDid\n && (expectedProviderDid === undefined || choice.providerDid === expectedProviderDid)) {\n return choice;\n }\n }\n return undefined;\n}\n\nfunction writeSessionChoice(storage: ConnectModalDeps['storage'], choice: SessionChoice): void {\n try {\n const choices = readSessionChoices(storage).filter(entry =>\n entry.delegateDid !== choice.delegateDid || entry.providerDid !== choice.providerDid\n );\n choices.push(choice);\n storage?.setItem(SESSION_CHOICES_STORAGE_KEY, JSON.stringify(choices.slice(-MAX_SESSION_CHOICES)));\n } catch { /* best effort */ }\n}\n\nfunction removeSessionChoice(\n storage: ConnectModalDeps['storage'],\n delegateDid: string,\n providerDid: string,\n): void {\n try {\n const choices = readSessionChoices(storage).filter(choice =>\n choice.delegateDid !== delegateDid || choice.providerDid !== providerDid\n );\n if (choices.length === 0) {\n storage?.removeItem(SESSION_CHOICES_STORAGE_KEY);\n } else {\n storage?.setItem(SESSION_CHOICES_STORAGE_KEY, JSON.stringify(choices));\n }\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 * Wraps `settler` so the returned thunk runs it through `settle()`. Defined\n * at module scope \u2014 not as an inline closure inside each render function \u2014\n * so the returned closure is lexically nested one level (inside this\n * function), not several levels inside `runConnectModal()`'s own render\n * closures (Sonar S2004). `settle` and `settler` are threaded through\n * unchanged, so behavior is identical to writing `() => settle(settler)`\n * inline.\n */\nfunction settleWith(settle: (settler: () => void) => void, settler: () => void): () => void {\n return () => settle(settler);\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 if (options.mode === 'refresh' && options.delegatePortableDid === undefined) {\n throw new Error('Connect: refresh requests require an existing `delegatePortableDid`.');\n }\n\n const deps: ConnectModalDeps = { ...defaultDeps(), ...options.deps };\n const wallets = dedupeWalletsByUrl(options.wallets ?? []);\n const rememberChoice = options.rememberChoice ?? true;\n const appName = options.appName ?? window.location.host;\n const applicationId = options.applicationId ?? window.location.origin;\n const isMobile = deps.isMobile();\n const refreshing = options.mode === 'refresh';\n\n const lastChoice = rememberChoice ? readLastChoice(deps.storage) : undefined;\n let savedRoute = rememberChoice && refreshing\n ? readSessionChoice(\n deps.storage,\n options.delegatePortableDid?.uri,\n options.expectedProviderDid,\n )\n : undefined;\n const expectedProviderDid = options.expectedProviderDid ?? savedRoute?.providerDid;\n const relayWalletPath = options.relayWalletPath ?? '/connect/app';\n const savedRouteEscapeLabel = options.walletUrl === undefined\n ? 'Choose another wallet or method'\n : 'Choose another method';\n\n // Refresh routes resolve by delegate first; general preferences remain a\n // best-effort fallback for sessions created before route-aware storage.\n const rememberedWalletUrl = lastChoice !== undefined\n && (refreshing || walletInCatalog(wallets, lastChoice.walletUrl))\n ? lastChoice.walletUrl\n : undefined;\n let walletUrl = savedRoute?.walletUrl\n ?? options.walletUrl\n ?? rememberedWalletUrl\n ?? wallets[0]?.url;\n\n // An exact refresh route wins over generic handler and global preferences.\n let method: ConnectMethod = savedRoute?.method ?? 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 style = document.createElement('style');\n style.textContent = MODAL_STYLES;\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 const title = refreshing ? `Reconnect to ${appName}` : `Connect to ${appName}`;\n modal.setAttribute('aria-label', title);\n\n // \u2500\u2500 Theme \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 // System light/dark is pure CSS (`prefers-color-scheme`), so it tracks\n // the visitor live. A forced appearance pins the token block instead.\n const theme = options.theme ?? {};\n const appearance = theme.appearance ?? 'auto';\n if (appearance !== 'auto') {\n modal.dataset.appearance = appearance;\n }\n\n // Dapp palette overrides land as inline custom properties: setProperty\n // parses each value as a lone declaration, so a hostile string cannot\n // escape into the stylesheet.\n const systemDark = window.matchMedia?.('(prefers-color-scheme: dark)');\n const hasPaletteOverrides = theme.accent !== undefined || theme.accentContrast !== undefined\n || theme.light !== undefined || theme.dark !== undefined;\n const applyPaletteTokens = (): void => {\n const systemScheme = systemDark?.matches === true ? 'dark' : 'light';\n const scheme = appearance === 'auto' ? systemScheme : appearance;\n const palette: ConnectModalPalette = {\n accent : theme.accent,\n accentContrast : theme.accentContrast,\n ...theme[scheme],\n };\n for (const key of Object.keys(PALETTE_TOKENS) as Array<keyof ConnectModalPalette>) {\n const value = palette[key];\n if (typeof value === 'string' && value.trim() !== '') {\n modal.style.setProperty(PALETTE_TOKENS[key], value);\n } else {\n modal.style.removeProperty(PALETTE_TOKENS[key]);\n }\n }\n };\n const onSchemeChange = (): void => applyPaletteTokens();\n if (hasPaletteOverrides) {\n applyPaletteTokens();\n if (appearance === 'auto') {\n systemDark?.addEventListener?.('change', onSchemeChange);\n }\n }\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 remintAt: number | undefined;\n let popupBusy = false;\n let pinResolve: ((pin: string) => void) | undefined;\n // Proxy pinResolve reads/clears for buildPinInputs (module scope), whose\n // per-input closures would otherwise be nested inside renderPin()'s own\n // executor chain too deeply (Sonar S2004).\n const getPinResolve = (): ((pin: string) => void) | undefined => pinResolve;\n const clearPinResolve = (): void => { pinResolve = undefined; };\n const discoveryCache = new Map<string, Promise<string | undefined>>();\n\n // Collapsed identity row: the selected wallet plus the next catalog\n // wallets, never repeating one. Slots stay stable across in-row\n // switches (only the highlight moves); the row recomposes only when a\n // wallet from outside it \u2014 grid pick or custom URL \u2014 becomes selected,\n // which puts that wallet in the first slot.\n let rowWallets: WalletOption[] = [];\n\n /** The catalog entry for `url`, or a synthesized option for custom URLs. */\n const walletByUrl = (url: string): WalletOption =>\n wallets.find((wallet) => wallet.url === url) ?? { name: hostnameOf(url) ?? url, url };\n\n const composeWalletRow = (): void => {\n if (walletUrl === undefined) {\n rowWallets = wallets.slice(0, WALLET_ROW_SIZE);\n return;\n }\n if (rowWallets.some((wallet) => wallet.url === walletUrl)) {\n return;\n }\n const selected = walletByUrl(walletUrl);\n rowWallets = [selected, ...wallets.filter((wallet) => wallet.url !== selected.url)].slice(0, WALLET_ROW_SIZE);\n };\n\n const selectWallet = (url: string): void => {\n walletUrl = url;\n renderFooter();\n void startMethod();\n };\n\n const cleanup = (): void => {\n relaySession?.cancel();\n clearRemint();\n document.removeEventListener('keydown', onKeydown);\n document.removeEventListener('visibilitychange', onVisibilityReturn);\n systemDark?.removeEventListener?.('change', onSchemeChange);\n try { host.remove(); } 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 && walletUrl !== undefined) {\n writeLastChoice(deps.storage, { method, walletUrl });\n writeSessionChoice(deps.storage, {\n delegateDid : result.delegatePortableDid.uri,\n providerDid : result.connectedDid,\n method,\n walletUrl,\n });\n }\n renderConnected();\n setTimeout(settleWith(settle, () => resolve(result)), 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(title, 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 /**\n * Schedules the \"finish in the wallet\" morph after a handoff link is\n * followed. Deferred one tick so the anchor's default new-tab navigation\n * completes before the anchor is replaced, and guarded so a session that\n * moved on meanwhile (re-mint, wallet response, settle) is never\n * overwritten.\n */\n const morphToAway = (walletName: string): void => {\n const session = relaySession;\n setTimeout((): void => {\n if (settled || session !== relaySession || session?.active !== true || pinResolve !== undefined) {\n return;\n }\n renderAway(walletName);\n }, 0);\n };\n\n /**\n * Builds one same-device handoff anchor for the wallet URI. The wallet\n * opens in a new tab so this modal \u2014 and the relay session under it \u2014\n * stays alive, with the pairing-code entry waiting when the user\n * switches back. `noopener` keeps the wallet tab from reaching back into\n * this one.\n */\n const buildHandoffLink = (handoff: WalletUriHandoff, walletName: string, className: string): HTMLAnchorElement => {\n const link = document.createElement('a');\n link.className = className;\n link.href = handoff.walletUri;\n link.target = '_blank';\n link.rel = 'noopener noreferrer';\n link.addEventListener('click', () => { morphToAway(walletName); });\n return link;\n };\n\n const renderQr = (handoff: WalletUriHandoff): void => {\n const wallet = walletUrl !== undefined ? walletByUrl(walletUrl) : undefined;\n const walletName = wallet?.name ?? 'your wallet';\n\n // The QR card is itself a handoff link on every device: opening it on\n // this device runs the exact handshake the camera path runs on another\n // one, and scanning it keeps working either way.\n const qrLink = buildHandoffLink(handoff, walletName, 'qr-box qr-link');\n qrLink.setAttribute('aria-label', `Open ${walletName} on this device`);\n // Fixed colors on the white card: dark-on-light QRs scan reliably in\n // both appearances (inverted codes trip up some camera apps).\n qrLink.replaceChildren(qrToSvg(encodeQr(handoff.walletUri), {\n dark : '#14141f',\n light : 'transparent',\n quietZone : 2,\n }));\n\n // The selected wallet's mark sits at the QR centre \u2014 the \"this is the\n // wallet you're connecting to\" cue. The 44px plate over the ~180px\n // symbol occludes ~5% of modules, well inside ECC level M's 15%\n // recovery budget (the compact variant scales the plate down to\n // match).\n if (wallet !== undefined) {\n const logo = el('div', 'qr-logo');\n logo.appendChild(buildWalletIcon(wallet));\n qrLink.appendChild(logo);\n }\n\n if (isMobile) {\n const link = buildHandoffLink(handoff, walletName, 'deep-link');\n if (wallet !== undefined) {\n link.appendChild(buildWalletIcon(wallet));\n }\n link.appendChild(el('span', 'deep-link-label', `Continue in ${walletName}`));\n\n qrLink.classList.add('compact');\n setStage(\n link,\n el('p', 'stage-subline', `${walletName} opens in a new tab \u2014 approve there, then come back for your code.`),\n el('div', 'stage-divider', 'or scan with another phone'),\n qrLink,\n );\n return;\n }\n\n setStage(\n qrLink,\n el('p', 'stage-caption', 'Scan with your phone\u2019s camera'),\n el('p', 'stage-subline', `${walletName} stays on your phone \u2014 or click the code to open it here.`),\n );\n };\n\n /**\n * Shown once a handoff link is followed on this device: the approval is\n * happening in the wallet tab, this one waits for the code. \"Start over\"\n * mints a fresh pointer \u2014 the right recovery, because the pointer the\n * wallet tab carried away is single-use.\n */\n const renderAway = (walletName: string): void => {\n setStage(\n el('div', 'spinner'),\n el('p', 'stage-caption', `Finish in ${walletName}`),\n el('p', 'stage-subline', isMobile\n ? `Approve the connection in the ${walletName} tab, then come back here for your code.`\n : 'Approve the connection in the tab that just opened, then come back here for your code.'),\n stageLinkButton('Start over', () => { void startPhone(); }),\n );\n };\n\n const renderClaimed = (): void => {\n const walletName = walletUrl !== undefined ? walletByUrl(walletUrl).name : 'your wallet';\n const pulse = document.createElement('div');\n pulse.className = 'claimed-pulse';\n setStage(\n pulse,\n el('p', 'stage-caption', `Request received \u2014 approve in ${walletName}`),\n el('p', 'stage-subline', 'Once you approve, you\u2019ll get a code to enter here.'),\n );\n };\n\n const renderPin = (attempt: number, previousError?: Error): Promise<string> => {\n return new Promise<string>((resolvePin) => {\n pinResolve = resolvePin;\n const walletName = walletUrl !== undefined ? walletByUrl(walletUrl).name : 'your wallet';\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 = buildPinInputs(boxes, getPinResolve, clearPinResolve, renderBusy);\n\n setStage(\n el('p', 'stage-caption', `Enter the code shown in ${walletName}`),\n boxes,\n ...(previousError !== undefined\n ? [el('p', 'stage-error', `That code doesn\u2019t match \u2014 check ${walletName}.`)]\n : [el('p', 'stage-subline', attempt === 1 ? 'This confirms you\u2019re the one approving.' : '')]),\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', settleWith(settle, () => resolve(undefined))),\n );\n };\n\n const escapeSavedRoute = (): void => {\n if (savedRoute === undefined) {\n return;\n }\n\n relaySession?.cancel();\n relaySession = undefined;\n clearRemint();\n removeSessionChoice(deps.storage, savedRoute.delegateDid, savedRoute.providerDid);\n savedRoute = undefined;\n if (options.walletUrl !== undefined) {\n walletUrl = options.walletUrl;\n }\n renderFooter();\n setStage(\n el('p', 'stage-caption', 'Choose another way to reconnect.'),\n el('p', 'stage-subline', 'We\u2019ll still require the same wallet profile used for this session.'),\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 ...(savedRoute !== undefined\n ? [stageLinkButton(savedRouteEscapeLabel, escapeSavedRoute)]\n : []),\n stageLinkButton('Close', settleWith(settle, () => reject(error ?? new Error(`[@enbox/browser] ${message}`)))),\n );\n };\n\n const renderPhoneUnavailable = (): void => {\n if (savedRoute !== undefined) {\n setStage(\n el('p', 'stage-caption', 'Your saved wallet connection is unavailable right now.'),\n el('p', 'stage-subline', 'Try again in a moment to reconnect the same session.'),\n stageButton('Try again', () => { void startPhone(); }),\n stageLinkButton(savedRouteEscapeLabel, escapeSavedRoute),\n );\n return;\n }\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 // The popup surface is a small window on desktop but a new tab on\n // phones \u2014 the copy names whichever the visitor will actually see.\n const popupSurface = isMobile ? 'tab' : 'window';\n\n const renderPopupPrompt = (): void => {\n const walletName = walletUrl !== undefined ? walletByUrl(walletUrl).name : 'your wallet';\n const exactReconnect = savedRoute !== undefined;\n const connectDescription = isMobile\n ? 'Your wallet opens in a new tab to approve this connection \u2014 no code needed.'\n : 'Your wallet opens in a small window to approve this connection.';\n const description = exactReconnect\n ? `We\u2019ll open the same ${walletName} profile used for this session.`\n : connectDescription;\n const connectButtonLabel = isMobile ? 'Open wallet' : 'Open wallet window';\n const buttonLabel = exactReconnect\n ? `Open ${walletName} ${popupSurface}`\n : connectButtonLabel;\n setStage(\n el('p', 'stage-caption', exactReconnect\n ? `Reconnect with ${walletName}`\n : 'Connect with a wallet in this browser'),\n el('p', 'stage-subline', description),\n stageButton(buttonLabel, () => { startPopup(); }),\n );\n };\n\n const renderPopupWaiting = (): void => {\n setStage(\n el('div', 'spinner'),\n el('p', 'stage-caption', `Finish in the wallet ${popupSurface}`),\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 ${popupSurface}.`\n : `The wallet ${popupSurface} was closed.`),\n stageButton(blocked ? 'Open it now' : `Reopen ${popupSurface}`, () => { startPopup(); }),\n ...(savedRoute !== undefined\n ? [stageLinkButton(savedRouteEscapeLabel, escapeSavedRoute)]\n : [stageLinkButton(isMobile ? 'Use a code instead' : 'Use your phone instead', () => { void switchMethod('phone'); })]),\n );\n };\n\n const renderPopupFailure = (error: unknown): void => {\n if (settled) { return; }\n\n const failure = error instanceof Error ? error : new Error(String(error));\n const popupBlocked = /popup blocked/i.test(failure.message);\n if (error instanceof PopupWindowClosedError || popupBlocked) {\n renderPopupInterrupted(popupBlocked);\n return;\n }\n\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 // \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 clearRemint = (): void => {\n clearTimeout(remintTimer);\n remintAt = undefined;\n };\n\n const remintNow = (): void => {\n // Never re-mint once the wallet has responded (pairing in progress).\n if (!settled && pinResolve === undefined && method === 'phone') {\n void startPhone();\n }\n };\n\n const scheduleRemint = (expiresInSeconds: number): void => {\n clearRemint();\n const delay = Math.max(REMINT_MIN_MS, expiresInSeconds * 1_000 - REMINT_SAFETY_MS);\n // The deadline is kept alongside the timer: background tabs (mobile\n // especially) throttle or freeze timers, so the visibility handler\n // re-checks it when the user returns.\n remintAt = Date.now() + delay;\n remintTimer = setTimeout(remintNow, delay);\n };\n\n const startPhone = async (): Promise<void> => {\n relaySession?.cancel();\n clearRemint();\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 applicationId,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n delegatePortableDid : options.delegatePortableDid,\n requestType : options.mode,\n expectedProviderDid,\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 wallet has the request \u2014 stop re-minting (a new pointer\n // would orphan the approval in progress) and show progress.\n clearRemint();\n renderClaimed();\n }\n },\n requestPin: (attempt, previousError): Promise<string> => {\n clearRemint();\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 = async (): Promise<void> => {\n // Synchronous popup open inside the click's call stack.\n relaySession?.cancel();\n clearRemint();\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 popupBusy = true;\n renderPopupWaiting();\n\n // `runPopup(...)` is invoked synchronously (its `window.open` runs before the\n // first `await`), preserving the user-gesture popup open. Awaiting it inside the\n // try means both a synchronous throw (a custom transport) and an async rejection\n // are handled here \u2014 no unhandled promise sits inside the try (Sonar S4822).\n try {\n const result = await deps.runPopup({\n walletUrl,\n permissionRequests : options.permissionRequests,\n appName,\n appIcon : options.appIcon,\n applicationId,\n timeoutMs : options.timeout,\n delegatePortableDid : options.delegatePortableDid,\n requestType : options.mode,\n expectedProviderDid,\n });\n if (settled) { return; }\n if (result === undefined) {\n renderDenied();\n } else {\n succeed(result);\n }\n } catch (error) {\n renderPopupFailure(error);\n } finally {\n popupBusy = false;\n }\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 clearRemint();\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: identity row (+ catalog panel), method link below \u2500\u2500\n const renderFooter = (): void => {\n footer.replaceChildren();\n\n if (savedRoute === undefined && options.walletUrl === undefined) {\n composeWalletRow();\n const switcher = buildWalletSwitcher();\n if (switcher.label !== undefined) {\n footer.appendChild(switcher.label);\n }\n footer.appendChild(switcher.row);\n footer.appendChild(switcher.panel);\n }\n\n const row = document.createElement('div');\n row.className = 'footer-row';\n\n if (method === 'phone' && savedRoute === undefined) {\n const alt = document.createElement('button');\n alt.className = 'footer-link method-link';\n // On a phone both methods open the wallet on this device \u2014 what the\n // popup channel actually buys the visitor is skipping the code.\n alt.textContent = isMobile ? 'Or connect without a code \u2192' : 'No phone? Use this browser \u2192';\n // startPopup runs synchronously in this click handler.\n alt.addEventListener('click', () => { startPopup(); });\n row.appendChild(alt);\n } else if (method === 'browser' && savedRoute === undefined) {\n const alt = document.createElement('button');\n alt.className = 'footer-link method-link';\n alt.textContent = isMobile ? 'Use a code instead \u2192' : 'Use your phone instead \u2192';\n alt.addEventListener('click', () => { void switchMethod('phone'); });\n row.appendChild(alt);\n }\n\n if (row.childElementCount > 0) {\n footer.appendChild(row);\n }\n };\n\n const buildWalletSwitcher = (): { label?: HTMLElement; row: HTMLDivElement; panel: HTMLDivElement } => {\n // Identity row: selected wallet + the next catalog wallets, then the\n // More tile expanding the full catalog in place.\n const row = document.createElement('div');\n row.className = 'wallet-row';\n row.setAttribute('role', 'radiogroup');\n row.setAttribute('aria-label', 'Wallet');\n\n for (const wallet of rowWallets) {\n const tile = document.createElement('button');\n tile.className = 'row-tile';\n tile.title = wallet.description ?? wallet.name;\n tile.setAttribute('role', 'radio');\n const isSelected = wallet.url === walletUrl;\n tile.setAttribute('aria-checked', isSelected ? 'true' : 'false');\n if (isSelected) {\n tile.classList.add('selected');\n }\n tile.appendChild(buildWalletIcon(wallet));\n tile.appendChild(el('span', 'row-tile-name', wallet.name));\n tile.addEventListener('click', () => {\n if (wallet.url !== walletUrl) {\n selectWallet(wallet.url);\n }\n });\n row.appendChild(tile);\n }\n\n const panel = document.createElement('div');\n panel.className = 'wallet-panel';\n panel.hidden = true;\n\n // The panel grid holds only the wallets NOT already visible in the\n // row, so expanding never shows the same wallet twice.\n const gridWallets = wallets.filter((wallet) => !walletInCatalog(rowWallets, wallet.url));\n\n const more = document.createElement('button');\n more.className = 'row-tile more-tile';\n more.title = 'All wallets';\n more.setAttribute('aria-expanded', 'false');\n more.appendChild(el('span', 'more-count', gridWallets.length > 0 ? `+${gridWallets.length}` : '\u22EF'));\n more.appendChild(el('span', 'row-tile-name', 'More'));\n more.addEventListener('click', () => {\n panel.hidden = !panel.hidden;\n more.setAttribute('aria-expanded', panel.hidden ? 'false' : 'true');\n if (!panel.hidden) {\n updateScrollHint();\n }\n });\n row.appendChild(more);\n\n const label = rowWallets.length > 0 ? el('div', 'wallet-row-label', 'Connecting with') : undefined;\n\n // Search filter \u2014 appears once the grid outgrows one row of tiles.\n const tiles: Array<{ wallet: (typeof wallets)[number]; el: HTMLButtonElement }> = [];\n const empty = document.createElement('div');\n empty.className = 'wallet-empty';\n empty.textContent = 'No other wallets match your search.';\n empty.hidden = true;\n\n if (gridWallets.length > WALLET_SEARCH_THRESHOLD) {\n const search = document.createElement('input');\n search.type = 'search';\n search.className = 'wallet-search';\n search.placeholder = 'Search wallets\u2026';\n search.setAttribute('aria-label', 'Search wallets');\n search.addEventListener('input', () => {\n const query = search.value.trim().toLowerCase();\n let visible = 0;\n for (const { wallet, el: tile } of tiles) {\n const match = query === ''\n || wallet.name.toLowerCase().includes(query)\n || wallet.url.toLowerCase().includes(query);\n tile.hidden = !match;\n if (match) { visible += 1; }\n }\n empty.hidden = visible > 0;\n updateScrollHint();\n });\n panel.appendChild(search);\n }\n\n // Tiles matching the identity row, four per row; past three rows the\n // grid scrolls in place, with a bottom fade hinting at more below.\n const scrollWrap = document.createElement('div');\n scrollWrap.className = 'wallet-scroll-wrap';\n scrollWrap.hidden = gridWallets.length === 0;\n const scroll = document.createElement('div');\n scroll.className = 'wallet-scroll';\n const grid = document.createElement('div');\n grid.className = 'wallet-grid';\n\n const updateScrollHint = (): void => {\n const overflowing = scroll.scrollHeight - scroll.clientHeight > 1;\n const atEnd = scroll.scrollTop + scroll.clientHeight >= scroll.scrollHeight - 1;\n scrollWrap.classList.toggle('scroll-hint', overflowing && !atEnd);\n };\n scroll.addEventListener('scroll', updateScrollHint);\n\n for (const wallet of gridWallets) {\n const tile = document.createElement('button');\n tile.className = 'wallet-tile';\n tile.title = wallet.description ?? wallet.name;\n tile.appendChild(buildWalletIcon(wallet));\n const tileName = document.createElement('span');\n tileName.className = 'wallet-tile-name';\n tileName.textContent = wallet.name;\n tile.appendChild(tileName);\n tile.addEventListener('click', () => {\n selectWallet(wallet.url);\n });\n tiles.push({ wallet, el: tile });\n grid.appendChild(tile);\n }\n scroll.appendChild(grid);\n scroll.appendChild(empty);\n scrollWrap.appendChild(scroll);\n panel.appendChild(scrollWrap);\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 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 selectWallet(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 selectWallet(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 return { label, row, panel };\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 // The visitor typically comes back from the wallet tab mid-session.\n const onVisibilityReturn = (): void => {\n if (document.visibilityState !== 'visible' || settled) {\n return;\n }\n\n // Background tabs throttle (or freeze) timers, so a re-mint that came\n // due while the user was away fires now instead of never.\n if (remintAt !== undefined && Date.now() >= remintAt) {\n remintNow();\n return;\n }\n\n // Returning with the code in hand: put the caret in the first empty\n // pairing-code box so they can type it straight away.\n if (pinResolve !== undefined) {\n const inputs = Array.from(shadow.querySelectorAll<HTMLInputElement>('.pin-input'));\n inputs.find((input) => input.value === '')?.focus();\n }\n };\n document.addEventListener('visibilitychange', onVisibilityReturn);\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 isValidRememberedWalletUrl(value: unknown): value is string {\n if (typeof value !== 'string' || value.trim() === '') {\n return false;\n }\n\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/** Drops catalog entries that repeat an earlier wallet's URL. */\nfunction dedupeWalletsByUrl(wallets: WalletOption[]): WalletOption[] {\n return wallets.filter((wallet, index) => wallets.findIndex((candidate) => candidate.url === wallet.url) === index);\n}\n\n/** Compact display form of a wallet URL for the switcher toggle. */\nfunction hostnameOf(url: string | undefined): string | undefined {\n if (url === undefined) {\n return undefined;\n }\n try {\n return new URL(url).hostname;\n } catch {\n return url;\n }\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(titleText: 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 = titleText;\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\n/**\n * Builds the PIN-entry boxes, wires their input/keydown/paste behavior, and\n * returns the input elements in order. Module-level \u2014 `renderPin()`'s own\n * `new Promise` executor already nests two levels deep inside\n * `runConnectModal()`, so a per-input closure defined there would sit too\n * deep for Sonar's S2004 nesting-depth check.\n *\n * `getPinResolve`/`clearPinResolve` proxy the `pinResolve` state kept in\n * `runConnectModal()`'s closure: a completed code needs it read once, then\n * cleared \u2014 in that order, before the busy state renders and the pending\n * promise resolves \u2014 exactly as it was inline.\n */\nfunction buildPinInputs(\n boxes: HTMLDivElement,\n getPinResolve: () => ((pin: string) => void) | undefined,\n clearPinResolve: () => void,\n renderBusy: (message: string) => void,\n): HTMLInputElement[] {\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 const pinResolve = getPinResolve();\n if (code.length === PIN_LENGTH && pinResolve !== undefined) {\n const resolveOnce = pinResolve;\n clearPinResolve();\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 return inputs;\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//\n// One static sheet; every color reads a `--ec-*` token. Light values sit on\n// `.modal`, dark values apply under `prefers-color-scheme` (so the system\n// appearance tracks live) and under a forced `data-appearance`. Dapp\n// palette overrides land as inline custom properties, which outrank all of\n// these \u2014 nothing user-provided is ever concatenated into this string.\n\n/** Light-appearance design tokens. */\nconst LIGHT_TOKENS = `\n --ec-bg: #ffffff;\n --ec-surface: #f5f6f8;\n --ec-text: #17171f;\n --ec-muted: #63636e;\n --ec-border: #e3e4e9;\n --ec-accent: #0a62d0;\n --ec-accent-contrast: #ffffff;\n --ec-danger: #c0392b;\n --ec-success: #1e9e5a;`;\n\n/** Dark-appearance design tokens. */\nconst DARK_TOKENS = `\n --ec-bg: #181822;\n --ec-surface: #23232f;\n --ec-text: #e9e9f0;\n --ec-muted: #9a9aa6;\n --ec-border: #33333f;\n --ec-accent: #58a6ff;\n --ec-accent-contrast: #0b1526;\n --ec-danger: #ff7a7a;\n --ec-success: #43d17c;`;\n\nconst MODAL_STYLES = `\n * { box-sizing: border-box; margin: 0; padding: 0; }\n\n /* Keep the hidden attribute authoritative: author display values (e.g.\n the panel's flex) would otherwise override the UA's [hidden] rule and\n leave \"collapsed\" sections permanently expanded. */\n [hidden] { display: none !important; }\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 padding: 16px;\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 @keyframes claimedPulse {\n 0%, 100% { transform: scale(0.85); opacity: 0.7; }\n 50% { transform: scale(1); opacity: 1; }\n }\n\n .modal {${LIGHT_TOKENS}\n --ec-accent-soft: color-mix(in srgb, var(--ec-accent) 14%, transparent);\n background: var(--ec-bg);\n color: var(--ec-text);\n border-radius: 16px;\n width: 400px;\n max-width: 100%;\n max-height: calc(100vh - 32px);\n overflow-y: auto;\n padding: 16px 20px 12px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);\n animation: slideUp 0.2s ease-out;\n display: flex;\n flex-direction: column;\n }\n @media (prefers-color-scheme: dark) {\n .modal {${DARK_TOKENS}\n }\n }\n .modal[data-appearance='light'] {${LIGHT_TOKENS}\n }\n .modal[data-appearance='dark'] {${DARK_TOKENS}\n }\n\n button, input { font-family: inherit; }\n button:focus-visible, a:focus-visible {\n outline: 2px solid var(--ec-accent);\n outline-offset: 2px;\n }\n\n .header { display: flex; justify-content: space-between; align-items: center; gap: 8px; }\n .header-identity { display: flex; align-items: center; gap: 10px; min-width: 0; }\n .header-icon { border-radius: 6px; flex-shrink: 0; }\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: var(--ec-muted); padding: 4px 8px; border-radius: 8px; line-height: 1;\n flex-shrink: 0;\n }\n .close-btn:hover { color: var(--ec-text); background: var(--ec-surface); }\n\n .stage {\n min-height: 240px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n text-align: center;\n padding: 12px 0 10px;\n }\n .stage.fade-in > * { animation: stageIn 0.15s ease-out; }\n\n .qr-box {\n position: relative;\n width: 200px;\n height: 200px;\n padding: 10px;\n border-radius: 12px;\n background: #ffffff;\n border: 1px solid #e3e4e9;\n }\n .qr-box svg { width: 100%; height: 100%; display: block; }\n\n /* Selected wallet's mark on the QR centre. Like the card, the plate is\n theme-invariant white so the logo sits on a scannable ground. */\n .qr-logo {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 44px;\n height: 44px;\n border-radius: 10px;\n background: #ffffff;\n border: 1px solid #e3e4e9;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .qr-logo .wallet-icon { width: 30px; height: 30px; }\n .qr-logo .wallet-badge { border-radius: 8px; font-size: 15px; }\n\n /* The QR card doubles as the same-device handoff link. */\n a.qr-box { display: block; cursor: pointer; }\n .qr-box.qr-link:hover {\n border-color: var(--ec-accent);\n box-shadow: 0 0 0 3px var(--ec-accent-soft);\n }\n .qr-box.compact { width: 160px; height: 160px; }\n .qr-box.compact .qr-logo { width: 36px; height: 36px; }\n .qr-box.compact .qr-logo .wallet-icon { width: 24px; height: 24px; }\n\n .stage-divider {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n color: var(--ec-muted);\n font-size: 12px;\n }\n .stage-divider::before, .stage-divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: var(--ec-border);\n }\n\n .claimed-pulse {\n width: 64px; height: 64px; border-radius: 50%;\n background: var(--ec-accent-soft); position: relative;\n }\n .claimed-pulse::after {\n content: ''; position: absolute; inset: 18px; border-radius: 50%;\n background: var(--ec-accent);\n animation: claimedPulse 1.6s ease-in-out infinite;\n }\n\n .stage-caption { font-size: 15px; font-weight: 600; }\n .stage-subline { font-size: 13px; color: var(--ec-muted); max-width: 300px; line-height: 1.45; }\n .stage-error { font-size: 13px; color: var(--ec-danger); }\n\n .deep-link {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n width: 100%;\n padding: 13px 16px;\n border-radius: 12px;\n background: var(--ec-accent);\n color: var(--ec-accent-contrast);\n font-weight: 600;\n font-size: 15px;\n text-decoration: none;\n }\n .deep-link .wallet-icon { width: 24px; height: 24px; }\n .deep-link .wallet-badge {\n border-radius: 6px;\n font-size: 12px;\n background: var(--ec-accent-contrast);\n }\n .deep-link .wallet-img { border-radius: 6px; }\n\n .pin-row { display: flex; gap: 10px; }\n .pin-row.shake { animation: shake 0.4s ease-in-out; }\n .pin-input {\n width: 46px; height: 54px;\n text-align: center;\n font-size: 24px; font-weight: 600;\n color: var(--ec-text);\n background: var(--ec-surface);\n border: 1px solid var(--ec-border);\n border-radius: 10px;\n outline: none;\n }\n .pin-input:focus { border-color: var(--ec-accent); }\n\n .check {\n width: 56px; height: 56px;\n display: flex; align-items: center; justify-content: center;\n border-radius: 50%;\n background: var(--ec-success);\n color: #ffffff;\n font-size: 28px;\n }\n\n .spinner {\n width: 32px; height: 32px;\n border-radius: 50%;\n border: 3px solid var(--ec-border);\n border-top-color: var(--ec-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: var(--ec-accent);\n color: var(--ec-accent-contrast);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n }\n .stage-btn:hover { filter: brightness(1.08); }\n\n .footer {\n border-top: 1px solid var(--ec-border);\n padding-top: 8px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .footer-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-wrap: wrap;\n gap: 2px 8px;\n }\n .footer-row > * { min-width: 0; }\n .footer-row > :only-child { margin-inline: auto; }\n\n .footer-link {\n background: none;\n border: none;\n color: var(--ec-muted);\n font-size: 13px;\n cursor: pointer;\n padding: 5px 8px;\n border-radius: 8px;\n }\n .footer-link:hover { color: var(--ec-text); background: var(--ec-surface); }\n .method-link { color: var(--ec-accent); }\n\n .wallet-row-label { font-size: 12px; color: var(--ec-muted); padding: 2px 2px 0; }\n\n .wallet-row {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 8px;\n }\n .row-tile, .wallet-tile {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px 6px;\n min-width: 0;\n background: var(--ec-surface);\n border: 1px solid var(--ec-border);\n border-radius: 12px;\n color: var(--ec-text);\n font-size: 11px;\n cursor: pointer;\n }\n .row-tile:hover, .wallet-tile:hover { border-color: var(--ec-accent); }\n .row-tile.selected {\n border-color: var(--ec-accent);\n background: var(--ec-accent-soft);\n box-shadow: inset 0 0 0 1px var(--ec-accent);\n }\n .row-tile.selected .row-tile-name { font-weight: 600; }\n .row-tile .wallet-icon, .wallet-tile .wallet-icon { width: 28px; height: 28px; }\n .row-tile-name, .wallet-tile-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n .more-tile { color: var(--ec-muted); }\n .more-tile:hover { color: var(--ec-text); }\n .more-tile[aria-expanded='true'] { border-color: var(--ec-accent); }\n .more-count {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 600;\n background: var(--ec-accent-soft);\n color: var(--ec-accent);\n }\n\n .wallet-panel { width: 100%; padding: 4px 0 2px; display: flex; flex-direction: column; gap: 8px; }\n .wallet-search {\n width: 100%; padding: 8px 12px;\n border-radius: 10px; border: 1px solid var(--ec-border); background: transparent;\n color: inherit; font: inherit; font-size: 13px;\n }\n .wallet-search:focus { outline: none; border-color: var(--ec-accent); }\n\n /* Cap the grid at three rows of tiles; past that it scrolls in place,\n and the wrapper's bottom fade hints that more wallets are below. */\n .wallet-scroll-wrap { position: relative; }\n .wallet-scroll { max-height: 220px; overflow-y: auto; }\n .wallet-scroll-wrap.scroll-hint::after {\n content: '';\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n height: 28px;\n background: linear-gradient(to bottom, transparent, var(--ec-bg));\n pointer-events: none;\n }\n .wallet-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 8px;\n }\n\n .wallet-icon { position: relative; width: 28px; height: 28px; flex-shrink: 0; display: inline-flex; }\n .wallet-badge {\n width: 100%; height: 100%; border-radius: 8px; display: inline-flex;\n align-items: center; justify-content: center; font-size: 13px;\n font-weight: 600; background: var(--ec-accent-soft); color: var(--ec-accent);\n }\n .wallet-img { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 8px; object-fit: cover; }\n\n .wallet-empty { padding: 10px 4px; font-size: 12px; color: var(--ec-muted); text-align: center; }\n\n .wallet-custom { display: flex; gap: 6px; }\n .url-input {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid var(--ec-border);\n border-radius: 10px;\n font-size: 13px;\n background: var(--ec-surface);\n color: var(--ec-text);\n outline: none;\n }\n .url-input:focus { border-color: var(--ec-accent); }\n .url-input.invalid { border-color: var(--ec-danger); }\n .url-go {\n padding: 8px 14px;\n border: none;\n border-radius: 10px;\n background: var(--ec-accent);\n color: var(--ec-accent-contrast);\n font-size: 13px;\n cursor: pointer;\n }\n .url-error { font-size: 12px; color: var(--ec-danger); }\n\n @media (prefers-reduced-motion: reduce) {\n .overlay, .modal, .stage.fade-in > *, .pin-row.shake { animation: none; }\n .claimed-pulse::after { animation: none; }\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 { createHandledDeferred } from './handled-deferred.js';\nimport {\n DWEB_CONNECT_ACK_MESSAGE_TYPE,\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/**\n * Grace period after the popup is seen closed for an already-posted response\n * to finish delivery before the close is treated as a denial.\n */\nconst CLOSED_RESPONSE_GRACE_MS = 1_500;\n\n/** Window name given to the wallet popup. */\nconst POPUP_WINDOW_NAME = 'enbox-dweb-connect';\n\n/** Outer size of the wallet popup window. */\nconst POPUP_WIDTH = 500;\nconst POPUP_HEIGHT = 700;\n\n/**\n * Builds the wallet popup's window features, centring it over the opener\n * window \u2014 without `left`/`top` browsers park the popup wherever they like\n * (usually offset into a corner). Falls back to centring on the screen when\n * the opener's metrics are unavailable, and lets the browser clamp\n * off-screen coordinates. Mobile browsers ignore the features entirely and\n * open a tab.\n */\nfunction popupWindowFeatures(): string {\n const base = `width=${POPUP_WIDTH},height=${POPUP_HEIGHT},menubar=no,toolbar=no,location=no,status=no`;\n\n // `screenX`/`outerWidth` describe the opener window; `screen.avail*`\n // describe its monitor \u2014 so the popup lands on the same display.\n const openerWidth = window.outerWidth > 0 ? window.outerWidth : (window.screen?.availWidth ?? 0);\n const openerHeight = window.outerHeight > 0 ? window.outerHeight : (window.screen?.availHeight ?? 0);\n if (openerWidth === 0 || openerHeight === 0) {\n return base;\n }\n\n const left = Math.max(0, Math.round((window.screenX ?? 0) + (openerWidth - POPUP_WIDTH) / 2));\n const top = Math.max(0, Math.round((window.screenY ?? 0) + (openerHeight - POPUP_HEIGHT) / 2));\n return `${base},left=${left},top=${top}`;\n}\n\n/** Guards against calling browser-only entry points outside a browser. */\nfunction assertBrowserEnvironment(): void {\n if (typeof window === 'undefined') {\n throw new TypeError('[@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 readonly _timeoutId?: ReturnType<typeof setTimeout>;\n private readonly _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 readonly _resolveResponse: (payload: string) => void;\n private readonly _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, popupWindowFeatures());\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. Early rejections\n // (timeout, popup closed during load) are pre-marked as handled until\n // the kernel attaches its own handlers via `awaitResponse()`.\n const response = createHandledDeferred<string>();\n this._responsePromise = response.promise;\n this._resolveResponse = response.resolve;\n this._rejectResponse = response.reject;\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 /**\n * {@inheritDoc ConnectTransport.confirmComplete}\n *\n * Posts the payload-less ack to the wallet popup (pinned `targetOrigin`)\n * so a wallet still holding its \"finishing up\" screen can flip to a\n * confirmed \"connected\" state before closing itself. A popup the user\n * already closed is skipped silently.\n */\n public async confirmComplete(): Promise<void> {\n if (this._popup.closed === true) { return; }\n this._popup.postMessage({ type: DWEB_CONNECT_ACK_MESSAGE_TYPE }, this._walletOrigin);\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. A wallet that posts its\n // response and immediately closes itself can lose the race between that\n // final message and this poll \u2014 especially when this page was\n // backgrounded (mobile tabs) and both signals arrive together on\n // resume \u2014 so give a queued response a grace window before treating the\n // close as a user denial.\n clearInterval(this._closedPollId);\n setTimeout((): void => {\n if (this._settled) { return; }\n this._settled = true;\n this.cleanup();\n this._resolveResponse(CONNECT_DENIED_TOKEN);\n }, CLOSED_RESPONSE_GRACE_MS);\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 * Internal deferred-promise helper for the DWeb Connect transports.\n *\n * @module\n */\n\n/** A promise paired with its `resolve`/`reject` settlers. */\nexport type HandledDeferred<T> = {\n /** The deferred promise. Rejections are pre-marked as handled. */\n promise: Promise<T>;\n\n /** Resolves {@link HandledDeferred.promise}. */\n resolve: (value: T) => void;\n\n /** Rejects {@link HandledDeferred.promise}. */\n reject: (error: Error) => void;\n};\n\n/**\n * Creates a promise alongside its `resolve`/`reject` settlers, with rejections\n * pre-marked as handled \u2014 so a rejection that settles the promise before any\n * consumer attaches handlers (e.g. a timeout firing first) never surfaces as\n * an unhandled rejection.\n */\nexport function createHandledDeferred<T>(): HandledDeferred<T> {\n let resolve!: (value: T) => void;\n let reject!: (error: Error) => void;\n\n // The executor runs synchronously, so `resolve`/`reject` are assigned\n // before the function returns.\n const promise = new Promise<T>((res, rej): void => {\n resolve = res;\n reject = rej;\n });\n promise.catch((): undefined => undefined);\n\n return { promise, resolve, reject };\n}\n", "/**\n * Wire shapes for the DWeb Connect popup/postMessage channel.\n *\n * The dapp and the wallet exchange exactly four 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 * 4. `ack` (dapp \u2192 wallet): payload-less completion signal \u2014 the dapp opened\n * the response successfully, so the wallet can flip to a confirmed\n * \"connected\" state before closing itself. Optional and observational;\n * wallets unaware of it simply ignore the message.\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/** Message type of the dapp's completion acknowledgement (dapp \u2192 wallet). */\nexport const DWEB_CONNECT_ACK_MESSAGE_TYPE = 'enbox-connect-ack';\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 * The dapp's completion acknowledgement: it opened the wallet's response\n * successfully. Carries no payload by design.\n */\nexport type DWebConnectAckMessage = {\n type: typeof DWEB_CONNECT_ACK_MESSAGE_TYPE;\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 const version = selectVersion(data.length);\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 const codewords = buildDataCodewords(data, version);\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 mask = selectBestMask(modules, isFunction);\n }\n\n applyMask(modules, isFunction, mask);\n drawFormatBits(modules, isFunction, mask);\n\n return { size, modules, version, mask };\n}\n\n/**\n * Smallest version (1\u2013{@link MAX_VERSION}) whose level-M byte-mode capacity\n * fits a `dataLength`-byte payload plus its mode/char-count header; `0` if\n * none fits.\n */\nfunction selectVersion(dataLength: number): number {\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 + dataLength * 8 <= capacityBits) {\n return candidate;\n }\n }\n return 0;\n}\n\n/**\n * Builds the packed data codewords for `data` at `version`: mode indicator,\n * char count, byte data, terminator, byte-alignment padding, and the\n * alternating pad-byte fill up to the version's level-M data capacity.\n */\nfunction buildDataCodewords(data: Uint8Array, version: number): Uint8Array {\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 let padIndex = 0;\n while (bits.length < capacityBits) {\n pushBits(padBytes[padIndex], 8);\n padIndex ^= 1; // alternate the two pad bytes\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 return codewords;\n}\n\n/** Applies each of the 8 mask patterns, scores it, and returns the lowest-penalty mask index. */\nfunction selectBestMask(modules: boolean[][], isFunction: boolean[][]): number {\n let bestMask = 0;\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 bestMask = candidate;\n }\n applyMask(modules, isFunction, candidate); // undo (XOR is involutive)\n }\n return bestMask;\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 // Visit columns in right-to-left pairs, shifting one column left of the\n // vertical timing column (index 6) so it is skipped \u2014 without mutating the\n // loop counter (Sonar S2310). `size` is always odd, so `right` is always\n // even and `right - 1` maps 6\u21925, 4\u21923, 2\u21921, matching the original traversal.\n const rightCol = right <= 6 ? right - 1 : right;\n bitIndex = placeColumnPairBits(modules, isFunction, codewords, rightCol, size, bitIndex);\n }\n}\n\n/**\n * Places codeword bits into the zig-zag column pair (`rightCol`,\n * `rightCol - 1`) top-to-bottom or bottom-to-top per {@link zigZagCoordinate},\n * starting at `bitIndex`; returns the updated bit index.\n */\nfunction placeColumnPairBits(\n modules: boolean[][],\n isFunction: boolean[][],\n codewords: Uint8Array,\n rightCol: number,\n size: number,\n bitIndex: number,\n): number {\n for (let vertical = 0; vertical < size; vertical++) {\n for (let j = 0; j < 2; j++) {\n const { x, y } = zigZagCoordinate(rightCol, vertical, j, size);\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 return bitIndex;\n}\n\n/** Module coordinate for column-pair `rightCol`, row `vertical`, sub-column `j` (0 = right, 1 = left). */\nfunction zigZagCoordinate(rightCol: number, vertical: number, j: number, size: number): { x: number; y: number } {\n const x = rightCol - j;\n const upward = ((rightCol + 1) & 2) === 0;\n const y = upward ? size - 1 - vertical : vertical;\n return { x, y };\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\n/** N1: runs of \u22655 same-colour modules in a row/column. */\nfunction penaltyAdjacentRuns(modules: boolean[][], size: number): number {\n let penalty = 0;\n\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 return penalty;\n}\n\n/** N2: 2\u00D72 blocks of the same colour. */\nfunction penaltyBlocks(modules: boolean[][], size: number): number {\n let penalty = 0;\n\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 return penalty;\n}\n\n/** Checks `line` for a 1:1:3:1:1 finder-like core starting at `start`, scoring a 4-module light flank on either side. */\nfunction 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/** N3: finder-like 1:1:3:1:1 patterns with 4-module light flank. */\nfunction penaltyFinderPatterns(modules: boolean[][], size: number): number {\n let penalty = 0;\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 return penalty;\n}\n\n/** N4: dark-module proportion deviation from 50%, in 5% steps. */\nfunction penaltyDarkRatio(modules: boolean[][], size: number): number {\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 return k * 10;\n}\n\nfunction computePenalty(modules: boolean[][]): number {\n const size = modules.length;\n let penalty = 0;\n\n penalty += penaltyAdjacentRuns(modules, size);\n penalty += penaltyBlocks(modules, size);\n penalty += penaltyFinderPatterns(modules, size);\n penalty += penaltyDarkRatio(modules, size);\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 { PortableDid } from '@enbox/dids';\nimport type {\n ConnectClientMetadata,\n ConnectPermissionRequest,\n ConnectRequest,\n ConnectRequestType,\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 resolveDelegatePortableDid,\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 /** Stable application identifier hint available to the wallet during approval. */\n applicationId?: 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 /** Existing delegate credentials reused by a refresh request. */\n delegatePortableDid?: PortableDid;\n\n /** User-facing request purpose. Absent means a normal connect. */\n requestType?: ConnectRequestType;\n\n /** Wallet profile DID that a refresh must renew. */\n expectedProviderDid?: string;\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>;\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 signal?: AbortSignal;\n }) => Pick<RelayClientTransport, 'requestProfile' | 'deliverRequest' | 'awaitResponse' | 'requiresPin'>\n & Partial<Pick<RelayClientTransport, 'confirmComplete'>>;\n}\n\n/**\n * Sleep used between relay polls that ends early when the page returns to\n * the foreground. Browsers throttle \u2014 and mobile browsers freeze \u2014 timers in\n * background tabs, so a plain interval sleep can leave the user staring at a\n * stale stage after approving in the wallet tab; cutting the sleep short on\n * `visibilitychange` makes the next poll (and with it the pairing-code\n * prompt) land the moment they switch back. Falls back to a plain sleep\n * outside DOM environments.\n */\nexport function visibilityAwareSleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n if (typeof document === 'undefined') {\n setTimeout(resolve, ms);\n return;\n }\n\n const finish = (): void => {\n clearTimeout(timer);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n resolve();\n };\n const onVisibilityChange = (): void => {\n if (document.visibilityState === 'visible') {\n finish();\n }\n };\n const timer = setTimeout(finish, ms);\n document.addEventListener('visibilitychange', onVisibilityChange);\n });\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 if (options.requestType === 'refresh' && options.delegatePortableDid === undefined) {\n throw new Error('Connect: refresh requests require an existing `delegatePortableDid`.');\n }\n\n const createTransport = options.createTransport\n ?? ((transportOptions): RelayClientTransport => new RelayClientTransport({\n ...transportOptions,\n sleep: visibilityAwareSleep,\n }));\n\n const cancellationController = options.cancelled === undefined ? undefined : new AbortController();\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 signal : cancellationController?.signal,\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 applicationId : options.applicationId,\n clientMetadata : options.clientMetadata,\n permissionRequests : options.permissionRequests,\n delegateDid : options.delegatePortableDid?.uri,\n requestType : options.requestType,\n expectedProviderDid : options.expectedProviderDid,\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 let responseCiphertext: string;\n try {\n responseCiphertext = await race;\n } catch (error) {\n cancellationController?.abort();\n throw error;\n }\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 const outcome = await attemptPinOpen({\n responseCiphertext,\n responsePrivateKey,\n clientDid : clientDid.uri,\n nonce,\n state,\n pin,\n expectedProviderDid : options.expectedProviderDid,\n delegatePortableDid : options.delegatePortableDid,\n confirmComplete : transport.confirmComplete?.bind(transport),\n });\n if (outcome.matched) {\n return outcome.result;\n }\n lastError = outcome.error;\n }\n\n throw new Error(`[@enbox/browser] The pairing code did not match after ${MAX_PIN_ATTEMPTS} attempts.`);\n}\n\n/** One PIN attempt's outcome: either the delegated credentials, or a retryable failure. */\ntype PinAttemptOutcome =\n | { matched: true; result: ConnectResult }\n | { matched: false; error: Error };\n\n/**\n * Opens `responseCiphertext` with one PIN attempt and, on success, resolves\n * the delegated credentials and fires the best-effort completion signal.\n * Kernel value-check failures (`'Connect:'`-prefixed) are structural, not a\n * mistyped code, so they rethrow instead of reporting a mismatch \u2014 the\n * retry loop in {@link runRelayConnect} treats that as fatal.\n */\nasync function attemptPinOpen(params: {\n responseCiphertext: string;\n responsePrivateKey: Jwk;\n clientDid: string;\n nonce: string;\n state: string;\n pin: string;\n expectedProviderDid: string | undefined;\n delegatePortableDid: PortableDid | undefined;\n confirmComplete: (() => Promise<void>) | undefined;\n}): Promise<PinAttemptOutcome> {\n try {\n const response = await openResponse({\n jwe : params.responseCiphertext,\n recipientPrivateKey : params.responsePrivateKey,\n expected : {\n clientDid : params.clientDid,\n nonce : params.nonce,\n state : params.state,\n providerDid : params.expectedProviderDid,\n },\n pin: params.pin,\n });\n\n const delegatePortableDid = resolveDelegatePortableDid({\n localDelegatePortableDid: params.delegatePortableDid,\n response,\n });\n\n // Best-effort completion signal so the wallet can flip its pairing\n // screen to a confirmed \"connected\" state instead of leaving the user\n // to dismiss it blind. Fire-and-forget \u2014 mirrors the kernel client.\n params.confirmComplete?.().catch((): undefined => undefined);\n\n return {\n matched : true,\n result : {\n delegatePortableDid,\n delegateGrants : response.delegateGrants,\n connectedDid : response.providerDid,\n sessionRevocations : response.sessionRevocations,\n },\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 return { matched: false, error: failure };\n }\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 { PortableDid } from '@enbox/dids';\nimport type { ConnectHandler, ConnectResult } from '@enbox/auth';\nimport type { ConnectPermissionRequest, ConnectRequestType } from '@enbox/connect';\n\nimport { runConnectModal } from './ui/connect-modal.js';\n\nimport type { ConnectMethod, ConnectModalTheme } 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 : 'Sumi',\n url : 'https://sumi-wallet.pages.dev',\n description : 'A refined home for your digital identity',\n },\n {\n name : 'Taffy',\n url : 'https://taffy-wallet.pages.dev',\n description : 'A playful take on your digital identity',\n },\n {\n name : 'Astoria',\n url : 'https://astoria-wallet.pages.dev',\n description : 'A grand home for your digital identity',\n },\n {\n name : 'Quay',\n url : 'https://quay-id.pages.dev',\n description : 'A safe harbor for your digital identity',\n },\n {\n name : 'Quoin',\n url : 'https://quoin-id.pages.dev',\n description : 'A cornerstone 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 * Stable application identifier hint available to the wallet during approval.\n * Defaults to the browser's canonical origin.\n */\n applicationId?: 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. Refreshes reuse\n * the route saved for their delegate DID; new connections use the latest\n * successful route as a convenience.\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 * Color scheme for the connect modal. By default it follows the\n * visitor's system light/dark appearance; apps can force an appearance\n * and/or override palette tokens (accent, surfaces, text) per scheme to\n * match their brand.\n */\n theme?: ConnectModalTheme;\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 applicationId,\n preferredMethod,\n rememberChoice,\n connectServerUrl,\n relayWalletPath,\n theme,\n } = options;\n\n return {\n async requestAccess(params: {\n permissionRequests: ConnectPermissionRequest[];\n delegatePortableDid?: PortableDid;\n requestType?: ConnectRequestType;\n expectedProviderDid?: string;\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 applicationId,\n connectServerUrl,\n relayWalletPath,\n timeout,\n theme,\n mode : params.requestType,\n delegatePortableDid : params.delegatePortableDid,\n expectedProviderDid : params.expectedProviderDid,\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`. `sendResponseAwaitingAck()` does the\n * same but stays alive briefly for the dapp's completion ack, so the\n * wallet can show a confirmed \"connected\" state before closing itself.\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 { createHandledDeferred } from './handled-deferred.js';\nimport {\n DWEB_CONNECT_ACK_MESSAGE_TYPE,\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/** Default budget for awaiting the dapp's completion ack after a response. */\nconst DEFAULT_ACK_TIMEOUT_MS = 5_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 _closed = false;\n private _requestReceived = false;\n private _requestSettled = false;\n private readonly _timeoutId?: ReturnType<typeof setTimeout>;\n private _messageListener?: (event: MessageEvent) => void;\n private _resolveAck?: (acked: boolean) => void;\n\n private readonly _requestPromise: Promise<ConnectRequest>;\n private readonly _resolveRequest: (request: ConnectRequest) => void;\n private readonly _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 // Early rejections (timeout before `awaitRequest()` is called) are\n // pre-marked as handled until the wallet attaches its own handlers.\n const request = createHandledDeferred<ConnectRequest>();\n this._requestPromise = request.promise;\n this._resolveRequest = request.resolve;\n this._rejectRequest = request.reject;\n\n this._messageListener = (event: MessageEvent): void => { this.onMessage(event); };\n window.addEventListener('message', this._messageListener);\n\n this._timeoutId = setTimeout((): void => {\n this.settleRequest(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 TypeError('[@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 try {\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 } catch (error) {\n transport.close();\n throw error;\n }\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.assertOpen();\n try {\n this.postResponse(idToken);\n } finally {\n this.close();\n }\n }\n\n /**\n * Posts the sealed response JWE back to the dapp like\n * {@link sendResponse}, then keeps the channel open briefly for the dapp's\n * completion ack \u2014 the signal that it opened the response successfully \u2014\n * before closing the transport.\n *\n * Lets the wallet's connect page show a confirmed \"connected\" state (and\n * close itself with confidence) instead of asking the user to dismiss the\n * screen blind. Dapps predating the ack simply never send one, so the\n * wallet should keep a manual dismiss affordance for the `false` case.\n *\n * @param idToken - The sealed response JWE.\n * @param options - The awaiting options.\n * @param options.timeoutMs - Ack budget in milliseconds; defaults to 5 s.\n * @returns Whether the dapp acknowledged completion within the budget.\n */\n public async sendResponseAwaitingAck(idToken: string, options: { timeoutMs?: number } = {}): Promise<boolean> {\n this.assertOpen();\n if (this._resolveAck !== undefined) {\n throw new Error('[@enbox/browser] A connect response is already awaiting acknowledgement.');\n }\n\n const ackPromise = new Promise<boolean>((resolve): void => {\n this._resolveAck = resolve;\n });\n\n let ackTimeoutId: ReturnType<typeof setTimeout> | undefined;\n try {\n this.postResponse(idToken);\n\n ackTimeoutId = setTimeout((): void => {\n this._resolveAck?.(false);\n }, options.timeoutMs ?? DEFAULT_ACK_TIMEOUT_MS);\n\n return await ackPromise;\n } finally {\n clearTimeout(ackTimeoutId);\n this.close();\n }\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 /**\n * Stops listening and releases the session's timers. A request or response\n * acknowledgement still pending at close is settled immediately. Idempotent.\n */\n public close(): void {\n if (this._closed) { return; }\n this._closed = true;\n clearTimeout(this._timeoutId);\n if (this._messageListener !== undefined) {\n window.removeEventListener('message', this._messageListener);\n this._messageListener = undefined;\n }\n\n if (!this._requestSettled) {\n this._requestSettled = true;\n this._rejectRequest(new Error('[@enbox/browser] Wallet connect transport closed before receiving a request.'));\n }\n const resolveAck = this._resolveAck;\n this._resolveAck = undefined;\n resolveAck?.(false);\n }\n\n private onMessage(event: MessageEvent): void {\n if (this._closed) { return; }\n const message = getTrustedMessage(event, this._dappOrigin, this._dappWindow);\n if (message === undefined) { return; }\n\n if (message.type === DWEB_CONNECT_ACK_MESSAGE_TYPE) {\n this._resolveAck?.(true);\n return;\n }\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 if (this._requestSettled) { return; }\n this._requestSettled = true;\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 private assertOpen(): void {\n if (this._closed) {\n throw new Error('[@enbox/browser] Wallet connect transport is closed.');\n }\n }\n\n private postResponse(idToken: string): void {\n this._dappWindow.postMessage({\n type : DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n payload : idToken,\n }, this._dappOrigin);\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", "export type ObjectUrlLease = Readonly<{\n url: string;\n /** Release immediately, cancelling any deferred release. Idempotent. */\n release(): void;\n /** Release after a grace period. The first deferred release wins. */\n releaseAfter(delayMs: number): void;\n}>;\n\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n\nfunction assertReleaseDelay(delayMs: number): void {\n if (!Number.isSafeInteger(delayMs) || delayMs < 0 || delayMs > MAX_TIMER_DELAY_MS) {\n throw new TypeError(`delayMs must be an integer between 0 and ${MAX_TIMER_DELAY_MS}.`);\n }\n}\n\n/** Private reference-counted ownership for one object URL. */\nexport class ObjectUrlReference {\n public readonly url: string;\n private _isRevoked = false;\n private _references = 0;\n private readonly _releaseTimers = new Set<ReturnType<typeof setTimeout>>();\n\n public constructor(blob: Blob, private readonly _onEmpty: (reference: ObjectUrlReference) => void) {\n this.url = globalThis.URL.createObjectURL(blob);\n }\n\n public get references(): number {\n return this._references;\n }\n\n public acquire(): ObjectUrlLease {\n if (this._isRevoked) {\n throw new Error('Object URL has been revoked.');\n }\n\n this._references += 1;\n let released = false;\n let releaseTimer: ReturnType<typeof setTimeout> | undefined;\n const release = (): void => {\n if (released) {\n return;\n }\n released = true;\n if (releaseTimer !== undefined) {\n clearTimeout(releaseTimer);\n this._releaseTimers.delete(releaseTimer);\n }\n if (this._isRevoked) {\n return;\n }\n this._references -= 1;\n if (this._references === 0) {\n this._onEmpty(this);\n }\n };\n return Object.freeze({\n url : this.url,\n release,\n releaseAfter : (delayMs: number): void => {\n assertReleaseDelay(delayMs);\n if (released || this._isRevoked || releaseTimer !== undefined) {\n return;\n }\n releaseTimer = setTimeout(release, delayMs);\n this._releaseTimers.add(releaseTimer);\n },\n });\n }\n\n public revoke(): void {\n if (!this._isRevoked) {\n this._isRevoked = true;\n for (const timer of this._releaseTimers) {\n clearTimeout(timer);\n }\n this._releaseTimers.clear();\n this._references = 0;\n globalThis.URL.revokeObjectURL(this.url);\n }\n }\n}\n", "import type { ObjectUrlLease } from './object-url-reference.js';\n\nimport { ObjectUrlReference } from './object-url-reference.js';\n\n/**\n * A reference-counted lease for a browser object URL.\n *\n * When replacing a URL already rendered by the DOM, `releaseAfter()` provides\n * a grace period without passing the lease through the component tree.\n */\nexport type BlobUrlLease = ObjectUrlLease;\n\n/** Owns object URLs for Blob identities until their last lease is released. */\nexport interface BlobUrlPool {\n acquire(blob: Blob): BlobUrlLease;\n dispose(): void;\n}\n\nclass DefaultBlobUrlPool implements BlobUrlPool {\n private readonly _references = new Map<Blob, ObjectUrlReference>();\n private _isDisposed = false;\n\n public acquire(blob: Blob): BlobUrlLease {\n if (this._isDisposed) {\n throw new Error('BlobUrlPool is disposed.');\n }\n\n let reference = this._references.get(blob);\n if (reference === undefined) {\n reference = new ObjectUrlReference(blob, (released): void => {\n this._references.delete(blob);\n released.revoke();\n });\n this._references.set(blob, reference);\n }\n return reference.acquire();\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n this._isDisposed = true;\n for (const reference of this._references.values()) {\n reference.revoke();\n }\n this._references.clear();\n }\n}\n\n/** Create a terminally disposable, reference-counted object URL pool. */\nexport function createBlobUrlPool(): BlobUrlPool {\n return new DefaultBlobUrlPool();\n}\n", "import type { FileEnvelopeData } from '@enbox/api';\n\nimport type { BlobUrlLease } from './blob-url-pool.js';\n\nimport { ObjectUrlReference } from './object-url-reference.js';\n\nconst DEFAULT_MAX_BYTES = 128 * 1024 * 1024;\nconst DEFAULT_MAX_ENTRIES = 50;\n\ntype CacheEntry = {\n bytes: number;\n filename: string;\n key: string;\n mimeType: string;\n url: ObjectUrlReference;\n};\n\ntype PendingRead = {\n controller: AbortController;\n generation: number;\n promise: Promise<CacheEntry | undefined>;\n};\n\n/** A cached file envelope represented by a leased browser object URL. */\nexport type FileEnvelopeUrlLease = BlobUrlLease & Readonly<{\n filename: string;\n mimeType: string;\n}>;\n\nexport type FileEnvelopeUrlStoreOptions<Request> = Readonly<{\n /** Select the stable cache key for a read request. */\n key(request: Request): string;\n /** Read and decode the file. The signal aborts invalidated work. */\n read(request: Request, signal: AbortSignal): Promise<FileEnvelopeData | undefined>;\n /** Choose the Blob exposed by the URL, retaining MIME/render policy in the caller. */\n blobForUrl(value: FileEnvelopeData): Blob;\n /** Maximum cached entries (default 50). Soft while every eviction candidate is leased. */\n maxEntries?: number;\n /** Maximum cached Blob bytes (default 128 MiB). Soft while every eviction candidate is leased. */\n maxBytes?: number;\n}>;\n\n/** A keyed, bounded object URL cache for decoded file envelopes. */\nexport interface FileEnvelopeUrlStore<Request> {\n acquire(request: Request): Promise<FileEnvelopeUrlLease | undefined>;\n acquireCached(request: Request): FileEnvelopeUrlLease | undefined;\n clear(): void;\n dispose(): void;\n invalidate(request: Request): void;\n}\n\nfunction assertLimit(value: number, name: string): void {\n if (value !== Infinity && (!Number.isSafeInteger(value) || value < 0)) {\n throw new TypeError(`${name} must be a non-negative safe integer or Infinity.`);\n }\n}\n\nfunction throwAborted(controller: AbortController): never {\n controller.abort();\n throw controller.signal.reason;\n}\n\nclass DefaultFileEnvelopeUrlStore<Request> implements FileEnvelopeUrlStore<Request> {\n private readonly _cache = new Map<string, CacheEntry>();\n private readonly _entries = new Set<CacheEntry>();\n private readonly _maxBytes: number;\n private readonly _maxEntries: number;\n private readonly _pending = new Map<string, PendingRead>();\n private _bytes = 0;\n private _generation = 0;\n private _isDisposed = false;\n\n public constructor(private readonly _options: FileEnvelopeUrlStoreOptions<Request>) {\n this._maxBytes = _options.maxBytes ?? DEFAULT_MAX_BYTES;\n this._maxEntries = _options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n assertLimit(this._maxBytes, 'maxBytes');\n assertLimit(this._maxEntries, 'maxEntries');\n }\n\n public async acquire(request: Request): Promise<FileEnvelopeUrlLease | undefined> {\n this._assertActive();\n const key = this._options.key(request);\n const cached = this._cache.get(key);\n if (cached !== undefined) {\n return this._acquire(cached);\n }\n\n const pending = this._pending.get(key) ?? this._startRead(request, key);\n const entry = await pending.promise;\n if (this._isDisposed || pending.generation !== this._generation) {\n return throwAborted(pending.controller);\n }\n if (entry === undefined) {\n return undefined;\n }\n if (this._cache.get(key) !== entry) {\n return throwAborted(pending.controller);\n }\n return this._acquire(entry);\n }\n\n public acquireCached(request: Request): FileEnvelopeUrlLease | undefined {\n this._assertActive();\n const entry = this._cache.get(this._options.key(request));\n return entry === undefined ? undefined : this._acquire(entry);\n }\n\n public invalidate(request: Request): void {\n this._assertActive();\n const key = this._options.key(request);\n const pending = this._pending.get(key);\n pending?.controller.abort();\n this._pending.delete(key);\n const entry = this._cache.get(key);\n if (entry !== undefined) {\n this._remove(entry);\n }\n }\n\n public clear(): void {\n this._assertActive();\n this._reset(false);\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n this._isDisposed = true;\n this._reset(true);\n }\n\n private _abortReads(): void {\n for (const pending of this._pending.values()) {\n pending.controller.abort();\n }\n this._pending.clear();\n }\n\n private _acquire(entry: CacheEntry): FileEnvelopeUrlLease {\n this._cache.delete(entry.key);\n this._cache.set(entry.key, entry);\n const lease = entry.url.acquire();\n this._evict();\n return Object.freeze({\n filename : entry.filename,\n mimeType : entry.mimeType,\n release : lease.release,\n releaseAfter : lease.releaseAfter,\n url : lease.url,\n });\n }\n\n private _assertActive(): void {\n if (this._isDisposed) {\n throw new Error('FileEnvelopeUrlStore is disposed.');\n }\n }\n\n private _assertCurrent(key: string, controller: AbortController, generation: number): void {\n if (\n this._isDisposed\n || controller.signal.aborted\n || this._generation !== generation\n || this._pending.get(key)?.controller !== controller\n ) {\n throwAborted(controller);\n }\n }\n\n private _evict(): void {\n while (this._cache.size > this._maxEntries || this._bytes > this._maxBytes) {\n const entry = [...this._cache.values()].find((candidate): boolean => candidate.url.references === 0);\n if (entry === undefined) {\n return;\n }\n this._remove(entry);\n }\n }\n\n private async _load(request: Request, key: string, controller: AbortController, generation: number): Promise<CacheEntry | undefined> {\n const value = await this._options.read(request, controller.signal);\n this._assertCurrent(key, controller, generation);\n if (value === undefined) {\n return undefined;\n }\n\n const blob = this._options.blobForUrl(value);\n this._assertCurrent(key, controller, generation);\n const url = new ObjectUrlReference(blob, (): void => this._released(entry));\n const entry: CacheEntry = {\n bytes : blob.size,\n filename : value.filename,\n key,\n mimeType : value.mimeType,\n url,\n };\n this._cache.set(key, entry);\n this._bytes += entry.bytes;\n this._entries.add(entry);\n return entry;\n }\n\n private _released(entry: CacheEntry): void {\n if (this._cache.get(entry.key) !== entry) {\n this._revoke(entry);\n } else {\n this._evict();\n }\n }\n\n private _remove(entry: CacheEntry): void {\n if (this._cache.get(entry.key) !== entry) {\n return;\n }\n this._cache.delete(entry.key);\n this._bytes -= entry.bytes;\n if (entry.url.references === 0) {\n this._revoke(entry);\n }\n }\n\n private _reset(revokeActive: boolean): void {\n this._generation += 1;\n this._abortReads();\n this._cache.clear();\n this._bytes = 0;\n for (const entry of this._entries) {\n if (revokeActive || entry.url.references === 0) {\n this._revoke(entry);\n }\n }\n }\n\n private _revoke(entry: CacheEntry): void {\n entry.url.revoke();\n this._entries.delete(entry);\n }\n\n private _startRead(request: Request, key: string): PendingRead {\n const controller = new AbortController();\n const generation = this._generation;\n const promise = this._load(request, key, controller, generation).finally((): void => {\n if (this._pending.get(key)?.controller === controller) {\n this._pending.delete(key);\n }\n });\n const pending = { controller, generation, promise };\n this._pending.set(key, pending);\n return pending;\n }\n}\n\n/** Create a bounded file-envelope URL store with deduplicated reads. */\nexport function createFileEnvelopeUrlStore<Request>(\n options: FileEnvelopeUrlStoreOptions<Request>,\n): FileEnvelopeUrlStore<Request> {\n return new DefaultFileEnvelopeUrlStore(options);\n}\n"],
|
|
5
|
+
"mappings": "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EbC,EAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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",
|
|
6
|
+
"names": ["CONNECT_DENIED_TOKEN", "ConnectProvider", "DidDht", "DidResolverCacheMemory", "DidWeb", "resolveDwnEndpointStatus", "UniversalResolver", "parseDrlUrl", "url", "idx", "prefix", "rest", "slashIdx", "didResolver", "UniversalResolver", "DidDht", "DidWeb", "DidResolverCacheMemory", "httpToHttpsRegex", "trailingSlashRegex", "DRL_CACHE_NAME", "getDwnEndpoints", "did", "result", "resolveDwnEndpointStatus", "openDrlCache", "handleEvent", "event", "path", "options", "drl", "responseCache", "cachedResponse", "match", "cacheTime", "fetchResource", "response", "error", "endpoints", "lastError", "endpoint", "url", "cacheResponse", "cache", "clonedResponse", "headers", "modifiedResponse", "installWorker", "workerSelf", "parsed", "parseDrlUrl", "installUrl", "loaderStyles", "tabContent", "elementsInjected", "overlayElement", "styleElement", "injectElements", "cancelNavigation", "removeElements", "activeNavigation", "navigateToDrl", "openAsTab", "tab", "linkFeaturesActive", "clickHandler", "pointerdownHandler", "addLinkFeatures", "anchor", "href", "target", "resetContextMenuTarget", "contextMenuTarget", "removeLinkFeatures", "e", "r", "activatePolyfills", "deactivatePolyfills", "clearDrlCache", "ConnectClient", "buildWalletIcon", "wallet", "wrap", "badge", "sources", "iconCandidates", "img", "index", "origin", "assertX25519PublicJwk", "CONNECT_DENIED_TOKEN", "ConnectClient", "createHandledDeferred", "resolve", "reject", "promise", "res", "rej", "DWEB_CONNECT_PATH", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "DWEB_CONNECT_ACK_MESSAGE_TYPE", "getTrustedMessage", "event", "expectedOrigin", "expectedSource", "data", "DEFAULT_TIMEOUT_MS", "CLOSED_POLL_INTERVAL_MS", "CLOSED_RESPONSE_GRACE_MS", "POPUP_WINDOW_NAME", "POPUP_WIDTH", "POPUP_HEIGHT", "popupWindowFeatures", "base", "openerWidth", "openerHeight", "left", "top", "assertBrowserEnvironment", "PopupWindowClosedError", "PopupClientTransport", "options", "popupUrl", "DWEB_CONNECT_PATH", "popup", "resolve", "reject", "response", "createHandledDeferred", "event", "state", "jwe", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "DWEB_CONNECT_ACK_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", "selectVersion", "codewords", "buildDataCodewords", "allCodewords", "buildInterleavedCodewords", "size", "modules", "isFunction", "drawFunctionPatterns", "drawCodewords", "mask", "selectBestMask", "applyMask", "drawFormatBits", "dataLength", "candidate", "capacityBits", "bits", "pushBits", "value", "length", "i", "byte", "padBytes", "padIndex", "bestMask", "bestPenalty", "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", "rightCol", "placeColumnPairBits", "vertical", "zigZagCoordinate", "invert", "penaltyAdjacentRuns", "runColor", "runLength", "penaltyBlocks", "c", "hasFinderPattern", "line", "start", "lightBefore", "v", "lightAfter", "penaltyFinderPatterns", "row", "column", "r", "penaltyDarkRatio", "module", "total", "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", "resolveDelegatePortableDid", "sealRequest", "MAX_PIN_ATTEMPTS", "RelayConnectCancelledError", "visibilityAwareSleep", "ms", "resolve", "finish", "timer", "onVisibilityChange", "runRelayConnect", "options", "createTransport", "transportOptions", "cancellationController", "transport", "clientDid", "responsePrivateKey", "responsePublicKey", "nonce", "state", "profile", "request", "requestJwe", "handoff", "race", "responseCiphertext", "error", "lastError", "attempt", "pin", "outcome", "attemptPinOpen", "params", "response", "delegatePortableDid", "failure", "LAST_CHOICE_STORAGE_KEY", "SESSION_CHOICES_STORAGE_KEY", "MAX_SESSION_CHOICES", "REMINT_SAFETY_MS", "REMINT_MIN_MS", "PIN_LENGTH", "WALLET_SEARCH_THRESHOLD", "WALLET_ROW_SIZE", "PALETTE_TOKENS", "discoverWalletConnectServerUrl", "walletOrigin", "fetchWalletWellKnown", "runPopupConnect", "options", "transport", "PopupClientTransport", "ConnectClient", "collectBrowserClientMetadata", "defaultIsMobile", "defaultDeps", "runRelayConnect", "probeWalletWellKnown", "readLastChoice", "storage", "raw", "parsed", "isValidRememberedWalletUrl", "writeLastChoice", "choice", "isSessionChoice", "value", "readSessionChoices", "readSessionChoice", "delegateDid", "expectedProviderDid", "choices", "index", "writeSessionChoice", "entry", "removeSessionChoice", "providerDid", "createRelaySession", "cancel", "session", "cancelled", "_", "reject", "RelayConnectCancelledError", "settleWith", "settle", "settler", "runConnectModal", "deps", "wallets", "dedupeWalletsByUrl", "rememberChoice", "appName", "applicationId", "isMobile", "refreshing", "lastChoice", "savedRoute", "relayWalletPath", "savedRouteEscapeLabel", "rememberedWalletUrl", "walletInCatalog", "walletUrl", "method", "resolve", "host", "shadow", "style", "MODAL_STYLES", "overlay", "modal", "title", "theme", "appearance", "systemDark", "hasPaletteOverrides", "applyPaletteTokens", "systemScheme", "scheme", "palette", "key", "onSchemeChange", "settled", "relaySession", "remintTimer", "remintAt", "popupBusy", "pinResolve", "getPinResolve", "clearPinResolve", "discoveryCache", "rowWallets", "walletByUrl", "url", "wallet", "hostnameOf", "composeWalletRow", "selected", "selectWallet", "renderFooter", "startMethod", "cleanup", "clearRemint", "onKeydown", "onVisibilityReturn", "succeed", "result", "renderConnected", "cancelModal", "buildHeader", "stage", "footer", "setStage", "nodes", "renderBusy", "message", "el", "morphToAway", "walletName", "renderAway", "buildHandoffLink", "handoff", "className", "link", "renderQr", "qrLink", "qrToSvg", "encodeQr", "logo", "buildWalletIcon", "stageLinkButton", "startPhone", "renderClaimed", "pulse", "renderPin", "attempt", "previousError", "resolvePin", "boxes", "inputs", "buildPinInputs", "check", "renderDenied", "stageButton", "escapeSavedRoute", "renderError", "error", "renderPhoneUnavailable", "startPopup", "popupSurface", "renderPopupPrompt", "exactReconnect", "description", "buttonLabel", "renderPopupWaiting", "renderPopupInterrupted", "blocked", "switchMethod", "renderPopupFailure", "failure", "popupBlocked", "PopupWindowClosedError", "resolveConnectServerUrl", "origin", "cached", "remintNow", "scheduleRemint", "expiresInSeconds", "delay", "connectServerUrl", "next", "switcher", "buildWalletSwitcher", "row", "alt", "tile", "isSelected", "panel", "gridWallets", "more", "updateScrollHint", "label", "tiles", "empty", "search", "query", "visible", "match", "scrollWrap", "scroll", "grid", "overflowing", "atEnd", "tileName", "custom", "input", "go", "urlError", "allowUnverified", "submitCustom", "valid", "e", "event", "trapFocus", "candidate", "tag", "text", "node", "onClick", "button", "titleText", "appIcon", "onCancel", "header", "identity", "icon", "closeBtn", "i", "submitIfComplete", "code", "resolveOnce", "digits", "digit", "digitIndex", "focusables", "first", "last", "active", "LIGHT_TOKENS", "DARK_TOKENS", "DEFAULT_WALLETS", "BrowserConnectHandler", "options", "wallets", "walletUrl", "timeout", "appName", "appIcon", "applicationId", "preferredMethod", "rememberChoice", "connectServerUrl", "relayWalletPath", "theme", "params", "runConnectModal", "X25519", "CONNECT_DENIED_TOKEN", "ConnectProvider", "DEFAULT_REQUEST_TIMEOUT_MS", "DEFAULT_ACK_TIMEOUT_MS", "WalletPostMessageTransport", "_WalletPostMessageTransport", "params", "request", "createHandledDeferred", "event", "options", "dappWindow", "dappOrigin", "resolveDappOrigin", "recipientPrivateKey", "X25519", "walletEpk", "transport", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "error", "idToken", "ackPromise", "resolve", "ackTimeoutId", "CONNECT_DENIED_TOKEN", "resolveAck", "message", "getTrustedMessage", "DWEB_CONNECT_ACK_MESSAGE_TYPE", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "jwe", "ConnectProvider", "outcome", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "explicitOrigin", "assertReleaseDelay", "delayMs", "ObjectUrlReference", "blob", "_onEmpty", "released", "releaseTimer", "release", "timer", "DefaultBlobUrlPool", "blob", "reference", "ObjectUrlReference", "released", "createBlobUrlPool", "DEFAULT_MAX_BYTES", "DEFAULT_MAX_ENTRIES", "assertLimit", "value", "name", "throwAborted", "controller", "DefaultFileEnvelopeUrlStore", "_options", "request", "key", "cached", "pending", "entry", "lease", "generation", "candidate", "blob", "url", "ObjectUrlReference", "revokeActive", "promise", "createFileEnvelopeUrlStore", "options", "createProfileReader", "isRetryableProfileReadStatus", "DwnInterface", "DateSort", "DwnInterfaceName", "DwnMethodName"]
|
|
7
7
|
}
|