@enbox/browser 0.3.41 → 0.3.42
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 +110 -47
- package/dist/browser.mjs.map +3 -3
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/ui/wallet-selector.js +391 -149
- package/dist/esm/ui/wallet-selector.js.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/ui/wallet-selector.d.ts +33 -1
- package/dist/types/ui/wallet-selector.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +2 -1
- package/src/ui/wallet-selector.ts +437 -162
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/dweb-connect-client.ts", "../src/dweb-connect-messages.ts", "../src/ui/wallet-selector.ts", "../src/browser-connect-handler.ts", "../src/dweb-connect-wallet.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @enbox/browser \u2014 The Enbox browser SDK.\n *\n * For browser-based dapps, this is the only package you need to import.\n * It re-exports the high-level API from `@enbox/api`, the authentication\n * layer from `@enbox/auth`, and provides browser-specific connect handlers.\n *\n * @example Single-import dapp setup\n * ```ts\n * import {\n * Enbox, BrowserConnectHandler,\n * defineProtocol, repository,\n * } from '@enbox/browser';\n *\n * const { enbox, session } = await Enbox.connect({\n * connectHandler: BrowserConnectHandler({ appName: 'My App' }),\n * protocols: [MyProtocol],\n * });\n * ```\n *\n * For non-browser environments (Node.js, CLI, desktop), import from\n * `@enbox/api` and `@enbox/auth` directly instead.\n *\n * @packageDocumentation\n */\n\n// \u2500\u2500\u2500 Re-exports from @enbox/api \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The high-level Enbox API: DWN records, protocols, repositories.\n\nexport {\n Enbox,\n defineProtocol,\n repository,\n} from '@enbox/api';\n\nexport type {\n EnboxAnonymousOptions,\n EnboxConnectOptions,\n EnboxConnectResult,\n EnboxParams,\n EnboxSessionParams,\n} from '@enbox/api';\n\n// \u2500\u2500\u2500 Re-exports from @enbox/auth \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Authentication lifecycle, session management, connect handlers.\n\nexport {\n AuthManager,\n AuthSession,\n normalizeProtocolRequests,\n WalletConnect,\n} from '@enbox/auth/browser';\n\nexport type {\n AuthEvent,\n AuthEventHandler,\n AuthManagerOptions,\n AuthState,\n ConnectHandler,\n ConnectOptions,\n ConnectResult,\n DisconnectOptions,\n HandlerConnectOptions,\n ImportFromPortableOptions,\n VaultConnectOptions,\n Permission,\n PortableIdentity,\n ProtocolRequest,\n RegistrationOptions,\n StorageAdapter,\n SyncOption,\n WalletConnectOptions,\n} from '@enbox/auth/browser';\n\n// \u2500\u2500\u2500 Re-exports from @enbox/connect \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The connect kernel pieces wallet apps need alongside the popup\n// transports: opening/sealing envelopes and the deny token.\n\nexport { CONNECT_DENIED_TOKEN, ConnectProvider } from '@enbox/connect';\nexport type { ConnectApproval, ConnectPermissionRequest, ConnectRequest } from '@enbox/connect';\n\n// \u2500\u2500\u2500 Browser-specific exports \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// DWeb Connect popup transports, wallet selector, DRL polyfills.\n\nexport * from './web-features.js';\nexport { BrowserConnectHandler, DEFAULT_WALLETS } from './browser-connect-handler.js';\nexport type { BrowserConnectHandlerOptions, WalletOption } from './browser-connect-handler.js';\nexport { connectViaPopup, PopupClientTransport, PopupWindowClosedError } from './dweb-connect-client.js';\nexport type { PopupClientTransportOptions, PopupConnectOptions } from './dweb-connect-client.js';\nexport { WalletPostMessageTransport } from './dweb-connect-wallet.js';\nexport type { WalletPostMessageTransportOptions } from './dweb-connect-wallet.js';\nexport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_PATH,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n} from './dweb-connect-messages.js';\nexport type {\n DWebConnectLoadedMessage,\n DWebConnectRequestMessage,\n DWebConnectResponseMessage,\n} from './dweb-connect-messages.js';\nexport { showWalletSelector } from './ui/wallet-selector.js';\n", "/*\n This file is run in dual environments to make installation of the Service Worker code easier.\n Be mindful that code placed in any open excution space may be evaluated multiple times in different contexts,\n so take care to gate additions to only activate code in the right env, such as a Service Worker scope or page window.\n*/\n\nimport type { DidMethodResolver } from '@enbox/dids';\n\nimport { DidDht, DidWeb, UniversalResolver } from '@enbox/dids';\n\n/**\n * Result returned by the `onCacheCheck` callback.\n * When returned, it signals that the response for the given DRL should be cached.\n */\nexport type CacheCheckResult = {\n /** Time-to-live for the cached DRL response, in milliseconds. */\n ttl?: number;\n};\n\n/**\n * Callback invoked to determine whether a DRL response should be cached and for how long.\n * Returning a truthy `CacheCheckResult` opts in to caching; returning a falsy value skips it.\n */\nexport type CacheCheckCallback = (\n event: FetchEvent | Event,\n drl: string,\n) => CacheCheckResult | undefined | null | Promise<CacheCheckResult | undefined | null>;\n\n/**\n * Configuration options for {@link activatePolyfills}.\n */\nexport type ActivatePolyfillsOptions = {\n /**\n * Path to the script to register as a Service Worker.\n * Falls back to `document.currentScript.src` or `import.meta.url`.\n *\n * **Required in strict CSP environments** where `new Function()` is blocked and `import.meta`\n * cannot be evaluated dynamically.\n */\n path?: string;\n /** Set to `false` to skip Service Worker installation. Defaults to `true`. */\n serviceWorker?: boolean;\n /** Set to `false` to skip injection of DRL loading-overlay styles. Defaults to `true`. */\n injectStyles?: boolean;\n /** Set to `false` to skip activation of DRL anchor/link click handling. Defaults to `true`. */\n links?: boolean;\n /** Callback to control per-request caching behaviour. */\n onCacheCheck?: CacheCheckCallback;\n /**\n * DID method resolvers to use for DRL resolution. Defaults to `[DidDht, DidWeb]`.\n * Pass a custom array to add or replace DID methods (e.g., `[DidDht, DidWeb, DidJwk]`).\n */\n didResolvers?: DidMethodResolver[];\n};\n\n/**\n * An `HTMLElement` that has a `src` property (e.g., `<img>`, `<video>`, `<audio>`).\n * Extended with `__src__` to stash the original DRL src during context-menu swaps.\n */\ninterface DrlMediaElement extends HTMLElement {\n src: string;\n __src__?: string;\n}\n\nlet didResolver = new UniversalResolver({ didResolvers: [DidDht, DidWeb] });\n\nimport { parseDrlUrl } from './drl-url-parser.js';\nexport { parseDrlUrl } from './drl-url-parser.js';\n\nconst httpToHttpsRegex = /^http:/;\nconst trailingSlashRegex = /\\/$/;\nconst DRL_CACHE_NAME = 'drl';\n\n/** @internal Exported for testing. Resolves DWN service endpoints from a DID. */\nexport async function getDwnEndpoints(did: string): Promise<string[]> {\n const { didDocument } = await didResolver.resolve(did);\n const endpoints = didDocument?.service?.find(\n (service) => service.type === 'DecentralizedWebNode'\n )?.serviceEndpoint;\n if (!endpoints) {return [];}\n return (Array.isArray(endpoints) ? endpoints : [endpoints]).filter(\n (url) => typeof url === 'string' && url.startsWith('http')\n );\n}\n\n/** Returns an open DRL cache, or `undefined` if the Cache API is unavailable. */\nasync function openDrlCache(): Promise<Cache | undefined> {\n if (typeof caches === 'undefined') {return undefined;}\n return caches.open(DRL_CACHE_NAME);\n}\n\n/** @internal Exported for testing. Handles a DRL fetch event. */\nexport async function handleEvent(\n event: FetchEvent, did: string, path: string, options?: ActivatePolyfillsOptions\n): Promise<Response> {\n const drl = event.request.url\n .replace(httpToHttpsRegex, 'https:')\n .replace(trailingSlashRegex, '');\n const responseCache = await openDrlCache();\n const cachedResponse = await responseCache?.match(drl);\n if (cachedResponse) {\n if (!navigator.onLine) {return cachedResponse;}\n const match = await options?.onCacheCheck?.(event, drl);\n if (match) {\n const cacheTime = cachedResponse.headers.get('dwn-cache-time');\n if (\n cacheTime &&\n Date.now() < Number(cacheTime) + (Number(match.ttl) || 0)\n ) {\n return cachedResponse;\n }\n }\n }\n try {\n if (path) {\n return await fetchResource(event, did, drl, path, responseCache, options);\n } else {\n const response = await didResolver.resolve(did);\n return new Response(JSON.stringify(response), {\n status : 200,\n headers : {\n 'Content-Type': 'application/json',\n },\n });\n }\n } catch (error) {\n if (error instanceof Response) {\n return error;\n }\n console.log(`Error in DID URL fetch: ${error}`);\n return new Response('DID URL fetch error', { status: 500 });\n }\n}\n\n/** @internal Exported for testing. Fetches a resource from DWN endpoints. */\nexport async function fetchResource(\n event: FetchEvent, did: string, drl: string, path: string,\n responseCache: Cache | undefined, options?: ActivatePolyfillsOptions\n): Promise<Response> {\n const endpoints = await getDwnEndpoints(did);\n if (!endpoints?.length) {\n throw new Response(\n 'DWeb Node resolution failed: no valid endpoints found.',\n { status: 530 }\n );\n }\n let lastError: Response | undefined;\n for (const endpoint of endpoints) {\n try {\n const url = `${endpoint.replace(trailingSlashRegex, '')}/${did}/${path}`;\n const response = await fetch(url, { headers: event.request.headers });\n if (response.ok) {\n const match = await options?.onCacheCheck?.(event, drl);\n if (match && responseCache) {\n cacheResponse(drl, url, response, responseCache);\n }\n return response;\n }\n console.log(`DWN endpoint error: ${response.status}`);\n lastError = new Response('DWeb Node request failed', {\n status: response.status,\n });\n } catch (error) {\n console.log(`DWN endpoint error: ${error}`);\n lastError = new Response('DWeb Node request failed', {\n status: 500,\n });\n }\n }\n return lastError!;\n}\n\n/** @internal Exported for testing. Caches a DRL response with metadata headers. */\nexport async function cacheResponse(drl: string, url: string, response: Response, cache: Cache): Promise<void> {\n try {\n const clonedResponse = response.clone();\n const headers = new Headers(clonedResponse.headers);\n headers.append('dwn-cache-time', Date.now().toString());\n headers.append('dwn-composed-url', url);\n const modifiedResponse = new Response(clonedResponse.body, { headers });\n await cache.put(drl, modifiedResponse);\n } catch (error) {\n console.log(`Failed to cache DRL response: ${error}`);\n }\n}\n\n/* Service Worker-based features */\n\nasync function installWorker(options: ActivatePolyfillsOptions = {}): Promise<void> {\n try {\n // Check to see if we are in a Service Worker already, if so, proceed\n // You can call the activatePolyfills() function in your own worker, or standalone as a root worker\n if (\n typeof ServiceWorkerGlobalScope !== 'undefined' &&\n self instanceof ServiceWorkerGlobalScope\n ) {\n const workerSelf = self as unknown as ServiceWorkerGlobalScope;\n workerSelf.skipWaiting();\n workerSelf.addEventListener('activate', (event: ExtendableEvent) => {\n // Claim clients to make the service worker take control immediately\n event.waitUntil(workerSelf.clients.claim());\n });\n workerSelf.addEventListener('fetch', (event: FetchEvent) => {\n const parsed = parseDrlUrl(event.request.url);\n if (parsed) {\n event.respondWith(handleEvent(event, parsed[0], parsed[1], options));\n }\n });\n }\n // If the code gets here, it is not a SW env, it is likely DOM, but check to be sure\n else if (globalThis?.navigator?.serviceWorker) {\n const registration = await navigator.serviceWorker.getRegistration('/');\n // You can only have one worker per path, so check to see if one is already registered\n if (!registration) {\n const installUrl: string | undefined =\n options.path ||\n (document?.currentScript as HTMLScriptElement | null)?.src ||\n import.meta.url;\n if (installUrl)\n {navigator.serviceWorker\n .register(installUrl, { type: 'module' })\n .catch((error: unknown) => {\n console.error(\n 'DWeb networking feature installation failed: ',\n error\n );\n });}\n }\n } else {\n throw new Error(\n 'DWeb networking features are not available for install in this environment'\n );\n }\n } catch (error) {\n console.error('Error in installing networking features:', error);\n }\n}\n\n/* DOM Environment Features */\n\nconst loaderStyles = `\n .drl-loading-overlay {\n position: fixed;\n inset: 0;\n display: flex;\n flex-wrap: wrap;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: 22px;\n color: #fff;\n background: rgba(0, 0, 0, 0.75);\n backdrop-filter: blur(15px);\n -webkit-backdrop-filter: blur(15px);\n z-index: 1000000;\n }\n\n .drl-loading-overlay > div {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .drl-loading-spinner {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .drl-loading-spinner div {\n position: relative;\n width: 2em;\n height: 2em;\n margin: 0.1em 0.25em 0 0;\n }\n .drl-loading-spinner div::after,\n .drl-loading-spinner div::before {\n content: ''; \n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 0.1em solid #FFF;\n position: absolute;\n left: 0;\n top: 0;\n opacity: 0;\n animation: drl-loading-spinner 2s linear infinite;\n }\n .drl-loading-spinner div::after {\n animation-delay: 1s;\n }\n\n .drl-loading-overlay span {\n --text-opacity: 2;\n display: flex;\n align-items: center;\n margin: 2em auto 0;\n padding: 0.2em 0.75em 0.25em;\n text-align: center;\n border-radius: 5em;\n background: rgba(255 255 255 / 8%);\n opacity: 0.8;\n transition: opacity 0.3s ease;\n cursor: pointer;\n }\n\n .drl-loading-overlay span:focus {\n opacity: 1;\n }\n\n .drl-loading-overlay span:hover {\n opacity: 1;\n }\n\n .drl-loading-overlay span::before {\n content: '\u2715 ';\n margin: 0 0.4em 0 0;\n color: red;\n font-size: 65%;\n font-weight: bold;\n }\n\n .drl-loading-overlay span::after {\n content: 'stop';\n display: block;\n font-size: 60%;\n line-height: 0;\n color: rgba(255 255 255 / 60%);\n }\n\n .drl-loading-overlay.new-tab-overlay span::after {\n content: 'close';\n }\n \n @keyframes drl-loading-spinner {\n 0% {\n transform: scale(0);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n opacity: 0;\n }\n }\n`;\nconst tabContent = `\n<!DOCTYPE html>\n<html lang='en'>\n<head>\n <meta charset='UTF-8'>\n <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n <title>Loading DRL...</title>\n <style>\n html, body {\n background-color: #151518;\n height: 100%;\n margin: 0;\n padding: 0;\n font-family: Arial, sans-serif;\n text-align: center;\n }\n ${loaderStyles}\n </style>\n</head>\n<body>\n <div class='drl-loading-overlay new-tab-overlay'>\n <div class='drl-loading-spinner'>\n <div></div>\n Loading DRL\n </div>\n <span onclick='window.close()' tabindex='0'></span>\n </div>\n</body>\n</html>\n`;\n\nlet elementsInjected = false;\nlet overlayElement: HTMLDivElement | null = null;\nlet styleElement: HTMLStyleElement | null = null;\n\nfunction injectElements(): void {\n if (elementsInjected) {return;}\n styleElement = document.createElement('style');\n styleElement.innerHTML = `\n ${loaderStyles}\n\n .drl-loading-overlay {\n opacity: 0;\n transition: opacity 0.3s ease;\n pointer-events: none;\n }\n\n :root[drl-link-loading] .drl-loading-overlay {\n opacity: 1;\n pointer-events: all;\n }\n `;\n document.head.append(styleElement);\n\n overlayElement = document.createElement('div');\n overlayElement.classList.add('drl-loading-overlay');\n overlayElement.innerHTML = `\n <div class='drl-loading-spinner'>\n <div></div>\n Loading DRL\n </div> \n <span tabindex='0'></span>\n `;\n overlayElement.lastElementChild!.addEventListener('click', cancelNavigation);\n document.body.prepend(overlayElement);\n elementsInjected = true;\n}\n\nfunction removeElements(): void {\n if (!elementsInjected) {return;}\n styleElement?.remove();\n styleElement = null;\n overlayElement?.remove();\n overlayElement = null;\n elementsInjected = false;\n}\n\nfunction cancelNavigation(): void {\n document.documentElement.removeAttribute('drl-link-loading');\n activeNavigation = null;\n}\n\nlet activeNavigation: string | null = null;\nlet linkFeaturesActive = false;\n\n// Stored references for listener cleanup in deactivatePolyfills()\nlet clickHandler: ((event: MouseEvent) => Promise<void>) | null = null;\nlet pointerdownHandler: ((event: PointerEvent) => Promise<void>) | null = null;\n\nfunction addLinkFeatures(): void {\n if (!linkFeaturesActive) {\n clickHandler = async (event: MouseEvent): Promise<void> => {\n const anchor = (event.target as Element)?.closest('a');\n if (anchor) {\n const href = anchor.href;\n const parsed = parseDrlUrl(href);\n if (parsed) {\n const did = parsed[0];\n const path = parsed[1];\n const openAsTab = anchor.target === '_blank';\n event.preventDefault();\n try {\n let tab: Window | null = null;\n if (openAsTab) {\n tab = window.open('', '_blank');\n if (tab) {tab.document.write(tabContent);}\n } else {\n activeNavigation = path;\n // this is to allow for cached DIDs to instantly load without any flash of loading UI\n setTimeout(\n () =>\n document.documentElement.setAttribute('drl-link-loading', ''),\n 50\n );\n }\n const endpoints = await getDwnEndpoints(did);\n if (!endpoints.length) {\n throw new Error('no valid DWN endpoints found');\n }\n const url = `${endpoints[0].replace(\n trailingSlashRegex,\n ''\n )}/${did}/${path}`;\n if (openAsTab) {\n if (tab && !tab.closed) {tab.location.href = url;}\n } else if (activeNavigation === path) {\n window.location.href = url;\n }\n } catch {\n if (activeNavigation === path) {\n cancelNavigation();\n }\n throw new Error(\n `DID endpoint resolution failed for the DRL: ${href}`\n );\n }\n }\n }\n };\n\n pointerdownHandler = async (event: PointerEvent): Promise<void> => {\n const target = event.composedPath()[0] as DrlMediaElement | undefined;\n if (\n (event.pointerType === 'mouse' && event.button === 2) ||\n (event.pointerType === 'touch' && event.isPrimary)\n ) {\n resetContextMenuTarget();\n if (target?.src && parseDrlUrl(target.src)) {\n contextMenuTarget = target;\n target.__src__ = target.src;\n const drl = target.src\n .replace(httpToHttpsRegex, 'https:')\n .replace(trailingSlashRegex, '');\n const responseCache = await openDrlCache();\n const response = await responseCache?.match(drl);\n if (response) {\n const url = response.headers.get('dwn-composed-url');\n if (url) {target.src = url;}\n }\n target.addEventListener('pointerup', resetContextMenuTarget, {\n once: true,\n });\n }\n } else if (target === contextMenuTarget) {\n resetContextMenuTarget();\n }\n };\n\n document.addEventListener('click', clickHandler);\n document.addEventListener('pointercancel', resetContextMenuTarget);\n document.addEventListener('pointerdown', pointerdownHandler);\n\n linkFeaturesActive = true;\n }\n}\n\nfunction removeLinkFeatures(): void {\n if (!linkFeaturesActive) {return;}\n if (clickHandler) {\n document.removeEventListener('click', clickHandler);\n clickHandler = null;\n }\n if (pointerdownHandler) {\n document.removeEventListener('pointerdown', pointerdownHandler);\n pointerdownHandler = null;\n }\n document.removeEventListener('pointercancel', resetContextMenuTarget);\n resetContextMenuTarget();\n cancelNavigation();\n linkFeaturesActive = false;\n}\n\nlet contextMenuTarget: DrlMediaElement | null = null;\nasync function resetContextMenuTarget(e?: Event): Promise<void> {\n if (e?.type === 'pointerup') {\n await new Promise<void>((r) => requestAnimationFrame(() => r()));\n }\n if (contextMenuTarget) {\n contextMenuTarget.src = contextMenuTarget.__src__!;\n delete contextMenuTarget.__src__;\n contextMenuTarget = null;\n }\n}\n\n/**\n * Activates various polyfills to enable Enbox features in Web environments.\n *\n * @param options - Configuration options to control the activation of polyfills.\n *\n * @example\n * // Activate all polyfills with default options, and cache every DRL for 1 minute\n * activatePolyfills({\n * onCacheCheck(event, route){\n * return {\n * ttl: 60_000\n * }\n * }\n * });\n *\n * @example\n * // Activate polyfills, but without Service Worker activation\n * activatePolyfills({ serviceWorker: false });\n *\n * @example\n * // Use custom DID resolvers\n * activatePolyfills({ didResolvers: [DidDht, DidWeb, DidJwk] });\n */\nexport function activatePolyfills(options: ActivatePolyfillsOptions = {}): void {\n if (options.didResolvers) {\n didResolver = new UniversalResolver({ didResolvers: options.didResolvers });\n }\n if (options.serviceWorker !== false) {\n installWorker(options);\n }\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n if (options.injectStyles !== false) {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', injectElements, {\n once: true,\n });\n } else {injectElements();}\n }\n if (options.links !== false) {addLinkFeatures();}\n }\n}\n\n/**\n * Removes all polyfill event listeners, injected DOM elements, and resets internal state.\n * Call this to fully clean up after {@link activatePolyfills}.\n *\n * Does **not** unregister an installed Service Worker \u2014 use\n * `navigator.serviceWorker.getRegistration('/').then(r => r?.unregister())` for that.\n */\nexport function deactivatePolyfills(): void {\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n removeLinkFeatures();\n removeElements();\n }\n}\n\n/**\n * Deletes the entire DRL response cache.\n * Useful for clearing stale cached DWN responses.\n *\n * @returns `true` if the cache existed and was deleted, `false` otherwise.\n * Returns `false` if the Cache API is unavailable.\n */\nexport async function clearDrlCache(): Promise<boolean> {\n if (typeof caches === 'undefined') {return false;}\n return caches.delete(DRL_CACHE_NAME);\n}\n", "/**\n * Parses a DRL URL (http(s)://dweb/{did}/{path}) without regex quantifiers.\n * Returns `[did, path]` or `null` if the URL does not match the DRL scheme.\n *\n * Extracted to a standalone module so it can be tested under Node.js (bun:test)\n * in addition to the browser-based vitest suite, ensuring SonarCloud's\n * merged coverage report includes these lines.\n */\nexport function parseDrlUrl(url: string): [string, string] | null {\n const idx = url.indexOf('://dweb/');\n if (idx === -1) { return null; }\n const prefix = url.slice(0, idx);\n if (prefix !== 'http' && prefix !== 'https') { return null; }\n const rest = url.slice(idx + 8); // '://dweb/'.length === 8\n if (rest.length === 0) { return null; }\n const slashIdx = rest.indexOf('/');\n if (slashIdx === -1) { return [rest, '']; }\n if (slashIdx === 0) { return null; } // DID segment must be non-empty\n return [rest.slice(0, slashIdx), rest.slice(slashIdx + 1)];\n}\n", "/**\n * DWeb Connect client \u2014 the dapp side of the popup/postMessage connect flow.\n *\n * {@link PopupClientTransport} implements the `@enbox/connect` kernel's\n * `ConnectTransport` over a wallet popup:\n *\n * 1. The dapp opens `${walletUrl}/dweb-connect` as a popup window.\n * 2. The wallet emits a `loaded` beacon carrying a fresh ephemeral X25519\n * public key and its origin.\n * 3. The kernel seals the signed connect request to that key (ECDH-ES,\n * `apv` bound to the wallet origin) and the transport posts the\n * ciphertext to the popup.\n * 4. The wallet posts back the sealed response JWE (or the deny token),\n * which the kernel opens and value-checks.\n *\n * Only ciphertext crosses the postMessage channel. Every message is checked\n * against the wallet origin derived from the configured wallet URL (never\n * `'*'`), and against the popup window as `event.source`.\n *\n * @module\n */\n\nimport type { Jwk } from '@enbox/crypto';\nimport type {\n ConnectClientMetadata,\n ConnectPermissionRequest,\n ConnectRequestProfile,\n ConnectResult,\n ConnectTransport,\n} from '@enbox/connect';\n\nimport { assertX25519PublicJwk, CONNECT_DENIED_TOKEN, ConnectClient } from '@enbox/connect';\n\nimport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_PATH,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n getTrustedMessage,\n} from './dweb-connect-messages.js';\n\n/** Default budget for the whole popup handshake (beacon + user consent + response). */\nconst DEFAULT_TIMEOUT_MS = 300_000;\n\n/** Interval at which the transport checks whether the user closed the popup. */\nconst CLOSED_POLL_INTERVAL_MS = 500;\n\n/** Window name given to the wallet popup. */\nconst POPUP_WINDOW_NAME = 'enbox-dweb-connect';\n\n/** Window features given to the wallet popup. */\nconst POPUP_WINDOW_FEATURES = 'width=500,height=700,menubar=no,toolbar=no,location=no,status=no';\n\n/** Guards against calling browser-only entry points outside a browser. */\nfunction assertBrowserEnvironment(): void {\n if (typeof window === 'undefined') {\n throw new Error('[@enbox/browser] DWeb Connect is only available in browser environments.');\n }\n}\n\n/**\n * Thrown when the user closes the wallet popup before the wallet finished\n * loading (i.e. before its `loaded` beacon arrived). Callers typically treat\n * this the same as a user denial.\n */\nexport class PopupWindowClosedError extends Error {\n constructor() {\n super('[@enbox/browser] Wallet popup was closed before the wallet finished loading.');\n this.name = 'PopupWindowClosedError';\n }\n}\n\n/** Options for constructing a {@link PopupClientTransport}. */\nexport type PopupClientTransportOptions = {\n /** Base URL of the wallet app (e.g. `https://enbox-wallet.pages.dev`). */\n walletUrl: string;\n\n /**\n * Total budget in milliseconds for the popup handshake. The popup is closed\n * and the handshake rejected when the wallet has not responded in time.\n * @default 300_000 (5 minutes)\n */\n timeoutMs?: number;\n};\n\n/**\n * Popup/postMessage {@link ConnectTransport} for browser dapps.\n *\n * Single-use: construct a new transport per handshake. The **constructor**\n * opens the wallet popup synchronously \u2014 so `window.open` runs inside the user\n * gesture, ahead of the kernel's awaited key generation, and survives strict\n * popup blockers; `requestProfile()` then awaits the wallet's `loaded` beacon;\n * `deliverRequest()` posts the sealed request ciphertext; `awaitResponse()`\n * resolves with the sealed response JWE, or the deny token when the user denies\n * or closes the popup after the handshake was established.\n *\n * Security properties:\n * - `targetOrigin` of every outbound `postMessage` is pinned to the origin\n * derived from `walletUrl` \u2014 never `'*'`.\n * - Inbound messages are dropped unless `event.origin` equals the pinned\n * wallet origin AND `event.source` is the popup window this transport opened.\n * - The beacon's `walletOrigin` field must equal the pinned origin, and its\n * `walletEpk` must be a public-only X25519 JWK; a malformed beacon from the\n * genuine popup fails the handshake closed.\n */\nexport class PopupClientTransport implements ConnectTransport {\n /** {@inheritDoc ConnectTransport.requiresPin} */\n public readonly requiresPin: boolean = false;\n\n private readonly _walletOrigin: string;\n private readonly _timeoutMs: number;\n\n private readonly _popup: Window;\n private _settled = false;\n private _walletEpkReceived = false;\n private _timeoutId?: ReturnType<typeof setTimeout>;\n private _closedPollId?: ReturnType<typeof setInterval>;\n private _messageListener?: (event: MessageEvent) => void;\n\n private readonly _walletEpkPromise: Promise<Jwk>;\n private _resolveWalletEpk?: (walletEpk: Jwk) => void;\n private _rejectWalletEpk?: (error: Error) => void;\n\n private readonly _responsePromise: Promise<string>;\n private _resolveResponse?: (payload: string) => void;\n private _rejectResponse?: (error: Error) => void;\n\n constructor(options: PopupClientTransportOptions) {\n assertBrowserEnvironment();\n\n this._walletOrigin = new URL(options.walletUrl).origin;\n this._timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n // Open the wallet popup SYNCHRONOUSLY, in the user-gesture call stack,\n // before the kernel's awaited `DidJwk.create()` / `X25519.generateKey()`\n // run. Strict popup blockers (Safari) reject a `window.open` issued once\n // the stack has yielded to a prior `await`, so opening it here \u2014 instead of\n // inside the awaited `requestProfile()` \u2014 is what keeps the flow usable.\n const popupUrl = new URL(DWEB_CONNECT_PATH, options.walletUrl).toString();\n const popup = window.open(popupUrl, POPUP_WINDOW_NAME, POPUP_WINDOW_FEATURES);\n if (!popup) {\n throw new Error('[@enbox/browser] Popup blocked. Allow popups for this site to connect to a wallet.');\n }\n this._popup = popup;\n\n this._walletEpkPromise = new Promise<Jwk>((resolve, reject): void => {\n this._resolveWalletEpk = resolve;\n this._rejectWalletEpk = reject;\n });\n\n // Created up-front so a response (or deny) arriving before\n // `awaitResponse()` is called is never dropped. The no-op catch marks\n // early rejections (timeout, popup closed during load) as handled until\n // the kernel attaches its own handlers via `awaitResponse()`.\n this._responsePromise = new Promise<string>((resolve, reject): void => {\n this._resolveResponse = resolve;\n this._rejectResponse = reject;\n });\n this._responsePromise.catch((): undefined => undefined);\n\n // Listen synchronously, before the wallet page can emit its `loaded`\n // beacon, so the beacon is never missed while the kernel awaits key\n // generation ahead of `requestProfile()`.\n this._messageListener = (event: MessageEvent): void => { this.onMessage(event); };\n window.addEventListener('message', this._messageListener);\n\n this._timeoutId = setTimeout((): void => {\n this.fail(new Error('[@enbox/browser] DWeb Connect timed out waiting for wallet response.'));\n }, this._timeoutMs);\n\n this._closedPollId = setInterval((): void => { this.onClosedPoll(); }, CLOSED_POLL_INTERVAL_MS);\n }\n\n /**\n * Awaits the already-open popup's `loaded` beacon, then returns the popup\n * channel profile: ECDH-ES encryption to the beacon's ephemeral key with the\n * pinned wallet origin as the `apv` binding, a `post_message` reply\n * descriptor, and the client-supplied `state` correlator.\n *\n * The popup was opened synchronously at construction, so this method only\n * awaits the beacon \u2014 it never issues the blocker-sensitive `window.open`.\n *\n * @param state - The handshake correlator minted by the {@link ConnectClient}.\n * @throws If the user closes the popup before the beacon arrives\n * ({@link PopupWindowClosedError}), the beacon is malformed, or on\n * timeout.\n */\n public async requestProfile(state: string): Promise<ConnectRequestProfile> {\n const walletEpk = await this._walletEpkPromise;\n\n return {\n encryption : { mode: 'ecdh-es', walletEpk, walletOrigin: this._walletOrigin },\n reply : { mode: 'post_message' },\n state,\n };\n }\n\n /**\n * Posts the sealed request ciphertext to the wallet popup with the\n * `targetOrigin` pinned to the wallet origin.\n */\n public async deliverRequest(jwe: string): Promise<void> {\n this._popup.postMessage({ type: DWEB_CONNECT_REQUEST_MESSAGE_TYPE, jwe }, this._walletOrigin);\n }\n\n /**\n * Awaits the wallet's response ciphertext: the sealed response JWE, or the\n * deny token when the user denies in the wallet or closes the popup.\n * Rejects on timeout.\n */\n public async awaitResponse(): Promise<string> {\n return await this._responsePromise;\n }\n\n private onMessage(event: MessageEvent): void {\n const message = getTrustedMessage(event, this._walletOrigin, this._popup);\n if (message === undefined) { return; }\n\n if (message.type === DWEB_CONNECT_LOADED_MESSAGE_TYPE) {\n this.onLoadedBeacon(message);\n return;\n }\n\n if (message.type === DWEB_CONNECT_RESPONSE_MESSAGE_TYPE) {\n this.onResponseMessage(message);\n }\n }\n\n private onLoadedBeacon(message: Record<string, unknown>): void {\n if (this._settled || this._walletEpkReceived) { return; }\n\n // The beacon passed the origin and source checks, so a malformed payload\n // is a protocol violation by the genuine popup \u2014 fail closed. The X25519\n // public-JWK shape check is delegated to the connect kernel.\n let walletEpk: Jwk;\n try {\n assertX25519PublicJwk(message.walletEpk);\n walletEpk = message.walletEpk;\n } catch {\n this.fail(new Error('[@enbox/browser] Wallet loaded beacon did not carry a valid X25519 public key.'));\n return;\n }\n\n if (message.walletOrigin !== this._walletOrigin) {\n this.fail(new Error('[@enbox/browser] Wallet loaded beacon origin does not match the configured wallet origin.'));\n return;\n }\n\n this._walletEpkReceived = true;\n this._resolveWalletEpk?.(walletEpk);\n }\n\n private onResponseMessage(message: Record<string, unknown>): void {\n if (this._settled) { return; }\n\n if (typeof message.payload !== 'string') {\n this.fail(new Error('[@enbox/browser] Wallet response message did not carry a ciphertext payload.'));\n return;\n }\n\n this._settled = true;\n this.cleanup();\n // No-op on the normal path; unblocks `requestProfile()` if a response\n // somehow arrives before the beacon.\n this._rejectWalletEpk?.(new Error('[@enbox/browser] Wallet responded before the handshake was established.'));\n this._resolveResponse?.(message.payload);\n }\n\n private onClosedPoll(): void {\n if (this._settled || this._popup.closed !== true) { return; }\n\n if (!this._walletEpkReceived) {\n // Closed before the wallet ever loaded \u2014 the handshake cannot proceed.\n this.fail(new PopupWindowClosedError());\n return;\n }\n\n // Closed after the handshake was established \u2014 treat as a user denial.\n this._settled = true;\n this.cleanup();\n this._resolveResponse?.(CONNECT_DENIED_TOKEN);\n }\n\n private fail(error: Error): void {\n if (this._settled) { return; }\n this._settled = true;\n this.cleanup();\n try { this._popup.close(); } catch { /* best effort */ }\n this._rejectWalletEpk?.(error);\n this._rejectResponse?.(error);\n }\n\n private cleanup(): void {\n clearTimeout(this._timeoutId);\n clearInterval(this._closedPollId);\n if (this._messageListener !== undefined) {\n window.removeEventListener('message', this._messageListener);\n this._messageListener = undefined;\n }\n }\n}\n\n/** Options for a one-shot {@link connectViaPopup} flow. */\nexport type PopupConnectOptions = {\n /** Base URL of the wallet app (e.g. `https://enbox-wallet.pages.dev`). */\n walletUrl: string;\n\n /** DWN protocols and permission scopes to request from the wallet. */\n permissionRequests: ConnectPermissionRequest[];\n\n /**\n * Timeout in milliseconds for the popup handshake.\n * @default 300_000 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Display name of the requesting application, shown in the wallet's\n * consent screen. Defaults to the dapp's host.\n */\n appName?: string;\n\n /**\n * Icon URL of the requesting application, shown alongside the app name in\n * the wallet's consent screen.\n */\n appIcon?: string;\n};\n\n/** Collects self-reported environment hints for the wallet's session display. */\nfunction collectBrowserClientMetadata(): ConnectClientMetadata {\n const resolvedOptions = Intl.DateTimeFormat().resolvedOptions();\n const languages = Array.isArray(globalThis.navigator.languages)\n ? globalThis.navigator.languages.filter((language) => typeof language === 'string' && language.length > 0)\n : undefined;\n\n return {\n origin : globalThis.location.origin,\n userAgent : globalThis.navigator.userAgent,\n platform : globalThis.navigator.platform,\n language : globalThis.navigator.language,\n ...(languages && languages.length > 0 ? { languages } : {}),\n ...(resolvedOptions.timeZone ? { timezone: resolvedOptions.timeZone } : {}),\n };\n}\n\n/**\n * Runs one DWeb Connect popup handshake end-to-end: opens the wallet popup,\n * drives the `@enbox/connect` kernel client over a {@link PopupClientTransport},\n * and returns the delegated credentials.\n *\n * @returns The delegate credentials, or `undefined` when the user denied the\n * request or closed the popup.\n * @throws If the popup is blocked, the handshake times out, or the wallet\n * returns an invalid response.\n */\nexport async function connectViaPopup(options: PopupConnectOptions): Promise<ConnectResult | undefined> {\n const transport = new PopupClientTransport({\n walletUrl : options.walletUrl,\n timeoutMs : options.timeout,\n });\n const client = new ConnectClient({ transport });\n\n try {\n return await client.connect({\n appName : options.appName ?? globalThis.location.host,\n appIcon : options.appIcon,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n });\n } catch (error) {\n if (error instanceof PopupWindowClosedError) {\n // The user closed the wallet before it loaded \u2014 same as a denial.\n return undefined;\n }\n throw error;\n }\n}\n", "/**\n * Wire shapes for the DWeb Connect popup/postMessage channel.\n *\n * The dapp and the wallet exchange exactly three message kinds over\n * `window.postMessage`:\n *\n * 1. `loaded` beacon (wallet \u2192 dapp): announces the wallet page is ready and\n * carries a fresh ephemeral X25519 public key plus the wallet's origin.\n * 2. `request` (dapp \u2192 wallet): the sealed connect request JWE \u2014 ciphertext\n * only, encrypted to the beacon key with ECDH-ES and the wallet origin\n * bound into the JWE `apv` header.\n * 3. `response` (wallet \u2192 dapp): the sealed connect response JWE, or the\n * literal deny token \u2014 again ciphertext only.\n *\n * Plaintext never crosses the channel, and both sides pin `targetOrigin`\n * and verify `event.origin` / `event.source` on every message.\n *\n * @module\n */\n\nimport type { Jwk } from '@enbox/crypto';\n\n/** Path of the wallet's DWeb Connect page, opened as a popup by the dapp. */\nexport const DWEB_CONNECT_PATH = '/dweb-connect';\n\n/** Message type of the wallet's `loaded` beacon (wallet \u2192 dapp). */\nexport const DWEB_CONNECT_LOADED_MESSAGE_TYPE = 'enbox-connect-loaded';\n\n/** Message type carrying the sealed connect request JWE (dapp \u2192 wallet). */\nexport const DWEB_CONNECT_REQUEST_MESSAGE_TYPE = 'enbox-connect-request';\n\n/** Message type carrying the sealed connect response JWE or deny token (wallet \u2192 dapp). */\nexport const DWEB_CONNECT_RESPONSE_MESSAGE_TYPE = 'enbox-connect-response';\n\n/**\n * The wallet's readiness beacon. Emitted to `window.opener` once the wallet's\n * DWeb Connect page has generated its per-session ephemeral X25519 key.\n */\nexport type DWebConnectLoadedMessage = {\n type: typeof DWEB_CONNECT_LOADED_MESSAGE_TYPE;\n\n /** Fresh ephemeral X25519 public JWK the dapp seals the request to. */\n walletEpk: Jwk;\n\n /** The wallet's own origin; must match the origin the dapp has pinned. */\n walletOrigin: string;\n};\n\n/** The dapp's sealed connect request, posted to the wallet popup. */\nexport type DWebConnectRequestMessage = {\n type: typeof DWEB_CONNECT_REQUEST_MESSAGE_TYPE;\n\n /** The sealed connect request as a Compact JWE string. */\n jwe: string;\n};\n\n/** The wallet's sealed connect response, posted back to the opener. */\nexport type DWebConnectResponseMessage = {\n type: typeof DWEB_CONNECT_RESPONSE_MESSAGE_TYPE;\n\n /** The sealed connect response JWE, or the literal `CONNECT_DENIED_TOKEN`. */\n payload: string;\n};\n\n/**\n * Applies the shared inbound-message trust filter for the popup channel:\n * pins the message to the expected `event.origin`, pins its `event.source` to\n * the expected window, and requires a non-null object payload.\n *\n * Returns the payload cast to a plain record when every check passes, or\n * `undefined` when the message must be dropped. Both the dapp-side and\n * wallet-side transports early-return on `undefined` before inspecting any\n * message field \u2014 this is the security-critical filter that keeps hostile\n * origins and stray windows off the channel.\n */\nexport function getTrustedMessage(\n event: MessageEvent,\n expectedOrigin: string,\n expectedSource: Window | undefined,\n): Record<string, unknown> | undefined {\n // Origin pinning: only messages from the expected origin count.\n if (event.origin !== expectedOrigin) { return undefined; }\n\n // Source pinning: the message must come from the expected window.\n if (event.source !== expectedSource) { return undefined; }\n\n const data: unknown = event.data;\n if (typeof data !== 'object' || data === null) { return undefined; }\n\n return data as Record<string, unknown>;\n}\n", "/**\n * Wallet selector modal \u2014 a self-contained, framework-agnostic UI component.\n *\n * Injected into the DOM as a Shadow DOM element to prevent style conflicts.\n * Inspired by WalletConnect's Web3Modal pattern.\n *\n * @module\n */\n\nimport type { WalletOption } from '../browser-connect-handler.js';\n\n/** Shows the wallet selector modal and resolves with the chosen wallet URL. */\nexport function showWalletSelector(wallets: WalletOption[]): Promise<string> {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new Error('[@enbox/browser] Wallet selector is only available in browser environments.');\n }\n\n return new Promise<string>((resolve, reject) => {\n // Create the host element with Shadow DOM isolation.\n const host = document.createElement('div');\n host.id = 'enbox-wallet-selector';\n const shadow = host.attachShadow({ mode: 'open' });\n\n let onKeydown: ((e: KeyboardEvent) => void) | undefined;\n const cleanup = (): void => {\n if (onKeydown !== undefined) {\n document.removeEventListener('keydown', onKeydown);\n onKeydown = undefined;\n }\n\n try { document.body.removeChild(host); } catch { /* best effort */ }\n };\n\n // Detect dark mode.\n const isDark = window.matchMedia?.('(prefers-color-scheme: dark)').matches;\n\n // Build styles.\n const style = document.createElement('style');\n style.textContent = buildStyles(isDark);\n shadow.appendChild(style);\n\n // Build modal DOM.\n const overlay = document.createElement('div');\n overlay.className = 'overlay';\n\n const modal = document.createElement('div');\n modal.className = 'modal';\n\n // Header\n const header = document.createElement('div');\n header.className = 'header';\n\n const title = document.createElement('h2');\n title.textContent = 'Connect Wallet';\n\n const closeBtn = document.createElement('button');\n closeBtn.className = 'close-btn';\n closeBtn.innerHTML = '×';\n closeBtn.addEventListener('click', () => {\n cleanup();\n reject(new Error('[@enbox/browser] Wallet selection cancelled.'));\n });\n\n header.appendChild(title);\n header.appendChild(closeBtn);\n modal.appendChild(header);\n\n // Wallet list\n const list = document.createElement('div');\n list.className = 'wallet-list';\n\n for (const wallet of wallets) {\n const item = document.createElement('button');\n item.className = 'wallet-item';\n\n const icon = document.createElement('img');\n icon.src = wallet.icon ?? faviconUrl(wallet.url);\n icon.alt = wallet.name;\n icon.width = 32;\n icon.height = 32;\n icon.onerror = (): void => { icon.style.display = 'none'; };\n\n const textGroup = document.createElement('div');\n textGroup.className = 'wallet-text';\n\n const name = document.createElement('span');\n name.className = 'wallet-name';\n name.textContent = wallet.name;\n\n textGroup.appendChild(name);\n\n if (wallet.description) {\n const desc = document.createElement('span');\n desc.className = 'wallet-description';\n desc.textContent = wallet.description;\n textGroup.appendChild(desc);\n }\n\n const arrow = document.createElement('span');\n arrow.className = 'arrow';\n arrow.textContent = '\\u203A'; // \u203A\n\n item.appendChild(icon);\n item.appendChild(textGroup);\n item.appendChild(arrow);\n\n item.addEventListener('click', () => {\n cleanup();\n resolve(wallet.url);\n });\n\n list.appendChild(item);\n }\n\n modal.appendChild(list);\n\n // Separator\n const sep = document.createElement('div');\n sep.className = 'separator';\n\n const sepLine1 = document.createElement('div');\n sepLine1.className = 'sep-line';\n const sepText = document.createElement('span');\n sepText.textContent = 'or';\n const sepLine2 = document.createElement('div');\n sepLine2.className = 'sep-line';\n\n sep.appendChild(sepLine1);\n sep.appendChild(sepText);\n sep.appendChild(sepLine2);\n modal.appendChild(sep);\n\n // Custom URL input\n const inputGroup = document.createElement('div');\n inputGroup.className = 'input-group';\n\n const input = document.createElement('input');\n input.type = 'url';\n input.placeholder = 'Enter wallet URL...';\n input.className = 'url-input';\n\n const goBtn = document.createElement('button');\n goBtn.className = 'go-btn';\n goBtn.textContent = 'Connect';\n goBtn.disabled = true;\n\n input.addEventListener('input', () => {\n goBtn.disabled = !isValidUrl(input.value);\n });\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' && isValidUrl(input.value)) {\n cleanup();\n resolve(normalizeUrl(input.value));\n }\n });\n\n goBtn.addEventListener('click', () => {\n if (isValidUrl(input.value)) {\n cleanup();\n resolve(normalizeUrl(input.value));\n }\n });\n\n inputGroup.appendChild(input);\n inputGroup.appendChild(goBtn);\n modal.appendChild(inputGroup);\n\n // Close on overlay click.\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) {\n cleanup();\n reject(new Error('[@enbox/browser] Wallet selection cancelled.'));\n }\n });\n\n // Close on Escape.\n onKeydown = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n cleanup();\n reject(new Error('[@enbox/browser] Wallet selection cancelled.'));\n }\n };\n document.addEventListener('keydown', onKeydown);\n\n overlay.appendChild(modal);\n shadow.appendChild(overlay);\n document.body.appendChild(host);\n\n // Focus the input for keyboard-first users.\n input.focus();\n });\n}\n\n// \u2500\u2500\u2500 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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction faviconUrl(walletUrl: string): string {\n return `https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=${walletUrl}&size=128`;\n}\n\nfunction isValidUrl(value: string): boolean {\n try {\n const url = new URL(value.includes('://') ? value : `https://${value}`);\n return url.protocol === 'https:' || url.protocol === 'http:';\n } catch {\n return false;\n }\n}\n\nfunction normalizeUrl(value: string): string {\n if (!value.includes('://')) {\n value = `https://${value}`;\n }\n const url = new URL(value);\n // Return origin only (strip path/trailing slash).\n return url.origin;\n}\n\nfunction buildStyles(isDark: boolean): string {\n const bg = isDark ? '#1a1a2e' : '#ffffff';\n const text = isDark ? '#e0e0e0' : '#1a1a2e';\n const muted = isDark ? '#888' : '#666';\n const border = isDark ? '#333' : '#e0e0e0';\n const itemBg = isDark ? '#16213e' : '#f8f9fa';\n const itemHover = isDark ? '#0f3460' : '#e9ecef';\n const accent = isDark ? '#4a9eff' : '#0066cc';\n const overlayBg = 'rgba(0, 0, 0, 0.5)';\n\n return `\n * { box-sizing: border-box; margin: 0; padding: 0; }\n\n .overlay {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n display: flex;\n align-items: center;\n justify-content: center;\n background: ${overlayBg};\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n animation: fadeIn 0.15s ease-out;\n }\n\n @keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes slideUp {\n from { transform: translateY(20px); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n }\n\n .modal {\n background: ${bg};\n color: ${text};\n border-radius: 16px;\n width: 380px;\n max-width: 90vw;\n max-height: 80vh;\n overflow-y: auto;\n padding: 24px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n animation: slideUp 0.2s ease-out;\n }\n\n .header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n }\n\n h2 {\n font-size: 18px;\n font-weight: 600;\n }\n\n .close-btn {\n background: none;\n border: none;\n font-size: 24px;\n cursor: pointer;\n color: ${muted};\n padding: 4px 8px;\n border-radius: 8px;\n line-height: 1;\n }\n .close-btn:hover { color: ${text}; background: ${itemBg}; }\n\n .wallet-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .wallet-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n background: ${itemBg};\n border: 1px solid ${border};\n border-radius: 12px;\n cursor: pointer;\n font-size: 15px;\n color: ${text};\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n }\n .wallet-item:hover { background: ${itemHover}; }\n\n .wallet-text {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n }\n\n .wallet-name { font-weight: 500; }\n\n .wallet-description {\n font-size: 12px;\n color: ${muted};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .arrow {\n font-size: 20px;\n color: ${muted};\n flex-shrink: 0;\n }\n\n .separator {\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 20px 0;\n color: ${muted};\n font-size: 13px;\n }\n .sep-line { flex: 1; height: 1px; background: ${border}; }\n\n .input-group {\n display: flex;\n gap: 8px;\n }\n\n .url-input {\n flex: 1;\n padding: 10px 14px;\n border: 1px solid ${border};\n border-radius: 10px;\n font-size: 14px;\n background: ${itemBg};\n color: ${text};\n outline: none;\n }\n .url-input:focus { border-color: ${accent}; }\n .url-input::placeholder { color: ${muted}; }\n\n .go-btn {\n padding: 10px 18px;\n border: none;\n border-radius: 10px;\n background: ${accent};\n color: #fff;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n }\n .go-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n }\n .go-btn:not(:disabled):hover { filter: brightness(1.1); }\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 { ConnectPermissionRequest } from '@enbox/connect';\nimport type { ConnectHandler, ConnectResult } from '@enbox/auth';\n\nimport { connectViaPopup } from './dweb-connect-client.js';\nimport { showWalletSelector } from './ui/wallet-selector.js';\n\n/** A wallet entry shown in the wallet selector modal. */\nexport interface WalletOption {\n /** Display name (e.g. \"Enbox\"). */\n name: string;\n\n /** Base URL of the wallet app (e.g. \"https://enbox-wallet.pages.dev\"). */\n url: string;\n\n /** Optional icon URL. If omitted, the wallet's favicon is used. */\n icon?: string;\n\n /** Short description shown below the wallet name in the selector. */\n description?: string;\n}\n\n/** Default wallets shown in the selector when no overrides are provided. */\nexport const DEFAULT_WALLETS: WalletOption[] = [\n {\n name : 'Enbox',\n url : 'https://enbox-wallet.pages.dev',\n description : 'Manage your digital identity and data',\n },\n {\n name : 'Prism',\n url : 'https://prism-wallet.pages.dev',\n description : 'A clear view into your digital identity',\n },\n {\n name : 'Matcha',\n url : 'https://matcha-wallet.pages.dev',\n description : 'A fresh approach to digital identity',\n },\n {\n name : 'Onyx',\n url : 'https://onyx-wallet.pages.dev',\n description : 'A refined home for your digital identity',\n },\n];\n\n/** Options for creating a BrowserConnectHandler. */\nexport interface BrowserConnectHandlerOptions {\n /**\n * Known wallets shown in the wallet selector modal.\n * If omitted, {@link DEFAULT_WALLETS} is used.\n */\n wallets?: WalletOption[];\n\n /**\n * Explicit wallet URL. If provided, the wallet selector is skipped\n * and this URL is used directly.\n */\n walletUrl?: string;\n\n /**\n * Timeout in milliseconds for the wallet popup flow.\n * @default 300_000 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Display name of the requesting application.\n * Shown in the wallet's permission consent screen.\n */\n appName?: string;\n\n /**\n * Icon URL of the requesting application.\n * Shown alongside the app name in the wallet's consent screen.\n * Defaults to `${window.location.origin}/favicon.ico` if omitted.\n */\n appIcon?: string;\n\n}\n\n/**\n * Create a browser-native connect handler using DWeb Connect\n * (popup + postMessage).\n *\n * This handler:\n * 1. Shows a wallet selector modal (or uses a provided walletUrl).\n * 2. Opens the selected wallet as a popup window.\n * 3. Runs the DWeb Connect postMessage protocol.\n * 4. Returns the delegate credentials on success.\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: fixedWalletUrl,\n timeout,\n appName,\n appIcon,\n } = options;\n\n return {\n async requestAccess(params: {\n permissionRequests: ConnectPermissionRequest[];\n }): Promise<ConnectResult | undefined> {\n // 1. Determine wallet URL.\n let walletUrl = fixedWalletUrl;\n if (!walletUrl) {\n walletUrl = await showWalletSelector(wallets);\n }\n\n // 2. Run the DWeb Connect popup flow over the connect kernel.\n return connectViaPopup({\n walletUrl,\n permissionRequests: params.permissionRequests,\n timeout,\n appName,\n appIcon,\n });\n },\n };\n}\n", "/**\n * DWeb Connect wallet transport \u2014 the wallet side of the popup/postMessage\n * connect flow, exported for wallet apps (e.g. the Enbox web wallet).\n *\n * A wallet's `/dweb-connect` page creates one transport per session:\n *\n * 1. `create()` generates a fresh ephemeral X25519 key pair and emits the\n * `loaded` beacon (public key + wallet origin) to the opener window with a\n * pinned `targetOrigin`.\n * 2. `awaitRequest()` receives the sealed request ciphertext and opens it via\n * the `@enbox/connect` kernel (`ConnectProvider.openRequest`), which\n * value-checks the `apv` origin binding against this wallet's origin.\n * 3. After the consent ceremony, the wallet posts the sealed response JWE via\n * `sendResponse()` \u2014 or the deny token via `deny()` \u2014 back to the opener,\n * again with a pinned `targetOrigin`.\n *\n * The dapp origin is never assumed: it is taken from an explicit option or\n * derived from `document.referrer`, and `create()` fails when neither is\n * available. `'*'` is never used as a `targetOrigin`.\n *\n * @module\n */\n\nimport type { ConnectRequest } from '@enbox/connect';\nimport type { Jwk } from '@enbox/crypto';\n\nimport { X25519 } from '@enbox/crypto';\nimport { CONNECT_DENIED_TOKEN, ConnectProvider } from '@enbox/connect';\n\nimport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n getTrustedMessage,\n} from './dweb-connect-messages.js';\n\n/** Default budget for awaiting the dapp's sealed request. */\nconst DEFAULT_REQUEST_TIMEOUT_MS = 300_000;\n\n/** Options for creating a {@link WalletPostMessageTransport}. */\nexport type WalletPostMessageTransportOptions = {\n /**\n * Origin of the dapp that opened this wallet popup. When omitted, it is\n * derived from `document.referrer`; creation fails when neither is\n * available \u2014 the transport never falls back to `'*'`.\n */\n dappOrigin?: string;\n\n /**\n * The dapp window to exchange messages with.\n * @default window.opener\n */\n dappWindow?: Window;\n\n /**\n * Budget in milliseconds for awaiting the dapp's sealed request.\n * @default 300_000 (5 minutes)\n */\n timeoutMs?: number;\n};\n\n/**\n * Wallet-side postMessage transport for the DWeb Connect popup flow.\n *\n * Security properties:\n * - `targetOrigin` of every outbound `postMessage` (beacon and response) is\n * pinned to the dapp origin \u2014 never `'*'`.\n * - Inbound messages are dropped unless `event.origin` equals the pinned dapp\n * origin AND `event.source` is the dapp window.\n * - The ephemeral X25519 private key never leaves the transport; the request\n * JWE is opened by the kernel with the `apv` header value-checked against\n * this wallet's own origin.\n */\nexport class WalletPostMessageTransport {\n private readonly _dappOrigin: string;\n private readonly _dappWindow: Window;\n private readonly _recipientPrivateKey: Jwk;\n\n private _requestReceived = false;\n private _timeoutId?: ReturnType<typeof setTimeout>;\n private _messageListener?: (event: MessageEvent) => void;\n\n private readonly _requestPromise: Promise<ConnectRequest>;\n private _resolveRequest?: (request: ConnectRequest) => void;\n private _rejectRequest?: (error: Error) => void;\n\n private constructor(params: { dappOrigin: string; dappWindow: Window; recipientPrivateKey: Jwk; timeoutMs: number }) {\n this._dappOrigin = params.dappOrigin;\n this._dappWindow = params.dappWindow;\n this._recipientPrivateKey = params.recipientPrivateKey;\n\n this._requestPromise = new Promise<ConnectRequest>((resolve, reject): void => {\n this._resolveRequest = resolve;\n this._rejectRequest = reject;\n });\n // Mark early rejections (timeout before `awaitRequest()` is called) as\n // handled until the wallet attaches its own handlers.\n this._requestPromise.catch((): undefined => undefined);\n\n this._messageListener = (event: MessageEvent): void => { this.onMessage(event); };\n window.addEventListener('message', this._messageListener);\n\n this._timeoutId = setTimeout((): void => {\n this.close();\n this._rejectRequest?.(new Error('[@enbox/browser] Timed out waiting for the connect request from the dapp.'));\n }, params.timeoutMs);\n }\n\n /**\n * Creates the transport for one connect session: resolves and pins the dapp\n * origin, generates a fresh ephemeral X25519 key pair, starts listening for\n * the sealed request, and emits the `loaded` beacon to the dapp window.\n *\n * @throws If not in a browser, if no dapp window is available, or if the\n * dapp origin can neither be supplied nor derived from the referrer.\n */\n public static async create(options: WalletPostMessageTransportOptions = {}): Promise<WalletPostMessageTransport> {\n if (typeof window === 'undefined') {\n throw new Error('[@enbox/browser] WalletPostMessageTransport is only available in browser environments.');\n }\n\n const dappWindow = options.dappWindow ?? window.opener as Window | null;\n if (!dappWindow) {\n throw new Error('[@enbox/browser] No opener window: the DWeb Connect page must be opened as a popup by the dapp.');\n }\n\n const dappOrigin = resolveDappOrigin(options.dappOrigin);\n\n const recipientPrivateKey = await X25519.generateKey();\n const walletEpk: Jwk = { kty: 'OKP', crv: 'X25519', x: recipientPrivateKey.x };\n\n const transport = new WalletPostMessageTransport({\n dappOrigin,\n dappWindow,\n recipientPrivateKey,\n timeoutMs: options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n });\n\n // The listener is registered, so the beacon cannot race the request.\n dappWindow.postMessage({\n type : DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n walletEpk,\n walletOrigin : globalThis.location.origin,\n }, dappOrigin);\n\n return transport;\n }\n\n /** The pinned origin of the dapp this transport exchanges messages with. */\n public get dappOrigin(): string {\n return this._dappOrigin;\n }\n\n /**\n * Awaits the dapp's sealed request and opens it via the kernel: ECDH-ES\n * decryption with this session's ephemeral key, `apv` value-checked against\n * this wallet's origin, JWT signature verification, and payload shape\n * assertion. Rejects on timeout, on an unopenable request, or when the\n * request does not use the `post_message` reply mode.\n */\n public async awaitRequest(): Promise<ConnectRequest> {\n return await this._requestPromise;\n }\n\n /**\n * Posts the sealed response JWE (or the deny token) back to the dapp window\n * with the `targetOrigin` pinned to the dapp origin, then closes the\n * transport.\n *\n * @param idToken - The sealed response JWE, or the literal deny token.\n */\n public sendResponse(idToken: string): void {\n this._dappWindow.postMessage({\n type : DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n payload : idToken,\n }, this._dappOrigin);\n this.close();\n }\n\n /** Posts the deny token back to the dapp \u2014 the user rejected the request. */\n public deny(): void {\n this.sendResponse(CONNECT_DENIED_TOKEN);\n }\n\n /** Stops listening and releases the session's timers. Idempotent. */\n public close(): void {\n clearTimeout(this._timeoutId);\n if (this._messageListener !== undefined) {\n window.removeEventListener('message', this._messageListener);\n this._messageListener = undefined;\n }\n }\n\n private onMessage(event: MessageEvent): void {\n const message = getTrustedMessage(event, this._dappOrigin, this._dappWindow);\n if (message === undefined) { return; }\n\n if (message.type !== DWEB_CONNECT_REQUEST_MESSAGE_TYPE || this._requestReceived) { return; }\n this._requestReceived = true;\n\n if (typeof message.jwe !== 'string') {\n this.settleRequest(new Error('[@enbox/browser] Connect request message did not carry a ciphertext payload.'));\n return;\n }\n\n void this.openRequest(message.jwe);\n }\n\n private async openRequest(jwe: string): Promise<void> {\n try {\n const request = await ConnectProvider.openRequest({\n jwe,\n decryption: {\n mode : 'ecdh-es',\n recipientPrivateKey : this._recipientPrivateKey,\n walletOrigin : globalThis.location.origin,\n },\n });\n\n if (request.reply.mode !== 'post_message') {\n this.settleRequest(new Error('[@enbox/browser] Connect request over the popup channel must use the `post_message` reply mode.'));\n return;\n }\n\n this.settleRequest(request);\n } catch (error) {\n this.settleRequest(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private settleRequest(outcome: ConnectRequest | Error): void {\n clearTimeout(this._timeoutId);\n if (outcome instanceof Error) {\n this.close();\n this._rejectRequest?.(outcome);\n return;\n }\n this._resolveRequest?.(outcome);\n }\n}\n\n/**\n * Resolves the dapp origin to pin: the explicit option when provided,\n * otherwise the origin of `document.referrer`. Never falls back to `'*'`.\n */\nfunction resolveDappOrigin(explicitOrigin: string | undefined): string {\n if (explicitOrigin !== undefined) {\n return new URL(explicitOrigin).origin;\n }\n\n if (document.referrer) {\n return new URL(document.referrer).origin;\n }\n\n throw new Error(\n '[@enbox/browser] Unable to determine the dapp origin: no `dappOrigin` option was provided and `document.referrer` is empty.'\n );\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["Enbox", "defineProtocol", "repository", "AuthManager", "AuthSession", "normalizeProtocolRequests", "WalletConnect", "CONNECT_DENIED_TOKEN", "ConnectProvider", "DidDht", "DidWeb", "UniversalResolver", "parseDrlUrl", "url", "idx", "prefix", "rest", "slashIdx", "didResolver", "UniversalResolver", "DidDht", "DidWeb", "httpToHttpsRegex", "trailingSlashRegex", "DRL_CACHE_NAME", "getDwnEndpoints", "did", "didDocument", "endpoints", "service", "url", "openDrlCache", "handleEvent", "event", "path", "options", "drl", "responseCache", "cachedResponse", "match", "cacheTime", "fetchResource", "response", "error", "lastError", "endpoint", "cacheResponse", "cache", "clonedResponse", "headers", "modifiedResponse", "installWorker", "workerSelf", "parsed", "parseDrlUrl", "installUrl", "loaderStyles", "tabContent", "elementsInjected", "overlayElement", "styleElement", "injectElements", "cancelNavigation", "removeElements", "activeNavigation", "linkFeaturesActive", "clickHandler", "pointerdownHandler", "addLinkFeatures", "anchor", "href", "openAsTab", "tab", "target", "resetContextMenuTarget", "contextMenuTarget", "removeLinkFeatures", "e", "r", "activatePolyfills", "deactivatePolyfills", "clearDrlCache", "assertX25519PublicJwk", "CONNECT_DENIED_TOKEN", "ConnectClient", "DWEB_CONNECT_PATH", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "getTrustedMessage", "event", "expectedOrigin", "expectedSource", "data", "DEFAULT_TIMEOUT_MS", "CLOSED_POLL_INTERVAL_MS", "POPUP_WINDOW_NAME", "POPUP_WINDOW_FEATURES", "assertBrowserEnvironment", "PopupWindowClosedError", "PopupClientTransport", "options", "popupUrl", "DWEB_CONNECT_PATH", "popup", "resolve", "reject", "event", "state", "jwe", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "message", "getTrustedMessage", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "walletEpk", "assertX25519PublicJwk", "CONNECT_DENIED_TOKEN", "error", "collectBrowserClientMetadata", "resolvedOptions", "languages", "language", "connectViaPopup", "transport", "client", "ConnectClient", "showWalletSelector", "wallets", "resolve", "reject", "host", "shadow", "onKeydown", "cleanup", "isDark", "style", "buildStyles", "overlay", "modal", "header", "title", "closeBtn", "
|
|
4
|
+
"sourcesContent": ["/**\n * @enbox/browser \u2014 The Enbox browser SDK.\n *\n * For browser-based dapps, this is the only package you need to import.\n * It re-exports the high-level API from `@enbox/api`, the authentication\n * layer from `@enbox/auth`, and provides browser-specific connect handlers.\n *\n * @example Single-import dapp setup\n * ```ts\n * import {\n * Enbox, BrowserConnectHandler,\n * defineProtocol, repository,\n * } from '@enbox/browser';\n *\n * const { enbox, session } = await Enbox.connect({\n * connectHandler: BrowserConnectHandler({ appName: 'My App' }),\n * protocols: [MyProtocol],\n * });\n * ```\n *\n * For non-browser environments (Node.js, CLI, desktop), import from\n * `@enbox/api` and `@enbox/auth` directly instead.\n *\n * @packageDocumentation\n */\n\n// \u2500\u2500\u2500 Re-exports from @enbox/api \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The high-level Enbox API: DWN records, protocols, repositories.\n\nexport {\n Enbox,\n defineProtocol,\n repository,\n} from '@enbox/api';\n\nexport type {\n EnboxAnonymousOptions,\n EnboxConnectOptions,\n EnboxConnectResult,\n EnboxParams,\n EnboxSessionParams,\n} from '@enbox/api';\n\n// \u2500\u2500\u2500 Re-exports from @enbox/auth \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Authentication lifecycle, session management, connect handlers.\n\nexport {\n AuthManager,\n AuthSession,\n normalizeProtocolRequests,\n WalletConnect,\n} from '@enbox/auth/browser';\n\nexport type {\n AuthEvent,\n AuthEventHandler,\n AuthManagerOptions,\n AuthState,\n ConnectHandler,\n ConnectOptions,\n ConnectResult,\n DisconnectOptions,\n HandlerConnectOptions,\n ImportFromPortableOptions,\n VaultConnectOptions,\n Permission,\n PortableIdentity,\n ProtocolRequest,\n RegistrationOptions,\n StorageAdapter,\n SyncOption,\n WalletConnectOptions,\n} from '@enbox/auth/browser';\n\n// \u2500\u2500\u2500 Re-exports from @enbox/connect \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The connect kernel pieces wallet apps need alongside the popup\n// transports: opening/sealing envelopes and the deny token.\n\nexport { CONNECT_DENIED_TOKEN, ConnectProvider } from '@enbox/connect';\nexport type { ConnectApproval, ConnectPermissionRequest, ConnectRequest } from '@enbox/connect';\n\n// \u2500\u2500\u2500 Browser-specific exports \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// DWeb Connect popup transports, wallet selector, DRL polyfills.\n\nexport * from './web-features.js';\nexport { BrowserConnectHandler, DEFAULT_WALLETS } from './browser-connect-handler.js';\nexport type { BrowserConnectHandlerOptions, WalletOption } from './browser-connect-handler.js';\nexport { connectViaPopup, PopupClientTransport, PopupWindowClosedError } from './dweb-connect-client.js';\nexport type { PopupClientTransportOptions, PopupConnectOptions } from './dweb-connect-client.js';\nexport { WalletPostMessageTransport } from './dweb-connect-wallet.js';\nexport type { WalletPostMessageTransportOptions } from './dweb-connect-wallet.js';\nexport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_PATH,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n} from './dweb-connect-messages.js';\nexport type {\n DWebConnectLoadedMessage,\n DWebConnectRequestMessage,\n DWebConnectResponseMessage,\n} from './dweb-connect-messages.js';\nexport type { WalletSelectorOptions } from './ui/wallet-selector.js';\nexport { probeWalletWellKnown, showWalletSelector, WALLET_WELL_KNOWN_PATH } from './ui/wallet-selector.js';\n", "/*\n This file is run in dual environments to make installation of the Service Worker code easier.\n Be mindful that code placed in any open excution space may be evaluated multiple times in different contexts,\n so take care to gate additions to only activate code in the right env, such as a Service Worker scope or page window.\n*/\n\nimport type { DidMethodResolver } from '@enbox/dids';\n\nimport { DidDht, DidWeb, UniversalResolver } from '@enbox/dids';\n\n/**\n * Result returned by the `onCacheCheck` callback.\n * When returned, it signals that the response for the given DRL should be cached.\n */\nexport type CacheCheckResult = {\n /** Time-to-live for the cached DRL response, in milliseconds. */\n ttl?: number;\n};\n\n/**\n * Callback invoked to determine whether a DRL response should be cached and for how long.\n * Returning a truthy `CacheCheckResult` opts in to caching; returning a falsy value skips it.\n */\nexport type CacheCheckCallback = (\n event: FetchEvent | Event,\n drl: string,\n) => CacheCheckResult | undefined | null | Promise<CacheCheckResult | undefined | null>;\n\n/**\n * Configuration options for {@link activatePolyfills}.\n */\nexport type ActivatePolyfillsOptions = {\n /**\n * Path to the script to register as a Service Worker.\n * Falls back to `document.currentScript.src` or `import.meta.url`.\n *\n * **Required in strict CSP environments** where `new Function()` is blocked and `import.meta`\n * cannot be evaluated dynamically.\n */\n path?: string;\n /** Set to `false` to skip Service Worker installation. Defaults to `true`. */\n serviceWorker?: boolean;\n /** Set to `false` to skip injection of DRL loading-overlay styles. Defaults to `true`. */\n injectStyles?: boolean;\n /** Set to `false` to skip activation of DRL anchor/link click handling. Defaults to `true`. */\n links?: boolean;\n /** Callback to control per-request caching behaviour. */\n onCacheCheck?: CacheCheckCallback;\n /**\n * DID method resolvers to use for DRL resolution. Defaults to `[DidDht, DidWeb]`.\n * Pass a custom array to add or replace DID methods (e.g., `[DidDht, DidWeb, DidJwk]`).\n */\n didResolvers?: DidMethodResolver[];\n};\n\n/**\n * An `HTMLElement` that has a `src` property (e.g., `<img>`, `<video>`, `<audio>`).\n * Extended with `__src__` to stash the original DRL src during context-menu swaps.\n */\ninterface DrlMediaElement extends HTMLElement {\n src: string;\n __src__?: string;\n}\n\nlet didResolver = new UniversalResolver({ didResolvers: [DidDht, DidWeb] });\n\nimport { parseDrlUrl } from './drl-url-parser.js';\nexport { parseDrlUrl } from './drl-url-parser.js';\n\nconst httpToHttpsRegex = /^http:/;\nconst trailingSlashRegex = /\\/$/;\nconst DRL_CACHE_NAME = 'drl';\n\n/** @internal Exported for testing. Resolves DWN service endpoints from a DID. */\nexport async function getDwnEndpoints(did: string): Promise<string[]> {\n const { didDocument } = await didResolver.resolve(did);\n const endpoints = didDocument?.service?.find(\n (service) => service.type === 'DecentralizedWebNode'\n )?.serviceEndpoint;\n if (!endpoints) {return [];}\n return (Array.isArray(endpoints) ? endpoints : [endpoints]).filter(\n (url) => typeof url === 'string' && url.startsWith('http')\n );\n}\n\n/** Returns an open DRL cache, or `undefined` if the Cache API is unavailable. */\nasync function openDrlCache(): Promise<Cache | undefined> {\n if (typeof caches === 'undefined') {return undefined;}\n return caches.open(DRL_CACHE_NAME);\n}\n\n/** @internal Exported for testing. Handles a DRL fetch event. */\nexport async function handleEvent(\n event: FetchEvent, did: string, path: string, options?: ActivatePolyfillsOptions\n): Promise<Response> {\n const drl = event.request.url\n .replace(httpToHttpsRegex, 'https:')\n .replace(trailingSlashRegex, '');\n const responseCache = await openDrlCache();\n const cachedResponse = await responseCache?.match(drl);\n if (cachedResponse) {\n if (!navigator.onLine) {return cachedResponse;}\n const match = await options?.onCacheCheck?.(event, drl);\n if (match) {\n const cacheTime = cachedResponse.headers.get('dwn-cache-time');\n if (\n cacheTime &&\n Date.now() < Number(cacheTime) + (Number(match.ttl) || 0)\n ) {\n return cachedResponse;\n }\n }\n }\n try {\n if (path) {\n return await fetchResource(event, did, drl, path, responseCache, options);\n } else {\n const response = await didResolver.resolve(did);\n return new Response(JSON.stringify(response), {\n status : 200,\n headers : {\n 'Content-Type': 'application/json',\n },\n });\n }\n } catch (error) {\n if (error instanceof Response) {\n return error;\n }\n console.log(`Error in DID URL fetch: ${error}`);\n return new Response('DID URL fetch error', { status: 500 });\n }\n}\n\n/** @internal Exported for testing. Fetches a resource from DWN endpoints. */\nexport async function fetchResource(\n event: FetchEvent, did: string, drl: string, path: string,\n responseCache: Cache | undefined, options?: ActivatePolyfillsOptions\n): Promise<Response> {\n const endpoints = await getDwnEndpoints(did);\n if (!endpoints?.length) {\n throw new Response(\n 'DWeb Node resolution failed: no valid endpoints found.',\n { status: 530 }\n );\n }\n let lastError: Response | undefined;\n for (const endpoint of endpoints) {\n try {\n const url = `${endpoint.replace(trailingSlashRegex, '')}/${did}/${path}`;\n const response = await fetch(url, { headers: event.request.headers });\n if (response.ok) {\n const match = await options?.onCacheCheck?.(event, drl);\n if (match && responseCache) {\n cacheResponse(drl, url, response, responseCache);\n }\n return response;\n }\n console.log(`DWN endpoint error: ${response.status}`);\n lastError = new Response('DWeb Node request failed', {\n status: response.status,\n });\n } catch (error) {\n console.log(`DWN endpoint error: ${error}`);\n lastError = new Response('DWeb Node request failed', {\n status: 500,\n });\n }\n }\n return lastError!;\n}\n\n/** @internal Exported for testing. Caches a DRL response with metadata headers. */\nexport async function cacheResponse(drl: string, url: string, response: Response, cache: Cache): Promise<void> {\n try {\n const clonedResponse = response.clone();\n const headers = new Headers(clonedResponse.headers);\n headers.append('dwn-cache-time', Date.now().toString());\n headers.append('dwn-composed-url', url);\n const modifiedResponse = new Response(clonedResponse.body, { headers });\n await cache.put(drl, modifiedResponse);\n } catch (error) {\n console.log(`Failed to cache DRL response: ${error}`);\n }\n}\n\n/* Service Worker-based features */\n\nasync function installWorker(options: ActivatePolyfillsOptions = {}): Promise<void> {\n try {\n // Check to see if we are in a Service Worker already, if so, proceed\n // You can call the activatePolyfills() function in your own worker, or standalone as a root worker\n if (\n typeof ServiceWorkerGlobalScope !== 'undefined' &&\n self instanceof ServiceWorkerGlobalScope\n ) {\n const workerSelf = self as unknown as ServiceWorkerGlobalScope;\n workerSelf.skipWaiting();\n workerSelf.addEventListener('activate', (event: ExtendableEvent) => {\n // Claim clients to make the service worker take control immediately\n event.waitUntil(workerSelf.clients.claim());\n });\n workerSelf.addEventListener('fetch', (event: FetchEvent) => {\n const parsed = parseDrlUrl(event.request.url);\n if (parsed) {\n event.respondWith(handleEvent(event, parsed[0], parsed[1], options));\n }\n });\n }\n // If the code gets here, it is not a SW env, it is likely DOM, but check to be sure\n else if (globalThis?.navigator?.serviceWorker) {\n const registration = await navigator.serviceWorker.getRegistration('/');\n // You can only have one worker per path, so check to see if one is already registered\n if (!registration) {\n const installUrl: string | undefined =\n options.path ||\n (document?.currentScript as HTMLScriptElement | null)?.src ||\n import.meta.url;\n if (installUrl)\n {navigator.serviceWorker\n .register(installUrl, { type: 'module' })\n .catch((error: unknown) => {\n console.error(\n 'DWeb networking feature installation failed: ',\n error\n );\n });}\n }\n } else {\n throw new Error(\n 'DWeb networking features are not available for install in this environment'\n );\n }\n } catch (error) {\n console.error('Error in installing networking features:', error);\n }\n}\n\n/* DOM Environment Features */\n\nconst loaderStyles = `\n .drl-loading-overlay {\n position: fixed;\n inset: 0;\n display: flex;\n flex-wrap: wrap;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: 22px;\n color: #fff;\n background: rgba(0, 0, 0, 0.75);\n backdrop-filter: blur(15px);\n -webkit-backdrop-filter: blur(15px);\n z-index: 1000000;\n }\n\n .drl-loading-overlay > div {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .drl-loading-spinner {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .drl-loading-spinner div {\n position: relative;\n width: 2em;\n height: 2em;\n margin: 0.1em 0.25em 0 0;\n }\n .drl-loading-spinner div::after,\n .drl-loading-spinner div::before {\n content: ''; \n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 0.1em solid #FFF;\n position: absolute;\n left: 0;\n top: 0;\n opacity: 0;\n animation: drl-loading-spinner 2s linear infinite;\n }\n .drl-loading-spinner div::after {\n animation-delay: 1s;\n }\n\n .drl-loading-overlay span {\n --text-opacity: 2;\n display: flex;\n align-items: center;\n margin: 2em auto 0;\n padding: 0.2em 0.75em 0.25em;\n text-align: center;\n border-radius: 5em;\n background: rgba(255 255 255 / 8%);\n opacity: 0.8;\n transition: opacity 0.3s ease;\n cursor: pointer;\n }\n\n .drl-loading-overlay span:focus {\n opacity: 1;\n }\n\n .drl-loading-overlay span:hover {\n opacity: 1;\n }\n\n .drl-loading-overlay span::before {\n content: '\u2715 ';\n margin: 0 0.4em 0 0;\n color: red;\n font-size: 65%;\n font-weight: bold;\n }\n\n .drl-loading-overlay span::after {\n content: 'stop';\n display: block;\n font-size: 60%;\n line-height: 0;\n color: rgba(255 255 255 / 60%);\n }\n\n .drl-loading-overlay.new-tab-overlay span::after {\n content: 'close';\n }\n \n @keyframes drl-loading-spinner {\n 0% {\n transform: scale(0);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n opacity: 0;\n }\n }\n`;\nconst tabContent = `\n<!DOCTYPE html>\n<html lang='en'>\n<head>\n <meta charset='UTF-8'>\n <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n <title>Loading DRL...</title>\n <style>\n html, body {\n background-color: #151518;\n height: 100%;\n margin: 0;\n padding: 0;\n font-family: Arial, sans-serif;\n text-align: center;\n }\n ${loaderStyles}\n </style>\n</head>\n<body>\n <div class='drl-loading-overlay new-tab-overlay'>\n <div class='drl-loading-spinner'>\n <div></div>\n Loading DRL\n </div>\n <span onclick='window.close()' tabindex='0'></span>\n </div>\n</body>\n</html>\n`;\n\nlet elementsInjected = false;\nlet overlayElement: HTMLDivElement | null = null;\nlet styleElement: HTMLStyleElement | null = null;\n\nfunction injectElements(): void {\n if (elementsInjected) {return;}\n styleElement = document.createElement('style');\n styleElement.innerHTML = `\n ${loaderStyles}\n\n .drl-loading-overlay {\n opacity: 0;\n transition: opacity 0.3s ease;\n pointer-events: none;\n }\n\n :root[drl-link-loading] .drl-loading-overlay {\n opacity: 1;\n pointer-events: all;\n }\n `;\n document.head.append(styleElement);\n\n overlayElement = document.createElement('div');\n overlayElement.classList.add('drl-loading-overlay');\n overlayElement.innerHTML = `\n <div class='drl-loading-spinner'>\n <div></div>\n Loading DRL\n </div> \n <span tabindex='0'></span>\n `;\n overlayElement.lastElementChild!.addEventListener('click', cancelNavigation);\n document.body.prepend(overlayElement);\n elementsInjected = true;\n}\n\nfunction removeElements(): void {\n if (!elementsInjected) {return;}\n styleElement?.remove();\n styleElement = null;\n overlayElement?.remove();\n overlayElement = null;\n elementsInjected = false;\n}\n\nfunction cancelNavigation(): void {\n document.documentElement.removeAttribute('drl-link-loading');\n activeNavigation = null;\n}\n\nlet activeNavigation: string | null = null;\nlet linkFeaturesActive = false;\n\n// Stored references for listener cleanup in deactivatePolyfills()\nlet clickHandler: ((event: MouseEvent) => Promise<void>) | null = null;\nlet pointerdownHandler: ((event: PointerEvent) => Promise<void>) | null = null;\n\nfunction addLinkFeatures(): void {\n if (!linkFeaturesActive) {\n clickHandler = async (event: MouseEvent): Promise<void> => {\n const anchor = (event.target as Element)?.closest('a');\n if (anchor) {\n const href = anchor.href;\n const parsed = parseDrlUrl(href);\n if (parsed) {\n const did = parsed[0];\n const path = parsed[1];\n const openAsTab = anchor.target === '_blank';\n event.preventDefault();\n try {\n let tab: Window | null = null;\n if (openAsTab) {\n tab = window.open('', '_blank');\n if (tab) {tab.document.write(tabContent);}\n } else {\n activeNavigation = path;\n // this is to allow for cached DIDs to instantly load without any flash of loading UI\n setTimeout(\n () =>\n document.documentElement.setAttribute('drl-link-loading', ''),\n 50\n );\n }\n const endpoints = await getDwnEndpoints(did);\n if (!endpoints.length) {\n throw new Error('no valid DWN endpoints found');\n }\n const url = `${endpoints[0].replace(\n trailingSlashRegex,\n ''\n )}/${did}/${path}`;\n if (openAsTab) {\n if (tab && !tab.closed) {tab.location.href = url;}\n } else if (activeNavigation === path) {\n window.location.href = url;\n }\n } catch {\n if (activeNavigation === path) {\n cancelNavigation();\n }\n throw new Error(\n `DID endpoint resolution failed for the DRL: ${href}`\n );\n }\n }\n }\n };\n\n pointerdownHandler = async (event: PointerEvent): Promise<void> => {\n const target = event.composedPath()[0] as DrlMediaElement | undefined;\n if (\n (event.pointerType === 'mouse' && event.button === 2) ||\n (event.pointerType === 'touch' && event.isPrimary)\n ) {\n resetContextMenuTarget();\n if (target?.src && parseDrlUrl(target.src)) {\n contextMenuTarget = target;\n target.__src__ = target.src;\n const drl = target.src\n .replace(httpToHttpsRegex, 'https:')\n .replace(trailingSlashRegex, '');\n const responseCache = await openDrlCache();\n const response = await responseCache?.match(drl);\n if (response) {\n const url = response.headers.get('dwn-composed-url');\n if (url) {target.src = url;}\n }\n target.addEventListener('pointerup', resetContextMenuTarget, {\n once: true,\n });\n }\n } else if (target === contextMenuTarget) {\n resetContextMenuTarget();\n }\n };\n\n document.addEventListener('click', clickHandler);\n document.addEventListener('pointercancel', resetContextMenuTarget);\n document.addEventListener('pointerdown', pointerdownHandler);\n\n linkFeaturesActive = true;\n }\n}\n\nfunction removeLinkFeatures(): void {\n if (!linkFeaturesActive) {return;}\n if (clickHandler) {\n document.removeEventListener('click', clickHandler);\n clickHandler = null;\n }\n if (pointerdownHandler) {\n document.removeEventListener('pointerdown', pointerdownHandler);\n pointerdownHandler = null;\n }\n document.removeEventListener('pointercancel', resetContextMenuTarget);\n resetContextMenuTarget();\n cancelNavigation();\n linkFeaturesActive = false;\n}\n\nlet contextMenuTarget: DrlMediaElement | null = null;\nasync function resetContextMenuTarget(e?: Event): Promise<void> {\n if (e?.type === 'pointerup') {\n await new Promise<void>((r) => requestAnimationFrame(() => r()));\n }\n if (contextMenuTarget) {\n contextMenuTarget.src = contextMenuTarget.__src__!;\n delete contextMenuTarget.__src__;\n contextMenuTarget = null;\n }\n}\n\n/**\n * Activates various polyfills to enable Enbox features in Web environments.\n *\n * @param options - Configuration options to control the activation of polyfills.\n *\n * @example\n * // Activate all polyfills with default options, and cache every DRL for 1 minute\n * activatePolyfills({\n * onCacheCheck(event, route){\n * return {\n * ttl: 60_000\n * }\n * }\n * });\n *\n * @example\n * // Activate polyfills, but without Service Worker activation\n * activatePolyfills({ serviceWorker: false });\n *\n * @example\n * // Use custom DID resolvers\n * activatePolyfills({ didResolvers: [DidDht, DidWeb, DidJwk] });\n */\nexport function activatePolyfills(options: ActivatePolyfillsOptions = {}): void {\n if (options.didResolvers) {\n didResolver = new UniversalResolver({ didResolvers: options.didResolvers });\n }\n if (options.serviceWorker !== false) {\n installWorker(options);\n }\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n if (options.injectStyles !== false) {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', injectElements, {\n once: true,\n });\n } else {injectElements();}\n }\n if (options.links !== false) {addLinkFeatures();}\n }\n}\n\n/**\n * Removes all polyfill event listeners, injected DOM elements, and resets internal state.\n * Call this to fully clean up after {@link activatePolyfills}.\n *\n * Does **not** unregister an installed Service Worker \u2014 use\n * `navigator.serviceWorker.getRegistration('/').then(r => r?.unregister())` for that.\n */\nexport function deactivatePolyfills(): void {\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n removeLinkFeatures();\n removeElements();\n }\n}\n\n/**\n * Deletes the entire DRL response cache.\n * Useful for clearing stale cached DWN responses.\n *\n * @returns `true` if the cache existed and was deleted, `false` otherwise.\n * Returns `false` if the Cache API is unavailable.\n */\nexport async function clearDrlCache(): Promise<boolean> {\n if (typeof caches === 'undefined') {return false;}\n return caches.delete(DRL_CACHE_NAME);\n}\n", "/**\n * Parses a DRL URL (http(s)://dweb/{did}/{path}) without regex quantifiers.\n * Returns `[did, path]` or `null` if the URL does not match the DRL scheme.\n *\n * Extracted to a standalone module so it can be tested under Node.js (bun:test)\n * in addition to the browser-based vitest suite, ensuring SonarCloud's\n * merged coverage report includes these lines.\n */\nexport function parseDrlUrl(url: string): [string, string] | null {\n const idx = url.indexOf('://dweb/');\n if (idx === -1) { return null; }\n const prefix = url.slice(0, idx);\n if (prefix !== 'http' && prefix !== 'https') { return null; }\n const rest = url.slice(idx + 8); // '://dweb/'.length === 8\n if (rest.length === 0) { return null; }\n const slashIdx = rest.indexOf('/');\n if (slashIdx === -1) { return [rest, '']; }\n if (slashIdx === 0) { return null; } // DID segment must be non-empty\n return [rest.slice(0, slashIdx), rest.slice(slashIdx + 1)];\n}\n", "/**\n * DWeb Connect client \u2014 the dapp side of the popup/postMessage connect flow.\n *\n * {@link PopupClientTransport} implements the `@enbox/connect` kernel's\n * `ConnectTransport` over a wallet popup:\n *\n * 1. The dapp opens `${walletUrl}/dweb-connect` as a popup window.\n * 2. The wallet emits a `loaded` beacon carrying a fresh ephemeral X25519\n * public key and its origin.\n * 3. The kernel seals the signed connect request to that key (ECDH-ES,\n * `apv` bound to the wallet origin) and the transport posts the\n * ciphertext to the popup.\n * 4. The wallet posts back the sealed response JWE (or the deny token),\n * which the kernel opens and value-checks.\n *\n * Only ciphertext crosses the postMessage channel. Every message is checked\n * against the wallet origin derived from the configured wallet URL (never\n * `'*'`), and against the popup window as `event.source`.\n *\n * @module\n */\n\nimport type { Jwk } from '@enbox/crypto';\nimport type {\n ConnectClientMetadata,\n ConnectPermissionRequest,\n ConnectRequestProfile,\n ConnectResult,\n ConnectTransport,\n} from '@enbox/connect';\n\nimport { assertX25519PublicJwk, CONNECT_DENIED_TOKEN, ConnectClient } from '@enbox/connect';\n\nimport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_PATH,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n getTrustedMessage,\n} from './dweb-connect-messages.js';\n\n/** Default budget for the whole popup handshake (beacon + user consent + response). */\nconst DEFAULT_TIMEOUT_MS = 300_000;\n\n/** Interval at which the transport checks whether the user closed the popup. */\nconst CLOSED_POLL_INTERVAL_MS = 500;\n\n/** Window name given to the wallet popup. */\nconst POPUP_WINDOW_NAME = 'enbox-dweb-connect';\n\n/** Window features given to the wallet popup. */\nconst POPUP_WINDOW_FEATURES = 'width=500,height=700,menubar=no,toolbar=no,location=no,status=no';\n\n/** Guards against calling browser-only entry points outside a browser. */\nfunction assertBrowserEnvironment(): void {\n if (typeof window === 'undefined') {\n throw new Error('[@enbox/browser] DWeb Connect is only available in browser environments.');\n }\n}\n\n/**\n * Thrown when the user closes the wallet popup before the wallet finished\n * loading (i.e. before its `loaded` beacon arrived). Callers typically treat\n * this the same as a user denial.\n */\nexport class PopupWindowClosedError extends Error {\n constructor() {\n super('[@enbox/browser] Wallet popup was closed before the wallet finished loading.');\n this.name = 'PopupWindowClosedError';\n }\n}\n\n/** Options for constructing a {@link PopupClientTransport}. */\nexport type PopupClientTransportOptions = {\n /** Base URL of the wallet app (e.g. `https://enbox-wallet.pages.dev`). */\n walletUrl: string;\n\n /**\n * Total budget in milliseconds for the popup handshake. The popup is closed\n * and the handshake rejected when the wallet has not responded in time.\n * @default 300_000 (5 minutes)\n */\n timeoutMs?: number;\n};\n\n/**\n * Popup/postMessage {@link ConnectTransport} for browser dapps.\n *\n * Single-use: construct a new transport per handshake. The **constructor**\n * opens the wallet popup synchronously \u2014 so `window.open` runs inside the user\n * gesture, ahead of the kernel's awaited key generation, and survives strict\n * popup blockers; `requestProfile()` then awaits the wallet's `loaded` beacon;\n * `deliverRequest()` posts the sealed request ciphertext; `awaitResponse()`\n * resolves with the sealed response JWE, or the deny token when the user denies\n * or closes the popup after the handshake was established.\n *\n * Security properties:\n * - `targetOrigin` of every outbound `postMessage` is pinned to the origin\n * derived from `walletUrl` \u2014 never `'*'`.\n * - Inbound messages are dropped unless `event.origin` equals the pinned\n * wallet origin AND `event.source` is the popup window this transport opened.\n * - The beacon's `walletOrigin` field must equal the pinned origin, and its\n * `walletEpk` must be a public-only X25519 JWK; a malformed beacon from the\n * genuine popup fails the handshake closed.\n */\nexport class PopupClientTransport implements ConnectTransport {\n /** {@inheritDoc ConnectTransport.requiresPin} */\n public readonly requiresPin: boolean = false;\n\n private readonly _walletOrigin: string;\n private readonly _timeoutMs: number;\n\n private readonly _popup: Window;\n private _settled = false;\n private _walletEpkReceived = false;\n private _timeoutId?: ReturnType<typeof setTimeout>;\n private _closedPollId?: ReturnType<typeof setInterval>;\n private _messageListener?: (event: MessageEvent) => void;\n\n private readonly _walletEpkPromise: Promise<Jwk>;\n private _resolveWalletEpk?: (walletEpk: Jwk) => void;\n private _rejectWalletEpk?: (error: Error) => void;\n\n private readonly _responsePromise: Promise<string>;\n private _resolveResponse?: (payload: string) => void;\n private _rejectResponse?: (error: Error) => void;\n\n constructor(options: PopupClientTransportOptions) {\n assertBrowserEnvironment();\n\n this._walletOrigin = new URL(options.walletUrl).origin;\n this._timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n // Open the wallet popup SYNCHRONOUSLY, in the user-gesture call stack,\n // before the kernel's awaited `DidJwk.create()` / `X25519.generateKey()`\n // run. Strict popup blockers (Safari) reject a `window.open` issued once\n // the stack has yielded to a prior `await`, so opening it here \u2014 instead of\n // inside the awaited `requestProfile()` \u2014 is what keeps the flow usable.\n const popupUrl = new URL(DWEB_CONNECT_PATH, options.walletUrl).toString();\n const popup = window.open(popupUrl, POPUP_WINDOW_NAME, POPUP_WINDOW_FEATURES);\n if (!popup) {\n throw new Error('[@enbox/browser] Popup blocked. Allow popups for this site to connect to a wallet.');\n }\n this._popup = popup;\n\n this._walletEpkPromise = new Promise<Jwk>((resolve, reject): void => {\n this._resolveWalletEpk = resolve;\n this._rejectWalletEpk = reject;\n });\n\n // Created up-front so a response (or deny) arriving before\n // `awaitResponse()` is called is never dropped. The no-op catch marks\n // early rejections (timeout, popup closed during load) as handled until\n // the kernel attaches its own handlers via `awaitResponse()`.\n this._responsePromise = new Promise<string>((resolve, reject): void => {\n this._resolveResponse = resolve;\n this._rejectResponse = reject;\n });\n this._responsePromise.catch((): undefined => undefined);\n\n // Listen synchronously, before the wallet page can emit its `loaded`\n // beacon, so the beacon is never missed while the kernel awaits key\n // generation ahead of `requestProfile()`.\n this._messageListener = (event: MessageEvent): void => { this.onMessage(event); };\n window.addEventListener('message', this._messageListener);\n\n this._timeoutId = setTimeout((): void => {\n this.fail(new Error('[@enbox/browser] DWeb Connect timed out waiting for wallet response.'));\n }, this._timeoutMs);\n\n this._closedPollId = setInterval((): void => { this.onClosedPoll(); }, CLOSED_POLL_INTERVAL_MS);\n }\n\n /**\n * Awaits the already-open popup's `loaded` beacon, then returns the popup\n * channel profile: ECDH-ES encryption to the beacon's ephemeral key with the\n * pinned wallet origin as the `apv` binding, a `post_message` reply\n * descriptor, and the client-supplied `state` correlator.\n *\n * The popup was opened synchronously at construction, so this method only\n * awaits the beacon \u2014 it never issues the blocker-sensitive `window.open`.\n *\n * @param state - The handshake correlator minted by the {@link ConnectClient}.\n * @throws If the user closes the popup before the beacon arrives\n * ({@link PopupWindowClosedError}), the beacon is malformed, or on\n * timeout.\n */\n public async requestProfile(state: string): Promise<ConnectRequestProfile> {\n const walletEpk = await this._walletEpkPromise;\n\n return {\n encryption : { mode: 'ecdh-es', walletEpk, walletOrigin: this._walletOrigin },\n reply : { mode: 'post_message' },\n state,\n };\n }\n\n /**\n * Posts the sealed request ciphertext to the wallet popup with the\n * `targetOrigin` pinned to the wallet origin.\n */\n public async deliverRequest(jwe: string): Promise<void> {\n this._popup.postMessage({ type: DWEB_CONNECT_REQUEST_MESSAGE_TYPE, jwe }, this._walletOrigin);\n }\n\n /**\n * Awaits the wallet's response ciphertext: the sealed response JWE, or the\n * deny token when the user denies in the wallet or closes the popup.\n * Rejects on timeout.\n */\n public async awaitResponse(): Promise<string> {\n return await this._responsePromise;\n }\n\n private onMessage(event: MessageEvent): void {\n const message = getTrustedMessage(event, this._walletOrigin, this._popup);\n if (message === undefined) { return; }\n\n if (message.type === DWEB_CONNECT_LOADED_MESSAGE_TYPE) {\n this.onLoadedBeacon(message);\n return;\n }\n\n if (message.type === DWEB_CONNECT_RESPONSE_MESSAGE_TYPE) {\n this.onResponseMessage(message);\n }\n }\n\n private onLoadedBeacon(message: Record<string, unknown>): void {\n if (this._settled || this._walletEpkReceived) { return; }\n\n // The beacon passed the origin and source checks, so a malformed payload\n // is a protocol violation by the genuine popup \u2014 fail closed. The X25519\n // public-JWK shape check is delegated to the connect kernel.\n let walletEpk: Jwk;\n try {\n assertX25519PublicJwk(message.walletEpk);\n walletEpk = message.walletEpk;\n } catch {\n this.fail(new Error('[@enbox/browser] Wallet loaded beacon did not carry a valid X25519 public key.'));\n return;\n }\n\n if (message.walletOrigin !== this._walletOrigin) {\n this.fail(new Error('[@enbox/browser] Wallet loaded beacon origin does not match the configured wallet origin.'));\n return;\n }\n\n this._walletEpkReceived = true;\n this._resolveWalletEpk?.(walletEpk);\n }\n\n private onResponseMessage(message: Record<string, unknown>): void {\n if (this._settled) { return; }\n\n if (typeof message.payload !== 'string') {\n this.fail(new Error('[@enbox/browser] Wallet response message did not carry a ciphertext payload.'));\n return;\n }\n\n this._settled = true;\n this.cleanup();\n // No-op on the normal path; unblocks `requestProfile()` if a response\n // somehow arrives before the beacon.\n this._rejectWalletEpk?.(new Error('[@enbox/browser] Wallet responded before the handshake was established.'));\n this._resolveResponse?.(message.payload);\n }\n\n private onClosedPoll(): void {\n if (this._settled || this._popup.closed !== true) { return; }\n\n if (!this._walletEpkReceived) {\n // Closed before the wallet ever loaded \u2014 the handshake cannot proceed.\n this.fail(new PopupWindowClosedError());\n return;\n }\n\n // Closed after the handshake was established \u2014 treat as a user denial.\n this._settled = true;\n this.cleanup();\n this._resolveResponse?.(CONNECT_DENIED_TOKEN);\n }\n\n private fail(error: Error): void {\n if (this._settled) { return; }\n this._settled = true;\n this.cleanup();\n try { this._popup.close(); } catch { /* best effort */ }\n this._rejectWalletEpk?.(error);\n this._rejectResponse?.(error);\n }\n\n private cleanup(): void {\n clearTimeout(this._timeoutId);\n clearInterval(this._closedPollId);\n if (this._messageListener !== undefined) {\n window.removeEventListener('message', this._messageListener);\n this._messageListener = undefined;\n }\n }\n}\n\n/** Options for a one-shot {@link connectViaPopup} flow. */\nexport type PopupConnectOptions = {\n /** Base URL of the wallet app (e.g. `https://enbox-wallet.pages.dev`). */\n walletUrl: string;\n\n /** DWN protocols and permission scopes to request from the wallet. */\n permissionRequests: ConnectPermissionRequest[];\n\n /**\n * Timeout in milliseconds for the popup handshake.\n * @default 300_000 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Display name of the requesting application, shown in the wallet's\n * consent screen. Defaults to the dapp's host.\n */\n appName?: string;\n\n /**\n * Icon URL of the requesting application, shown alongside the app name in\n * the wallet's consent screen.\n */\n appIcon?: string;\n};\n\n/** Collects self-reported environment hints for the wallet's session display. */\nfunction collectBrowserClientMetadata(): ConnectClientMetadata {\n const resolvedOptions = Intl.DateTimeFormat().resolvedOptions();\n const languages = Array.isArray(globalThis.navigator.languages)\n ? globalThis.navigator.languages.filter((language) => typeof language === 'string' && language.length > 0)\n : undefined;\n\n return {\n origin : globalThis.location.origin,\n userAgent : globalThis.navigator.userAgent,\n platform : globalThis.navigator.platform,\n language : globalThis.navigator.language,\n ...(languages && languages.length > 0 ? { languages } : {}),\n ...(resolvedOptions.timeZone ? { timezone: resolvedOptions.timeZone } : {}),\n };\n}\n\n/**\n * Runs one DWeb Connect popup handshake end-to-end: opens the wallet popup,\n * drives the `@enbox/connect` kernel client over a {@link PopupClientTransport},\n * and returns the delegated credentials.\n *\n * @returns The delegate credentials, or `undefined` when the user denied the\n * request or closed the popup.\n * @throws If the popup is blocked, the handshake times out, or the wallet\n * returns an invalid response.\n */\nexport async function connectViaPopup(options: PopupConnectOptions): Promise<ConnectResult | undefined> {\n const transport = new PopupClientTransport({\n walletUrl : options.walletUrl,\n timeoutMs : options.timeout,\n });\n const client = new ConnectClient({ transport });\n\n try {\n return await client.connect({\n appName : options.appName ?? globalThis.location.host,\n appIcon : options.appIcon,\n clientMetadata : collectBrowserClientMetadata(),\n permissionRequests : options.permissionRequests,\n });\n } catch (error) {\n if (error instanceof PopupWindowClosedError) {\n // The user closed the wallet before it loaded \u2014 same as a denial.\n return undefined;\n }\n throw error;\n }\n}\n", "/**\n * Wire shapes for the DWeb Connect popup/postMessage channel.\n *\n * The dapp and the wallet exchange exactly three message kinds over\n * `window.postMessage`:\n *\n * 1. `loaded` beacon (wallet \u2192 dapp): announces the wallet page is ready and\n * carries a fresh ephemeral X25519 public key plus the wallet's origin.\n * 2. `request` (dapp \u2192 wallet): the sealed connect request JWE \u2014 ciphertext\n * only, encrypted to the beacon key with ECDH-ES and the wallet origin\n * bound into the JWE `apv` header.\n * 3. `response` (wallet \u2192 dapp): the sealed connect response JWE, or the\n * literal deny token \u2014 again ciphertext only.\n *\n * Plaintext never crosses the channel, and both sides pin `targetOrigin`\n * and verify `event.origin` / `event.source` on every message.\n *\n * @module\n */\n\nimport type { Jwk } from '@enbox/crypto';\n\n/** Path of the wallet's DWeb Connect page, opened as a popup by the dapp. */\nexport const DWEB_CONNECT_PATH = '/dweb-connect';\n\n/** Message type of the wallet's `loaded` beacon (wallet \u2192 dapp). */\nexport const DWEB_CONNECT_LOADED_MESSAGE_TYPE = 'enbox-connect-loaded';\n\n/** Message type carrying the sealed connect request JWE (dapp \u2192 wallet). */\nexport const DWEB_CONNECT_REQUEST_MESSAGE_TYPE = 'enbox-connect-request';\n\n/** Message type carrying the sealed connect response JWE or deny token (wallet \u2192 dapp). */\nexport const DWEB_CONNECT_RESPONSE_MESSAGE_TYPE = 'enbox-connect-response';\n\n/**\n * The wallet's readiness beacon. Emitted to `window.opener` once the wallet's\n * DWeb Connect page has generated its per-session ephemeral X25519 key.\n */\nexport type DWebConnectLoadedMessage = {\n type: typeof DWEB_CONNECT_LOADED_MESSAGE_TYPE;\n\n /** Fresh ephemeral X25519 public JWK the dapp seals the request to. */\n walletEpk: Jwk;\n\n /** The wallet's own origin; must match the origin the dapp has pinned. */\n walletOrigin: string;\n};\n\n/** The dapp's sealed connect request, posted to the wallet popup. */\nexport type DWebConnectRequestMessage = {\n type: typeof DWEB_CONNECT_REQUEST_MESSAGE_TYPE;\n\n /** The sealed connect request as a Compact JWE string. */\n jwe: string;\n};\n\n/** The wallet's sealed connect response, posted back to the opener. */\nexport type DWebConnectResponseMessage = {\n type: typeof DWEB_CONNECT_RESPONSE_MESSAGE_TYPE;\n\n /** The sealed connect response JWE, or the literal `CONNECT_DENIED_TOKEN`. */\n payload: string;\n};\n\n/**\n * Applies the shared inbound-message trust filter for the popup channel:\n * pins the message to the expected `event.origin`, pins its `event.source` to\n * the expected window, and requires a non-null object payload.\n *\n * Returns the payload cast to a plain record when every check passes, or\n * `undefined` when the message must be dropped. Both the dapp-side and\n * wallet-side transports early-return on `undefined` before inspecting any\n * message field \u2014 this is the security-critical filter that keeps hostile\n * origins and stray windows off the channel.\n */\nexport function getTrustedMessage(\n event: MessageEvent,\n expectedOrigin: string,\n expectedSource: Window | undefined,\n): Record<string, unknown> | undefined {\n // Origin pinning: only messages from the expected origin count.\n if (event.origin !== expectedOrigin) { return undefined; }\n\n // Source pinning: the message must come from the expected window.\n if (event.source !== expectedSource) { return undefined; }\n\n const data: unknown = event.data;\n if (typeof data !== 'object' || data === null) { return undefined; }\n\n return data as Record<string, unknown>;\n}\n", "/**\n * Wallet selector modal \u2014 a self-contained, framework-agnostic UI component.\n *\n * Injected into the DOM as a Shadow DOM element to prevent style conflicts.\n * Inspired by WalletConnect's Web3Modal pattern.\n *\n * The modal is a single view with three zones:\n *\n * 1. **Quick connect** \u2014 a one-tap button that connects with the recommended\n * (first) wallet without scrolling the grid.\n * 2. **Wallet grid** \u2014 a scrollable grid of wallet tiles with a search filter.\n * Each tile renders the wallet's own favicon, falling back to a letter\n * badge (never a third-party favicon proxy).\n * 3. **Custom URL** \u2014 paste any wallet URL; it is validated against the\n * wallet's `/.well-known/enbox-connect` discovery document before the\n * selection resolves.\n *\n * @module\n */\n\nimport type { WalletOption } from '../browser-connect-handler.js';\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/** Options controlling {@link showWalletSelector} behavior. */\nexport interface WalletSelectorOptions {\n /**\n * Validate a pasted wallet origin before resolving with it.\n *\n * Defaults to {@link probeWalletWellKnown}, which fetches the wallet's\n * `/.well-known/enbox-connect` document. Injectable for testing.\n */\n validateWalletUrl?: (origin: string) => Promise<boolean>;\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 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 false;\n }\n\n const payload = await response.json() as { connectServerUrl?: unknown } | null;\n return typeof payload?.connectServerUrl === 'string';\n } catch {\n return false;\n }\n}\n\n/** Shows the wallet selector modal and resolves with the chosen wallet URL. */\nexport function showWalletSelector(\n wallets: WalletOption[],\n options: WalletSelectorOptions = {},\n): Promise<string> {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new Error('[@enbox/browser] Wallet selector is only available in browser environments.');\n }\n\n const validateWalletUrl = options.validateWalletUrl ?? probeWalletWellKnown;\n\n return new Promise<string>((resolve, reject) => {\n // Create the host element with Shadow DOM isolation.\n const host = document.createElement('div');\n host.id = 'enbox-wallet-selector';\n const shadow = host.attachShadow({ mode: 'open' });\n\n let onKeydown: ((e: KeyboardEvent) => void) | undefined;\n const cleanup = (): void => {\n if (onKeydown !== undefined) {\n document.removeEventListener('keydown', onKeydown);\n onKeydown = undefined;\n }\n\n try { document.body.removeChild(host); } catch { /* best effort */ }\n };\n\n const settleResolve = (url: string): void => {\n cleanup();\n resolve(url);\n };\n\n const settleReject = (): void => {\n cleanup();\n reject(new Error('[@enbox/browser] Wallet selection cancelled.'));\n };\n\n // Detect dark mode.\n const isDark = window.matchMedia?.('(prefers-color-scheme: dark)').matches ?? false;\n\n // Build styles.\n const style = document.createElement('style');\n style.textContent = buildStyles(isDark);\n shadow.appendChild(style);\n\n // Build modal DOM.\n const overlay = document.createElement('div');\n overlay.className = 'overlay';\n\n const modal = document.createElement('div');\n modal.className = 'modal';\n\n modal.appendChild(buildHeader(settleReject));\n\n const recommended = wallets[0];\n if (recommended !== undefined) {\n modal.appendChild(buildQuickConnect(recommended, settleResolve));\n }\n\n modal.appendChild(buildWalletGrid(wallets, settleResolve));\n modal.appendChild(buildSeparator());\n modal.appendChild(buildCustomUrl(validateWalletUrl, settleResolve));\n\n // Close on overlay click.\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) {\n settleReject();\n }\n });\n\n // Close on Escape.\n onKeydown = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n settleReject();\n }\n };\n document.addEventListener('keydown', onKeydown);\n\n overlay.appendChild(modal);\n shadow.appendChild(overlay);\n document.body.appendChild(host);\n\n // Focus the search box for keyboard-first users.\n shadow.querySelector<HTMLInputElement>('.wallet-search')?.focus();\n });\n}\n\n// \u2500\u2500\u2500 DOM builders \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 buildHeader(onCancel: () => void): HTMLDivElement {\n const header = document.createElement('div');\n header.className = 'header';\n\n const title = document.createElement('h2');\n title.textContent = 'Connect a wallet';\n\n const closeBtn = document.createElement('button');\n closeBtn.className = 'close-btn';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = '×';\n closeBtn.addEventListener('click', onCancel);\n\n header.appendChild(title);\n header.appendChild(closeBtn);\n return header;\n}\n\nfunction buildQuickConnect(recommended: WalletOption, onSelect: (url: string) => void): HTMLButtonElement {\n const quick = document.createElement('button');\n quick.className = 'quick-connect';\n\n const bolt = document.createElement('span');\n bolt.className = 'quick-bolt';\n bolt.textContent = '\u26A1'; // \u26A1\n\n const text = document.createElement('span');\n text.className = 'quick-text';\n\n const label = document.createElement('span');\n label.className = 'quick-label';\n label.textContent = 'Quick connect';\n\n const sub = document.createElement('span');\n sub.className = 'quick-sub';\n sub.textContent = `Connect with ${recommended.name}`;\n\n text.appendChild(label);\n text.appendChild(sub);\n quick.appendChild(bolt);\n quick.appendChild(text);\n quick.addEventListener('click', () => onSelect(recommended.url));\n return quick;\n}\n\nfunction buildWalletGrid(wallets: WalletOption[], onSelect: (url: string) => void): HTMLDivElement {\n const section = document.createElement('div');\n section.className = 'grid-section';\n\n const search = document.createElement('input');\n search.type = 'search';\n search.className = 'wallet-search';\n search.placeholder = 'Search wallets\u2026';\n\n const grid = document.createElement('div');\n grid.className = 'wallet-grid';\n\n const empty = document.createElement('div');\n empty.className = 'grid-empty';\n empty.textContent = 'No wallets match your search.';\n empty.style.display = 'none';\n\n const tiles = wallets.map((wallet) => {\n const tile = buildWalletTile(wallet, onSelect);\n grid.appendChild(tile);\n return { name: wallet.name.toLowerCase(), tile };\n });\n\n search.addEventListener('input', () => {\n const query = search.value.trim().toLowerCase();\n let visible = 0;\n for (const { name, tile } of tiles) {\n const match = name.includes(query);\n tile.style.display = match ? '' : 'none';\n if (match) {\n visible += 1;\n }\n }\n empty.style.display = visible === 0 ? '' : 'none';\n });\n\n section.appendChild(search);\n section.appendChild(grid);\n section.appendChild(empty);\n return section;\n}\n\nfunction buildWalletTile(wallet: WalletOption, onSelect: (url: string) => void): HTMLButtonElement {\n const tile = document.createElement('button');\n tile.className = 'wallet-item';\n tile.title = wallet.description ?? wallet.name;\n\n tile.appendChild(buildWalletIcon(wallet));\n\n const name = document.createElement('span');\n name.className = 'wallet-name';\n name.textContent = wallet.name;\n tile.appendChild(name);\n\n tile.addEventListener('click', () => onSelect(wallet.url));\n return tile;\n}\n\n/**\n * Build a wallet icon that prefers the wallet's own favicon and degrades to a\n * letter badge. We never call a third-party favicon proxy: those 404 for many\n * origins and leak the wallet URL to the proxy.\n */\nfunction 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 = 40;\n img.height = 40;\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\nfunction buildSeparator(): HTMLDivElement {\n const sep = document.createElement('div');\n sep.className = 'separator';\n\n const line1 = document.createElement('div');\n line1.className = 'sep-line';\n const sepText = document.createElement('span');\n sepText.textContent = 'or';\n const line2 = document.createElement('div');\n line2.className = 'sep-line';\n\n sep.appendChild(line1);\n sep.appendChild(sepText);\n sep.appendChild(line2);\n return sep;\n}\n\nfunction buildCustomUrl(\n validateWalletUrl: (origin: string) => Promise<boolean>,\n onSelect: (url: string) => void,\n): HTMLDivElement {\n const section = document.createElement('div');\n section.className = 'custom-section';\n\n const label = document.createElement('label');\n label.className = 'custom-label';\n label.textContent = 'Have a wallet URL?';\n\n const inputGroup = document.createElement('div');\n inputGroup.className = 'input-group';\n\n const input = document.createElement('input');\n input.type = 'url';\n input.placeholder = 'https://your-wallet.example';\n input.className = 'url-input';\n\n const goBtn = document.createElement('button');\n goBtn.className = 'go-btn';\n goBtn.textContent = 'Connect';\n goBtn.disabled = true;\n\n const errorLine = document.createElement('div');\n errorLine.className = 'url-error';\n errorLine.style.display = 'none';\n\n // When validation fails we let the user override, since the popup handshake\n // is the ultimate gate \u2014 a valid wallet behind strict CORS should not be\n // permanently blocked.\n let allowUnverified = false;\n\n const resetState = (): void => {\n allowUnverified = false;\n goBtn.textContent = 'Connect';\n errorLine.style.display = 'none';\n goBtn.disabled = !isValidUrl(input.value);\n };\n\n const submit = async (): Promise<void> => {\n if (!isValidUrl(input.value)) {\n return;\n }\n\n const origin = normalizeUrl(input.value);\n if (allowUnverified) {\n onSelect(origin);\n return;\n }\n\n goBtn.disabled = true;\n goBtn.textContent = 'Verifying\u2026';\n errorLine.style.display = 'none';\n\n const valid = await validateWalletUrl(origin);\n if (valid) {\n onSelect(origin);\n return;\n }\n\n allowUnverified = true;\n goBtn.disabled = false;\n goBtn.textContent = 'Connect anyway';\n errorLine.textContent = `Couldn't verify an Enbox wallet at ${origin}.`;\n errorLine.style.display = '';\n };\n\n input.addEventListener('input', resetState);\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n void submit();\n }\n });\n goBtn.addEventListener('click', () => void submit());\n\n inputGroup.appendChild(input);\n inputGroup.appendChild(goBtn);\n section.appendChild(label);\n section.appendChild(inputGroup);\n section.appendChild(errorLine);\n return section;\n}\n\n// \u2500\u2500\u2500 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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction isValidUrl(value: string): boolean {\n try {\n const url = new URL(value.includes('://') ? value : `https://${value}`);\n return url.protocol === 'https:' || url.protocol === 'http:';\n } catch {\n return false;\n }\n}\n\nfunction normalizeUrl(value: string): string {\n const withScheme = value.includes('://') ? value : `https://${value}`;\n // Return origin only (strip path/trailing slash).\n return new URL(withScheme).origin;\n}\n\nfunction buildStyles(isDark: boolean): string {\n const bg = isDark ? '#1a1a2e' : '#ffffff';\n const text = isDark ? '#e0e0e0' : '#1a1a2e';\n const muted = isDark ? '#888' : '#666';\n const border = isDark ? '#333' : '#e0e0e0';\n const itemBg = isDark ? '#16213e' : '#f8f9fa';\n const itemHover = isDark ? '#0f3460' : '#e9ecef';\n const accent = isDark ? '#4a9eff' : '#0066cc';\n const accentAlt = isDark ? '#7b5cff' : '#5b8def';\n const danger = isDark ? '#ff6b6b' : '#c0392b';\n const overlayBg = 'rgba(0, 0, 0, 0.5)';\n\n return `\n * { box-sizing: border-box; margin: 0; padding: 0; }\n\n .overlay {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n display: flex;\n align-items: center;\n justify-content: center;\n background: ${overlayBg};\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n animation: fadeIn 0.15s ease-out;\n }\n\n @keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes slideUp {\n from { transform: translateY(20px); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n }\n\n .modal {\n background: ${bg};\n color: ${text};\n border-radius: 16px;\n width: 420px;\n max-width: 92vw;\n max-height: 86vh;\n overflow-y: auto;\n padding: 24px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n animation: slideUp 0.2s ease-out;\n }\n\n .header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 18px;\n }\n\n h2 { font-size: 18px; font-weight: 600; }\n\n .close-btn {\n background: none;\n border: none;\n font-size: 24px;\n cursor: pointer;\n color: ${muted};\n padding: 4px 8px;\n border-radius: 8px;\n line-height: 1;\n }\n .close-btn:hover { color: ${text}; background: ${itemBg}; }\n\n .quick-connect {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n text-align: left;\n padding: 14px 16px;\n margin-bottom: 18px;\n border: none;\n border-radius: 12px;\n cursor: pointer;\n color: #fff;\n background: linear-gradient(135deg, ${accent}, ${accentAlt});\n transition: filter 0.15s;\n }\n .quick-connect:hover { filter: brightness(1.08); }\n .quick-bolt { font-size: 22px; line-height: 1; }\n .quick-text { display: flex; flex-direction: column; gap: 2px; }\n .quick-label { font-weight: 600; font-size: 15px; }\n .quick-sub { font-size: 12px; opacity: 0.85; }\n\n .wallet-search {\n width: 100%;\n padding: 10px 14px;\n margin-bottom: 12px;\n border: 1px solid ${border};\n border-radius: 10px;\n font-size: 14px;\n background: ${itemBg};\n color: ${text};\n outline: none;\n }\n .wallet-search:focus { border-color: ${accent}; }\n .wallet-search::placeholder { color: ${muted}; }\n\n .wallet-grid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 10px;\n max-height: 216px;\n overflow-y: auto;\n padding: 2px;\n }\n\n .wallet-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 14px 8px;\n background: ${itemBg};\n border: 1px solid ${border};\n border-radius: 12px;\n cursor: pointer;\n color: ${text};\n transition: background 0.15s, border-color 0.15s;\n }\n .wallet-item:hover { background: ${itemHover}; border-color: ${accent}; }\n\n .wallet-icon {\n position: relative;\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .wallet-badge {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n background: ${itemHover};\n color: ${text};\n font-size: 18px;\n font-weight: 600;\n }\n .wallet-img {\n position: relative;\n width: 40px;\n height: 40px;\n border-radius: 10px;\n object-fit: cover;\n background: ${bg};\n }\n\n .wallet-name {\n font-size: 13px;\n font-weight: 500;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .grid-empty {\n grid-column: 1 / -1;\n padding: 16px;\n text-align: center;\n color: ${muted};\n font-size: 13px;\n }\n\n .separator {\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 20px 0;\n color: ${muted};\n font-size: 13px;\n }\n .sep-line { flex: 1; height: 1px; background: ${border}; }\n\n .custom-label {\n display: block;\n font-size: 13px;\n color: ${muted};\n margin-bottom: 8px;\n }\n\n .input-group { display: flex; gap: 8px; }\n\n .url-input {\n flex: 1;\n padding: 10px 14px;\n border: 1px solid ${border};\n border-radius: 10px;\n font-size: 14px;\n background: ${itemBg};\n color: ${text};\n outline: none;\n }\n .url-input:focus { border-color: ${accent}; }\n .url-input::placeholder { color: ${muted}; }\n\n .go-btn {\n padding: 10px 18px;\n border: none;\n border-radius: 10px;\n background: ${accent};\n color: #fff;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n }\n .go-btn:disabled { opacity: 0.4; cursor: not-allowed; }\n .go-btn:not(:disabled):hover { filter: brightness(1.1); }\n\n .url-error {\n margin-top: 8px;\n font-size: 12px;\n color: ${danger};\n }\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 { ConnectPermissionRequest } from '@enbox/connect';\nimport type { ConnectHandler, ConnectResult } from '@enbox/auth';\n\nimport { connectViaPopup } from './dweb-connect-client.js';\nimport { showWalletSelector } from './ui/wallet-selector.js';\n\n/** A wallet entry shown in the wallet selector modal. */\nexport interface WalletOption {\n /** Display name (e.g. \"Enbox\"). */\n name: string;\n\n /** Base URL of the wallet app (e.g. \"https://enbox-wallet.pages.dev\"). */\n url: string;\n\n /** Optional icon URL. If omitted, the wallet's favicon is used. */\n icon?: string;\n\n /** Short description shown below the wallet name in the selector. */\n description?: string;\n}\n\n/** Default wallets shown in the selector when no overrides are provided. */\nexport const DEFAULT_WALLETS: WalletOption[] = [\n {\n name : 'Enbox',\n url : 'https://enbox-wallet.pages.dev',\n description : 'Manage your digital identity and data',\n },\n {\n name : 'Prism',\n url : 'https://prism-wallet.pages.dev',\n description : 'A clear view into your digital identity',\n },\n {\n name : 'Matcha',\n url : 'https://matcha-wallet.pages.dev',\n description : 'A fresh approach to digital identity',\n },\n {\n name : 'Onyx',\n url : 'https://onyx-wallet.pages.dev',\n description : 'A refined home for your digital identity',\n },\n];\n\n/** Options for creating a BrowserConnectHandler. */\nexport interface BrowserConnectHandlerOptions {\n /**\n * Known wallets shown in the wallet selector modal.\n * If omitted, {@link DEFAULT_WALLETS} is used.\n */\n wallets?: WalletOption[];\n\n /**\n * Explicit wallet URL. If provided, the wallet selector is skipped\n * and this URL is used directly.\n */\n walletUrl?: string;\n\n /**\n * Timeout in milliseconds for the wallet popup flow.\n * @default 300_000 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Display name of the requesting application.\n * Shown in the wallet's permission consent screen.\n */\n appName?: string;\n\n /**\n * Icon URL of the requesting application.\n * Shown alongside the app name in the wallet's consent screen.\n * Defaults to `${window.location.origin}/favicon.ico` if omitted.\n */\n appIcon?: string;\n\n}\n\n/**\n * Create a browser-native connect handler using DWeb Connect\n * (popup + postMessage).\n *\n * This handler:\n * 1. Shows a wallet selector modal (or uses a provided walletUrl).\n * 2. Opens the selected wallet as a popup window.\n * 3. Runs the DWeb Connect postMessage protocol.\n * 4. Returns the delegate credentials on success.\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: fixedWalletUrl,\n timeout,\n appName,\n appIcon,\n } = options;\n\n return {\n async requestAccess(params: {\n permissionRequests: ConnectPermissionRequest[];\n }): Promise<ConnectResult | undefined> {\n // 1. Determine wallet URL.\n let walletUrl = fixedWalletUrl;\n if (!walletUrl) {\n walletUrl = await showWalletSelector(wallets);\n }\n\n // 2. Run the DWeb Connect popup flow over the connect kernel.\n return connectViaPopup({\n walletUrl,\n permissionRequests: params.permissionRequests,\n timeout,\n appName,\n appIcon,\n });\n },\n };\n}\n", "/**\n * DWeb Connect wallet transport \u2014 the wallet side of the popup/postMessage\n * connect flow, exported for wallet apps (e.g. the Enbox web wallet).\n *\n * A wallet's `/dweb-connect` page creates one transport per session:\n *\n * 1. `create()` generates a fresh ephemeral X25519 key pair and emits the\n * `loaded` beacon (public key + wallet origin) to the opener window with a\n * pinned `targetOrigin`.\n * 2. `awaitRequest()` receives the sealed request ciphertext and opens it via\n * the `@enbox/connect` kernel (`ConnectProvider.openRequest`), which\n * value-checks the `apv` origin binding against this wallet's origin.\n * 3. After the consent ceremony, the wallet posts the sealed response JWE via\n * `sendResponse()` \u2014 or the deny token via `deny()` \u2014 back to the opener,\n * again with a pinned `targetOrigin`.\n *\n * The dapp origin is never assumed: it is taken from an explicit option or\n * derived from `document.referrer`, and `create()` fails when neither is\n * available. `'*'` is never used as a `targetOrigin`.\n *\n * @module\n */\n\nimport type { ConnectRequest } from '@enbox/connect';\nimport type { Jwk } from '@enbox/crypto';\n\nimport { X25519 } from '@enbox/crypto';\nimport { CONNECT_DENIED_TOKEN, ConnectProvider } from '@enbox/connect';\n\nimport {\n DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n DWEB_CONNECT_REQUEST_MESSAGE_TYPE,\n DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n getTrustedMessage,\n} from './dweb-connect-messages.js';\n\n/** Default budget for awaiting the dapp's sealed request. */\nconst DEFAULT_REQUEST_TIMEOUT_MS = 300_000;\n\n/** Options for creating a {@link WalletPostMessageTransport}. */\nexport type WalletPostMessageTransportOptions = {\n /**\n * Origin of the dapp that opened this wallet popup. When omitted, it is\n * derived from `document.referrer`; creation fails when neither is\n * available \u2014 the transport never falls back to `'*'`.\n */\n dappOrigin?: string;\n\n /**\n * The dapp window to exchange messages with.\n * @default window.opener\n */\n dappWindow?: Window;\n\n /**\n * Budget in milliseconds for awaiting the dapp's sealed request.\n * @default 300_000 (5 minutes)\n */\n timeoutMs?: number;\n};\n\n/**\n * Wallet-side postMessage transport for the DWeb Connect popup flow.\n *\n * Security properties:\n * - `targetOrigin` of every outbound `postMessage` (beacon and response) is\n * pinned to the dapp origin \u2014 never `'*'`.\n * - Inbound messages are dropped unless `event.origin` equals the pinned dapp\n * origin AND `event.source` is the dapp window.\n * - The ephemeral X25519 private key never leaves the transport; the request\n * JWE is opened by the kernel with the `apv` header value-checked against\n * this wallet's own origin.\n */\nexport class WalletPostMessageTransport {\n private readonly _dappOrigin: string;\n private readonly _dappWindow: Window;\n private readonly _recipientPrivateKey: Jwk;\n\n private _requestReceived = false;\n private _timeoutId?: ReturnType<typeof setTimeout>;\n private _messageListener?: (event: MessageEvent) => void;\n\n private readonly _requestPromise: Promise<ConnectRequest>;\n private _resolveRequest?: (request: ConnectRequest) => void;\n private _rejectRequest?: (error: Error) => void;\n\n private constructor(params: { dappOrigin: string; dappWindow: Window; recipientPrivateKey: Jwk; timeoutMs: number }) {\n this._dappOrigin = params.dappOrigin;\n this._dappWindow = params.dappWindow;\n this._recipientPrivateKey = params.recipientPrivateKey;\n\n this._requestPromise = new Promise<ConnectRequest>((resolve, reject): void => {\n this._resolveRequest = resolve;\n this._rejectRequest = reject;\n });\n // Mark early rejections (timeout before `awaitRequest()` is called) as\n // handled until the wallet attaches its own handlers.\n this._requestPromise.catch((): undefined => undefined);\n\n this._messageListener = (event: MessageEvent): void => { this.onMessage(event); };\n window.addEventListener('message', this._messageListener);\n\n this._timeoutId = setTimeout((): void => {\n this.close();\n this._rejectRequest?.(new Error('[@enbox/browser] Timed out waiting for the connect request from the dapp.'));\n }, params.timeoutMs);\n }\n\n /**\n * Creates the transport for one connect session: resolves and pins the dapp\n * origin, generates a fresh ephemeral X25519 key pair, starts listening for\n * the sealed request, and emits the `loaded` beacon to the dapp window.\n *\n * @throws If not in a browser, if no dapp window is available, or if the\n * dapp origin can neither be supplied nor derived from the referrer.\n */\n public static async create(options: WalletPostMessageTransportOptions = {}): Promise<WalletPostMessageTransport> {\n if (typeof window === 'undefined') {\n throw new Error('[@enbox/browser] WalletPostMessageTransport is only available in browser environments.');\n }\n\n const dappWindow = options.dappWindow ?? window.opener as Window | null;\n if (!dappWindow) {\n throw new Error('[@enbox/browser] No opener window: the DWeb Connect page must be opened as a popup by the dapp.');\n }\n\n const dappOrigin = resolveDappOrigin(options.dappOrigin);\n\n const recipientPrivateKey = await X25519.generateKey();\n const walletEpk: Jwk = { kty: 'OKP', crv: 'X25519', x: recipientPrivateKey.x };\n\n const transport = new WalletPostMessageTransport({\n dappOrigin,\n dappWindow,\n recipientPrivateKey,\n timeoutMs: options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n });\n\n // The listener is registered, so the beacon cannot race the request.\n dappWindow.postMessage({\n type : DWEB_CONNECT_LOADED_MESSAGE_TYPE,\n walletEpk,\n walletOrigin : globalThis.location.origin,\n }, dappOrigin);\n\n return transport;\n }\n\n /** The pinned origin of the dapp this transport exchanges messages with. */\n public get dappOrigin(): string {\n return this._dappOrigin;\n }\n\n /**\n * Awaits the dapp's sealed request and opens it via the kernel: ECDH-ES\n * decryption with this session's ephemeral key, `apv` value-checked against\n * this wallet's origin, JWT signature verification, and payload shape\n * assertion. Rejects on timeout, on an unopenable request, or when the\n * request does not use the `post_message` reply mode.\n */\n public async awaitRequest(): Promise<ConnectRequest> {\n return await this._requestPromise;\n }\n\n /**\n * Posts the sealed response JWE (or the deny token) back to the dapp window\n * with the `targetOrigin` pinned to the dapp origin, then closes the\n * transport.\n *\n * @param idToken - The sealed response JWE, or the literal deny token.\n */\n public sendResponse(idToken: string): void {\n this._dappWindow.postMessage({\n type : DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,\n payload : idToken,\n }, this._dappOrigin);\n this.close();\n }\n\n /** Posts the deny token back to the dapp \u2014 the user rejected the request. */\n public deny(): void {\n this.sendResponse(CONNECT_DENIED_TOKEN);\n }\n\n /** Stops listening and releases the session's timers. Idempotent. */\n public close(): void {\n clearTimeout(this._timeoutId);\n if (this._messageListener !== undefined) {\n window.removeEventListener('message', this._messageListener);\n this._messageListener = undefined;\n }\n }\n\n private onMessage(event: MessageEvent): void {\n const message = getTrustedMessage(event, this._dappOrigin, this._dappWindow);\n if (message === undefined) { return; }\n\n if (message.type !== DWEB_CONNECT_REQUEST_MESSAGE_TYPE || this._requestReceived) { return; }\n this._requestReceived = true;\n\n if (typeof message.jwe !== 'string') {\n this.settleRequest(new Error('[@enbox/browser] Connect request message did not carry a ciphertext payload.'));\n return;\n }\n\n void this.openRequest(message.jwe);\n }\n\n private async openRequest(jwe: string): Promise<void> {\n try {\n const request = await ConnectProvider.openRequest({\n jwe,\n decryption: {\n mode : 'ecdh-es',\n recipientPrivateKey : this._recipientPrivateKey,\n walletOrigin : globalThis.location.origin,\n },\n });\n\n if (request.reply.mode !== 'post_message') {\n this.settleRequest(new Error('[@enbox/browser] Connect request over the popup channel must use the `post_message` reply mode.'));\n return;\n }\n\n this.settleRequest(request);\n } catch (error) {\n this.settleRequest(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private settleRequest(outcome: ConnectRequest | Error): void {\n clearTimeout(this._timeoutId);\n if (outcome instanceof Error) {\n this.close();\n this._rejectRequest?.(outcome);\n return;\n }\n this._resolveRequest?.(outcome);\n }\n}\n\n/**\n * Resolves the dapp origin to pin: the explicit option when provided,\n * otherwise the origin of `document.referrer`. Never falls back to `'*'`.\n */\nfunction resolveDappOrigin(explicitOrigin: string | undefined): string {\n if (explicitOrigin !== undefined) {\n return new URL(explicitOrigin).origin;\n }\n\n if (document.referrer) {\n return new URL(document.referrer).origin;\n }\n\n throw new Error(\n '[@enbox/browser] Unable to determine the dapp origin: no `dappOrigin` option was provided and `document.referrer` is empty.'\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Enbox", "defineProtocol", "repository", "AuthManager", "AuthSession", "normalizeProtocolRequests", "WalletConnect", "CONNECT_DENIED_TOKEN", "ConnectProvider", "DidDht", "DidWeb", "UniversalResolver", "parseDrlUrl", "url", "idx", "prefix", "rest", "slashIdx", "didResolver", "UniversalResolver", "DidDht", "DidWeb", "httpToHttpsRegex", "trailingSlashRegex", "DRL_CACHE_NAME", "getDwnEndpoints", "did", "didDocument", "endpoints", "service", "url", "openDrlCache", "handleEvent", "event", "path", "options", "drl", "responseCache", "cachedResponse", "match", "cacheTime", "fetchResource", "response", "error", "lastError", "endpoint", "cacheResponse", "cache", "clonedResponse", "headers", "modifiedResponse", "installWorker", "workerSelf", "parsed", "parseDrlUrl", "installUrl", "loaderStyles", "tabContent", "elementsInjected", "overlayElement", "styleElement", "injectElements", "cancelNavigation", "removeElements", "activeNavigation", "linkFeaturesActive", "clickHandler", "pointerdownHandler", "addLinkFeatures", "anchor", "href", "openAsTab", "tab", "target", "resetContextMenuTarget", "contextMenuTarget", "removeLinkFeatures", "e", "r", "activatePolyfills", "deactivatePolyfills", "clearDrlCache", "assertX25519PublicJwk", "CONNECT_DENIED_TOKEN", "ConnectClient", "DWEB_CONNECT_PATH", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "getTrustedMessage", "event", "expectedOrigin", "expectedSource", "data", "DEFAULT_TIMEOUT_MS", "CLOSED_POLL_INTERVAL_MS", "POPUP_WINDOW_NAME", "POPUP_WINDOW_FEATURES", "assertBrowserEnvironment", "PopupWindowClosedError", "PopupClientTransport", "options", "popupUrl", "DWEB_CONNECT_PATH", "popup", "resolve", "reject", "event", "state", "jwe", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "message", "getTrustedMessage", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "walletEpk", "assertX25519PublicJwk", "CONNECT_DENIED_TOKEN", "error", "collectBrowserClientMetadata", "resolvedOptions", "languages", "language", "connectViaPopup", "transport", "client", "ConnectClient", "WALLET_WELL_KNOWN_PATH", "probeWalletWellKnown", "origin", "wellKnownUrl", "WALLET_WELL_KNOWN_PATH", "response", "showWalletSelector", "wallets", "options", "validateWalletUrl", "resolve", "reject", "host", "shadow", "onKeydown", "cleanup", "settleResolve", "url", "settleReject", "isDark", "style", "buildStyles", "overlay", "modal", "buildHeader", "recommended", "buildQuickConnect", "buildWalletGrid", "buildSeparator", "buildCustomUrl", "e", "onCancel", "header", "title", "closeBtn", "onSelect", "quick", "bolt", "text", "label", "sub", "section", "search", "grid", "empty", "tiles", "wallet", "tile", "buildWalletTile", "query", "visible", "name", "match", "buildWalletIcon", "wrap", "badge", "sources", "iconCandidates", "img", "index", "sep", "line1", "sepText", "line2", "inputGroup", "input", "goBtn", "errorLine", "allowUnverified", "resetState", "isValidUrl", "submit", "normalizeUrl", "value", "withScheme", "bg", "muted", "border", "itemBg", "itemHover", "accent", "DEFAULT_WALLETS", "BrowserConnectHandler", "options", "wallets", "fixedWalletUrl", "timeout", "appName", "appIcon", "params", "walletUrl", "showWalletSelector", "connectViaPopup", "X25519", "CONNECT_DENIED_TOKEN", "ConnectProvider", "DEFAULT_REQUEST_TIMEOUT_MS", "WalletPostMessageTransport", "_WalletPostMessageTransport", "params", "resolve", "reject", "event", "options", "dappWindow", "dappOrigin", "resolveDappOrigin", "recipientPrivateKey", "X25519", "walletEpk", "transport", "DWEB_CONNECT_LOADED_MESSAGE_TYPE", "idToken", "DWEB_CONNECT_RESPONSE_MESSAGE_TYPE", "CONNECT_DENIED_TOKEN", "message", "getTrustedMessage", "DWEB_CONNECT_REQUEST_MESSAGE_TYPE", "jwe", "request", "ConnectProvider", "error", "outcome", "explicitOrigin"]
|
|
7
7
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -44,5 +44,5 @@ export { BrowserConnectHandler, DEFAULT_WALLETS } from './browser-connect-handle
|
|
|
44
44
|
export { connectViaPopup, PopupClientTransport, PopupWindowClosedError } from './dweb-connect-client.js';
|
|
45
45
|
export { WalletPostMessageTransport } from './dweb-connect-wallet.js';
|
|
46
46
|
export { DWEB_CONNECT_LOADED_MESSAGE_TYPE, DWEB_CONNECT_PATH, DWEB_CONNECT_REQUEST_MESSAGE_TYPE, DWEB_CONNECT_RESPONSE_MESSAGE_TYPE, } from './dweb-connect-messages.js';
|
|
47
|
-
export { showWalletSelector } from './ui/wallet-selector.js';
|
|
47
|
+
export { probeWalletWellKnown, showWalletSelector, WALLET_WELL_KNOWN_PATH } from './ui/wallet-selector.js';
|
|
48
48
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,mEAAmE;AACnE,EAAE;AACF,kEAAkE;AAElE,OAAO,EACL,KAAK,EACL,cAAc,EACd,UAAU,GACX,MAAM,YAAY,CAAC;AAUpB,mEAAmE;AACnE,EAAE;AACF,kEAAkE;AAElE,OAAO,EACL,WAAW,EACX,WAAW,EACX,yBAAyB,EACzB,aAAa,GACd,MAAM,qBAAqB,CAAC;AAuB7B,mEAAmE;AACnE,EAAE;AACF,iEAAiE;AACjE,4DAA4D;AAE5D,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGvE,mEAAmE;AACnE,EAAE;AACF,iEAAiE;AAEjE,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEtF,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEzG,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAEtE,OAAO,EACL,gCAAgC,EAChC,iBAAiB,EACjB,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,mEAAmE;AACnE,EAAE;AACF,kEAAkE;AAElE,OAAO,EACL,KAAK,EACL,cAAc,EACd,UAAU,GACX,MAAM,YAAY,CAAC;AAUpB,mEAAmE;AACnE,EAAE;AACF,kEAAkE;AAElE,OAAO,EACL,WAAW,EACX,WAAW,EACX,yBAAyB,EACzB,aAAa,GACd,MAAM,qBAAqB,CAAC;AAuB7B,mEAAmE;AACnE,EAAE;AACF,iEAAiE;AACjE,4DAA4D;AAE5D,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGvE,mEAAmE;AACnE,EAAE;AACF,iEAAiE;AAEjE,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEtF,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEzG,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAEtE,OAAO,EACL,gCAAgC,EAChC,iBAAiB,EACjB,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,4BAA4B,CAAC;AAOpC,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC"}
|