{"version":3,"sources":["../src/server.ts","../src/client.ts","../src/popup.ts","../src/index.ts"],"sourcesContent":["import debug from 'debug'\nimport EventEmitter3, { type EventEmitter } from 'eventemitter3'\nimport { type JSONRPCError, type JSONRPCErrorResponse, type JSONRPCParams, JSONRPCServer, type JSONRPCSuccessResponse } from 'json-rpc-2.0'\nimport { v4 as uuidv4 } from 'uuid'\nimport { arrayChanged, cleanupAccounts } from '.'\n\nconst serverLog = debug('upProvider:server')\n\n// Unique identifier for UP Provider JSONRPC messages\nconst UP_PROVIDER_JSONRPC_TYPE = 'upProvider:jsonrpc' as const\ninterface UPClientChannelEvents {\n  connect: (args: { chainId: `0x${string}` }) => void\n  disconnect: () => void\n  contextAccountsChanged: (accounts: `0x${string}`[]) => void\n  accountsChanged: (accounts: `0x${string}`[]) => void\n  requestAccounts: (accounts: `0x${string}`[]) => void\n  chainChanged: (chainId: number) => void\n  injected: (accounts: `0x${string}`[]) => void\n  sentTransaction: (tx: { from: `0x${string}`; to: `0x${string}`; value?: bigint; error?: JSONRPCError; result?: any }) => void\n}\n\n/**\n * API for client channel, each time an iframe's UPClientProvider is allocated and connected\n * the UPProviderConnector will create and emit a new UPClientChannel.\n * The UPClientChannel will have the API to control that channel.\n * The configuration will default to values from the UPProviderConnector but enable will be false.\n */\ninterface UPClientChannel {\n  readonly window: Window\n  readonly element: HTMLIFrameElement | null\n  readonly id: string\n\n  /**\n   * Return an array listing the events for which the emitter has registered\n   * listeners.\n   */\n  eventNames(): Array<EventEmitter.EventNames<UPClientChannelEvents>>\n\n  /**\n   * Return the listeners registered for a given event.\n   */\n  listeners<T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T): Array<EventEmitter.EventListener<UPClientChannelEvents, T>>\n\n  /**\n   * Return the number of listeners listening to a given event.\n   */\n  listenerCount(event: EventEmitter.EventNames<UPClientChannelEvents>): number\n\n  /**\n   * Calls each of the listeners registered for a given event.\n   */\n  emit<T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, ...args: EventEmitter.EventArgs<UPClientChannelEvents, T>): boolean\n\n  /**\n   * Add a listener for a given event.\n   */\n  on<T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, fn: EventEmitter.EventListener<UPClientChannelEvents, T>, context?: any): this\n  addListener<T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, fn: EventEmitter.EventListener<UPClientChannelEvents, T>, context?: any): this\n\n  /**\n   * Add a one-time listener for a given event.\n   */\n  once<T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, fn: EventEmitter.EventListener<UPClientChannelEvents, T>, context?: any): this\n\n  /**\n   * Remove the listeners of a given event.\n   */\n  removeListener<T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, fn?: EventEmitter.EventListener<UPClientChannelEvents, T>, context?: any, once?: boolean): this\n  off<T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, fn?: EventEmitter.EventListener<UPClientChannelEvents, T>, context?: any, once?: boolean): this\n\n  /**\n   * Remove all listeners, or those of the specified event.\n   */\n  removeAllListeners(event?: EventEmitter.EventNames<UPClientChannelEvents>): this\n\n  /**\n   * Resume after a delay\n   * @param delay - delay in milliseconds\n   */\n  resume(delay: number): void\n  /**\n   * Send message to dapp.\n   * @param method - method name/event\n   * @param params - parameters\n   */\n  send(method: string, params: unknown[]): Promise<void>\n\n  /**\n   * This represents the normal \"eth_accounts\" method list.\n   * @param accounts - list of addresses\n   */\n  setAllowedAccounts(accounts: `0x${string}`[]): Promise<void>\n\n  /**\n   * This represents the normal \"eth_accounts\" method list. (setter mirrors setAllowedAccounts)\n   */\n  set allowedAccounts(accounts: `0x${string}`[])\n\n  /**\n   * This represents the normal \"eth_accounts\" method list.\n   * @returns list of accounts\n   */\n  get allowedAccounts(): `0x${string}`[]\n\n  /**\n   * These are extra accounts sent to each provider. In the ue.io grid, this is used to\n   * represent the account that is the grid owner.\n   * @param accounts - list of addresses\n   */\n  setContextAccounts(contextAccounts: `0x${string}`[]): Promise<void>\n\n  /**\n   * These are extra accounts sent to each provider. In the ue.io grid, this is used to\n   * represent the account that is the grid owner. (setter mirrors setContextAccounts)\n   * @param accounts - list of addresses\n   */\n  set contextAccounts(contextAccounts: `0x${string}`[])\n\n  /**\n   * These are extra accounts sent to each provider. In the ue.io grid, this is used to\n   * represent the account that is the grid owner.\n   * @returns list of addresses\n   */\n  get contextAccounts(): `0x${string}`[]\n\n  /**\n   * ChainId\n   * @param chainId - chain id\n   */\n  setChainId(chainId: number): Promise<void>\n\n  /**\n   * ChainId\n   * @param chainId - chain id\n   */\n  set chainId(chainId: number)\n\n  /**\n   * ChainId\n   * @returns chain id\n   */\n  get chainId(): number\n\n  /**\n   * Enable or disable the channel.\n   * @param enable - enable or disable the channel\n   */\n  setEnable(enable: boolean): Promise<void>\n\n  /**\n   * Enable or disable the channel.\n   * @returns is channel enabled\n   */\n  get enable(): boolean\n\n  /**\n   * Enable or disable the channel.\n   * @param enable - enable or disable the channel\n   */\n  set enable(value: boolean)\n\n  /**\n   * RPC urls\n   * @param rpcUrls - list of rpc urls (used by client provider to short circuit requests)\n   */\n  setRpcUrls(rpcUrls: string[]): Promise<void>\n\n  /**\n   * RPC urls\n   * @param rpcUrls - list of rpc urls (used by client provider to short circuit requests)\n   */\n  set rpcUrls(rpcUrls: string[])\n\n  /**\n   * RPC urls\n   * @returns list of rpc urls (used by client provider to short circuit requests)\n   */\n  get rpcUrls(): string[]\n\n  /**\n   * Helper to setup the channel with all the necessary information.\n   * @param enable - enable\n   * @param accounts - accounts (allowed accounts)\n   * @param contextAccounts - context accounts\n   * @param chainId - chainId\n   */\n  setupChannel(enable: boolean, accounts: `0x${string}`[], contextAccounts: `0x${string}`[], chainId: number): Promise<void>\n\n  /**\n   * Show or hide the popup/modal\n   * @param show - true to show, false to hide\n   */\n  showPopup(show: boolean): Promise<void>\n\n  /**\n   * Close the channel\n   */\n  close(): void\n\n  _serverChannel: MessagePort\n}\n\nfunction createUPClientChannel(\n  serverChannel: MessagePort,\n  window: Window,\n  element: HTMLIFrameElement | null,\n  id: string,\n  server: JSONRPCServer,\n  getter: () => boolean,\n  setter: (value: boolean) => void\n): UPClientChannel {\n  let accounts: `0x${string}`[] = []\n  let contextAccounts: `0x${string}`[] = []\n  let chainId = 0\n  let rpcUrls: string[] = []\n  let bufferedEvents: Array<[keyof UPClientChannelEvents, unknown[]]> | undefined = []\n  \n  const emitter = new EventEmitter3<UPClientChannelEvents>()\n  \n  const channel: UPClientChannel = {\n    _serverChannel: serverChannel,\n    window,\n    element,\n    id,\n    \n    eventNames: () => emitter.eventNames(),\n    listeners: <T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T) => emitter.listeners(event),\n    listenerCount: (event: EventEmitter.EventNames<UPClientChannelEvents>) => emitter.listenerCount(event),\n    \n    emit: <T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, ...args: EventEmitter.EventArgs<UPClientChannelEvents, T>): boolean => {\n      if (bufferedEvents) {\n        bufferedEvents.push([event, args])\n        return false\n      }\n      return emitter.emit(event, ...args)\n    },\n    \n    on: <T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, fn: EventEmitter.EventListener<UPClientChannelEvents, T>, context?: any) => {\n      channel.resume(100)\n      emitter.on(event, fn, context)\n      return channel\n    },\n    \n    addListener: <T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, fn: EventEmitter.EventListener<UPClientChannelEvents, T>, context?: any) => {\n      channel.resume(100)\n      emitter.addListener(event, fn, context)\n      return channel\n    },\n    \n    once: <T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, fn: EventEmitter.EventListener<UPClientChannelEvents, T>, context?: any) => {\n      emitter.once(event, fn, context)\n      return channel\n    },\n    \n    removeListener: <T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, fn?: EventEmitter.EventListener<UPClientChannelEvents, T>, context?: any, once?: boolean) => {\n      emitter.removeListener(event, fn, context, once)\n      return channel\n    },\n    \n    off: <T extends EventEmitter.EventNames<UPClientChannelEvents>>(event: T, fn?: EventEmitter.EventListener<UPClientChannelEvents, T>, context?: any, once?: boolean) => {\n      emitter.off(event, fn, context, once)\n      return channel\n    },\n    \n    removeAllListeners: (event?: EventEmitter.EventNames<UPClientChannelEvents>) => {\n      emitter.removeAllListeners(event)\n      return channel\n    },\n    \n    resume: (delay = 0) => {\n      const buffered = bufferedEvents\n      if (!buffered) {\n        return\n      }\n      bufferedEvents = undefined\n      setTimeout(() => {\n        while (buffered.length > 0) {\n          const val = buffered.shift()\n          if (val) {\n            const [event, args] = val\n            emitter.emit(event, ...(args as any))\n          }\n        }\n      }, delay)\n    },\n    \n    send: async (method: string, params: unknown[]): Promise<void> => {\n      const message = {\n        jsonrpc: '2.0',\n        id: uuidv4(),\n        method,\n        params,\n      }\n      serverChannel.postMessage(message)\n    },\n    \n    setAllowedAccounts: async (newAccounts: `0x${string}`[]): Promise<void> => {\n      serverLog('allowedAccounts', newAccounts)\n      const accountsChanged = arrayChanged(accounts, newAccounts)\n      if (accountsChanged) {\n        const wasEmpty = accounts.length === 0\n        accounts = [...newAccounts]\n        if (getter()) {\n          await channel.send('accountsChanged', cleanupAccounts([...accounts]))\n          if (wasEmpty !== (accounts.length === 0)) {\n            if (getter() && accounts.length > 0) {\n              const hexChainId = `0x${chainId.toString(16)}` as `0x${string}`\n              channel.emit('connect', { chainId: hexChainId })\n              channel.send('connect', [{ chainId: hexChainId }])\n            } else {\n              channel.emit('disconnect')\n              channel.send('disconnect', [])\n            }\n          }\n        }\n      }\n    },\n    \n    set allowedAccounts(newAccounts: `0x${string}`[]) {\n      channel.setAllowedAccounts(newAccounts)\n    },\n    \n    get allowedAccounts(): `0x${string}`[] {\n      return [...accounts]\n    },\n    \n    setContextAccounts: async (newContextAccounts: `0x${string}`[]): Promise<void> => {\n      const accountsChanged = arrayChanged(contextAccounts, newContextAccounts)\n      if (accountsChanged) {\n        serverLog('contextAccounts', newContextAccounts)\n        contextAccounts = [...newContextAccounts]\n        await channel.send('contextAccountsChanged', cleanupAccounts([...contextAccounts]))\n      }\n    },\n    \n    set contextAccounts(newContextAccounts: `0x${string}`[]) {\n      channel.setContextAccounts(newContextAccounts)\n    },\n    \n    get contextAccounts(): `0x${string}`[] {\n      return [...contextAccounts]\n    },\n    \n    setupChannel: async (enable: boolean, newAccounts: `0x${string}`[], newContextAccounts: `0x${string}`[], newChainId: number): Promise<void> => {\n      const accountsChanged = arrayChanged(accounts, newAccounts)\n      let sendAccountsChanged = false\n      if (accountsChanged) {\n        serverLog('allowedAccounts', newAccounts)\n        accounts = [...newAccounts]\n        sendAccountsChanged = enable\n      }\n      const contextAccountsChanged = arrayChanged(contextAccounts, newContextAccounts)\n      let sendContextAccountsChanged = false\n      if (contextAccountsChanged) {\n        serverLog('contextAccounts', newContextAccounts)\n        contextAccounts = [...newContextAccounts]\n        sendContextAccountsChanged = true\n      }\n      let sendChainChanged = false\n      if (chainId !== newChainId) {\n        serverLog('chainId', newChainId)\n        chainId = newChainId\n        sendChainChanged = true\n      }\n      if (enable !== channel.enable) {\n        serverLog('enable', enable)\n        setter(enable)\n        sendAccountsChanged = true\n      }\n      if (sendChainChanged) {\n        await channel.send('chainChanged', [newChainId])\n        channel.emit('chainChanged', newChainId)\n      }\n      if (sendContextAccountsChanged) {\n        await channel.send('contextAccountsChanged', cleanupAccounts([...contextAccounts]))\n      }\n      if (sendAccountsChanged) {\n        await channel.send('accountsChanged', cleanupAccounts(getter() ? [...accounts] : []))\n        if (getter() && accounts.length > 0) {\n          const hexChainId = `0x${chainId.toString(16)}` as `0x${string}`\n          channel.emit('connect', { chainId: hexChainId })\n          channel.send('connect', [{ chainId: hexChainId }])\n        } else {\n          channel.emit('disconnect')\n          channel.send('disconnect', [])\n        }\n      }\n    },\n    \n    setEnable: async (value: boolean): Promise<void> => {\n      if (value !== channel.enable) {\n        setter(value)\n        channel.send('accountsChanged', cleanupAccounts(getter() ? [...accounts] : []))\n        if (getter() && accounts.length > 0) {\n          const hexChainId = `0x${chainId.toString(16)}` as `0x${string}`\n          channel.emit('connect', { chainId: hexChainId })\n          channel.send('connect', [{ chainId: hexChainId }])\n        } else {\n          channel.emit('disconnect')\n          channel.send('disconnect', [])\n        }\n      }\n    },\n    \n    set enable(value: boolean) {\n      channel.setEnable(value)\n    },\n    \n    get enable(): boolean {\n      return getter()\n    },\n    \n    setChainId: async (newChainId: number): Promise<void> => {\n      if (chainId !== newChainId) {\n        chainId = newChainId\n        await channel.send('chainChanged', [newChainId])\n        channel.emit('chainChanged', newChainId)\n      }\n    },\n    \n    get chainId(): number {\n      return chainId\n    },\n    \n    set chainId(newChainId: number) {\n      channel.setChainId(newChainId)\n    },\n    \n    setRpcUrls: async (newRpcUrls: string[]): Promise<void> => {\n      if (arrayChanged(newRpcUrls, rpcUrls)) {\n        rpcUrls = newRpcUrls\n        await channel.send('rpcUrlsChanged', newRpcUrls)\n      }\n    },\n    \n    get rpcUrls(): string[] {\n      return [...rpcUrls]\n    },\n    \n    set rpcUrls(newRpcUrls: string[]) {\n      channel.setRpcUrls(newRpcUrls)\n    },\n    \n    showPopup: async (show: boolean): Promise<void> => {\n      serverLog('showPopup requested:', show)\n      await channel.send('showPopup', [show])\n    },\n    \n    close: () => {\n      const el: any = element || window\n      try {\n        if (el.upChannel === channel) {\n          el.upChannel = undefined\n        }\n      } catch {\n        // ignore\n      }\n      serverChannel.close()\n    }\n  }\n  \n  return channel\n}\n\ninterface UPProviderEndpointEvents {\n  accountsChanged: (accounts: `0x${string}`[]) => void\n  chainChanged: (chainId: number) => void\n  connect: ({ chainId }: { chainId: number }) => void\n  disconnect: (error: Error) => void\n}\ninterface UPProviderEndpoint {\n  on<T extends EventEmitter.EventNames<UPProviderEndpointEvents>>(event: T, fn: EventEmitter.EventListener<UPProviderEndpointEvents, T>, context?: any): this\n  off<T extends EventEmitter.EventNames<UPProviderEndpointEvents>>(event: T, fn: EventEmitter.EventListener<UPProviderEndpointEvents, T>, context?: any): this\n  request(message: { method: string; params: JSONRPCParams }, clientParams?: any): Promise<any>\n  request(method: string | { method: string; params: JSONRPCParams }, params?: JSONRPCParams, clientParams?: any): Promise<any>\n}\n\ntype UPProviderConnectorOptions = {\n  providerHandler?: (e: MessageEvent) => void\n  allowedAccounts: `0x${string}`[]\n  contextAccounts: `0x${string}`[]\n  provider: UPProviderEndpoint\n  providerAccountsChangedCallback?: (accounts: `0x${string}`[]) => void\n  promise: Promise<void>\n  rpcUrls: string[]\n  chainId: number\n}\n\ninterface UPProviderConnectorEvents {\n  channelCreated: (id: HTMLIFrameElement | Window | string, channel: UPClientChannel) => void\n}\n\n/**\n * API for provider connector\n */\ninterface UPProviderConnector {\n  /**\n   * Return an array listing the events for which the emitter has registered\n   * listeners.\n   */\n  eventNames(): Array<EventEmitter.EventNames<UPProviderConnectorEvents>>\n\n  /**\n   * Return the listeners registered for a given event.\n   */\n  listeners<T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T): Array<EventEmitter.EventListener<UPProviderConnectorEvents, T>>\n\n  /**\n   * Return the number of listeners listening to a given event.\n   */\n  listenerCount(event: EventEmitter.EventNames<UPProviderConnectorEvents>): number\n\n  /**\n   * Calls each of the listeners registered for a given event.\n   */\n  emit<T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, ...args: EventEmitter.EventArgs<UPProviderConnectorEvents, T>): boolean\n\n  /**\n   * Add a listener for a given event.\n   */\n  on<T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, fn: EventEmitter.EventListener<UPProviderConnectorEvents, T>, context?: any): this\n  addListener<T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, fn: EventEmitter.EventListener<UPProviderConnectorEvents, T>, context?: any): this\n\n  /**\n   * Add a one-time listener for a given event.\n   */\n  once<T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, fn: EventEmitter.EventListener<UPProviderConnectorEvents, T>, context?: any): this\n\n  /**\n   * Remove the listeners of a given event.\n   */\n  removeListener<T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, fn?: EventEmitter.EventListener<UPProviderConnectorEvents, T>, context?: any, once?: boolean): this\n  off<T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, fn?: EventEmitter.EventListener<UPProviderConnectorEvents, T>, context?: any, once?: boolean): this\n\n  /**\n   * Remove all listeners, or those of the specified event.\n   */\n  removeAllListeners(event?: EventEmitter.EventNames<UPProviderConnectorEvents>): this\n\n  close(): void\n\n  get provider(): UPProviderEndpoint\n\n  /**\n   * Get a map of all clients by their ID.\n   */\n  get channels(): Map<string, UPClientChannel>\n\n  /**\n   * Find the client for the element, window or proxy object of the client.\n   * @param id\n   * @returns actual UPClientChannel\n   */\n  getChannel(id: string | Window | HTMLIFrameElement | UPClientChannel | null): UPClientChannel | null\n\n  /**\n   * Inject additional addresses into the client's accountsChanged event.\n   * Account[0] will be linked to the signed when making transactions.\n   * Starting at Account[1] is where additional addresses are injected.\n   * This routine injects on all connections. You can also inject using\n   * the channel's allowedAccounts method.\n   * @param page list of addresses\n   */\n  setContextAccounts(accounts: `0x${string}`[]): Promise<void>\n  set contextAccounts(accounts: `0x${string}`[])\n  get contextAccounts(): `0x${string}`[]\n\n  setAllowedAccounts(accounts: `0x${string}`[]): Promise<void>\n  set allowedAccounts(accounts: `0x${string}`[])\n  get allowedAccounts(): `0x${string}`[]\n\n  setChainId(chainId: number): Promise<void>\n  set chainId(chainId: number)\n  get chainId(): number\n\n  /**\n   * Connect this provider externally. This will be called during initial construction\n   * but can be called at a later time if desired to re-initialize or tear down\n   * the connection.\n   * @param provider\n   * @param rpcUrls\n   */\n  setupProvider(provider: UPProviderEndpoint, rpcUrls: string | string[]): Promise<void>\n}\n\nfunction _createUPProviderConnector(\n  channels: Map<string, UPClientChannel>,\n  options: UPProviderConnectorOptions\n): UPProviderConnector {\n  const emitter = new EventEmitter3<UPProviderConnectorEvents>()\n  \n  const getChannels = (): Map<string, UPClientChannel> => channels\n  \n  const connector: UPProviderConnector = {\n    eventNames: () => emitter.eventNames(),\n    listeners: <T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T) => emitter.listeners(event),\n    listenerCount: (event: EventEmitter.EventNames<UPProviderConnectorEvents>) => emitter.listenerCount(event),\n    \n    emit: <T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, ...args: EventEmitter.EventArgs<UPProviderConnectorEvents, T>): boolean => {\n      return emitter.emit(event, ...args)\n    },\n    \n    on: <T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, fn: EventEmitter.EventListener<UPProviderConnectorEvents, T>, context?: any) => {\n      emitter.on(event, fn, context)\n      return connector\n    },\n    \n    addListener: <T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, fn: EventEmitter.EventListener<UPProviderConnectorEvents, T>, context?: any) => {\n      emitter.addListener(event, fn, context)\n      return connector\n    },\n    \n    once: <T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, fn: EventEmitter.EventListener<UPProviderConnectorEvents, T>, context?: any) => {\n      emitter.once(event, fn, context)\n      return connector\n    },\n    \n    removeListener: <T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, fn?: EventEmitter.EventListener<UPProviderConnectorEvents, T>, context?: any, once?: boolean) => {\n      emitter.removeListener(event, fn, context, once)\n      return connector\n    },\n    \n    off: <T extends EventEmitter.EventNames<UPProviderConnectorEvents>>(event: T, fn?: EventEmitter.EventListener<UPProviderConnectorEvents, T>, context?: any, once?: boolean) => {\n      emitter.off(event, fn, context, once)\n      return connector\n    },\n    \n    removeAllListeners: (event?: EventEmitter.EventNames<UPProviderConnectorEvents>) => {\n      emitter.removeAllListeners(event)\n      return connector\n    },\n    \n    close: () => {\n      if (options.providerHandler) {\n        window.removeEventListener('message', options.providerHandler as any)\n        options.providerHandler = undefined\n      }\n    },\n\n    get provider(): UPProviderEndpoint {\n      return options.provider\n    },\n\n    setAllowedAccounts: async (accounts: `0x${string}`[]): Promise<void> => {\n      const allowedAccountsChanged = arrayChanged(options.allowedAccounts, accounts)\n      if (allowedAccountsChanged) {\n        options.allowedAccounts = [...accounts]\n        for (const item of connector.channels.values()) {\n          await item.setAllowedAccounts(item.enable ? cleanupAccounts(options.allowedAccounts) : [])\n        }\n      }\n    },\n    \n    get allowedAccounts(): `0x${string}`[] {\n      return cleanupAccounts(options.allowedAccounts)\n    },\n    \n    set allowedAccounts(accounts: `0x${string}`[]) {\n      connector.setAllowedAccounts(accounts)\n    },\n\n    setChainId: async (chainId: number): Promise<void> => {\n      if (options.chainId !== chainId) {\n        options.chainId = chainId\n        for (const item of connector.channels.values()) {\n          await item.setChainId(options.chainId)\n        }\n      }\n    },\n    \n    get chainId(): number {\n      return options.chainId\n    },\n    \n    set chainId(chainId: number) {\n      connector.setChainId(chainId)\n    },\n    \n    get channels(): Map<string, UPClientChannel> {\n      return new Map(getChannels())\n    },\n\n    getChannel: (id: string | Window | HTMLIFrameElement | UPClientChannel | null): UPClientChannel | null => {\n      let _id = id\n      if (typeof _id === 'string') {\n        return getChannels().get(_id) || null\n      }\n\n      // Special handling when running inside an iframe and looking up parent window\n      // Do this BEFORE any property access that might fail on cross-origin objects\n      if (window.parent !== window && _id === window.parent) {\n        serverLog('getChannel: Looking up parent window channel')\n        // Check if we already have a channel for the parent window\n        for (const item of getChannels().values()) {\n          // For parent window, we can't compare directly due to cross-origin\n          // Instead, check if this is our special parent window channel\n          if (item.window === window.parent) {\n            return item\n          }\n        }\n        // No existing channel for parent window\n        return null\n      }\n\n      if (window.opener !== window && _id === window.opener) {\n        serverLog('getChannel: Looking up parent window channel')\n        // Check if we already have a channel for the parent window\n        for (const item of getChannels().values()) {\n          // For parent window, we can't compare directly due to cross-origin\n          // Instead, check if this is our special parent window channel\n          if (item.window === window.opener) {\n            return item\n          }\n        }\n        // No existing channel for parent window\n        return null\n      }\n\n      // Now safe to check if it's a UPClientChannel (only for non-parent windows)\n      if ('element' in (_id as any) || 'window' in (_id as any)) {\n        _id = (_id as UPClientChannel).element || (_id as UPClientChannel).window\n      }\n\n      for (const item of getChannels().values()) {\n        if (item.window === _id || item.element === _id) {\n          return item\n        }\n      }\n      return null\n    },\n\n    setContextAccounts: async (contextAccounts: `0x${string}`[]) => {\n      const contextAccountsChanged = arrayChanged(options.contextAccounts, contextAccounts)\n      if (contextAccountsChanged) {\n        options.contextAccounts = [...contextAccounts]\n        for (const item of connector.channels.values()) {\n          await item.setContextAccounts(cleanupAccounts(options.contextAccounts))\n        }\n      }\n    },\n    \n    get contextAccounts(): `0x${string}`[] {\n      return cleanupAccounts(options.contextAccounts)\n    },\n    \n    set contextAccounts(contextAccounts: `0x${string}`[]) {\n      connector.setContextAccounts(contextAccounts)\n    },\n\n    setupProvider: async (provider: any, rpcUrls: string | string[]): Promise<void> => {\n      // Create a new promise that will be awaited by new connections\n      const previousPromise = options.promise\n      options.promise = new Promise<void>((resolve, reject) => {\n        ;(async () => {\n          try {\n            // Wait for any previous initialization to complete\n            await previousPromise\n            const oldCallback = options.providerAccountsChangedCallback\n            if (options.provider && oldCallback && typeof options.provider.off === 'function') {\n              options.provider.off('accountsChanged', oldCallback)\n              options.providerAccountsChangedCallback = undefined\n            }\n            options.provider = provider\n            const newRpcUrls = Array.isArray(rpcUrls) ? rpcUrls : [rpcUrls]\n            if (arrayChanged(newRpcUrls, options.rpcUrls)) {\n              options.rpcUrls = newRpcUrls\n              for (const item of connector.channels.values()) {\n                await item.setRpcUrls(options.rpcUrls)\n              }\n            }\n            const _chainId = Number(\n              (await options.provider?.request({\n                method: 'eth_chainId',\n                params: [],\n              })) || options.chainId\n            )\n            if (_chainId !== options.chainId) {\n              options.chainId = _chainId\n              for (const item of connector.channels.values()) {\n                await item.setChainId(options.chainId)\n              }\n            }\n            const _accounts =\n              (await options.provider?.request({\n                method: 'eth_accounts',\n                params: [],\n              })) || []\n            const accountsChanged = arrayChanged(options.allowedAccounts, _accounts)\n            if (accountsChanged) {\n              options.allowedAccounts = [..._accounts]\n              for (const item of connector.channels.values()) {\n                await item.setAllowedAccounts(cleanupAccounts(options.allowedAccounts))\n              }\n            }\n            const accountsChangedCallback = async (_accounts: `0x${string}`[]) => {\n              const accountsChanged = arrayChanged(options.allowedAccounts, _accounts)\n              if (accountsChanged) {\n                options.allowedAccounts = [..._accounts]\n                for (const item of connector.channels.values()) {\n                  await item.setAllowedAccounts(cleanupAccounts(options.allowedAccounts))\n                }\n              }\n            }\n            if (options.provider && typeof options.provider.on === 'function') {\n              options.providerAccountsChangedCallback = accountsChangedCallback\n              options.provider.on('accountsChanged', accountsChangedCallback)\n            }\n            resolve()\n          } catch (err) {\n            reject(err)\n          }\n        })()\n      })\n    }\n  }\n  \n  return connector\n}\n\nlet globalUPProvider: UPProviderConnector | null = null\n\n/**\n * Global method to find channel in case `up-channel-connected` event was missed.\n *\n * @param id how to find the UPClientChannel instance (this can be the id, frame (not the frame's element id) or window)\n * @returns UPClientChannel\n */\nfunction getUPProviderChannel(id: string | Window | HTMLIFrameElement | UPClientChannel | null): UPClientChannel | null {\n  if (id == null) {\n    return null\n  }\n  if (!globalUPProvider) {\n    throw new Error('Global UP Provider not set up')\n  }\n  return globalUPProvider.getChannel(id)\n}\n\n/**\n * Install a global UPProvider inside of the particular window which will listen for client\n * connections and establish them. It will fire `up-channel-connected` on the particular iframe if it's reachable.\n * It will fire a local `channelCreated` event as well.\n *\n * @param provider the initial provider to proxy\n * @param rpcUrls rpc urls to give to the clients to locally connect for non eth_sendTransaction and so on.\n * @returns The global provider and event sing for `channelCreated` events.\n */\nfunction createUPProviderConnector(provider?: any, rpcUrls?: string | string[]): UPProviderConnector {\n  if (globalUPProvider) {\n    return globalUPProvider\n  }\n  const channels = new Map<string, UPClientChannel>()\n\n  // Allow for late initialization of class properties.\n  const options: UPProviderConnectorOptions = {\n    provider: provider ?? null,\n    rpcUrls: Array.isArray(rpcUrls) ? rpcUrls : rpcUrls != null ? [rpcUrls] : [],\n    chainId: 0,\n    allowedAccounts: [],\n    contextAccounts: [],\n    promise: Promise.resolve(),\n  }\n  globalUPProvider = _createUPProviderConnector(channels, options)\n\n  serverLog('server listen', window)\n\n  // Server handler to accept new client provider connections\n  options.providerHandler = (event: MessageEvent) => {\n    // Handle wrapped JSONRPC messages for cross-origin scenarios (when no channel exists yet)\n    if (event.data?.type === UP_PROVIDER_JSONRPC_TYPE) {\n      // Find the channel for this source\n      for (const [channelId, channel] of channels) {\n        if (channel.window === event.source) {\n          // Forward to the channel's handler\n          const serverChannel = (channel as any)._serverChannel\n          if (serverChannel) {\n            // Unwrap and send through the channel\n            serverChannel.postMessage(event.data.payload)\n          }\n          return\n        }\n      }\n      // If no channel found, ignore (might be from another wallet)\n      return\n    }\n\n    // Handle both regular provider requests and iframe-specific requests\n    if (event.data === 'upProvider:hasProvider' || event.data === 'upProvider:requestIframeProvider') {\n      // If we're running inside an iframe, only respond to iframe-specific requests\n      const isInIframe = window.parent !== window\n      if (isInIframe && event.data === 'upProvider:hasProvider') {\n        serverLog('Ignoring regular provider request while in iframe')\n        return\n      }\n\n      let iframe: HTMLIFrameElement | null = null\n\n      // Log all iframes found\n      const allIframes = document.querySelectorAll('iframe')\n      serverLog('Found iframes:', allIframes.length)\n\n      // Try to find the iframe that sent this message\n      // For cross-origin iframes, we can't access contentWindow directly\n      for (const element of document.querySelectorAll('iframe')) {\n        try {\n          if (element.contentWindow === event.source) {\n            serverLog('server hasProvider - matched iframe', element)\n            iframe = element\n            break\n          }\n        } catch (e) {\n          // Cross-origin access denied - this is expected for cross-origin iframes\n          // We'll handle this case below by using the Window reference directly\n          serverLog('Cross-origin iframe detected, cannot access contentWindow for', element.src)\n        }\n      }\n\n      if (!iframe) {\n        serverLog('No matching iframe found, using Window reference directly')\n      }\n\n      const previous = iframe ? getUPProviderChannel(iframe) : getUPProviderChannel(event.source as Window)\n      let channelId: string\n      let serverChannel = event.ports?.[0]\n      const server = new JSONRPCServer()\n      // Enable by default for iframe/popup mode (when requestIframeProvider is used)\n      let enabled = event.data === 'upProvider:requestIframeProvider'\n\n      // If no port was provided (cross-origin case), create our own MessageChannel\n      let createdChannel: MessageChannel | undefined\n      if (!serverChannel) {\n        serverLog('No port received, creating MessageChannel in server')\n        createdChannel = new MessageChannel()\n        serverChannel = createdChannel.port1\n      }\n\n      // Server handler to forward requests to the provider\n      if (previous) {\n        channelId = previous.id\n      } else {\n        channelId = uuidv4()\n      }\n\n      // Wrapper for representation of client connection inside of global provider space.\n      const channel_ = createUPClientChannel(\n        serverChannel,\n        event.source as Window,\n        iframe,\n        channelId,\n        server,\n        () => enabled,\n        (value: boolean) => {\n          enabled = value\n        }\n      )\n\n      server.applyMiddleware(async (_, request) => {\n        await options.promise\n        const { method: _method, params: _params, id, jsonrpc } = request\n        const method =\n          typeof _method === 'string'\n            ? _method\n            : (\n                _method as unknown as {\n                  method: string\n                  params: unknown[]\n                }\n              ).method\n        const params =\n          typeof _method === 'string'\n            ? _params\n            : (\n                _method as unknown as {\n                  method: string\n                  params: unknown[]\n                }\n              ).params\n        switch (method) {\n          case 'chainChanged':\n            serverLog('short circuit response', request, [options.chainId])\n            channel_.emit('chainChanged', options.chainId)\n            return {\n              ...request,\n              result: [options.chainId],\n            } as JSONRPCSuccessResponse\n          case 'accounts': {\n            const accounts = cleanupAccounts(enabled ? [...channel_.allowedAccounts] : [])\n            serverLog('short circuit response', request)\n            channel_.emit('requestAccounts', accounts)\n            return {\n              ...request,\n              result: accounts,\n            } as JSONRPCSuccessResponse\n          }\n          case 'contextAccountsChanged': {\n            const accounts = cleanupAccounts([...channel_.contextAccounts])\n            serverLog('short circuit response', request)\n            channel_.emit('contextAccountsChanged', accounts)\n            return {\n              ...request,\n              result: accounts,\n            } as JSONRPCSuccessResponse\n          }\n          case 'wallet_switchEthereumChain': {\n            serverLog('short circuit response', request)\n            globalUPProvider?.setChainId(Number(params[0]?.chainId ?? options.chainId))\n            return {\n              ...request,\n              result: null,\n            } as JSONRPCSuccessResponse\n          }\n          case 'eth_requestAccounts': {\n            const accounts = cleanupAccounts(enabled ? [...channel_.allowedAccounts] : [])\n            serverLog('short circuit response', request, accounts)\n            channel_.emit('requestAccounts', accounts)\n            return {\n              ...request,\n              result: accounts,\n            } as JSONRPCSuccessResponse\n          }\n          case 'eth_chainId':\n            return {\n              ...request,\n              result: `0x${options.chainId.toString(16)}`,\n            } as JSONRPCSuccessResponse\n          case 'eth_accounts': {\n            const accounts = cleanupAccounts(enabled ? [...channel_.allowedAccounts] : [])\n            channel_.emit('accountsChanged', accounts)\n            return {\n              ...request,\n              result: accounts,\n            } as JSONRPCSuccessResponse\n          }\n        }\n        try {\n          if (!options.provider) {\n            throw new Error('Global Provider not connected')\n          }\n          const response = await options.provider.request({ method, params })\n          serverLog('response', request, response)\n          return {\n            id,\n            jsonrpc,\n            result: response,\n          } as JSONRPCSuccessResponse\n        } catch (error) {\n          console.error(error)\n          const response = {\n            id,\n            jsonrpc,\n            error,\n          } as JSONRPCErrorResponse\n          serverLog('response error', request, response)\n          return response\n        }\n      })\n\n      const channelHandler = (event: MessageEvent) => {\n        // Handle wrapped JSONRPC messages for cross-origin scenarios\n        if (event.data?.type === UP_PROVIDER_JSONRPC_TYPE) {\n          const jsonrpcMessage = event.data.payload\n          if (jsonrpcMessage) {\n            // Process as regular JSONRPC message\n            const mockEvent = { data: jsonrpcMessage }\n            channelHandler(mockEvent as MessageEvent)\n          }\n          return\n        }\n\n        if (event.data.type === 'upProvider:windowInitialized') {\n          serverLog('channel created', event.data.type, event.data)\n          globalUPProvider?.emit('channelCreated', channel_.element || channel_.window || null, channel_)\n          const destination = channel_.element || channel_.window || null\n          if (destination != null) {\n            let usePostMessage = false\n            try {\n              ;(destination as any).upChannel = channel_\n            } catch {\n              // Ignore\n              usePostMessage = true\n            }\n            const detail = {\n              channel: channel_,\n              chainId: options.chainId,\n              allowedAccounts: [],\n              contextAccounts: options.contextAccounts,\n              rpcUrls: options.rpcUrls,\n              enable: false,\n            }\n            serverLog('channel receipt', detail)\n            const event = new CustomEvent('up-channel-connected', {\n              detail,\n            })\n            if (usePostMessage) {\n              // Need to specify target origin for cross-origin communication\n              ;(destination as Window)?.postMessage({ ...detail, channel: undefined }, '*')\n            } else {\n              try {\n                destination.dispatchEvent(event)\n              } catch {}\n            }\n          }\n          return\n        }\n        try {\n          const request = {\n            ...event.data,\n            id: `${channelId}:${event.data.id}`,\n          }\n          server.receive(request).then(\n            response => {\n              serverLog('server response', response)\n              if (response && typeof response.id === 'string') {\n                if (request.method === 'eth_sendTransaction') {\n                  if (response.error) {\n                    console.error('Error sending transaction', response.error)\n                  }\n                  channel_.emit('sentTransaction', {\n                    from: request.params[0]?.from,\n                    to: request.params[0]?.to,\n                    value: request.params[0]?.value,\n                    result: response.result,\n                    error: response.error,\n                  })\n                }\n\n                // Handle wallet_requestPermissions response for popup/iframe modes\n                // return [{\n                //   parentCapability: 'eth_accounts',\n                //   invoker: window.location.origin,\n                //   caveats: [{\n                //     type: 'restrictReturnedAccounts',\n                //     value: accounts\n                //   }]\n                // }]\n                if (request.method === 'wallet_requestPermissions' && response.result) {\n                  // Only update accounts automatically for iframe/popup modes\n                  const isIframeOrPopup = channel_.element !== null || (channel_.window && channel_.window !== window)\n\n                  if (isIframeOrPopup) {\n                    const permissions = response.result[0]\n                    if (permissions?.caveats?.[0]?.type === 'restrictReturnedAccounts' && Array.isArray(permissions.caveats[0].value)) {\n                      const newAccounts = permissions.caveats[0].value as `0x${string}`[]\n                      const currentAccounts = channel_.allowedAccounts\n\n                      // Check if accounts changed using same logic as elsewhere\n                      if ((currentAccounts?.length ?? 0) !== (newAccounts?.length ?? 0) || currentAccounts?.some((account, index) => account !== newAccounts[index])) {\n                        serverLog('wallet_requestPermissions returned new accounts, updating and sending accountsChanged', {\n                          enabled,\n                          isIframeOrPopup,\n                          newAccounts,\n                          currentAccounts,\n                        })\n                        // Update the accounts - this will trigger accountsChanged event\n                        channel_.setAllowedAccounts(newAccounts)\n                      }\n                    }\n                  }\n                }\n                if (!response.id.startsWith(`${channelId}:`)) {\n                  console.error(`Invalid response id ${response.id} on channel ${channelId}`)\n                  return\n                }\n                // Check if we need to wrap the response for cross-origin\n                const responseMessage = {\n                  ...response,\n                  id: JSON.parse(response.id.replace(`${channelId}:`, '')),\n                }\n\n                // Check if this is a cross-origin scenario where we can't use MessageChannel\n                // We should use MessageChannel if we have serverChannel, regardless of window comparison\n                const needsWrapping = !serverChannel && channel_.window\n                if (needsWrapping && channel_.window) {\n                  // Wrap and send via window.postMessage\n                  channel_.window.postMessage(\n                    {\n                      type: UP_PROVIDER_JSONRPC_TYPE,\n                      payload: responseMessage,\n                    },\n                    '*'\n                  )\n                } else {\n                  // Use MessageChannel\n                  serverLog('Sending response via MessageChannel, serverChannel exists:', !!serverChannel, 'responseMessage:', responseMessage)\n                  if (serverChannel) {\n                    serverChannel.postMessage(responseMessage)\n                  } else {\n                    console.error('serverChannel is null/undefined, cannot send response!')\n                  }\n                }\n              }\n            },\n            (error: any) => {\n              if (request.method === 'eth_sendTransaction') {\n                if (error) {\n                  console.error('Error sending transaction', error)\n                }\n                channel_.emit('sentTransaction', {\n                  from: request.params[0]?.from,\n                  to: request.params[0]?.to,\n                  value: request.params[0]?.value,\n                  error,\n                })\n              }\n              const errorMessage = {\n                error,\n                id: JSON.parse(request.id.replace(`${channelId}:`, '')),\n              }\n\n              // Check if this is a cross-origin scenario where we can't use MessageChannel\n              // We should use MessageChannel if we have serverChannel, regardless of window comparison\n              const needsWrapping = !serverChannel && channel_.window\n              if (needsWrapping && channel_.window) {\n                // Wrap and send via window.postMessage\n                channel_.window.postMessage(\n                  {\n                    type: UP_PROVIDER_JSONRPC_TYPE,\n                    payload: errorMessage,\n                  },\n                  '*'\n                )\n              } else {\n                // Use MessageChannel\n                serverChannel?.postMessage(errorMessage)\n              }\n            }\n          )\n        } catch (error) {\n          console.error('Error parsing JSON RPC request', error, event)\n        }\n      }\n\n      channels.set(channelId, channel_)\n      serverLog('server hasProvider', event.data, event.ports)\n      serverChannel.addEventListener('message', channelHandler)\n      serverChannel.start()\n\n      serverLog('server accept', serverChannel)\n\n      // Wait for provider to be fully initialized before sending windowInitialize\n      options.promise.then(() => {\n        // For iframe/popup mode (enabled=true), send the allowed accounts\n        // For extension mode (enabled=false), send empty accounts until explicitly connected\n        const initMessage = {\n          type: 'upProvider:windowInitialize',\n          chainId: options.chainId,\n          allowedAccounts: cleanupAccounts(enabled ? options.allowedAccounts : []),\n          contextAccounts: cleanupAccounts(options.contextAccounts),\n          rpcUrls: options.rpcUrls,\n        }\n\n        serverLog('Sending windowInitialize after provider ready', initMessage)\n\n        if (createdChannel) {\n          // Send the port along with the init message via postMessage\n          serverLog('Sending created port back to client')\n          ;(event.source as Window).postMessage(initMessage, event.origin, [createdChannel.port2])\n        } else {\n          // Normal flow - send via the channel\n          serverChannel?.postMessage(initMessage)\n        }\n\n        if (enabled && options.allowedAccounts.length > 0) {\n          channel_.emit('connect', { chainId: `0x${options.chainId.toString(16)}` })\n        }\n      })\n    }\n  }\n  window.addEventListener('message', options.providerHandler)\n\n  // If provider was passed, set it up after handler is registered\n  if (provider) {\n    globalUPProvider.setupProvider(provider, rpcUrls || []).catch(console.error)\n  }\n\n  return globalUPProvider\n}\n\nexport { type UPClientChannel, type UPClientChannelEvents, type UPProviderConnector, type UPProviderConnectorEvents, type UPProviderEndpoint, type UPProviderEndpointEvents, getUPProviderChannel, createUPProviderConnector }\n","import debug from 'debug'\nimport EventEmitter3, { type EventEmitter } from 'eventemitter3'\nimport { JSONRPCClient, type JSONRPCParams } from 'json-rpc-2.0'\nimport { v5 as uuidv5, v4 as uuidv4 } from 'uuid'\nimport image from './UniversalProfiles_Apps_Logo_96px.svg'\nimport { create } from 'domain'\nimport { createWalletPopup, type ModalPopup } from './popup'\nimport { cleanupAccounts } from './index'\nimport { start } from 'repl'\n\nconst clientLog = debug('upProvider:client')\n\n// Unique identifier for UP Provider JSONRPC messages\nconst UP_PROVIDER_JSONRPC_TYPE = 'upProvider:jsonrpc' as const\n\ntype RequestQueueItem = {\n  resolve: (value: void | PromiseLike<void>) => unknown\n  reject: (reason: unknown) => unknown\n  sent: boolean\n  id: number | string\n  method: string\n  params: unknown[]\n}\n\ntype UPWindowConfig =\n  | Window\n  | null\n  | undefined\n  | {\n      url: string\n      mode: 'popup' | 'iframe'\n      name?: string\n      get: () => Promise<Record<string, unknown>>\n      set: (value: Record<string, unknown>) => Promise<void>\n      preventRegistration?: boolean\n      rdns?: string\n      icon?: string\n    }\n\ninterface UPClientProviderEvents {\n  connect: (args: { chainId: `0x${string}` }) => void\n  disconnect: () => void\n  accountsChanged: (accounts: `0x${string}`[]) => void\n  contextAccountsChanged: (contextAccounts: `0x${string}`[]) => void\n  requestAccounts: (accounts: `0x${string}`[]) => void\n  chainChanged: (chainId: number) => void\n  injected: (page: `0x${string}`) => void\n  rpcUrls: (rpcUrls: string[]) => void\n  windowClosed: () => void\n  initialized: () => void\n}\n\n/**\n * Internal closure for UPClientProvider to allow late initialization of class.\n */\ntype UPClientProviderOptions = {\n  client?: JSONRPCClient\n  chainId: () => number\n  switchChainId: (chainId: number) => void\n  connectEmitted: boolean\n  allowedAccounts: () => `0x${string}`[]\n  contextAccounts: () => `0x${string}`[]\n  window?: Window\n  clientChannel?: MessagePort\n  startupPromise: Promise<void>\n  popup?: ModalPopup\n  preStartupPromise: Promise<void>\n  allocateConnection: () => Promise<void>\n  isPopup?: boolean\n  isIframe?: boolean\n  loginPromise?: PromiseLike<any>\n  restart: () => void\n  init?: {\n    chainId: number\n    allowedAccounts: `0x${string}`[]\n    contextAccounts: `0x${string}`[]\n    rpcUrls: string[]\n  }\n}\n\nconst pendingRequests = new Map<string, RequestQueueItem>()\n\n/**\n * Public interface for UPClientProvider.\n */\ninterface UPClientProvider {\n  get isUPClientProvider(): boolean\n  /**\n   * Return an array listing the events for which the emitter has registered\n   * listeners.\n   */\n  eventNames(): Array<EventEmitter.EventNames<UPClientProviderEvents>>\n\n  /**\n   * Return the listeners registered for a given event.\n   */\n  listeners<T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T): Array<EventEmitter.EventListener<UPClientProviderEvents, T>>\n\n  /**\n   * Return the number of listeners listening to a given event.\n   */\n  listenerCount(event: EventEmitter.EventNames<UPClientProviderEvents>): number\n\n  /**\n   * Calls each of the listeners registered for a given event.\n   */\n  emit<T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, ...args: EventEmitter.EventArgs<UPClientProviderEvents, T>): boolean\n\n  /**\n   * Add a listener for a given event.\n   */\n  on<T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, fn: EventEmitter.EventListener<UPClientProviderEvents, T>, context?: any): this\n  addListener<T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, fn: EventEmitter.EventListener<UPClientProviderEvents, T>, context?: any): this\n\n  /**\n   * Add a one-time listener for a given event.\n   */\n  once<T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, fn: EventEmitter.EventListener<UPClientProviderEvents, T>, context?: any): this\n\n  /**\n   * Remove the listeners of a given event.\n   */\n  removeListener<T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, fn?: EventEmitter.EventListener<UPClientProviderEvents, T>, context?: any, once?: boolean): this\n  off<T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, fn?: EventEmitter.EventListener<UPClientProviderEvents, T>, context?: any, once?: boolean): this\n\n  /**\n   * Remove all listeners, or those of the specified event.\n   */\n  removeAllListeners(event?: EventEmitter.EventNames<UPClientProviderEvents>): this\n\n  request(method: string, params?: JSONRPCParams, clientParams?: any): Promise<any>\n  request(method: { method: string; params?: JSONRPCParams }, clientParams?: any): Promise<any>\n\n  /**\n   * Get the current chainId this is configured for and connected to.\n   */\n  get chainId(): number\n\n  /**\n   * Mirrors allowedAccounts, the accounts the provider is connected to\n   */\n  get accounts(): `0x${string}`[]\n\n  /**\n   * Additional context accounts provided by the parent connector.\n   * Inside of the universaleverything grid this will contain the account\n   * of the owner of the displayed grid (i.e. the owner of the profile being displayed.)\n   */\n  get contextAccounts(): `0x${string}`[]\n\n  get isConnected(): boolean\n\n  get isMiniApp(): Promise<boolean>\n\n  resume(delay?: number): void\n}\n\n/**\n * Internal factory function for UPClientProvider to use closure-based private variables.\n */\nfunction createUPClientProvider(options: UPClientProviderOptions) {\n  let bufferedEvents: Array<[keyof UPClientProviderEvents, unknown[]]> | undefined = []\n  \n  const emitter = new EventEmitter3<UPClientProviderEvents>()\n  \n  const provider: UPClientProvider = {\n    get isUPClientProvider(): boolean {\n      return true\n    },\n    \n    eventNames: () => emitter.eventNames(),\n    listeners: <T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T) => emitter.listeners(event),\n    listenerCount: (event: EventEmitter.EventNames<UPClientProviderEvents>) => emitter.listenerCount(event),\n    \n    emit: <T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, ...args: EventEmitter.EventArgs<UPClientProviderEvents, T>): boolean => {\n      if (bufferedEvents) {\n        bufferedEvents.push([event, args])\n        return false\n      }\n      return emitter.emit(event, ...args)\n    },\n    \n    on: <T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, fn: EventEmitter.EventListener<UPClientProviderEvents, T>, context?: any) => {\n      provider.resume(500)\n      emitter.on(event, fn, context)\n      return provider\n    },\n    \n    addListener: <T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, fn: EventEmitter.EventListener<UPClientProviderEvents, T>, context?: any) => {\n      provider.resume(500)\n      emitter.addListener(event, fn, context)\n      return provider\n    },\n    \n    once: <T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, fn: EventEmitter.EventListener<UPClientProviderEvents, T>, context?: any) => {\n      emitter.once(event, fn, context)\n      return provider\n    },\n    \n    removeListener: <T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, fn?: EventEmitter.EventListener<UPClientProviderEvents, T>, context?: any, once?: boolean) => {\n      emitter.removeListener(event, fn, context, once)\n      return provider\n    },\n    \n    off: <T extends EventEmitter.EventNames<UPClientProviderEvents>>(event: T, fn?: EventEmitter.EventListener<UPClientProviderEvents, T>, context?: any, once?: boolean) => {\n      emitter.off(event, fn, context, once)\n      return provider\n    },\n    \n    removeAllListeners: (event?: EventEmitter.EventNames<UPClientProviderEvents>) => {\n      emitter.removeAllListeners(event)\n      return provider\n    },\n    \n    resume: (delay = 0) => {\n      const buffered = bufferedEvents\n      if (!buffered) {\n        return\n      }\n      bufferedEvents = undefined\n      setTimeout(() => {\n        while (buffered.length > 0) {\n          const val = buffered.shift()\n          if (val) {\n            const [event, args] = val\n            emitter.emit(event, ...(args as any))\n          }\n        }\n      }, delay)\n    },\n\n    get isConnected(): boolean {\n      return options.allowedAccounts().length > 0\n    },\n\n    get isMiniApp(): Promise<boolean> {\n      return options\n        ?.startupPromise.catch(() => false)\n        .then(() => true)\n    },\n\n    request: async (_method: string | { method: string; params?: JSONRPCParams }, _params?: JSONRPCParams, _clientParams?: any): Promise<any> => {\n      await options?.preStartupPromise\n      const method = typeof _method === 'string' ? _method : _method.method\n      const params = typeof _method === 'string' ? _params : _method.params\n      if (!options?.client) {\n        if ((options?.isPopup || options.isIframe) && (method === 'wallet_requestPermissions' || method === 'eth_sendTransaction' || method === 'eth_requestAccounts' || (method === 'eth_accounts' && provider.accounts?.length === 0))) {\n          await options?.allocateConnection()\n          await options?.startupPromise\n        }\n      }\n      if (method === 'eth_requestAccounts' || method === 'wallet_requestPermissions') {\n        const shouldShowUI = method === 'wallet_requestPermissions' || !provider.accounts?.length\n        \n        if ((options?.isIframe || options?.isPopup) && shouldShowUI) {\n          if (options.popup) {\n            options.popup?.openModal()\n          }\n\n          if (!options.loginPromise) {\n            options.loginPromise = options\n              .client?.request('embedded_login', ['force'], _clientParams)\n              .then((result: unknown) => {\n                return result\n              })\n          }\n          const result = await options.loginPromise\n          \n          if (method === 'wallet_requestPermissions') {\n            const accounts = Array.isArray(result) ? result : provider.accounts\n            \n            if (options?.popup) {\n              clientLog('Closing modal after wallet_requestPermissions')\n              options?.popup?.closeModal()\n            }\n            \n            return [{\n              parentCapability: 'eth_accounts',\n              invoker: window.location.origin,\n              caveats: [{\n                type: 'restrictReturnedAccounts',\n                value: accounts\n              }]\n            }]\n          }\n        }\n        if (method === 'wallet_requestPermissions') {\n          const accounts = provider.accounts\n\n          if (options?.popup) {\n            clientLog('Closing modal after wallet_requestPermissions')\n            options?.popup?.closeModal()\n          }\n          \n          return [{\n            parentCapability: 'eth_accounts',\n            invoker: window.location.origin,\n            caveats: [{\n              type: 'restrictReturnedAccounts',\n              value: accounts\n            }]\n          }]\n        }\n      }\n      if (method === 'eth_requestAccounts' || method === 'eth_accounts') {\n        if (provider.chainId && provider.accounts.length > 0) {\n          if (!options?.connectEmitted) {\n            provider.emit('connect', { chainId: `0x${provider.chainId.toString(16)}` })\n            options.connectEmitted = true\n          }\n        } else {\n          options.connectEmitted = false\n        }\n        return provider.accounts\n      }\n      if (method === 'eth_chainId') {\n        return `0x${provider.chainId.toString(16)}`\n      }\n      if (method === 'wallet_switchEthereumChain') {\n        options.switchChainId(Number(params?.[0]?.chainId))\n        return `0x${provider.chainId.toString(16)}`\n      }\n      if (method === 'eth_accounts') {\n        return provider.accounts\n      }\n      const clientParams = typeof _method === 'string' ? _clientParams : _params\n      if (method === 'up_contextAccounts') {\n        return options.contextAccounts()\n      }\n      \n      if (!options?.client) {\n        clientLog('Client not ready, allocating connection first')\n        await options?.allocateConnection()\n        await options?.startupPromise\n      }\n      \n      if (method === 'wallet_requestPermissions') {\n        const result = await options?.client?.request(method, params, clientParams)\n        if (result && result[0]?.caveats?.[0]?.type === 'restrictReturnedAccounts' && Array.isArray(result[0].caveats[0].value)) {\n          const newAccounts = result[0].caveats[0].value as `0x${string}`[]\n          const currentAccounts = options?.allowedAccounts() || []\n          \n          if ((currentAccounts?.length ?? 0) !== (newAccounts?.length ?? 0) || currentAccounts?.some((account, index) => account !== newAccounts[index])) {\n            clientLog('wallet_requestPermissions returned different accounts, expecting accountsChanged event')\n          }\n        }\n        return result\n      }\n      \n      return options?.client?.request(method, params, clientParams) || null\n    },\n\n    get chainId() {\n      return options?.chainId() || 0\n    },\n\n    get accounts() {\n      return options?.allowedAccounts() || []\n    },\n\n    get contextAccounts() {\n      return options?.contextAccounts() || []\n    }\n  }\n  \n  return provider\n}\n\n/**\n * @internal\n * Search for the parent provider and connect it. This routine is internally called\n * @param up - search input if specific window should be pinged.\n * @param remote - the provider doing the pinging.\n * @param options - the internal closure for that provider.\n * @returns The provider if it successfully connected or throws an error.\n */\nasync function testWindow(up: Window | undefined | null, remote: UPClientProvider, options: UPClientProviderOptions): Promise<UPClientProvider> {\n  const _up = up || (typeof window !== 'undefined' ? window.parent : undefined)\n  if (!_up) {\n    throw new Error('No UP found')\n  }\n  return new Promise<UPClientProvider>((resolve, reject) => {\n    let timeout: number | NodeJS.Timeout = 0\n    const channel = new MessageChannel()\n\n    const testFn = (event: MessageEvent) => {\n      // Handle wrapped JSONRPC responses for cross-origin scenarios\n      if (event.data?.type === UP_PROVIDER_JSONRPC_TYPE && !options.clientChannel) {\n        const jsonrpcMessage = event.data.payload\n        if (jsonrpcMessage && typeof jsonrpcMessage.id !== 'undefined') {\n          // This is a JSONRPC response, handle it\n          const pending = pendingRequests.get(String(jsonrpcMessage.id))\n          if (pending) {\n            if (jsonrpcMessage.error) {\n              pending.reject(jsonrpcMessage.error)\n            } else {\n              pending.resolve(jsonrpcMessage.result)\n            }\n            pendingRequests.delete(String(jsonrpcMessage.id))\n          }\n        }\n        return\n      }\n\n      if (event.data?.type === 'upProvider:windowInitialize') {\n        const { chainId, allowedAccounts, contextAccounts, rpcUrls } = event.data\n\n        clientLog('client init', event.data, _up)\n        window.removeEventListener('message', testFn)\n        if (timeout) {\n          clearTimeout(timeout)\n          timeout = 0\n        }\n\n        // Check if we received a port from the server (cross-origin case)\n        if (event.ports?.[0]) {\n          clientLog('Received MessageChannel port from server')\n          options.clientChannel = event.ports[0]\n          // Don't start yet - will start after listener is attached in doSearch\n        } else {\n          // Use our original port (same-origin case)\n          options.clientChannel = channel.port1\n          // Don't start yet - will start after listener is attached in doSearch\n        }\n\n        options.window = _up\n        try {\n          _up.addEventListener('close', () => {\n            options.restart()\n            remote.emit('windowClosed')\n          })\n        } catch {\n          // Ignore\n        }\n        options.init = { chainId, allowedAccounts, contextAccounts, rpcUrls }\n        clientLog('client connected', event.data.type, event.data)\n        options.clientChannel.postMessage({\n          type: 'upProvider:windowInitialized',\n          chainId,\n          allowedAccounts,\n          contextAccounts,\n          rpcUrls,\n        })\n        resolve(remote)\n      }\n    }\n\n    // Only listen on channel.port1 if we're expecting to use it (same-origin)\n    // For cross-origin, we'll receive a port from the server\n    channel.port1.addEventListener('message', testFn)\n    channel.port1.start()\n    window.addEventListener('message', testFn)\n\n    // Check if we can access the window's origin (same-origin check)\n    let canTransferPort = false\n    try {\n      // If we can access the location, we're same-origin\n      // Check if we can access the location\n      void _up.location.href\n      canTransferPort = true\n    } catch (e) {\n      // Cross-origin - can't transfer MessageChannel\n      clientLog('Cross-origin detected, will send without port')\n    }\n\n    // Use stored target origin or default to '*'\n    const targetOrigin = (options as any).targetOrigin || '*'\n    clientLog('Using target origin for postMessage:', targetOrigin)\n\n    // Determine which message to send based on the context\n    let messageType = 'upProvider:hasProvider'\n\n    // If we're looking for an iframe provider (authURL has a URL), use a specific message\n    if ((options as any).isIframe) {\n      messageType = 'upProvider:requestIframeProvider'\n    }\n\n    // Send with or without port based on origin check\n    if (canTransferPort) {\n      _up.postMessage(messageType, targetOrigin, [channel.port2])\n    } else {\n      _up.postMessage(messageType, targetOrigin)\n    }\n\n    timeout = setTimeout(() => {\n      timeout = 0\n      window.removeEventListener('message', testFn)\n      channel.port1.removeEventListener('message', testFn)\n\n      clientLog('client', 'No UP found', _up)\n      reject(new Error('No UP found'))\n    }, 1000)\n  })\n}\n\n/**\n * Find the up connector in the parent or popup window.\n * @param authURL - optionlly pass a URL for a popup to be launched in an iframe to connect\n * @param remote - the up provider to be connect\n * @param options - the internal closure for that provider.\n * @returns\n */\nasync function findUP(authURL: UPWindowConfig, remote: UPClientProvider, options: UPClientProviderOptions): Promise<UPClientProvider | undefined> {\n  const current = typeof window !== 'undefined' && window instanceof Window ? window.opener || window.parent : null\n  if (current) {\n    const up = await testWindow(current, remote, options)\n    if (up) {\n      return up\n    }\n  }\n  if (authURL == null) {\n    throw new Error('No UP found')\n  }\n  if (typeof authURL === 'object' && authURL instanceof Window) {\n    throw new Error('No UP found')\n  }\n  throw new Error('No UP found')\n}\n\n/**\n * Helper routines to initiate the search procedure for the parent provider.\n * @param authURL - optional URL for popup window\n * @param remote - the up provider to be connected\n * @param options - the internal closure for that provider.\n * @param search - if true then it will search, else it expects either a window or URL.\n * @returns The connected provider or throws an error.\n */\nasync function findDestination(authURL: UPWindowConfig, remote: UPClientProvider, options: UPClientProviderOptions, search = false): Promise<UPClientProvider> {\n  let theWindow: UPWindowConfig = typeof authURL === 'object' && (authURL as { url?: string })?.url ? null : authURL\n\n  // Store the target origin in options for use in testWindow\n  if (typeof authURL === 'object' && !(authURL instanceof Window) && authURL?.url) {\n    try {\n      ;(options as any).targetOrigin = new URL(authURL.url).origin\n      clientLog('Stored target origin:', (options as any).targetOrigin)\n    } catch (e) {\n      clientLog('Could not determine target origin from URL')\n    }\n  }\n\n  if (typeof authURL === 'object' && !(authURL instanceof Window) && authURL?.url) {\n    const info = localStorage.getItem(`upProvider:info:${authURL}`)\n    if (info) {\n      const { chainId, allowedAccounts, contextAccounts, rpcUrls } = JSON.parse(info)\n      options.init = { chainId, allowedAccounts, contextAccounts, rpcUrls }\n    }\n    if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n      if (authURL.mode === 'popup') {\n        const childWindow = window.open(authURL.url, 'UE Wallet', 'width=400,height=600')\n        if (childWindow) {\n          clientLog('popup opened')\n          // childWindow.addEventListener('close', () => {\n          //   clientLog('popup closed')\n          //   options.restart()\n          //   remote.emit('windowClosed')\n          // })\n          theWindow = childWindow\n        }\n      }\n      if (authURL.mode === 'iframe') {\n        const { popup, isNew } = await createWalletPopup(authURL.url)\n        if (popup) {\n          options.popup = popup\n          const { window: current } = await popup.createModal()\n\n          if (current) {\n            clientLog(isNew ? 'New iframe created' : 'Reusing existing iframe')\n\n            // Only set up event listeners for new popups\n            if (isNew) {\n              const close = (event: MessageEvent) => {\n                if (event.data?.type === 'upProvider:modalClosed') {\n                  clientLog('iframe modal closed (keeping connection)')\n                  // Don't restart or emit windowClosed - just hide the modal\n                  // The connection should persist\n                  window.removeEventListener('message', close)\n                }\n              }\n              window.addEventListener('message', close)\n              try {\n                current.addEventListener('close', () => {\n                  clientLog('iframe window actually closed')\n                  // Only restart if the window is actually destroyed, not just hidden\n                  options.restart()\n                  remote.emit('windowClosed')\n                  window.removeEventListener('message', close)\n                })\n              } catch {\n                // Ignore - cross-origin frames might not allow this\n              }\n            }\n\n            theWindow = current\n\n            // Only wait for ready message on new iframes\n            if (authURL.mode === 'iframe' && current && isNew) {\n              clientLog('Waiting for new iframe to announce ready')\n              \n              // Wait for the iframe to announce it's ready (DOM loaded)\n              await new Promise<void>(resolve => {\n                let timeoutId: NodeJS.Timeout | number\n                \n                const readyHandler = (event: MessageEvent) => {\n                  // Debug logging\n                  if (event.data === 'upProvider:ready') {\n                    clientLog('Received upProvider:ready from:', event.source, 'expected:', current, 'match:', event.source === current)\n                  }\n\n                  // For cross-origin iframes, event.source might not be accessible or comparable\n                  // So just check for the message type\n                  if (event.data === 'upProvider:ready') {\n                    clientLog('Iframe announced ready')\n                    clearTimeout(timeoutId)  // Clear the timeout since we got the ready message\n                    window.removeEventListener('message', readyHandler)\n                    resolve()\n                  }\n                }\n                window.addEventListener('message', readyHandler)\n\n                // Timeout after 3 seconds - this is expected if the iframe doesn't send ready\n                timeoutId = setTimeout(() => {\n                  window.removeEventListener('message', readyHandler)\n                  clientLog('Iframe ready timeout (proceeding anyway - this is normal)')\n                  resolve()\n                }, 3000)\n              })\n              \n              // Don't wait for provider initialization here - it blocks the channel setup!\n              // The provider will send accountsChanged through the channel once it's ready\n            }\n          }\n        }\n      }\n    }\n  }\n  let up: UPClientProvider | undefined = await testWindow(theWindow as Window | undefined | null, remote, options).catch(error => {\n    if (search) {\n      return undefined\n    }\n    throw error\n  })\n  \n\n  if (search && !up) {\n    let retry = 3\n    while (retry > 0) {\n      let current: Window | undefined = theWindow || (window.opener && window.opener !== window ? window.opener : window.parent && window.parent !== window ? window.parent : undefined)\n      while (current) {\n        up = await testWindow(current, remote, options).catch(() => undefined)\n        if (up) {\n          break\n        }\n        if (current === window.top) {\n          break\n        }\n        current = theWindow || (current.opener && current.opener !== current ? current.opener : current.parent && current.parent !== current ? current.parent : undefined)\n      }\n      if (up) {\n        break\n      }\n\n      // Wait for a second for each try.\n      await new Promise(resolve => setTimeout(resolve, 1000))\n\n      retry--\n    }\n  }\n  if (!up) {\n    throw new Error('No UP found')\n  }\n  return up\n}\n\n/**\n * Create clientUPProvider. This can be used like a normal window.ethereum or window.lukso provider.\n * It will on initialization look for a connection to a global provider.\n *\n * @param authURL Optionally put a URL to a authentication provider to provide the global provider.\n * @param search If false then don't search but take the passed in value as is.\n * @returns the client UPProvider\n */\nfunction createClientUPProvider(authURL?: UPWindowConfig, search = true): UPClientProvider {\n  let chainId = 0\n  let allowedAccounts: `0x${string}`[] = []\n  let contextAccounts: `0x${string}`[] = []\n  let rpcUrls: string[] = []\n  let startupResolve: () => void\n  let preStartupResolve: () => void = () => {}\n  const preStartupPromise = new Promise<void>(resolve => {\n    preStartupResolve = resolve\n  }).then(() => {\n    clientLog('pre startup resolved')\n  })\n  let startupPromise = new Promise<void>(resolve => {\n    startupResolve = resolve\n  }).then(() => {\n    remote.emit('initialized')\n  })\n\n  const allocateConnection = async () => {\n    const client = new JSONRPCClient(async (jsonRPCRequest: any) => {\n      await doSearch(client).then(up => {\n        options.client = client\n        return up\n      })\n\n      return new Promise((resolve, reject) => {\n        const { id, method, params } = jsonRPCRequest\n\n        pendingRequests.set(id, {\n          resolve,\n          reject,\n          sent: false,\n          id,\n          method,\n          params,\n        })\n\n        // Debug log the request being sent\n        clientLog('Sending JSONRPC request:', method, 'id:', id, 'via:', options.clientChannel ? 'MessageChannel' : 'postMessage')\n        \n        // Check if the channel is still valid\n        if (options.clientChannel) {\n          try {\n            options.clientChannel.postMessage(jsonRPCRequest)\n          } catch (e) {\n            console.error('*** MessageChannel postMessage failed:', e)\n            // Channel might be closed, need to reconnect\n            clientLog('MessageChannel appears to be broken, may need to reconnect')\n          }\n        } else if (options.window) {\n          // For cross-origin scenarios, wrap the JSONRPC message\n          options.window.postMessage(\n            {\n              type: UP_PROVIDER_JSONRPC_TYPE,\n              payload: jsonRPCRequest,\n            },\n            (options as any).targetOrigin || '*'\n          )\n        }\n      })\n    })\n\n    const request_ = client.request.bind(client)\n\n    const wrapper = async (method: string, params?: unknown[]) => {\n      await preStartupPromise\n      switch (method) {\n        case 'eth_accounts':\n        case 'eth_requestAccounts':\n          if (allowedAccounts.length > 0) {\n            return allowedAccounts\n          }\n          break\n        case 'wallet_switchEthereumChain': {\n          const { chainId: _chainId } = params?.[0] as { chainId: number | `0x${string}` }\n          if (_chainId) {\n            chainId = Number(_chainId)\n            persist()\n            remote.emit('chainChanged', chainId)\n          }\n          return `0x${chainId.toString(16)}`\n        }\n        case 'eth_chainId':\n          return `0x${chainId.toString(16)}`\n        case 'eth_call':\n          // Is this call is used to evaluate or simulate a transaction then we have to send it to the parent provider.\n          // Otherwise we can send it directly to a configured RPC endpoint.\n          if (rpcUrls.length > 0 && Object.keys((params?.[0] ?? {}) as Record<string, unknown>).every(key => !/^gasPrice|maxFeePerGas|maxPriorityFeePerGas|value$/.test(key))) {\n            clientLog('client direct rpc', rpcUrls, method, params)\n\n            const urls = [...rpcUrls]\n            const errors = []\n            while (urls.length > 0) {\n              const url = urls.shift()\n              try {\n                if (!url) {\n                  throw new Error('No RPC URL found')\n                }\n\n                const result = fetch(url, {\n                  method: 'POST',\n                  headers: {\n                    'Content-Type': 'application/json',\n                  },\n                  body: JSON.stringify({\n                    jsonrpc: '2.0',\n                    id: uuidv4(),\n                    method,\n                    params,\n                  }),\n                }).then(response => {\n                  if (response.ok) {\n                    return response.json()\n                  }\n                  throw new Error('Network response was not ok')\n                })\n\n                return result\n              } catch (error) {\n                // This is a real error log (maybe goes to sentry)\n                console.error('error', error)\n                errors.push(error)\n              }\n            }\n            const err: any = new Error(`All RPC URLs failed: ${errors.map(e => (e as { message: string }).message).join(', ')}`)\n            err.errors = errors\n            throw err\n          }\n      }\n      return request_(method, params)\n    }\n\n    client.request = async (method: string | { method: string; params: unknown[] }, params?: unknown[]) => {\n      const methodName = typeof method === 'string' ? method : method.method\n      switch (methodName) {\n        case 'wallet_revokePermissions':\n          // This is a special case for revoke permissions.\n          if ((allowedAccounts?.length ?? 0) > 0) {\n            allowedAccounts = []\n            persist()\n            remote.emit(\n              'accountsChanged',\n              // Cleanup wrong null or undefined.\n              cleanupAccounts(allowedAccounts)\n            )\n          }\n          if ((contextAccounts?.length ?? 0) > 0) {\n            contextAccounts = []\n            persist()\n            remote.emit(\n              'contextAccountsChanged',\n              // Cleanup wrong null or undefined.\n              cleanupAccounts(contextAccounts)\n            )\n          }\n          remote.emit('disconnect')\n          return null\n      }\n\n      await doSearch(client)\n\n      await startupPromise\n\n      // make it compatible with old and new type RPC.\n      if (typeof method === 'string') {\n        return await wrapper(method, params)\n      }\n      const { method: _method, params: _params } = method\n      return await wrapper(_method, _params)\n    }\n\n    await doSearch(client)\n  }\n\n  const options: UPClientProviderOptions = {\n    chainId: () => chainId,\n    switchChainId: (_chainId: number) => {\n      chainId = _chainId\n      persist()\n      remote.emit('chainChanged', chainId)\n    },\n    restart: () => {},\n    connectEmitted: false,\n    allowedAccounts: () => allowedAccounts,\n    contextAccounts: () => contextAccounts,\n    startupPromise,\n    preStartupPromise,\n    allocateConnection,\n    isPopup: (authURL as { url?: string })?.url !== undefined,\n    isIframe: (authURL as { mode?: string })?.mode === 'iframe',\n  }\n\n  options.restart = function restart() {\n    clientLog('Restarting connection - cleaning up state')\n\n    // Clean up connection state\n    options.window = undefined\n    options.clientChannel = undefined\n    options.connectEmitted = false\n    \n    // Clear the search promise so next connection will set up listeners\n    searchPromise = null\n\n    // Reset the startup promise\n    options.startupPromise = startupPromise = new Promise<void>(resolve => {\n      startupResolve = resolve\n    }).then(() => {\n      remote.emit('initialized')\n    })\n  }\n\n  const remote = createUPClientProvider(options)\n  let searchPromise: Promise<UPClientProvider> | null\n\n  if (authURL && !(authURL instanceof Window)) {\n    authURL.get().then((value: Record<string, unknown>) => {\n      if (value.chainId) {\n        chainId = value.chainId as number\n      }\n      if (value.allowedAccounts) {\n        allowedAccounts = value.allowedAccounts as `0x${string}`[]\n      }\n      if (value.rpcUrls) {\n        rpcUrls = value.rpcUrls as string[]\n      }\n      preStartupResolve()\n    })\n  } else {\n    preStartupResolve()\n  }\n  if (authURL instanceof Window || !authURL || !authURL?.preventRegistration) {\n    // Register the provider as a wallet by announcing it.\n    const info = authURL && !(authURL instanceof Window) ? authURL : undefined\n    const rdns = info?.rdns || 'dev.lukso.auth'\n    const dns = rdns.split('.').reverse().join('.')\n    const providerInfo = {\n      uuid: uuidv5(dns, uuidv5.DNS),\n      name: info?.name || 'UE Universal Profile',\n      icon: info?.icon || `data:image/svg+xml,${encodeURIComponent(image)}`,\n      rdns,\n    }\n\n    // Announce event.\n    const announceEvent = new CustomEvent('eip6963:announceProvider', {\n      detail: Object.freeze({ info: providerInfo, provider: remote }),\n    })\n\n    // The Wallet dispatches an announce event which is heard by\n    // the DApp code that had run earlier\n    window.dispatchEvent(announceEvent)\n\n    // The Wallet listens to the request events which may be\n    // dispatched later and re-dispatches the `EIP6963AnnounceProviderEvent`\n    window.addEventListener('eip6963:requestProvider', () => {\n      window.dispatchEvent(announceEvent)\n    })\n  }\n  const persist = () => {\n    if (authURL && !(authURL instanceof Window)) {\n      authURL.set({\n        chainId,\n        allowedAccounts,\n        rpcUrls,\n      })\n    }\n  }\n  const doSearch = async (client: JSONRPCClient): Promise<UPClientProvider> => {\n    if (searchPromise) {\n      return searchPromise\n    }\n    const activeSearchPromise = findDestination(authURL, remote, options, search)\n      .then(up => {\n        up?.addListener('windowClosed', () => {\n          searchPromise = null\n        })\n        const init:\n          | {\n              chainId: number\n              allowedAccounts: `0x${string}`[]\n              contextAccounts: `0x${string}`[]\n              rpcUrls: string[]\n            }\n          | undefined = options.init\n        if (init) {\n          ;({ chainId, allowedAccounts, contextAccounts, rpcUrls } = init || {})\n          persist()\n        }\n        \n        // If we have initial accounts from the provider initialization message, use them\n        if ((options as any).initialAccounts?.length) {\n          clientLog('Applying initial accounts from provider initialization:', (options as any).initialAccounts)\n          allowedAccounts = (options as any).initialAccounts\n          persist()\n          // Clear the temporary storage\n          delete (options as any).initialAccounts\n        }\n        // Set up message listener based on connection type\n        if (options.clientChannel) {\n          // MessageChannel-based communication (same-origin)\n          clientLog('Setting up MessageChannel listener, channel exists:', !!options.clientChannel)\n          options.clientChannel.addEventListener('message', event => {\n            try {\n              const response = event.data\n              clientLog('client MessageChannel message received:', response)\n              clientLog('Message details - method:', response?.method, 'params:', response?.params, 'id:', response?.id)\n              switch (response.method) {\n                case 'chainChanged':\n                  chainId = response.params[0]\n                  persist()\n                  up.emit('chainChanged', chainId)\n                  return\n                case 'contextAccountsChanged':\n                  if ((contextAccounts?.length ?? 0) !== (response.params?.length ?? 0) || contextAccounts?.some((account, index) => account !== response.params[index])) {\n                    contextAccounts = response.params\n                    up.emit(\n                      'contextAccountsChanged',\n                      // Cleanup wrong null or undefined.\n                      cleanupAccounts(contextAccounts)\n                    )\n                  }\n                  return\n                case 'accountsChanged':\n                  clientLog('Received accountsChanged:', response.params)\n                  if ((allowedAccounts?.length ?? 0) !== (response.params?.length ?? 0) || allowedAccounts?.some((account, index) => account !== response.params[index])) {\n                    clientLog('Updating allowedAccounts from', allowedAccounts, 'to', response.params)\n                    allowedAccounts = response.params\n                    persist()\n                    up.emit(\n                      'accountsChanged',\n                      // Cleanup wrong null or undefined.\n                      cleanupAccounts(allowedAccounts)\n                    )\n                  }\n                  return\n                case 'rpcUrlsChanged':\n                  rpcUrls = response.params\n                  persist()\n                  up.emit('rpcUrls', rpcUrls)\n                  return\n                case 'showPopup':\n                  clientLog('Received showPopup request:', response.params)\n                  if (options.popup) {\n                    const shouldShow = response.params?.[0]\n                    if (shouldShow === true) {\n                      clientLog('Opening modal popup')\n                      options.popup.openModal()\n                    } else if (shouldShow === false) {\n                      clientLog('Closing modal popup')\n                      options.popup.closeModal()\n                    }\n                  } else {\n                    clientLog('No popup available to control')\n                  }\n                  return\n                case 'connect':\n                  up.emit('connect', response.params[0])\n                  return\n                case 'disconnect':\n                  options.connectEmitted = false\n                  options.loginPromise = undefined\n                  if ((allowedAccounts?.length ?? 0) > 0) {\n                    allowedAccounts = []\n                    persist()\n                    up.emit(\n                      'accountsChanged',\n                      // Cleanup wrong null or undefined.\n                      cleanupAccounts(allowedAccounts)\n                    )\n                  }\n                  if ((contextAccounts?.length ?? 0) > 0) {\n                    contextAccounts = []\n                    persist()\n                    up.emit(\n                      'contextAccountsChanged',\n                      // Cleanup wrong null or undefined.\n                      cleanupAccounts(contextAccounts)\n                    )\n                  }\n                  up.emit('disconnect')\n                  return\n              }\n              const item = pendingRequests.get(response.id)\n              clientLog('Response received for id:', response.id, 'found in pending:', !!item, 'method was:', item?.method)\n              if (response.id && item) {\n                const { resolve, reject } = item\n                if (response.result !== undefined) {\n                  client.receive({ ...response, id: item.id }) // Handle the response\n                  resolve() // Resolve the corresponding promise\n                } else if (response.error) {\n                  const { error: _error, jsonrpc } = response\n                  const { method, params, id } = item\n                  const error = {\n                    ..._error,\n                    message: `${_error.message} ${JSON.stringify(method)}(${JSON.stringify(params)})`,\n                  }\n                  // This is a real error log (maybe goes to sentry)\n                  console.error('error', { error, method, params, id, jsonrpc })\n                  client.receive({ ...response, id: item.id })\n                  reject(error) // Reject in case of error\n                }\n                pendingRequests.delete(response.id) // Clean up the request\n              }\n            } catch (error) {\n              // This is a real error log (maybe goes to sentry)\n              console.error('Error parsing JSON RPC response', error, event)\n            }\n          })\n          clientLog('Starting MessageChannel listener')\n          options.clientChannel.start()\n        } else if (options.window) {\n          // Window postMessage-based communication (cross-origin)\n          const messageHandler = (event: MessageEvent) => {\n            // Only handle wrapped JSONRPC messages\n            if (event.data?.type === UP_PROVIDER_JSONRPC_TYPE) {\n              try {\n                const response = event.data.payload\n                clientLog('client (cross-origin)', response)\n                switch (response.method) {\n                  case 'chainChanged':\n                    chainId = response.params[0]\n                    persist()\n                    up.emit('chainChanged', chainId)\n                    return\n                  case 'contextAccountsChanged':\n                    if ((contextAccounts?.length ?? 0) !== (response.params?.length ?? 0) || contextAccounts?.some((account: any, index: number) => account !== response.params[index])) {\n                      contextAccounts = response.params\n                      up.emit('contextAccountsChanged', cleanupAccounts(contextAccounts))\n                    }\n                    return\n                  case 'accountsChanged':\n                    clientLog('Received accountsChanged (cross-origin):', response.params)\n                    if ((allowedAccounts?.length ?? 0) !== (response.params?.length ?? 0) || allowedAccounts?.some((account: any, index: number) => account !== response.params[index])) {\n                      clientLog('Updating allowedAccounts from', allowedAccounts, 'to', response.params)\n                      allowedAccounts = response.params\n                      persist()\n                      up.emit('accountsChanged', cleanupAccounts(allowedAccounts))\n                    }\n                    return\n                  case 'rpcUrlsChanged':\n                    rpcUrls = response.params\n                    persist()\n                    up.emit('rpcUrls', rpcUrls)\n                    return\n                  case 'showPopup':\n                    clientLog('Received showPopup request (cross-origin):', response.params)\n                    if (options.popup) {\n                      const shouldShow = response.params?.[0]\n                      if (shouldShow === true) {\n                        clientLog('Opening modal popup')\n                        options.popup.openModal()\n                      } else if (shouldShow === false) {\n                        clientLog('Closing modal popup')\n                        options.popup.closeModal()\n                      }\n                    } else {\n                      clientLog('No popup available to control')\n                    }\n                    return\n                  case 'connect':\n                    up.emit('connect', response.params[0])\n                    return\n                  case 'disconnect':\n                    options.connectEmitted = false\n                    if ((allowedAccounts?.length ?? 0) > 0) {\n                      allowedAccounts = []\n                      persist()\n                      up.emit('accountsChanged', cleanupAccounts(allowedAccounts))\n                    }\n                    if ((contextAccounts?.length ?? 0) > 0) {\n                      contextAccounts = []\n                      persist()\n                      up.emit('contextAccountsChanged', cleanupAccounts(contextAccounts))\n                    }\n                    up.emit('disconnect')\n                    return\n                }\n                // Handle regular JSONRPC responses\n                const item = pendingRequests.get(response.id)\n                clientLog('Cross-origin response received for id:', response.id, 'found in pending:', !!item, 'method was:', item?.method)\n                if (response.id && item) {\n                  const { resolve, reject } = item\n                  if (response.result !== undefined) {\n                    client.receive({ ...response, id: item.id })\n                    resolve()\n                  } else if (response.error) {\n                    const { error: _error, jsonrpc } = response\n                    const { method, params, id } = item\n                    const error = {\n                      ..._error,\n                      message: `${_error.message} ${JSON.stringify(method)}(${JSON.stringify(params)})`,\n                    }\n                    console.error('error', { error, method, params, id, jsonrpc })\n                    client.receive({ ...response, id: item.id })\n                    reject(error)\n                  }\n                  pendingRequests.delete(response.id)\n                }\n              } catch (error) {\n                console.error('Error parsing wrapped JSON RPC response', error, event.data)\n              }\n            }\n          }\n          window.addEventListener('message', messageHandler)\n        }\n        options.client = client\n        const fn = startupResolve\n        if (fn) {\n          fn()\n        }\n        startupResolve = () => {}\n        return up\n      })\n      .catch(error => {\n        options.client = client\n\n        startupResolve()\n        searchPromise = null\n        throw error\n      })\n      .then(up => {\n        if (!up) {\n          searchPromise = null\n        }\n        return up\n      })\n    searchPromise = activeSearchPromise\n    return activeSearchPromise\n  }\n\n  if (!authURL || !(authURL as { url: string; mode: 'popup' | 'iframe' })?.url || (authURL as { url: string; mode: 'popup' | 'iframe' })?.mode === 'iframe') {\n    allocateConnection()\n  }\n\n  return remote\n}\n\nexport { type UPClientProvider, type UPClientProviderEvents, createClientUPProvider }\n","import debug from 'debug'\n\nconst popupLog = debug('upProvider:popup')\n\nexport interface ModalPopup {\n  openModal(): void\n  closeModal(): void\n  destroyModal(): void\n  createModal(): Promise<{ isNew: boolean; window: Window }>\n  isOpen: boolean\n  contentWindow?: Window\n}\n\nclass VanillaModalPopup implements ModalPopup {\n  private modalElement: HTMLDivElement\n  private iframeElement: HTMLIFrameElement\n  private closeButton: HTMLSpanElement\n  private iframeSrc: string\n  private promise?: Promise<Window>\n  private resolve?: (window: Window) => void\n  private reject?: (error: Error) => void\n\n  isOpen = false\n  contentWindow?: Window\n\n  constructor(iframeSrc: string, id: string) {\n    this.iframeSrc = iframeSrc\n\n    // Create modal structure\n    this.modalElement = document.createElement('div')\n    this.modalElement.id = id\n    this.modalElement.className = 'up-modal'\n    this.modalElement.innerHTML = `\n      <div class=\"up-modal-content\">\n        <span class=\"up-close-button\">&times;</span>\n        <iframe src=\"about:blank\" allow=\"publickey-credentials-get; publickey-credentials-create\"></iframe>\n      </div>\n    `\n\n    // Get references\n    this.closeButton = this.modalElement.querySelector('.up-close-button')!\n    this.iframeElement = this.modalElement.querySelector('iframe')!\n\n    // Bind events\n    this.closeButton.addEventListener('click', () => this.closeModal())\n    // this.modalElement.addEventListener('click', (e) => {\n    //   if (e.target === this.modalElement) {\n    //     this.closeModal()\n    //   }\n    // })\n\n    this.iframeElement.addEventListener('load', this.handleIframeLoad)\n    this.iframeElement.addEventListener('error', this.handleIframeError)\n\n    // Add styles if not already present\n    if (!document.getElementById('up-modal-styles')) {\n      const style = document.createElement('style')\n      style.id = 'up-modal-styles'\n      style.textContent = `\n        .up-modal {\n          display: none;\n          position: fixed;\n          top: 0;\n          left: 0;\n          width: 100%;\n          height: 100%;\n          background-color: rgba(0, 0, 0, 0.5);\n          justify-content: center;\n          align-items: center;\n          z-index: 9999;\n        }\n        .up-modal.show {\n          display: flex;\n        }\n        .up-modal-content {\n          background-color: #fff;\n          border-radius: 8px;\n          overflow: hidden;\n          position: relative;\n          width: 480px;\n          height: 640px;\n          box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);\n        }\n        @media (max-width: 768px) {\n          .up-modal-content {\n            width: 100%;\n            height: 100%;\n            border-radius: 0;\n          }\n        }\n        .up-close-button {\n          position: absolute;\n          top: 10px;\n          right: 15px;\n          font-size: 24px;\n          cursor: pointer;\n          z-index: 10;\n          color: #000;\n          background: rgba(255, 255, 255, 0.8);\n          width: 30px;\n          height: 30px;\n          border-radius: 50%;\n          display: flex;\n          align-items: center;\n          justify-content: center;\n          line-height: 1;\n        }\n        .up-close-button:hover {\n          background: rgba(255, 255, 255, 1);\n        }\n        .up-modal iframe {\n          width: 100%;\n          height: 100%;\n          border: none;\n        }\n      `\n      document.head.appendChild(style)\n    }\n\n    // Add to DOM\n    document.body.appendChild(this.modalElement)\n  }\n\n  private handleIframeLoad = () => {\n    popupLog('Iframe loaded, contentWindow:', this.iframeElement.contentWindow)\n    this.contentWindow = this.iframeElement.contentWindow || undefined\n    this.resolve?.(this.contentWindow!)\n  }\n\n  private handleIframeError = (e: ErrorEvent) => {\n    popupLog('Iframe error occurred:', e.error, e.message)\n    this.reject?.(e.error)\n    this.closeModal()\n  }\n\n  async createModal(): Promise<{ isNew: boolean; window: Window }> {\n    popupLog('createModal called, has promise:', !!this.promise, 'iframe src:', this.iframeSrc)\n\n    if (this.promise) {\n      popupLog('Reusing existing popup promise')\n      return this.promise.then(window => ({\n        isNew: false,\n        window,\n      }))\n    }\n\n    popupLog('Creating new popup promise')\n\n    this.promise = new Promise<Window>((resolve, reject) => {\n      this.resolve = resolve\n      this.reject = reject\n\n      // Set the iframe src first\n      if (this.iframeSrc) {\n        this.iframeElement.src = this.iframeSrc\n      }\n\n      // Auto-open in debug mode after iframe src is set\n      const debugMode = window.location.search.includes('debug=true') || localStorage.getItem('upProvider:debug') === 'true'\n      if (debugMode) {\n        // Delay to ensure iframe starts loading\n        setTimeout(() => this.openModal(), 100)\n      }\n    })\n\n    return this.promise.then(window => ({\n      isNew: true,\n      window,\n    }))\n  }\n\n  openModal() {\n    if (this.isOpen) {\n      return\n    }\n    // Use requestAnimationFrame to ensure DOM is ready and styles are applied\n    requestAnimationFrame(() => {\n      this.isOpen = true\n      this.modalElement.classList.add('show')\n      popupLog('Opening popup')\n\n      // Dispatch custom event\n      this.modalElement.dispatchEvent(\n        new CustomEvent('open', {\n          bubbles: true,\n          composed: true,\n        })\n      )\n\n      window.parent.postMessage({ type: 'upProvider:modalOpened' }, '*')\n    })\n  }\n\n  closeModal() {\n    // Log the call stack to see what's triggering the close\n    popupLog('closeModal called from:', new Error().stack)\n\n    // Debug mode - check for debug flag in URL or localStorage\n    const debugMode = window.location.search.includes('debug=true') || localStorage.getItem('upProvider:debug') === 'true'\n\n    if (debugMode) {\n      popupLog('Debug mode: keeping modal open')\n      return\n    }\n\n    this.isOpen = false\n    this.modalElement.classList.remove('show')\n    popupLog('Closing popup')\n\n    // Dispatch custom event\n    this.modalElement.dispatchEvent(\n      new CustomEvent('close', {\n        bubbles: true,\n        composed: true,\n      })\n    )\n\n    window.parent.postMessage({ type: 'upProvider:modalClosed' }, '*')\n  }\n\n  destroyModal() {\n    this.contentWindow = undefined\n    this.closeModal()\n\n    // Remove event listeners\n    this.iframeElement.removeEventListener('load', this.handleIframeLoad)\n    this.iframeElement.removeEventListener('error', this.handleIframeError)\n\n    // Remove from DOM\n    this.modalElement.remove()\n\n    popupLog('Destroying popup')\n\n    // Dispatch custom event\n    this.modalElement.dispatchEvent(\n      new CustomEvent('destroy', {\n        bubbles: true,\n        composed: true,\n      })\n    )\n  }\n}\n\nexport async function createWalletPopup(_url: string): Promise<{ popup: ModalPopup; isNew: boolean }> {\n  if (typeof window === 'undefined' || typeof document === 'undefined') {\n    throw new Error('This function can only be called in a browser environment.')\n  }\n\n  const url = new URL(_url)\n  const key = `up-wallet-popup-${url.hostname.replace(/\\./g, '-')}${url.pathname.split('/').join('-')}`\n\n  // Check for existing popup\n  const existingElement = document.getElementById(key)\n  if (existingElement && (existingElement as any)._popup) {\n    return { isNew: false, popup: (existingElement as any)._popup }\n  }\n\n  popupLog('Instantiating new popup')\n  const popup = new VanillaModalPopup(_url, key)\n\n  // Store reference on the element for reuse\n  const element = document.getElementById(key)\n  if (element) {\n    ;(element as any)._popup = popup\n  }\n\n  return popup\n    .createModal()\n    .then(({ isNew }) => ({ isNew, popup }))\n    .catch(error => {\n      popupLog('Error creating popup:', error)\n      popup.destroyModal()\n      throw error\n    })\n}\n","export * from './client'\nexport * from './server'\nexport * from './popup'\n\n/**\n * Small helper function to compare two arrays of addresses.\n * This allow null, undefined, or empty strings to be considered the same.\n * @param _addresses1 - array 1\n * @param _addresses2 - array 2\n * @returns Returns true if there were changes between the two arrays.\n */\nexport const arrayChanged = (_addresses1?: Array<`0x${string}` | string | null | undefined>, _addresses2?: Array<`0x${string}` | string | null | undefined>) => {\n  const addresses1 = _addresses1 ?? []\n  const addresses2 = _addresses2 ?? []\n  for (let i = 0; i < addresses1.length || i < addresses2.length; i++) {\n    const is1Null = addresses1[i] === null || addresses1[i] === undefined\n    const is2Null = addresses2[i] === null || addresses2[i] === undefined\n    if (is1Null && is2Null) {\n      continue\n    }\n    if (addresses1[i] !== addresses2[i]) {\n      return true\n    }\n  }\n  return false\n}\n\n/**\n * Cleanup accounts array so there are no sparse values (i.e. empty values in the middle, this is not compatible\n *  with many of the web3 libraries (web3.js and viem)).\n * @param values - original array\n * @returns Returns copy of array which makes 0x00..., null, undefined and empty string mark the end of the array\n *         This is useful for cleaning up the array of accounts.\n */\nexport const cleanupAccounts = (values: Array<`0x${string}` | undefined>): `0x${string}`[] => {\n  const output = []\n  for (const value of values) {\n    if (!value || /^0x0+$/.test(value)) {\n      break\n    }\n    output.push(value)\n  }\n  return output as Array<`0x${string}`>\n}\n"],"mappings":"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","names":["debug","EventEmitter3","uuidv4","debug","debug","debug","window","EventEmitter3","uuidv4","_accounts","accountsChanged","event"]}