{"version":3,"sources":["../../src/dappCore/injectConnectors.ts"],"sourcesContent":["import {logger} from '../utils/logging'\n\nimport {sendRequestProxy} from './sendRequestProxy'\nimport {setupClientChannel} from './setupClientChannel'\nimport type {\n  UntypedConnectorKind,\n  EventHandler,\n  MessagingClient,\n  ServiceEvent,\n  WalletOverrides,\n  ScriptContext,\n  InjectedConnectorFactory,\n  DappConnectorsConfig,\n  RequestArgument,\n  InitChannelData,\n  InjectedConnector,\n} from './types'\nimport {hardenUnreliableRequest} from './utils'\n\nexport type CreateConnectorsParams<\n  Config extends DappConnectorsConfig,\n  ConnectorKind extends UntypedConnectorKind,\n> = {\n  connectorsToInject: Record<\n    UntypedConnectorKind,\n    InjectedConnectorFactory<Config>\n  >\n  config: Config\n  currentContext: ScriptContext\n  targetContext: ScriptContext\n  sendPortPostMessage: (message: unknown, transfer: Transferable[]) => void\n  overridableWallets: ReadonlyArray<string>\n  isInitiallyConnected?: boolean\n  onBeforeFirstSend?: () => Promise<void>\n  onBeforeRequest?: (args: {\n    connectorKind: null | ConnectorKind\n    method: string\n    args: RequestArgument[]\n  }) => unknown\n  initChannelData?: InitChannelData\n}\n\nfunction createConnectors<\n  Config extends DappConnectorsConfig,\n  ConnectorKind extends UntypedConnectorKind,\n>({\n  connectorsToInject,\n  config,\n  currentContext,\n  targetContext,\n  sendPortPostMessage,\n  onBeforeFirstSend,\n  onBeforeRequest,\n  overridableWallets,\n  initChannelData,\n  isInitiallyConnected,\n}: CreateConnectorsParams<Config, ConnectorKind>): [\n  InjectedConnector[],\n  (() => Promise<WalletOverrides>) | null,\n] {\n  logger.debug('\"createConnectors\"')\n  const connectors: InjectedConnector[] = []\n\n  const eventHandlers = new Map<ConnectorKind, EventHandler>()\n  const multiplexedHandler = setupClientChannel<ConnectorKind>({\n    connectorPlatform: config.connectorPlatform,\n    appId: config.appId,\n    onBeforeRequest,\n    onBeforeFirstSend,\n    currentContext,\n    targetContext,\n    eventHandler: async (connectorKind, method, args) => {\n      if (connectorKind == null) return\n\n      const eventHandler = eventHandlers.get(connectorKind)\n      if (eventHandler) {\n        await eventHandler(method as ServiceEvent, args)\n      }\n    },\n    sendPortPostMessage,\n    initChannelData,\n  })\n\n  const getWalletOverridesRequest = async () =>\n    (await multiplexedHandler(null)(\n      'getWalletOverrides',\n      [],\n    )) as unknown as WalletOverrides\n\n  // The \"getWalletOverrides\" call invoked as the very first call to the service worker is not 100% reliable,\n  // so we need to harden it. As far as we tried, the service worker seems to not always wake up\n  // fast enough for the request to go through on the first try (not sure if that's a bug in Chrome).\n  // Happened especially when opening a dapp right after opening the browser.\n  // https://stackoverflow.com/questions/69816133/mv3-serviceworker-wont-wake-up-when-sent-a-message-from-the-contentscript\n  const getWalletOverrides =\n    overridableWallets.length > 0\n      ? () =>\n          hardenUnreliableRequest(\n            getWalletOverridesRequest,\n            Object.fromEntries(\n              overridableWallets.map((w) => [w, false]),\n            ) as WalletOverrides,\n          )\n      : null\n\n  for (const connectorKind of Object.keys(\n    config.connectors,\n  ) as ConnectorKind[]) {\n    try {\n      const sendRequest = multiplexedHandler(connectorKind)\n      const proxy = sendRequestProxy(sendRequest)\n\n      let isConnected = !!isInitiallyConnected\n\n      const client: MessagingClient = {\n        proxy,\n        connect: async (meta) => {\n          logger.debug('\"createConnectors\": connect called')\n          await proxy.connectMessagingClient(meta)\n          isConnected = true\n          logger.debug('\"createConnectors\": connect finished')\n        },\n        cancelRequests: async () => {\n          logger.debug('\"createConnectors\": cancelRequests called')\n          await proxy.cancelMessagingClientRequests()\n          logger.debug('\"createConnectors\": cancelRequests finished')\n        },\n        isConnected: () => {\n          logger.debug(`\"createConnectors\": isConnected ${isConnected}`)\n          return isConnected\n        },\n      }\n\n      const connector = connectorsToInject[connectorKind](client, config)\n      if (connector) {\n        const eventHandler: EventHandler = async (method, args) => {\n          await connector.eventHandler(method, args)\n        }\n        eventHandlers.set(connectorKind, eventHandler)\n\n        connectors.push(connector)\n      }\n    } catch (e) {\n      // We will continue with the other connectors even if one of them fails.\n      // eslint-disable-next-line no-console\n      console.error(e)\n    }\n  }\n  return [connectors, getWalletOverrides]\n}\n\n/**\n * Initialize already created connectors in a race-condition safe order.\n *\n * Note that declaring this function \"async\" causes race-conditions\n * with content script and page script, as the content script is no\n * longer guaranteed to end before the page script is executed.\n * This is mainly issue in the EVM ecosystem.\n *\n * Therefore we:\n * 1. Sort connectors, so that the ones with simple \"inject\" without any\n * asynchronous dependencies comes first.\n * 2. Inject connectors with synchronous \"inject\" without calling \"await\", so\n * that these functions are guaranteed to run before page load (even though the\n * function is \"async\", but no \"await\" was called until this point).\n * 3. Inject the remaining connectors after doing async logic (e.g. fetching wallet overrides).\n */\nconst initializeConnectors = (\n  connectors: InjectedConnector[],\n  getWalletOverrides: (() => Promise<WalletOverrides>) | null,\n) => {\n  for (const connector of connectors) {\n    try {\n      logger.debug(\n        `\"createConnectors\": ${connector.connectorKind} initialization start`,\n      )\n      connector.inject(window)\n      logger.debug(\n        `\"createConnectors\": ${connector.connectorKind} initialization finished`,\n      )\n    } catch (e) {\n      // We will continue with the other connectors even if one of them fails.\n      // eslint-disable-next-line no-console\n      console.error(e)\n    }\n  }\n\n  getWalletOverrides?.().then((walletOverrides) => {\n    for (const connector of connectors) {\n      try {\n        connector.injectOverrides?.(window, walletOverrides)\n      } catch (e) {\n        // We will continue with the other connectors even if one of them fails.\n        // eslint-disable-next-line no-console\n        console.error(e)\n      }\n    }\n  })\n}\n\nexport function injectConnectors<\n  Config extends DappConnectorsConfig,\n  ConnectorKind extends UntypedConnectorKind,\n>(params: CreateConnectorsParams<Config, ConnectorKind>) {\n  const [connectorsToInitialize, getWalletOverrides] = createConnectors(params)\n\n  // Be mindful with `await` in this file! See `initializeConnectors` explanation of how\n  // it is safe to use it when initializing connectors.\n  initializeConnectors(connectorsToInitialize, getWalletOverrides)\n}\n\nexport type InjectConnectors = typeof injectConnectors\n"],"mappings":"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","names":[]}