UNPKG

@web3auth/no-modal

Version:
1,858 lines 98.1 kB
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
import _objectSpread from '@babel/runtime/helpers/objectSpread2';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import { CHAIN_NAMESPACES, BUTTON_POSITION, CONFIRMATION_STRATEGY } from '@toruslabs/base-controllers';
import { SMART_ACCOUNT_EIP_STANDARD, EIP7702_SUPPORTED_SMART_ACCOUNT_TYPES } from '@toruslabs/ethereum-controllers';
import { SafeEventEmitter, BUILD_ENV, serializeError, UX_MODE, cloneDeep, CookieStorage, LocalStorageAdapter, MemoryStorage } from '@web3auth/auth';
import deepmerge from 'deepmerge';
import { deserialize } from './base/deserialize.js';
import { LOGIN_MODE, SMART_ACCOUNT_WALLET_SCOPE, WEB3AUTH_STATE_STORAGE_KEY } from './base/constants.js';
import { WalletInitializationError, WalletLoginError } from './base/errors/index.js';
import { log } from './base/loglevel.js';
import { CONNECTOR_STATUS, CONNECTOR_INITIAL_AUTHENTICATION_MODE, CONNECTOR_EVENTS } from './base/connector/constants.js';
import { Analytics, ANALYTICS_INTEGRATION_TYPE, ANALYTICS_SDK_TYPE, ANALYTICS_EVENTS } from './base/analytics.js';
import { sdkVersion, fetchProjectConfig, withAbort, getErrorAnalyticsProperties, getCaipChainId, isHexStrict, getHostname, getWhitelabelAnalyticsProperties, getAaAnalyticsProperties, getWalletServicesAnalyticsProperties, isBrowser, parseChainNamespaceFromCitadelResponse, normalizeWalletName } from './base/utils.js';
import { WALLET_CONNECTORS } from './base/wallet/index.js';
import { CONNECTOR_NAMESPACES } from './base/chain/IChainInterface.js';
import { CONNECTED_STATUSES, CAN_LOGOUT_STATUSES, CAN_AUTHORIZE_STATUSES } from './base/connector/connectorStatus.js';
import { assertAuthConnector, authConnector, isAuthConnector } from './connectors/auth-connector/authConnector.js';
import { AccountLinkingError } from './account-linking/errors.js';
import { CommonJRPCProvider } from './providers/base-provider/CommonJRPCProvider.js';
import { walletServicesPlugin } from './plugins/wallet-services-plugin/plugin.js';
import { metaMaskConnector, METAMASK_ERC_6963_PROVIDER_RDNS } from './connectors/metamask-connector/metamaskConnector.js';
import { storageAvailable } from './base/connector/utils.js';
import { PLUGIN_STATUS, PLUGIN_NAMESPACES } from './base/plugin/IPlugin.js';

const _excluded = ["walletScope", "eipStandard"];
const PRIMARY_CONNECTED_WALLET_KEY = "__primary__";
class Web3AuthNoModal extends SafeEventEmitter {
  constructor(options, initialState) {
    super();
    _defineProperty(this, "coreOptions", void 0);
    _defineProperty(this, "status", CONNECTOR_STATUS.NOT_READY);
    _defineProperty(this, "loginMode", LOGIN_MODE.NO_MODAL);
    _defineProperty(this, "aaProvider", null);
    _defineProperty(this, "connectors", []);
    _defineProperty(this, "commonJRPCProvider", null);
    _defineProperty(this, "analytics", void 0);
    _defineProperty(this, "plugins", {});
    _defineProperty(this, "consentRequired", false);
    _defineProperty(this, "projectConfig", null);
    _defineProperty(this, "storage", void 0);
    _defineProperty(this, "connectionReconnected", false);
    /** Connected wallet state keyed by linked account id; the primary session uses a reserved key. */
    _defineProperty(this, "connectedWalletConnectorMap", new Map());
    _defineProperty(this, "activeWalletConnectorKey", PRIMARY_CONNECTED_WALLET_KEY);
    _defineProperty(this, "state", {
      primaryConnectorName: null,
      cachedConnector: null,
      currentChainId: null,
      idToken: null,
      accessToken: null,
      refreshToken: null,
      activeAccount: null,
      cachedConnectorNamespace: null
    });
    if (!options.clientId) throw WalletInitializationError.invalidParams("Please provide a valid clientId in constructor");
    if (options.enableLogging) log.enableAll();else log.setLevel("error");
    if (!options.initialAuthenticationMode) options.initialAuthenticationMode = CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_AND_SIGN;
    this.coreOptions = _objectSpread(_objectSpread({}, options), {}, {
      authBuildEnv: options.authBuildEnv || BUILD_ENV.PRODUCTION
    });
    this.storage = this.getStorageMethod();
    this.analytics = new Analytics();
    if (options.disableAnalytics) {
      this.analytics.disable();
    }
    this.analytics.setGlobalProperties({
      integration_type: ANALYTICS_INTEGRATION_TYPE.NATIVE_SDK
    });
    this.loadState(initialState).then(() => {
      if (this.state.idToken && this.coreOptions.ssr && !this.consentRequired) {
        this.status = this.coreOptions.initialAuthenticationMode === CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_AND_SIGN ? CONNECTOR_STATUS.AUTHORIZED : CONNECTOR_STATUS.CONNECTED;
      }
      return undefined;
    }).catch(() => {});
  }
  get currentChain() {
    var _this$coreOptions$cha;
    if (!this.currentChainId) return undefined;
    return (_this$coreOptions$cha = this.coreOptions.chains) === null || _this$coreOptions$cha === void 0 ? void 0 : _this$coreOptions$cha.find(chain => chain.chainId === this.currentChainId);
  }
  get connected() {
    return Boolean(this.primaryConnector);
  }
  get connection() {
    return this.getConnectedWalletConnectionByKey(this.activeWalletConnectorKey);
  }
  get primaryConnectorName() {
    return this.state.primaryConnectorName;
  }
  get cachedConnector() {
    return this.state.cachedConnector;
  }
  get currentChainId() {
    var _this$coreOptions$cha2;
    return this.state.currentChainId || this.coreOptions.defaultChainId || ((_this$coreOptions$cha2 = this.coreOptions.chains) === null || _this$coreOptions$cha2 === void 0 || (_this$coreOptions$cha2 = _this$coreOptions$cha2[0]) === null || _this$coreOptions$cha2 === void 0 ? void 0 : _this$coreOptions$cha2.chainId) || null;
  }

  /**
   * This is always the primary connector that is connected to the user.
   */
  get primaryConnector() {
    var _this$currentChain;
    return this.getConnector(this.primaryConnectorName, (_this$currentChain = this.currentChain) === null || _this$currentChain === void 0 ? void 0 : _this$currentChain.chainNamespace);
  }
  get accountAbstractionProvider() {
    return this.aaProvider;
  }
  get idToken() {
    return this.state.idToken || null;
  }
  get accessToken() {
    return this.state.accessToken || null;
  }
  get refreshToken() {
    return this.state.refreshToken || null;
  }
  get activeAccount() {
    return this.state.activeAccount;
  }

  /**
   * This is the current active connector.
   */
  get activeConnector() {
    const activeConnectedWallet = this.getConnectedWalletConnectorStateByKey(this.activeWalletConnectorKey);
    if (activeConnectedWallet) {
      return activeConnectedWallet.connector;
    }
    if (this.activeWalletConnectorKey !== PRIMARY_CONNECTED_WALLET_KEY) {
      throw new Error(`Signing connector not found for account "${this.activeWalletConnectorKey}".`);
    }
    return this.primaryConnector;
  }
  set provider(_) {
    throw new Error("Not implemented");
  }
  async init(options) {
    // init analytics
    const startTime = Date.now();
    this.analytics.init();
    this.analytics.identify(this.coreOptions.clientId, {
      web3auth_client_id: this.coreOptions.clientId,
      web3auth_network: this.coreOptions.web3AuthNetwork
    });
    this.analytics.setGlobalProperties({
      dapp_url: window.location.origin,
      sdk_name: ANALYTICS_SDK_TYPE.WEB_NO_MODAL,
      sdk_version: sdkVersion,
      // Required for organization analytics
      web3auth_client_id: this.coreOptions.clientId,
      web3auth_network: this.coreOptions.web3AuthNetwork
    });
    let trackData = {};
    try {
      var _authConnector$authIn, _this$coreOptions$uiC;
      const {
        signal
      } = options || {};
      // get project config
      let projectConfig;
      try {
        var _this$coreOptions$acc;
        projectConfig = await fetchProjectConfig({
          clientId: this.coreOptions.clientId,
          web3AuthNetwork: this.coreOptions.web3AuthNetwork,
          aaProvider: (_this$coreOptions$acc = this.coreOptions.accountAbstractionConfig) === null || _this$coreOptions$acc === void 0 ? void 0 : _this$coreOptions$acc.smartAccountType,
          authBuildEnv: this.coreOptions.authBuildEnv
        });
      } catch (e) {
        const error = await serializeError(e);
        log.error("Failed to fetch project configurations", error);
        throw WalletInitializationError.notReady("failed to fetch project configurations", error);
      }

      // init config
      this.projectConfig = projectConfig;
      this.initAccountAbstractionConfig(projectConfig);
      this.initChainsConfig(projectConfig);
      await this.initCachedConnectorAndChainId();
      this.initUIConfig(projectConfig);
      this.initWalletServicesConfig(projectConfig);
      this.initSessionTimeConfig(projectConfig);
      this.analytics.setGlobalProperties({
        team_id: projectConfig.teamId
      });
      trackData = this.getInitializationTrackData();

      // setup common JRPC provider
      await withAbort(() => this.setupCommonJRPCProvider(), signal);

      // initialize connectors
      this.on(CONNECTOR_EVENTS.CONNECTORS_UPDATED, async ({
        connectors: newConnectors
      }) => {
        const onAbortHandler = () => {
          var _this$connectors;
          if (((_this$connectors = this.connectors) === null || _this$connectors === void 0 ? void 0 : _this$connectors.length) > 0) {
            this.cleanup();
          }
        };
        await withAbort(() => Promise.all(newConnectors.map(this.setupConnector.bind(this))), signal, onAbortHandler);

        // emit connector ready event
        if (this.status === CONNECTOR_STATUS.NOT_READY) {
          this.status = CONNECTOR_STATUS.READY;
          this.emit(CONNECTOR_EVENTS.READY);
        }
      });
      await withAbort(() => this.loadConnectors({
        projectConfig
      }), signal);
      await withAbort(() => this.initPlugins(), signal);

      // track completion event
      const authConnector = this.getConnector(WALLET_CONNECTORS.AUTH);
      trackData = _objectSpread(_objectSpread({}, trackData), {}, {
        connectors: this.connectors.map(connector => connector.name),
        plugins: Object.keys(this.plugins),
        auth_ux_mode: (authConnector === null || authConnector === void 0 || (_authConnector$authIn = authConnector.authInstance) === null || _authConnector$authIn === void 0 || (_authConnector$authIn = _authConnector$authIn.options) === null || _authConnector$authIn === void 0 ? void 0 : _authConnector$authIn.uxMode) || ((_this$coreOptions$uiC = this.coreOptions.uiConfig) === null || _this$coreOptions$uiC === void 0 ? void 0 : _this$coreOptions$uiC.uxMode)
      });
      this.analytics.track(ANALYTICS_EVENTS.SDK_INITIALIZATION_COMPLETED, _objectSpread(_objectSpread({}, trackData), {}, {
        duration: Date.now() - startTime
      }));
    } catch (error) {
      if (error instanceof DOMException && error.name === "AbortError") return;

      // track failure event
      this.analytics.track(ANALYTICS_EVENTS.SDK_INITIALIZATION_FAILED, _objectSpread(_objectSpread(_objectSpread({}, trackData), getErrorAnalyticsProperties(error)), {}, {
        duration: Date.now() - startTime
      }));
      log.error("Failed to initialize modal", error);
      throw error;
    }
  }

  // we need to take into account the chainNamespace as for external connectors, same connector name can be used for multiple chain namespaces
  getConnector(connectorName, chainNamespace) {
    return this.connectors.find(connector => {
      if (connector.name !== connectorName) return false;
      if (chainNamespace) {
        if (connector.connectorNamespace === CONNECTOR_NAMESPACES.MULTICHAIN) return true;
        return connector.connectorNamespace === chainNamespace;
      }
      return true;
    }) || null;
  }
  async clearCache() {
    this.connectedWalletConnectorMap.clear();
    this.activeWalletConnectorKey = PRIMARY_CONNECTED_WALLET_KEY;
    this.connectionReconnected = false;
    await this.setState({
      primaryConnectorName: null,
      cachedConnector: null,
      cachedConnectorNamespace: null,
      currentChainId: null,
      idToken: null,
      accessToken: null,
      refreshToken: null,
      activeAccount: null,
      hasUserConsent: undefined
    });
  }
  async cleanup() {
    for (const connector of this.connectors) {
      // if the connector is not ready, we don't need to cleanup
      // this means that we load the connector (coz of the dashboard config) but the clients did not use it (i.e. with `showOnModal` set to false)
      // example use case: external wallet **ONLY** login mode but the ClientID has enabled Auth connection in dashboard.
      if (connector.cleanup && connector.status !== CONNECTOR_STATUS.NOT_READY) await connector.cleanup();
    }
  }
  async switchChain(params) {
    var _this$currentChain2;
    if (params.chainId === ((_this$currentChain2 = this.currentChain) === null || _this$currentChain2 === void 0 ? void 0 : _this$currentChain2.chainId)) return;
    const newChainConfig = this.coreOptions.chains.find(x => x.chainId === params.chainId);
    if (!newChainConfig) throw WalletInitializationError.invalidParams("Invalid chainId");
    if (CONNECTED_STATUSES.includes(this.status)) {
      const activeConnector = this.activeConnector;
      if (!activeConnector) throw WalletInitializationError.notReady("Active signing connector is not ready");

      // Single-namespace connectors cannot cross namespace boundaries — MULTICHAIN connectors
      // (Auth, WC) enforce their own switchChain policy internally.
      if (activeConnector.connectorNamespace !== CONNECTOR_NAMESPACES.MULTICHAIN && activeConnector.connectorNamespace !== newChainConfig.chainNamespace) {
        throw WalletLoginError.connectionError(`Cannot switch between chain namespaces with ${activeConnector.name}. Disconnect and reconnect with the target chain.`);
      }
      await activeConnector.switchChain(params);
      return;
    }
    if (this.commonJRPCProvider) {
      await this.commonJRPCProvider.switchChain(params);
      return;
    }
    throw WalletInitializationError.notReady(`No wallet is ready`);
  }

  /**
   * Connect to a specific wallet connector
   * @param connectorName - Key of the wallet connector to use.
   */
  async connectTo(connectorName, loginParams, loginMode) {
    this.loginMode = loginMode || "no-modal";
    const connector = this.getConnector(connectorName, loginParams === null || loginParams === void 0 ? void 0 : loginParams.chainNamespace);
    if (!connector || !this.commonJRPCProvider) throw WalletInitializationError.notFound(`Please add wallet connector for ${connectorName} wallet, before connecting`);
    const initialChain = this.getInitialChainIdForConnector(connector);
    const finalLoginParams = _objectSpread(_objectSpread({}, loginParams), {}, {
      chainId: initialChain.chainId,
      getAuthTokenInfo: this.coreOptions.initialAuthenticationMode === CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_AND_SIGN
    });

    // track connection started event
    const startTime = Date.now();
    let eventData;
    if (connectorName === WALLET_CONNECTORS.AUTH) {
      var _authInstance;
      const authLoginParams = loginParams;
      const authConnectionConfig = connector.getOAuthProviderConfig({
        authConnection: authLoginParams.authConnection,
        authConnectionId: authLoginParams.authConnectionId,
        groupedAuthConnectionId: authLoginParams.groupedAuthConnectionId
      });
      eventData = {
        connector: connectorName,
        connector_type: connector.type,
        chain_id: getCaipChainId(initialChain),
        chain_name: initialChain.displayName,
        chain_namespace: initialChain.chainNamespace,
        auth_connection: authLoginParams.authConnection,
        auth_connection_id: authLoginParams.authConnectionId,
        group_auth_connection_id: authLoginParams.groupedAuthConnectionId,
        mfa_level: authLoginParams.mfaLevel,
        wallet_key_enabled: authLoginParams.getWalletKey,
        extra_login_options_enabled: Boolean(authLoginParams.extraLoginOptions),
        dapp_share_enabled: Boolean(authLoginParams.dappShare),
        curve: authLoginParams.curve,
        auth_dapp_url: authLoginParams.dappUrl,
        is_sfa: Boolean(authLoginParams.idToken),
        is_default_auth_connection: authConnectionConfig === null || authConnectionConfig === void 0 ? void 0 : authConnectionConfig.isDefault,
        auth_ux_mode: (_authInstance = connector.authInstance) === null || _authInstance === void 0 || (_authInstance = _authInstance.options) === null || _authInstance === void 0 ? void 0 : _authInstance.uxMode
      };
    } else {
      eventData = {
        connector: connectorName,
        connector_type: connector.type,
        is_injected: connector.isInjected,
        chain_id: getCaipChainId(initialChain),
        chain_name: initialChain.displayName,
        chain_namespace: initialChain.chainNamespace
      };
    }

    // track connection started event
    this.analytics.track(ANALYTICS_EVENTS.CONNECTION_STARTED, eventData);
    return new Promise((resolve, reject) => {
      let connectedEventCompleted = false;
      let authorizedEventReceived = false;
      const cleanup = () => {
        this.removeListener(CONNECTOR_EVENTS.CONNECTED, onConnected);
        this.removeListener(CONNECTOR_EVENTS.ERRORED, onErrored);
        this.removeListener(CONNECTOR_EVENTS.AUTHORIZED, onAuthorized);
      };
      const checkCompletion = async () => {
        // In CONNECT_AND_SIGN mode, wait for both connected event and authorized event
        if (finalLoginParams.getAuthTokenInfo) {
          if (connectedEventCompleted && authorizedEventReceived) {
            await completeConnection();
          }
        } else if (connectedEventCompleted) {
          await completeConnection();
        }
      };
      const completeConnection = async () => {
        try {
          // track connection completed event
          const userInfo = await this.getUserInfo();
          this.analytics.track(ANALYTICS_EVENTS.CONNECTION_COMPLETED, _objectSpread(_objectSpread({}, eventData), {}, {
            is_mfa_enabled: userInfo === null || userInfo === void 0 ? void 0 : userInfo.isMfaEnabled,
            duration: Date.now() - startTime
          }));
          cleanup();
          resolve(this.connection);
        } catch (error) {
          cleanup();
          reject(error);
        }
      };
      const onConnected = async () => {
        connectedEventCompleted = true;
        await checkCompletion();
      };
      const onAuthorized = async () => {
        authorizedEventReceived = true;
        await checkCompletion();
      };
      const onErrored = async err => {
        // track connection failed event
        this.analytics.track(ANALYTICS_EVENTS.CONNECTION_FAILED, _objectSpread(_objectSpread(_objectSpread({}, eventData), getErrorAnalyticsProperties(err)), {}, {
          duration: Date.now() - startTime
        }));
        cleanup();
        reject(err);
      };
      this.once(CONNECTOR_EVENTS.CONNECTED, onConnected);
      if (finalLoginParams.getAuthTokenInfo) {
        this.once(CONNECTOR_EVENTS.AUTHORIZED, onAuthorized);
      }
      this.once(CONNECTOR_EVENTS.ERRORED, onErrored);
      connector.connect(finalLoginParams);
      this.setCurrentChain(initialChain.chainId);
    });
  }
  async logout(options = {
    cleanup: false
  }) {
    if (!CAN_LOGOUT_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
    if (this.primaryConnector.status === CONNECTOR_STATUS.DISCONNECTING) return;
    await this.primaryConnector.disconnect(options);
  }
  async getUserInfo() {
    var _this$primaryConnecto, _userInfo$linkedAccou, _userInfo$linkedAccou2;
    log.debug("Getting user info", this.status, (_this$primaryConnecto = this.primaryConnector) === null || _this$primaryConnecto === void 0 ? void 0 : _this$primaryConnecto.name);
    if (!CAN_AUTHORIZE_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
    const userInfo = await this.primaryConnector.getUserInfo();
    const linkedAccounts = (_userInfo$linkedAccou = (_userInfo$linkedAccou2 = userInfo.linkedAccounts) === null || _userInfo$linkedAccou2 === void 0 ? void 0 : _userInfo$linkedAccou2.map(account => _objectSpread(_objectSpread({}, account), {}, {
      active: this.state.activeAccount ? account.id === this.state.activeAccount.id : account.isPrimary
    }))) !== null && _userInfo$linkedAccou !== void 0 ? _userInfo$linkedAccou : [];
    this.syncConnectedWalletLinkedAccounts(linkedAccounts);
    return _objectSpread(_objectSpread({}, userInfo), {}, {
      linkedAccounts
    });
  }
  async getLinkedAccounts() {
    if (!CAN_AUTHORIZE_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
    assertAuthConnector(this.primaryConnector, "Linked accounts can only be fetched when connected with the AUTH connector.");
    const linkedAccounts = await this.primaryConnector.getLinkedAccounts();
    const resolvedLinkedAccounts = linkedAccounts.map(account => _objectSpread(_objectSpread({}, account), {}, {
      active: this.state.activeAccount ? account.id === this.state.activeAccount.id : account.isPrimary
    }));
    this.syncConnectedWalletLinkedAccounts(resolvedLinkedAccounts);
    return resolvedLinkedAccounts;
  }
  getConnectedAccountsWithProviders() {
    if (!CONNECTED_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
    if (this.status !== CONNECTOR_STATUS.AUTHORIZED) {
      // before the wallet is authorized, we don't have the user info, so we return an empty array
      return [];
    }
    const connectedAccounts = [];
    for (const [, value] of this.connectedWalletConnectorMap.entries()) {
      const hasWalletProvider = Boolean(value.signingProvider || value.solanaWallet);
      if (hasWalletProvider && this.hasUsableConnectedSwitchConnector(value.connector)) {
        connectedAccounts.push(value);
      }
    }
    return connectedAccounts;
  }
  async enableMFA(loginParams) {
    var _authConnector$authIn2;
    if (!CONNECTED_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
    if (this.primaryConnector.name !== WALLET_CONNECTORS.AUTH) throw WalletLoginError.unsupportedOperation(`EnableMFA is not supported for this connector.`);
    const authConnector = this.primaryConnector;
    const trackData = {
      connector: this.primaryConnector.name,
      auth_ux_mode: (_authConnector$authIn2 = authConnector.authInstance) === null || _authConnector$authIn2 === void 0 || (_authConnector$authIn2 = _authConnector$authIn2.options) === null || _authConnector$authIn2 === void 0 ? void 0 : _authConnector$authIn2.uxMode
    };
    try {
      this.analytics.track(ANALYTICS_EVENTS.MFA_ENABLEMENT_STARTED, trackData);
      await this.primaryConnector.enableMFA(loginParams);
    } catch (error) {
      this.analytics.track(ANALYTICS_EVENTS.MFA_ENABLEMENT_FAILED, _objectSpread(_objectSpread({}, trackData), getErrorAnalyticsProperties(error)));
      throw error;
    }
  }
  async manageMFA(loginParams) {
    var _authConnector$authIn3;
    if (!CONNECTED_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
    if (this.primaryConnector.name !== WALLET_CONNECTORS.AUTH) throw WalletLoginError.unsupportedOperation(`ManageMFA is not supported for this connector.`);
    const authConnector = this.primaryConnector;
    const trackData = {
      connector: this.primaryConnector.name,
      auth_ux_mode: (_authConnector$authIn3 = authConnector.authInstance) === null || _authConnector$authIn3 === void 0 || (_authConnector$authIn3 = _authConnector$authIn3.options) === null || _authConnector$authIn3 === void 0 ? void 0 : _authConnector$authIn3.uxMode
    };
    try {
      this.analytics.track(ANALYTICS_EVENTS.MFA_MANAGEMENT_SELECTED, trackData);
      await this.primaryConnector.manageMFA(loginParams);
    } catch (error) {
      this.analytics.track(ANALYTICS_EVENTS.MFA_MANAGEMENT_FAILED, _objectSpread(_objectSpread({}, trackData), getErrorAnalyticsProperties(error)));
      throw error;
    }
  }
  async getAuthTokenInfo() {
    if (!CAN_AUTHORIZE_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
    const trackData = {
      connector: this.primaryConnector.name
    };
    try {
      this.analytics.track(ANALYTICS_EVENTS.IDENTITY_TOKEN_STARTED, trackData);
      // Thread the controller's active chain into connector auth so multichain
      // connectors sign for the same chain the app/session is currently using.
      const authTokenInfo = await this.primaryConnector.getAuthTokenInfo(this.currentChainId);
      this.analytics.track(ANALYTICS_EVENTS.IDENTITY_TOKEN_COMPLETED, trackData);
      return {
        idToken: authTokenInfo.idToken
      };
    } catch (error) {
      this.analytics.track(ANALYTICS_EVENTS.IDENTITY_TOKEN_FAILED, _objectSpread(_objectSpread({}, trackData), getErrorAnalyticsProperties(error)));
      throw error;
    }
  }
  getPlugin(name) {
    return this.plugins[name] || null;
  }
  async switchAccount(account) {
    const authConnector = this.getMainAuthConnector();
    const switchResult = await authConnector.switchAccount(account, {
      activeAccount: this.state.activeAccount,
      currentChainId: this.currentChainId
    });
    if (!switchResult) {
      return;
    }
    try {
      var _this$projectConfig;
      await this.processSwitchAccountResult(authConnector, switchResult, {
        projectConfig: (_this$projectConfig = this.projectConfig) !== null && _this$projectConfig !== void 0 ? _this$projectConfig : undefined
      });
      await authConnector.trackSwitchAccountCompleted(switchResult.targetAccount);
    } catch (error) {
      await authConnector.trackSwitchAccountFailed(switchResult.targetAccount, error);
      throw error;
    }
  }
  async linkAccount(params) {
    if (!(params !== null && params !== void 0 && params.connectorName)) {
      throw WalletInitializationError.invalidParams("connectorName is required when calling linkAccount on the no-modal SDK");
    }
    const {
      chainId
    } = this.resolveLinkAccountChainConfig(params.chainId);
    const isolatedConnector = await this.createLinkingWalletConnector(params.connectorName, chainId);
    return this.linkAccountWithConnector(params.connectorName, chainId, isolatedConnector);
  }
  async unlinkAccount(address) {
    var _await$authConnector$, _this$state$activeAcc;
    const authConnector = this.getMainAuthConnector();
    const linkedAccounts = (_await$authConnector$ = (await authConnector.getUserInfo()).linkedAccounts) !== null && _await$authConnector$ !== void 0 ? _await$authConnector$ : [];
    const targetAccount = this.findLinkedAccountByAddress(linkedAccounts, address);
    if (!targetAccount) {
      throw AccountLinkingError.accountNotLinked(`Account with address "${address}" is not linked`);
    }
    if (targetAccount.connector === WALLET_CONNECTORS.AUTH || targetAccount.isPrimary) {
      throw AccountLinkingError.cannotUnlinkPrimaryAccount();
    }
    if (((_this$state$activeAcc = this.state.activeAccount) === null || _this$state$activeAcc === void 0 ? void 0 : _this$state$activeAcc.id) === targetAccount.id) {
      throw AccountLinkingError.cannotUnlinkActiveAccount();
    }
    const result = await authConnector.unlinkAccount({
      address,
      authSessionTokens: {
        accessToken: this.accessToken,
        idToken: this.idToken
      }
    });
    await this.setState({
      idToken: result.idToken
    });

    // disconnect the connector for unlinked account
    const connectorToDisconnect = this.getConnectedWalletConnector(targetAccount);
    if (connectorToDisconnect) {
      try {
        if (connectorToDisconnect.connected) {
          await connectorToDisconnect.disconnect({
            cleanup: true
          });
        }
      } catch (error) {
        log.debug(`Failed to disconnect linked account "${targetAccount.id}" during unlink`, error);
      } finally {
        this.deleteConnectedWalletConnector(targetAccount);
      }
    }
    return result;
  }
  setAnalyticsProperties(properties) {
    this.analytics.setGlobalProperties(properties);
  }
  initChainsConfig(projectConfig) {
    var _this$coreOptions$acc2;
    // merge chains from project config with core options, core options chains will take precedence over project config chains
    const chainMap = new Map();
    const allChains = [...(projectConfig.chains || []), ...(this.coreOptions.chains || [])];
    for (const chain of allChains) {
      const existingChain = chainMap.get(chain.chainId);
      if (!existingChain) chainMap.set(chain.chainId, chain);else chainMap.set(chain.chainId, _objectSpread(_objectSpread({}, existingChain), chain));
    }
    this.coreOptions.chains = Array.from(chainMap.values());

    // validate chains and namespaces
    if (this.coreOptions.chains.length === 0) {
      log.error("chain info not found. Please configure chains on dashboard at https://dashboard.web3auth.io");
      throw WalletInitializationError.invalidParams("Please configure chains on dashboard at https://dashboard.web3auth.io");
    }
    const validChainNamespaces = new Set(Object.values(CHAIN_NAMESPACES));
    for (const chain of this.coreOptions.chains) {
      if (!chain.chainNamespace || !validChainNamespaces.has(chain.chainNamespace)) {
        log.error(`Please provide a valid chainNamespace in chains for chain ${chain.chainId}`);
        throw WalletInitializationError.invalidParams(`Please provide a valid chainNamespace in chains for chain ${chain.chainId}`);
      }
      if (chain.chainNamespace !== CHAIN_NAMESPACES.OTHER && !isHexStrict(chain.chainId)) {
        log.error(`Please provide a valid chainId in chains for chain ${chain.chainId}`);
        throw WalletInitializationError.invalidParams(`Please provide a valid chainId as hex string in chains for chain ${chain.chainId}`);
      }
      if (chain.chainNamespace !== CHAIN_NAMESPACES.OTHER) {
        try {
          new URL(chain.rpcTarget);
        } catch (error) {
          // TODO: add support for chain.wsTarget
          log.error(`Please provide a valid rpcTarget in chains for chain ${chain.chainId}`, error);
          throw WalletInitializationError.invalidParams(`Please provide a valid rpcTarget in chains for chain ${chain.chainId}`);
        }
      }
    }

    // if AA is enabled and smart account is not 7702, filter out chains that are not AA-supported
    const is7702SmartAccount = ((_this$coreOptions$acc2 = this.coreOptions.accountAbstractionConfig) === null || _this$coreOptions$acc2 === void 0 ? void 0 : _this$coreOptions$acc2.smartAccountEipStandard) === SMART_ACCOUNT_EIP_STANDARD.EIP_7702;
    if (this.coreOptions.accountAbstractionConfig && !is7702SmartAccount) {
      // write a for loop over accountAbstractionConfig.chains and check if the chainId is valid
      if (this.coreOptions.accountAbstractionConfig.chains.length === 0) {
        log.error("Please configure chains for smart accounts on dashboard at https://dashboard.web3auth.io");
        throw WalletInitializationError.invalidParams("Please configure chains for smart accounts on dashboard at https://dashboard.web3auth.io");
      }
      for (const chain of this.coreOptions.accountAbstractionConfig.chains) {
        if (!isHexStrict(chain.chainId)) {
          log.error(`Please provide a valid chainId in accountAbstractionConfig.chains for chain ${chain.chainId}`);
          throw WalletInitializationError.invalidParams(`Please provide a valid chainId in accountAbstractionConfig.chains for chain ${chain.chainId}`);
        }
        try {
          var _chain$bundlerConfig;
          new URL((_chain$bundlerConfig = chain.bundlerConfig) === null || _chain$bundlerConfig === void 0 ? void 0 : _chain$bundlerConfig.url);
        } catch (error) {
          log.error(`Please provide a valid bundlerConfig.url in accountAbstractionConfig.chains for chain ${chain.chainId}`, error);
          throw WalletInitializationError.invalidParams(`Please provide a valid bundlerConfig.url in accountAbstractionConfig.chains for chain ${chain.chainId}`);
        }
        if (!chainMap.has(chain.chainId)) {
          log.error(`Please provide chain config for AA chain in accountAbstractionConfig.chains for chain ${chain.chainId}`);
          throw WalletInitializationError.invalidParams(`Please provide chain config for AA chain in accountAbstractionConfig.chains for chain ${chain.chainId}`);
        }
      }
      // const aaSupportedChainIds = new Set(
      //   this.coreOptions.accountAbstractionConfig?.chains
      //     ?.filter((chain) => chain.chainId && chain.bundlerConfig?.url)
      //     .map((chain) => chain.chainId) || []
      // );
      // this.coreOptions.chains = this.coreOptions.chains.filter(
      //   (chain) => chain.chainNamespace !== CHAIN_NAMESPACES.EIP155 || aaSupportedChainIds.has(chain.chainId)
      // );
      // if (this.coreOptions.chains.length === 0) {
      //   log.error("Account Abstraction is enabled but no supported chains found");
      //   throw WalletInitializationError.invalidParams("Account Abstraction is enabled but no supported chains found");
      // }
    }
  }
  initAccountAbstractionConfig(projectConfig) {
    var _this$coreOptions$acc3;
    const isAAEnabled = Boolean(this.coreOptions.accountAbstractionConfig || (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.smartAccounts));
    if (!isAAEnabled) return;

    // merge smart account config from project config with core options, core options will take precedence over project config
    const _ref = (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.smartAccounts) || {},
      {
        walletScope,
        eipStandard
      } = _ref,
      configWithoutWalletScope = _objectWithoutProperties(_ref, _excluded);
    const aaChainMap = new Map();
    const allAaChains = [...((configWithoutWalletScope === null || configWithoutWalletScope === void 0 ? void 0 : configWithoutWalletScope.chains) || []), ...(((_this$coreOptions$acc3 = this.coreOptions.accountAbstractionConfig) === null || _this$coreOptions$acc3 === void 0 ? void 0 : _this$coreOptions$acc3.chains) || [])];
    for (const chain of allAaChains) {
      const existingChain = aaChainMap.get(chain.chainId);
      if (!existingChain) aaChainMap.set(chain.chainId, chain);else aaChainMap.set(chain.chainId, _objectSpread(_objectSpread({}, existingChain), chain));
    }
    this.coreOptions.accountAbstractionConfig = _objectSpread(_objectSpread({
      smartAccountEipStandard: eipStandard
    }, deepmerge(configWithoutWalletScope || {}, this.coreOptions.accountAbstractionConfig || {})), {}, {
      chains: Array.from(aaChainMap.values())
    });

    // if eipStandard is 7702, validate smart account type
    const {
      smartAccountEipStandard,
      smartAccountType
    } = this.coreOptions.accountAbstractionConfig;
    const is7702SmartAccount = smartAccountEipStandard === SMART_ACCOUNT_EIP_STANDARD.EIP_7702;
    if (is7702SmartAccount && smartAccountType && !EIP7702_SUPPORTED_SMART_ACCOUNT_TYPES.includes(smartAccountType)) {
      throw WalletInitializationError.invalidParams(`Smart account type "${smartAccountType}" does not support EIP-7702. Supported: ${EIP7702_SUPPORTED_SMART_ACCOUNT_TYPES.join(", ")}`);
    }

    // determine if we should use AA with external wallet
    if (this.coreOptions.useAAWithExternalWallet === undefined) {
      this.coreOptions.useAAWithExternalWallet = walletScope === SMART_ACCOUNT_WALLET_SCOPE.ALL;
    }
  }
  initUIConfig(projectConfig) {
    this.coreOptions.uiConfig = deepmerge.all([{
      mode: "light",
      uxMode: UX_MODE.POPUP
    }, cloneDeep(projectConfig.whitelabel || {}), this.coreOptions.uiConfig || {}]);
  }
  initSessionTimeConfig(projectConfig) {
    if (this.coreOptions.sessionTime) return;
    if (projectConfig.sessionTime) this.coreOptions.sessionTime = projectConfig.sessionTime;
  }
  async initCachedConnectorAndChainId() {
    // init chainId using cached chainId if it exists and is valid, otherwise use the defaultChainId or the first chain
    const cachedChainId = this.state.currentChainId;
    const isCachedChainIdValid = cachedChainId && this.coreOptions.chains.some(chain => chain.chainId === cachedChainId);
    if (this.coreOptions.defaultChainId && !isHexStrict(this.coreOptions.defaultChainId)) throw WalletInitializationError.invalidParams("Please provide a valid defaultChainId in constructor");
    const currentChainId = isCachedChainIdValid ? cachedChainId : this.coreOptions.defaultChainId || this.coreOptions.chains[0].chainId;
    await this.setState({
      currentChainId
    });
  }
  initWalletServicesConfig(projectConfig) {
    var _this$coreOptions$wal, _this$coreOptions$wal2, _this$coreOptions$wal3, _ref2, _this$coreOptions$wal4, _this$coreOptions$wal5;
    const {
      enableKeyExport,
      walletUi
    } = projectConfig;
    const {
      enablePortfolioWidget = false,
      enableTokenDisplay = true,
      enableNftDisplay = true,
      enableWalletConnect = true,
      enableBuyButton = true,
      enableSendButton = true,
      enableSwapButton = true,
      enableReceiveButton = true,
      enableShowAllTokensButton = true,
      enableConfirmationModal = false,
      enableDefiPositionsDisplay = true,
      portfolioWidgetPosition = BUTTON_POSITION.BOTTOM_LEFT,
      defaultPortfolio = "token"
    } = walletUi || {};
    const projectConfigWhiteLabel = {
      showWidgetButton: enablePortfolioWidget,
      hideNftDisplay: !enableNftDisplay,
      hideTokenDisplay: !enableTokenDisplay,
      hideTransfers: !enableSendButton,
      hideTopup: !enableBuyButton,
      hideReceive: !enableReceiveButton,
      hideSwap: !enableSwapButton,
      hideShowAllTokens: !enableShowAllTokensButton,
      hideWalletConnect: !enableWalletConnect,
      hideDefiPositionsDisplay: !enableDefiPositionsDisplay,
      buttonPosition: portfolioWidgetPosition,
      defaultPortfolio
    };
    const whiteLabel = deepmerge.all([projectConfigWhiteLabel, ((_this$coreOptions$wal = this.coreOptions.walletServicesConfig) === null || _this$coreOptions$wal === void 0 ? void 0 : _this$coreOptions$wal.whiteLabel) || {}]);
    const confirmationStrategy = (_this$coreOptions$wal2 = (_this$coreOptions$wal3 = this.coreOptions.walletServicesConfig) === null || _this$coreOptions$wal3 === void 0 ? void 0 : _this$coreOptions$wal3.confirmationStrategy) !== null && _this$coreOptions$wal2 !== void 0 ? _this$coreOptions$wal2 : enableConfirmationModal ? CONFIRMATION_STRATEGY.MODAL : CONFIRMATION_STRATEGY.AUTO_APPROVE;
    const isKeyExportEnabled = (_ref2 = (_this$coreOptions$wal4 = (_this$coreOptions$wal5 = this.coreOptions.walletServicesConfig) === null || _this$coreOptions$wal5 === void 0 ? void 0 : _this$coreOptions$wal5.enableKeyExport) !== null && _this$coreOptions$wal4 !== void 0 ? _this$coreOptions$wal4 : enableKeyExport) !== null && _ref2 !== void 0 ? _ref2 : true;
    this.coreOptions.walletServicesConfig = _objectSpread(_objectSpread({}, this.coreOptions.walletServicesConfig), {}, {
      confirmationStrategy,
      whiteLabel,
      enableKeyExport: isKeyExportEnabled
    });
  }
  getInitializationTrackData() {
    try {
      var _this$coreOptions$cha3, _this$coreOptions$cha4, _this$coreOptions$cha5, _this$coreOptions$cha6, _this$coreOptions$uiC2;
      const defaultChain = (_this$coreOptions$cha3 = this.coreOptions.chains) === null || _this$coreOptions$cha3 === void 0 ? void 0 : _this$coreOptions$cha3.find(chain => chain.chainId === this.coreOptions.defaultChainId);
      const rpcHostnames = Array.from(new Set((_this$coreOptions$cha4 = this.coreOptions.chains) === null || _this$coreOptions$cha4 === void 0 ? void 0 : _this$coreOptions$cha4.map(chain => getHostname(chain.rpcTarget)))).filter(Boolean);
      return _objectSpread(_objectSpread(_objectSpread({
        chain_ids: (_this$coreOptions$cha5 = this.coreOptions.chains) === null || _this$coreOptions$cha5 === void 0 ? void 0 : _this$coreOptions$cha5.map(chain => getCaipChainId(chain)),
        chain_names: (_this$coreOptions$cha6 = this.coreOptions.chains) === null || _this$coreOptions$cha6 === void 0 ? void 0 : _this$coreOptions$cha6.map(chain => chain.displayName),
        chain_rpc_targets: rpcHostnames,
        default_chain_id: defaultChain ? getCaipChainId(defaultChain) : undefined,
        default_chain_name: defaultChain === null || defaultChain === void 0 ? void 0 : defaultChain.displayName,
        logging_enabled: this.coreOptions.enableLogging,
        custom_storage: Boolean(this.coreOptions.storage),
        session_time: this.coreOptions.sessionTime,
        sfa_key_enabled: this.coreOptions.useSFAKey,
        mipd_enabled: this.coreOptions.multiInjectedProviderDiscovery,
        private_key_provider_enabled: Boolean(this.coreOptions.privateKeyProvider),
        ssr_enabled: this.coreOptions.ssr,
        auth_build_env: this.coreOptions.authBuildEnv,
        auth_ux_mode: (_this$coreOptions$uiC2 = this.coreOptions.uiConfig) === null || _this$coreOptions$uiC2 === void 0 ? void 0 : _this$coreOptions$uiC2.uxMode,
        auth_mfa_level: this.coreOptions.mfaLevel,
        auth_mfa_settings: Object.keys(this.coreOptions.mfaSettings || {}),
        aa_enabled_for_external_wallets: this.coreOptions.accountAbstractionConfig ? this.coreOptions.useAAWithExternalWallet : undefined
      }, getWhitelabelAnalyticsProperties(this.coreOptions.uiConfig)), getAaAnalyticsProperties(this.coreOptions.accountAbstractionConfig)), getWalletServicesAnalyticsProperties(this.coreOptions.walletServicesConfig));
    } catch (error) {
      log.error("Failed to get initialization track data", error);
      return {};
    }
  }
  async setupCommonJRPCProvider() {
    this.commonJRPCProvider = await CommonJRPCProvider.getProviderInstance({
      chain: this.currentChain,
      chains: this.coreOptions.chains
    });

    // sync chainId
    this.commonJRPCProvider.on("chainChanged", async chainId => {
      await this.setCurrentChain(chainId);
    });
  }
  async setupConnector(connector) {
    this.subscribeToConnectorEvents(connector);
    try {
      const initialChain = this.getInitialChainIdForConnector(connector);
      const autoConnect = this.checkIfAutoConnect(connector);
      await connector.init({
        autoConnect,
        chainId: initialChain.chainId,
        getAuthTokenInfo: this.coreOptions.initialAuthenticationMode === CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_AND_SIGN
      });
    } catch (e) {
      log.error(e, connector.name);
    }
  }
  async loadConnectors({
    projectConfig,
    modalMode
  }) {
    var _this$coreOptions$mul;
    // always add auth connector
    const connectorFns = [...(this.coreOptions.connectors || []), authConnector()];
    const config = {
      projectConfig,
      coreOptions: this.coreOptions,
      analytics: this.analytics
    };

    // add injected connectors
    const isExternalWalletEnabled = Boolean(projectConfig.externalWalletAuth);
    const isMipdEnabled = isExternalWalletEnabled && ((_this$coreOptions$mul = this.coreOptions.multiInjectedProviderDiscovery) !== null && _this$coreOptions$mul !== void 0 ? _this$coreOptions$mul : true);
    const chainNamespaces = new Set(this.coreOptions.chains.map(chain => chain.chainNamespace));

    // prioritize using MM connector over injected connector for EVM chains
    if (isBrowser() && chainNamespaces.has(CHAIN_NAMESPACES.EIP155)) {
      // only set headless to true if modal SDK is used, otherwise just use the modal from native Metamask SDK
      connectorFns.push(metaMaskConnector(modalMode ? {
        ui: {
          headless: true
        }
      } : undefined));
    }
    if (isMipdEnabled && isBrowser()) {
      // Solana chains
      if (chainNamespaces.has(CHAIN_NAMESPACES.SOLANA)) {
        const {
          createSolanaMipd,
          hasSolanaWalletStandardFeatures,
          walletStandardConnector
        } = await import('./connectors/injected-solana-connector/index.js');
        const solanaMipd = createSolanaMipd();
        // subscribe to new injected connectors
        solanaMipd.on("register", async (...wallets) => {
          const newConnectors = wallets.filter(hasSolanaWalletStandardFeatures).map(wallet => walletStandardConnector(wallet)(config));
          this.setConnectors(newConnectors);
        });
        connectorFns.push(...solanaMipd.get().filter(wallet => hasSolanaWalletStandardFeatures(wallet)).map(walletStandardConnector));
      }
      // EVM chains
      if (chainNamespaces.has(CHAIN_NAMESPACES.EIP155)) {
        const {
          createMipd,
          injectedEvmConnector
        } = await import('./connectors/injected-evm-connector/index.js');
        const evmMipd = createMipd();
        // `@metamask/connect-evm` SDK announces its own EIP-6963 provider (`io.metamask.mmc`) so
        // it can be discovered by generic wallet pickers. We already register MetaMask via
        // `metaMaskConnector`, so we must exclude the SDK-announced provider here; otherwise
        // it is misclassified as an injected wallet and the modal shows MetaMask as installed,
        // even when the user does not have the extension installed.
        const isNonSdkAnnouncedProvider = providerDetail => providerDetail.info.rdns !== METAMASK_ERC_6963_PROVIDER_RDNS;
        // subscribe to new injected connectors
        evmMipd.subscribe(providerDetails => {
          const filteredProviderDetails = providerDetails.filter(isNonSdkAnnouncedProvider);
          const newConnectors = filteredProviderDetails.map(providerDetail => injectedEvmConnector(providerDetail)(config));
          this.setConnectors(newConnectors);
        });
        connectorFns.push(...evmMipd.getProviders().filter(isNonSdkAnnouncedProvider).map(injectedEvmConnector));
      }
    }

    // add WalletConnectV2 connector if external wallets are enabled
    if (isBrowser() && isExternalWalletEnabled && (chainNamespaces.has(CHAIN_NAMESPACES.SOLANA) || chainNamespaces.has(CHAIN_NAMESPACES.EIP155))) {
      const {
        walletConnectV2Connector
      } = await import('./connectors/wallet-connect-v2-connector/index.js');
      connectorFns.push(walletConnectV2Connector());
    }
    const connectors = connectorFns.map(connectorFn => connectorFn(config));
    this.setConnectors(connectors);
  }
  async initPlugins() {
    const {
      chains,
      plugins
    } = this.coreOptions;
    const pluginFns = plugins || [];
    const isWsSupportedChain = chains.some(x => x.chainNamespace === CHAIN_NAMESPACES.EIP155 || x.chainNamespace === CHAIN_NAMESPACES.SOLANA);
    if (isWsSupportedChain) {
      pluginFns.push(walletServicesPlugin());
    }
    for (const pluginFn of pluginFns) {
      const plugin = pluginFn();
      if (!this.plugins[plugin.name]) this.plugins[plugin.name] = plugin;
    }
  }
  setConnectors(connectors) {
    const getConnectorKey = connector => `${connector.connectorNamespace}-${connector.name}`;
    const connectorSet = new Set(this.connectors.map(getConnectorKey));
    const newConnectors = connectors.map(connector => {
      const key = getConnectorKey(connector);
      if (connectorSet.has(key)) return null;
      connectorSet.add(key);
      return connector;
    }).filter(connector => connector !== null);
    if (newConnectors.length > 0) {
      this.connectors = [...this.connectors, ...newConnectors];
      // only emit new connectors
      this.emit(CONNECTOR_EVENTS.CONNECTORS_UPDATED, {
        connectors: newConnectors
      });
    }
  }
  subscribeToConnectorEvents(connector) {
    connector.on(CONNECTOR_EVENTS.CONNECTED, async data => {
      if (this.primaryConnectorName && this.primaryConnectorName !== data.connectorName) {
        // Ignore registered connectors that are not the active primary session connector.
        return;
      }
      if (!this.commonJRPCProvider) throw WalletInitializationError.notFound(`CommonJrpcProvider not found`);
      const {
        ethereumProvider,
        solanaWallet
      } = data;
      // Seed the primary connector synchronously so AUTHORIZED can resolve a connection
      // even while we are still restoring a previously active linked wallet.
      this.setConnectedWalletConnectorState(this.buildImmediateConnectedWalletConnectorState({
        connector,
        ethereumProvider,
        solanaWallet,
        usePrimaryProxy: true
      }));
      this.setActiveWalletConnectorKey();
      this.connectionReconnected = data.reconnected;
      const {
        activeAccount,
        currentChainId
      } = this.state;

      // when ssr is enabled, we need to get the idToken from the connector.
      if (this.coreOptions.ssr) {
        try {
          var _data$accessToken, _data$refreshToken;
          const data = await connector.getAuthTokenInfo(currentChainId);
          if (!data.idToken) throw WalletLoginError.connectionError("No idToken found");
          await this.setState({
            idToken: data.idToken,
            accessToken: (_data$accessToken = data.accessToken) !== null && _data$accessToken !== void 0 ? _data$accessToken : null,
            refreshToken: (_data$refreshToken = data.refreshToken) !== null && _data$refreshToken !== void 0 ? _data$refreshToken : null
          });
        } catch (error) {
          log.error(error);
          this.deleteConnectedWalletConnector();
          this.setActiveWalletConnectorKey();
          this.status = CONNECTOR_STATUS.ERRORED;
          this.emit(CONNECTOR_EVENTS.ERRORED, error, this.loginMode);
          return;
        }
      }
      // The following block only hits during rehydration

      let rehydrateWithLinkedAccount = false;
      // for rehydration, if the active account is not the primary account, i.e. not `null`, create an isolated connector and connect to the chain
      if (activeAccount && !activeAccount.isPrimary && activeAccount.connector !== WALLET_CONNECTORS.AUTH) {
        var _ref3, _walletConnector$prov, _linkedAccountConnect, _ref4, _walletConnector$sola, _linkedAccountConnect2;
        const accountLinkingConnector = isAuthConnector(connector) ? connector : this.getConnector(WALLET_CONNECTORS.AUTH);
        assertAuthConnector(accountLinkingConnector, "Account switching requires the AUTH connector to be available.");
        const targetChainId = accountLinkingConnector.getChainIdForLinkedAccount(activeAccount, currentChainId);
        const walletConnector = await this.createIsolatedWalletConnector(activeAccount.connector, targetChainId);
        let linkedAccountConnection = null;
        if (!this.hasUsableConnectedSwitchConnector(walletConnector)) {
          linkedAccountConnection = await walletConnector.connect({
            chainId: targetChainId
          });
          if (!linkedAccountConnection) {
            throw AccountLinkingError.requestFailed(`Failed to connect isolated connector "${activeAccount.connector}" for account switch.`);
          }
        }
        const connectedWalletState = await this.resolveConnectedWalletConnectorState({
          connector: walletConnector,
          ethereumProvider: (_ref3 = (_walletConnector$prov = walletConnector.provider) !== null && _walletConnector$prov !== void 0 ? _walletConnector$prov : (_linkedAccountConnect = linkedAccountConnection) === null || _linkedAccountConnect === void 0 ? void 0 : _linkedAccountConnect.ethereumProvider) !== null && _ref3 !== void 0 ? _ref3 : null,
          solanaWallet: (_ref4 = (_walletConnector$sola = walletConnector.solanaWallet) !== null && _walletConnector$sola !== void 0 ? _walletConnector$sola : (_linkedAccountConnect2 = linkedAccountConnection) === null || _linkedAccountConnect2 === void 0 ? void 0 : _linkedAccountConnect2.solanaWallet) !== null && _ref4 !== void 0 ? _ref4 : null,
          usePrimaryProxy: false,
          account: activeAccount
        });
        this.setConnectedWalletConnectorState(connectedWalletState, activeAccount);
        this.setActiveWalletConnectorKey(activeAccount);
        rehydrateWithLinkedAccount = true;
      }
      if (ethereumProvider) {
        await this.bindPrimaryEthereumSigningProxy(ethereumProvider, data.connectorName);
      }
      const primaryConnectedWalletState = await this.resolveConnectedWalletConnectorState({
        connector,
        ethereumProvider,
        solanaWallet,
        usePrimaryProxy: true
      });
      this.setConnectedWalletConnectorState(primaryConnectedWalletState);
      await this.setState({
        primaryConnectorName: data.connectorName
      });
      this.cacheWallet(data.connectorName, data.connectorNamespace);
      const isConnectAndSign = this.coreOptions.initialAuthenticationMode === CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_AND_SIGN;
      const pendingUserConsent = this.consentRequired && !this.state.hasUserConsent;
      if (pendingUserConsent && !isConnectAndSign) {
        this.status = CONNECTOR_STATUS.CONSENT_REQUIRING;
        this.emit(CONNECTOR_EVENTS.CONSENT_REQUIRING, _objectSpread({}, data));
        log.debug("consent_requiring", this.status, this.primaryConnectorName);
      } else {
        // In CONNECT_AND_SIGN mode the AUTHORIZED handler can run before this point (e.g. when `ssr=true`
        // this handler `await`s `connector.getAuthTokenInfo()` which fires AUTHORIZED mid-execution).
        // Don't downgrade an already-advanced status (CONSENT_REQUIRING or AUTHORIZED) back to CONNECTED;
        // otherwise `acceptConsent` would throw "Cannot accept consent: not in consent_requiring state".
        if (this.status !== CONNECTOR_STATUS.CONSENT_REQUIRING && this.status !== CONNECTOR_STATUS.AUTHORIZED) {
          this.status = CONNECTOR_STATUS.CONNECTED;
        }
        // Defer plugin connection until consent is accepted; otherwise plugins would start before the consent step completes.
        // `completeConsentAcceptance` connects the plugins once the user accepts the consent.
        if (!pendingUserConsent) {
          this.connectToPlugins(_objectSpread(_objectSpread({}, data), {}, {
            connector: data.connectorName
          }));
        }

        // `pendingUserConsent` signals listeners (LoginModal, React/Vue contexts) to skip processing this CONNECTED event,
        // so the upcoming AUTHORIZED -> CONSENT_REQUIRING transition is not overridden by a late CONNECTED handler in CONNECT_AND_SIGN mode.
        this.emit(CONNECTOR_EVENTS.CONNECTED, _objectSpread(_objectSpread({}, data), {}, {
          loginMode: this.loginMode,
          pendingUserConsent
        }));

        // if we're rehydrating with a linked account, we need to emit a CONNECTION_UPDATED event
        // so that upstream listeners and context are updated with the linked connection.
        if (rehydrateWithLinkedAccount) {
          this.emit(CONNECTOR_EVENTS.CONNECTION_UPDATED, this.connection);
        }
      }
    });
    connector.on(CONNECTOR_EVENTS.DISCONNECTED, async data => {
      if (this.shouldIgnoreInactiveConnectorEvent(connector, CONNECTOR_EVENTS.DISCONNECTED)) return;
      const disconnectedConnector = data === null || data === void 0 ? void 0 : data.connector;
      const {
        activeAccount
      } = this.state;
      if (!activeAccount || activeAccount && activeAccount.isPrimary || disconnectedConnector === WALLET_CONNECTORS.AUTH) {
        // If the primary session disconnects, tear down every other connected wallet connector
        // and clear the entire map.
        await Promise.all(Array.from(this.connectedWalletConnectorMap.entries()).map(async ([accountId, connectedWallet]) => {
          if (connectedWallet.connector === connector) {
            this.connectedWalletConnectorMap.delete(accountId);
            return;
          }
          try {
            if (connectedWallet.connected && connectedWallet.connector.connected) {
              await connectedWallet.connector.disconnect({
                cleanup: true
              });
            }
          } catch (error) {
            log.debug("Connected wallet connector disconnect on primary disconnect", error);
          } finally {
            this.connectedWalletConnectorMap.delete(accountId);
          }
        }));
      }
      this.connectedWalletConnectorMap.clear();
      this.activeWalletConnectorKey = PRIMARY_CONNECTED_WALLET_KEY;
      this.connectionReconnected = false;
      // re-setup commonJRPCProvider
      this.commonJRPCProvider.removeAllListeners();
      this.setupCommonJRPCProvider();

      // get back to ready state for rehydrating.
      this.status = CONNECTOR_STATUS.READY;
      const cachedConnector = this.state.cachedConnector;
      if (this.primaryConnectorName === cachedConnector) {
        await this.clearCache();
      }
      log.debug("disconnected", this.status, this.primaryConnectorName);
      await Promise.all(Object.values(this.plugins).map(async plugin => {
        if (!plugin.SUPPORTED_CONNECTORS.includes(connector.name)) return;
        if (plugin.status !== PLUGIN_STATUS.CONNECTED) return;
        return plugin.disconnect().catch(error => {
          // swallow error if connector doesn't supports this plugin.
          if (error.code === 5211) {
            return;
          }
          // throw error;
          log.error(error);
        });
      }));
      await this.setState({
        primaryConnectorName: null,
        hasUserConsent: undefined,
        activeAccount: null
      });
      this.emit(CONNECTOR_EVENTS.DISCONNECTED);
    });
    connector.on(CONNECTOR_EVENTS.CONNECTING, data => {
      this.status = CONNECTOR_STATUS.CONNECTING;
      this.emit(CONNECTOR_EVENTS.CONNECTING, data);
      log.debug("connecting", this.status, this.primaryConnectorName);
    });
    connector.on(CONNECTOR_EVENTS.ERRORED, async data => {
      if (this.shouldIgnoreInactiveConnectorEvent(connector, CONNECTOR_EVENTS.ERRORED)) {
        log.error("Inactive connector emitted errored event", {
          connector: connector.name,
          error: data
        });
        return;
      }
      this.status = CONNECTOR_STATUS.ERRORED;
      await this.clearCache();
      this.emit(CONNECTOR_EVENTS.ERRORED, data, this.loginMode);
      log.debug("errored", this.status, this.primaryConnectorName);
    });
    connector.on(CONNECTOR_EVENTS.REHYDRATION_ERROR, async error => {
      if (this.shouldIgnoreInactiveConnectorEvent(connector, CONNECTOR_EVENTS.REHYDRATION_ERROR)) {
        log.error("Inactive connector emitted rehydration error", {
          connector: connector.name,
          error
        });
        return;
      }
      this.status = CONNECTOR_STATUS.READY;
      await this.clearCache();
      this.emit(CONNECTOR_EVENTS.REHYDRATION_ERROR, error);
    });
    connector.on(CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED, async data => {
      if (this.shouldIgnoreInactiveConnectorEvent(connector, CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED)) return;
      // External wallets can resolve to a different active chain than the requested one,
      // so let connector-reported chain updates reconcile Web3Auth state after connect.
      if (typeof (data === null || data === void 0 ? void 0 : data.data) === "object" && (data === null || data === void 0 ? void 0 : data.data) !== null && "chainId" in data.data && typeof data.data.chainId === "string") {
        const previousChain = this.currentChain;
        await this.setCurrentChain(data.data.chainId);
        const currentChain = this.currentChain;
        const connectorEthereumProvider = connector.provider;
        if ((previousChain === null || previousChain === void 0 ? void 0 : previousChain.chainNamespace) !== (currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) && (currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) === CHAIN_NAMESPACES.EIP155 && connectorEthereumProvider) {
          // from sol -> evm namespace switch, we need to re-create AccountAbstractionProvider
          await this.bindPrimaryEthereumSigningProxy(connectorEthereumProvider, connector.name);
        }
      }
      log.debug("connector data updated", data);
      this.emit(CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED, data);
    });
    connector.on(CONNECTOR_EVENTS.CACHE_CLEAR, async data => {
      if (this.shouldIgnoreInactiveConnectorEvent(connector, CONNECTOR_EVENTS.CACHE_CLEAR)) return;
      log.debug("connector cache clear", data);
      await this.clearCache();
    });
    connector.on(CONNECTOR_EVENTS.MFA_ENABLED, isMFAEnabled => {
      var _authConnector$authIn4;
      log.debug("mfa enabled", isMFAEnabled);
      const authConnector = this.primaryConnector;

      // mfa_enabled event is only emitted when using "popup" ux_mode
      // TODO: handle mfa_enabled event when using "redirect" ux_mode
      this.analytics.track(ANALYTICS_EVENTS.MFA_ENABLEMENT_COMPLETED, {
        connector: this.primaryConnector.name,
        auth_ux_mode: (_authConnector$authIn4 = authConnector.authInstance) === null || _authConnector$authIn4 === void 0 || (_authConnector$authIn4 = _authConnector$authIn4.options) === null || _authConnector$authIn4 === void 0 ? void 0 : _authConnector$authIn4.uxMode,
        is_mfa_enabled: isMFAEnabled
      });
      this.emit(CONNECTOR_EVENTS.MFA_ENABLED, isMFAEnabled);
    });
    connector.on(CONNECTOR_EVENTS.AUTHORIZING, data => {
      this.status = CONNECTOR_STATUS.AUTHORIZING;
      this.emit(CONNECTOR_EVENTS.AUTHORIZING, data);
      log.debug("authorizing", this.status, this.primaryConnectorName);
    });
    connector.on(CONNECTOR_EVENTS.AUTHORIZED, async data => {
      var _data$authTokenInfo$a, _data$authTokenInfo$r;
      await this.setState({
        idToken: data.authTokenInfo.idToken,
        accessToken: (_data$authTokenInfo$a = data.authTokenInfo.accessToken) !== null && _data$authTokenInfo$a !== void 0 ? _data$authTokenInfo$a : null,
        refreshToken: (_data$authTokenInfo$r = data.authTokenInfo.refreshToken) !== null && _data$authTokenInfo$r !== void 0 ? _data$authTokenInfo$r : null
      });
      // if the user has not consented yet, we will ask for consent
      if (this.consentRequired && this.connection && !this.state.hasUserConsent) {
        this.status = CONNECTOR_STATUS.CONSENT_REQUIRING;
        this.emit(CONNECTOR_EVENTS.CONSENT_REQUIRING, {
          connectorName: data.connector
        });
        log.debug("consent_requiring", this.status, this.primaryConnectorName);
      } else {
        this.status = CONNECTOR_STATUS.AUTHORIZED;
        this.emit(CONNECTOR_EVENTS.AUTHORIZED, data);
        log.debug("authorized", this.status, this.primaryConnectorName);
      }
    });
  }
  checkInitRequirements() {
    if (this.status === CONNECTOR_STATUS.READY) throw WalletInitializationError.notReady("Connector is already initialized");
  }
  checkIfAutoConnect(connector) {
    var _this$currentChain3;
    let autoConnect = this.cachedConnector === connector.name && this.state.cachedConnectorNamespace === connector.connectorNamespace;
    if (autoConnect && (_this$currentChain3 = this.currentChain) !== null && _this$currentChain3 !== void 0 && _this$currentChain3.chainNamespace) {
      if (connector.connectorNamespace === CONNECTOR_NAMESPACES.MULTICHAIN) autoConnect = true;else autoConnect = connector.connectorNamespace === this.currentChain.chainNamespace;
    }
    return autoConnect;
  }

  /**
   * Gets the initial chain configuration for a connector
   * @throws WalletInitializationError If no chain is found for the connector's namespace
   */
  getInitialChainIdForConnector(connector) {
    var _initialChain;
    let initialChain = this.currentChain;
    const defaultChainId = this.coreOptions.defaultChainId;
    const isMultiChainConnector = connector.connectorNamespace === CONNECTOR_NAMESPACES.MULTICHAIN;

    // if the connector is a multi-chain connector and a default chain id is set, use the default chain id
    if (isMultiChainConnector && defaultChainId) {
      initialChain = this.coreOptions.chains.find(chain => chain.chainId === defaultChainId) || this.currentChain;
    } else if (((_initialChain = initialChain) === null || _initialChain === void 0 ? void 0 : _initialChain.chainNamespace) !== connector.connectorNamespace && connector.connectorNamespace !== CONNECTOR_NAMESPACES.MULTICHAIN) {
      initialChain = this.coreOptions.chains.find(x => x.chainNamespace === connector.connectorNamespace);
    }
    if (!initialChain) throw WalletInitializationError.invalidParams(`No chain found for ${connector.connectorNamespace}`);
    return initialChain;
  }
  async completeConsentAcceptance() {
    const connection = this.connection;
    if (!connection) {
      throw WalletLoginError.connectionError("Cannot accept consent: no active connection");
    }
    if (this.status !== CONNECTOR_STATUS.CONSENT_REQUIRING) {
      throw WalletLoginError.connectionError("Cannot accept consent: not in consent_requiring state");
    }
    await this.setState({
      hasUserConsent: true
    });
    const isConnectAndSign = this.coreOptions.initialAuthenticationMode === CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_AND_SIGN;
    if (isConnectAndSign && this.state.idToken) {
      this.status = CONNECTOR_STATUS.AUTHORIZED;
      log.debug("consent accepted, authorized", this.status, this.primaryConnectorName);
    } else {
      this.status = CONNECTOR_STATUS.CONNECTED;
      log.debug("consent accepted, connected", this.status, this.primaryConnectorName);
    }

    // connect to wallet-service plugin
    if (this.primaryConnectorName === WALLET_CONNECTORS.AUTH) {
      this.connectToPlugins({
        connector: this.primaryConnectorName
      });
    }
    this.emit(CONNECTOR_EVENTS.CONSENT_ACCEPTED, {
      reconnected: this.connectionReconnected
    });
  }
  resolveLinkAccountChainConfig(chainId) {
    var _this$coreOptions$cha7;
    const finalChainId = chainId || this.state.currentChainId;
    const chainConfig = (_this$coreOptions$cha7 = this.coreOptions.chains) === null || _this$coreOptions$cha7 === void 0 ? void 0 : _this$coreOptions$cha7.find(chain => chain.chainId === finalChainId);
    if (!chainConfig) {
      throw AccountLinkingError.walletProofFailed("No chainId is available. Please specify chainId in LinkAccountParams or ensure the SDK has an active chain.");
    }
    return chainConfig;
  }

  /**
   * Resolves the chain ID for a switch account operation.
   * If the account's chain namespace is the same as the current chain namespace, return the current chain ID.
   * If the account's chain namespace is different from the current chain namespace, return the chainId the account was linked in.
   *
   * @param account - The account to switch to.
   * @param activeChainId - The current active chain ID.
   * @returns The resolved chain ID.
   */
  resolveSwitchAccountChainId(account, activeChainId) {
    const targetChainNamespace = account.chainNamespace ? parseChainNamespaceFromCitadelResponse(account.chainNamespace) : null;
    if (targetChainNamespace && this.currentChain.chainNamespace === targetChainNamespace) {
      return this.currentChain.chainId;
    }
    return activeChainId;
  }
  async createLinkingWalletConnector(connectorName, chainId, config) {
    try {
      const linkingConnector = await this.createIsolatedWalletConnector(connectorName, chainId, config);
      return linkingConnector;
    } catch (error) {
      if (error instanceof AccountLinkingError && error.code === 5405) {
        throw error;
      }
      throw AccountLinkingError.walletProofFailed(error instanceof Error ? error.message : String(error), error);
    }
  }
  async createSwitchingWalletConnector(connectorName, chainId, config) {
    return this.createIsolatedWalletConnector(connectorName, chainId, config);
  }
  getConnectedWalletConnector(account) {
    var _this$getConnectedWal, _this$getConnectedWal2;
    return (_this$getConnectedWal = (_this$getConnectedWal2 = this.getConnectedWalletConnectorState(account)) === null || _this$getConnectedWal2 === void 0 ? void 0 : _this$getConnectedWal2.connector) !== null && _this$getConnectedWal !== void 0 ? _this$getConnectedWal : null;
  }
  getConnectedWalletConnectorState(account) {
    return this.getConnectedWalletConnectorStateByKey(this.getConnectedWalletConnectorKey(account));
  }
  setConnectedWalletConnectorState(connectedWallet, account) {
    this.connectedWalletConnectorMap.set(this.getConnectedWalletConnectorKey(account), connectedWallet);
  }
  setConnectedWalletConnector(connector, account) {
    var _connector$solanaWall;
    this.setConnectedWalletConnectorState(_objectSpread(_objectSpread({}, this.getConnectedWalletLinkedAccountInfo(account)), {}, {
      connector,
      signingProvider: connector.provider,
      solanaWallet: (_connector$solanaWall = connector.solanaWallet) !== null && _connector$solanaWall !== void 0 ? _connector$solanaWall : null,
      connected: connector.connected || connector.status === CONNECTOR_STATUS.CONNECTED
    }), account);
  }
  deleteConnectedWalletConnector(account) {
    this.connectedWalletConnectorMap.delete(this.getConnectedWalletConnectorKey(account));
  }
  getConnectedWalletConnection(account) {
    return this.getConnectedWalletConnectionByKey(this.getConnectedWalletConnectorKey(account));
  }
  hasUsableConnectedSwitchConnector(connector) {
    if (!connector) return false;
    const isConnected = connector.connected || connector.status === CONNECTOR_STATUS.CONNECTED;
    return Boolean(isConnected && (connector.provider || connector.solanaWallet));
  }
  setActiveWalletConnectorKey(account) {
    this.activeWalletConnectorKey = this.getConnectedWalletConnectorKey(account);
  }
  getConnectedWalletConnectorKey(account) {
    return !account || account.isPrimary ? PRIMARY_CONNECTED_WALLET_KEY : account.id;
  }
  getConnectedWalletConnectorStateByKey(accountKey) {
    var _this$connectedWallet;
    return (_this$connectedWallet = this.connectedWalletConnectorMap.get(accountKey)) !== null && _this$connectedWallet !== void 0 ? _this$connectedWallet : null;
  }
  isLinkedAccountInfo(account) {
    return Boolean(account && "connector" in account);
  }
  toConnectedWalletLinkedAccountInfo(account) {
    return {
      id: account.id,
      isPrimary: account.isPrimary,
      eoaAddress: account.eoaAddress,
      aaAddress: account.aaAddress,
      aaProvider: account.aaProvider,
      active: account.active,
      accountType: account.accountType,
      address: account.address,
      authConnectionId: account.authConnectionId,
      groupedAuthConnectionId: account.groupedAuthConnectionId,
      chainNamespace: account.chainNamespace
    };
  }
  getConnectedWalletLinkedAccountInfo(account) {
    const existingConnectedWallet = this.getConnectedWalletConnectorState(account);
    const resolvedAccount = this.isLinkedAccountInfo(account) ? account : existingConnectedWallet;
    if (resolvedAccount) {
      return this.toConnectedWalletLinkedAccountInfo(resolvedAccount);
    }
    const isPrimaryAccount = !account || account.isPrimary;
    const accountId = account && !account.isPrimary ? account.id : PRIMARY_CONNECTED_WALLET_KEY;
    return {
      id: accountId,
      isPrimary: isPrimaryAccount,
      eoaAddress: "",
      aaAddress: undefined,
      aaProvider: undefined,
      active: this.state.activeAccount ? this.state.activeAccount.id === accountId : isPrimaryAccount,
      accountType: "",
      address: null,
      authConnectionId: null,
      groupedAuthConnectionId: null,
      chainNamespace: null
    };
  }
  syncConnectedWalletLinkedAccounts(linkedAccounts) {
    for (const linkedAccount of linkedAccounts) {
      const accountKey = this.getConnectedWalletConnectorKey(linkedAccount);
      const connectedWallet = this.connectedWalletConnectorMap.get(accountKey);
      if (!connectedWallet) {
        continue;
      }
      this.connectedWalletConnectorMap.set(accountKey, _objectSpread(_objectSpread({}, connectedWallet), this.toConnectedWalletLinkedAccountInfo(linkedAccount)));
    }
  }
  refreshConnectedWalletActiveStates(activeAccount) {
    for (const [accountKey, connectedWallet] of this.connectedWalletConnectorMap.entries()) {
      const isPrimaryAccount = accountKey === PRIMARY_CONNECTED_WALLET_KEY || connectedWallet.isPrimary;
      this.connectedWalletConnectorMap.set(accountKey, _objectSpread(_objectSpread({}, connectedWallet), {}, {
        active: activeAccount ? connectedWallet.id === activeAccount.id : isPrimaryAccount
      }));
    }
  }
  getConnectedWalletConnectionByKey(accountKey) {
    const connectedWallet = this.getConnectedWalletConnectorStateByKey(accountKey);
    if (!connectedWallet) {
      return null;
    }
    if (!connectedWallet.signingProvider && !connectedWallet.solanaWallet) {
      throw new Error(`Connected connector "${connectedWallet.connector.name}" is not ready.`);
    }
    return this.buildConnectionFromConnectedWalletConnectorState(connectedWallet);
  }
  buildConnectionFromConnectedWalletConnectorState(connectedWallet) {
    var _connectedWallet$sola;
    return {
      ethereumProvider: connectedWallet.signingProvider,
      solanaWallet: (_connectedWallet$sola = connectedWallet.solanaWallet) !== null && _connectedWallet$sola !== void 0 ? _connectedWallet$sola : null,
      connectorName: connectedWallet.connector.name,
      connectorNamespace: connectedWallet.connector.connectorNamespace
    };
  }
  buildImmediateConnectedWalletConnectorState(params) {
    var _this$commonJRPCProvi;
    const {
      connector,
      ethereumProvider,
      solanaWallet,
      usePrimaryProxy,
      account
    } = params;
    const isSolanaOnly = connector.connectorNamespace === CHAIN_NAMESPACES.SOLANA;
    const connectedWallet = _objectSpread(_objectSpread({}, this.getConnectedWalletLinkedAccountInfo(account)), {}, {
      connector,
      signingProvider: isSolanaOnly ? null : ethereumProvider ? usePrimaryProxy ? (_this$commonJRPCProvi = this.commonJRPCProvider) !== null && _this$commonJRPCProvi !== void 0 ? _this$commonJRPCProvi : ethereumProvider : ethereumProvider : null,
      solanaWallet: solanaWallet !== null && solanaWallet !== void 0 ? solanaWallet : null,
      connected: connector.connected || connector.status === CONNECTOR_STATUS.CONNECTED || connector.status === CONNECTOR_STATUS.AUTHORIZED
    });
    return connectedWallet;
  }
  async resolveConnectedWalletConnectorState(params) {
    const {
      connector,
      ethereumProvider,
      solanaWallet,
      usePrimaryProxy,
      account
    } = params;
    return this.buildImmediateConnectedWalletConnectorState({
      connector,
      ethereumProvider,
      solanaWallet,
      usePrimaryProxy,
      account
    });
  }
  async linkAccountWithConnector(connectorName, chainId, connectorToLink) {
    const authConnector = this.getMainAuthConnector();
    const result = await authConnector.linkAccount({
      connectorName,
      chainId,
      connectorToLink,
      authSessionTokens: {
        accessToken: this.accessToken,
        idToken: this.idToken
      }
    });
    await this.setState({
      idToken: result.idToken
    });
    await this.cacheConnectedLinkedWalletConnector(authConnector, connectorToLink);
    return result;
  }
  getMainAuthConnector() {
    if (!CONNECTED_STATUSES.includes(this.status) || !this.primaryConnector) {
      throw WalletLoginError.notConnectedError("No wallet is connected. Connect with AUTH before unlinking an account.");
    }
    const mainConnector = this.primaryConnector;
    assertAuthConnector(mainConnector, "Account linking is only supported when connected with the AUTH connector.");
    return mainConnector;
  }

  /**
   * Processes the result of a switch account operation.
   *
   * - If the target account is a primary account, we will switch back to the primary account.
   * - If the target account is an external account and already connected (i.e. connector is available with connected state), we will just switch to it without re-connecting again.
   * - If the target account is an external account and not connected (i.e. connector is not available with connected state), we will create a new isolated connector and connect to it.
   * @param authConnector - The main auth connector to use.
   * @param switchResult - The result of the switch account operation.
   * @param options - The options for the switch account operation.
   * @returns A promise that resolves when the switch account operation is complete.
   */
  async processSwitchAccountResult(authConnector, switchResult, options = {}) {
    const resolvedSwitchChainId = this.resolveSwitchAccountChainId(switchResult.targetAccount, switchResult.activeChainId);
    if (switchResult.kind === "primary") {
      var _primaryConnectedWall, _this$commonJRPCProvi2, _switchResult$solanaW;
      const existingPrimaryConnectedWalletState = this.getConnectedWalletConnectorState();
      const primaryConnectedWalletState = existingPrimaryConnectedWalletState !== null && existingPrimaryConnectedWalletState !== void 0 ? existingPrimaryConnectedWalletState : await this.resolveConnectedWalletConnectorState({
        connector: authConnector,
        ethereumProvider: switchResult.ethereumProvider,
        solanaWallet: switchResult.solanaWallet,
        usePrimaryProxy: true,
        account: switchResult.targetAccount
      });
      this.setConnectedWalletConnectorState(_objectSpread(_objectSpread({}, primaryConnectedWalletState), {}, {
        connector: authConnector,
        signingProvider: (_primaryConnectedWall = primaryConnectedWalletState.signingProvider) !== null && _primaryConnectedWall !== void 0 ? _primaryConnectedWall : switchResult.ethereumProvider ? (_this$commonJRPCProvi2 = this.commonJRPCProvider) !== null && _this$commonJRPCProvi2 !== void 0 ? _this$commonJRPCProvi2 : switchResult.ethereumProvider : null,
        solanaWallet: (_switchResult$solanaW = switchResult.solanaWallet) !== null && _switchResult$solanaW !== void 0 ? _switchResult$solanaW : primaryConnectedWalletState.solanaWallet,
        connected: authConnector.connected || authConnector.status === CONNECTOR_STATUS.CONNECTED
      }));
      this.setActiveWalletConnectorKey();
    } else {
      var _ref5, _options$walletConnec;
      const walletConnector = (_ref5 = (_options$walletConnec = options.walletConnector) !== null && _options$walletConnec !== void 0 ? _options$walletConnec : this.getConnectedWalletConnector(switchResult.targetAccount)) !== null && _ref5 !== void 0 ? _ref5 : await this.createSwitchingWalletConnector(switchResult.targetAccount.connector, resolvedSwitchChainId, options.projectConfig);
      let linkedAccountConnection = null;
      try {
        var _ref6, _walletConnector$prov2, _linkedAccountConnect3, _ref7, _walletConnector$sola2, _linkedAccountConnect4;
        if (!this.hasUsableConnectedSwitchConnector(walletConnector)) {
          const switchChainConfig = this.coreOptions.chains.find(c => c.chainId === resolvedSwitchChainId);
          if (!switchChainConfig) {
            throw WalletLoginError.connectionError(`Chain config is not available for chain ${resolvedSwitchChainId}`);
          }
          const caipChainId = getCaipChainId(switchChainConfig);
          const caipAccountId = `${caipChainId}:${switchResult.targetAccount.eoaAddress}`;
          linkedAccountConnection = await walletConnector.connect({
            chainId: resolvedSwitchChainId,
            caipAccountIds: [caipAccountId]
          });
          if (!linkedAccountConnection) {
            throw AccountLinkingError.requestFailed(`Failed to connect isolated connector "${switchResult.targetAccount.connector}" for account switch.`);
          }
        }
        await authConnector.assertSwitchAccountConnectorMatchesTarget(walletConnector, switchResult.targetAccount);
        const connectedWalletState = await this.resolveConnectedWalletConnectorState({
          connector: walletConnector,
          ethereumProvider: (_ref6 = (_walletConnector$prov2 = walletConnector.provider) !== null && _walletConnector$prov2 !== void 0 ? _walletConnector$prov2 : (_linkedAccountConnect3 = linkedAccountConnection) === null || _linkedAccountConnect3 === void 0 ? void 0 : _linkedAccountConnect3.ethereumProvider) !== null && _ref6 !== void 0 ? _ref6 : null,
          solanaWallet: (_ref7 = (_walletConnector$sola2 = walletConnector.solanaWallet) !== null && _walletConnector$sola2 !== void 0 ? _walletConnector$sola2 : (_linkedAccountConnect4 = linkedAccountConnection) === null || _linkedAccountConnect4 === void 0 ? void 0 : _linkedAccountConnect4.solanaWallet) !== null && _ref7 !== void 0 ? _ref7 : null,
          usePrimaryProxy: false,
          account: switchResult.targetAccount
        });
        this.setConnectedWalletConnectorState(connectedWalletState, switchResult.targetAccount);
        this.setActiveWalletConnectorKey(switchResult.targetAccount);
      } catch (error) {
        throw authConnector.toSwitchAccountConnectorError(switchResult.targetAccount, error);
      }
    }
    await this.setCurrentChain(resolvedSwitchChainId);
    await this.setState({
      activeAccount: switchResult.activeAccount
    });
    this.syncConnectedWalletLinkedAccounts([switchResult.targetAccount]);
    this.refreshConnectedWalletActiveStates(switchResult.activeAccount);
    const connection = this.connection;
    if (!connection) {
      throw WalletLoginError.connectionError("Failed to resolve the active connection after switching accounts.");
    }
    this.emit(CONNECTOR_EVENTS.CONNECTION_UPDATED, connection);
  }
  isActiveConnectorEventSource(connector) {
    if (!this.primaryConnectorName) return true;
    const activeConnector = this.primaryConnector;
    if (activeConnector) return activeConnector === connector;
    return connector.name === this.primaryConnectorName;
  }
  shouldIgnoreInactiveConnectorEvent(connector, event) {
    if (this.isActiveConnectorEventSource(connector)) return false;
    log.debug("Ignoring connector lifecycle event from inactive connector", {
      event,
      sourceConnector: connector.name,
      activeConnector: this.primaryConnectorName
    });
    return true;
  }
  findLinkedAccountByAddress(linkedAccounts, address) {
    var _linkedAccounts$find;
    const normalizedAddress = address.toLowerCase();
    return (_linkedAccounts$find = linkedAccounts.find(account => {
      var _account$address, _account$eoaAddress;
      if (!account.chainNamespace || parseChainNamespaceFromCitadelResponse(account.chainNamespace) !== CHAIN_NAMESPACES.EIP155) {
        return false;
      }
      return ((_account$address = account.address) === null || _account$address === void 0 ? void 0 : _account$address.toLowerCase()) === normalizedAddress || ((_account$eoaAddress = account.eoaAddress) === null || _account$eoaAddress === void 0 ? void 0 : _account$eoaAddress.toLowerCase()) === normalizedAddress;
    })) !== null && _linkedAccounts$find !== void 0 ? _linkedAccounts$find : null;
  }
  findLinkedAccountByWalletAddress(linkedAccounts, address) {
    var _linkedAccounts$find2;
    return (_linkedAccounts$find2 = linkedAccounts.find(account => {
      if (!account.chainNamespace) {
        return false;
      }
      const chainNamespace = parseChainNamespaceFromCitadelResponse(account.chainNamespace);
      if (chainNamespace === CHAIN_NAMESPACES.EIP155) {
        var _account$address2, _account$eoaAddress2;
        const normalizedAddress = address.toLowerCase();
        return ((_account$address2 = account.address) === null || _account$address2 === void 0 ? void 0 : _account$address2.toLowerCase()) === normalizedAddress || ((_account$eoaAddress2 = account.eoaAddress) === null || _account$eoaAddress2 === void 0 ? void 0 : _account$eoaAddress2.toLowerCase()) === normalizedAddress;
      }
      if (chainNamespace === CHAIN_NAMESPACES.SOLANA) {
        return account.address === address || account.eoaAddress === address;
      }
      return false;
    })) !== null && _linkedAccounts$find2 !== void 0 ? _linkedAccounts$find2 : null;
  }
  async getConnectedWalletAddress(connector) {
    var _connector$solanaWall2, _accounts$;
    const solanaAddress = (_connector$solanaWall2 = connector.solanaWallet) === null || _connector$solanaWall2 === void 0 || (_connector$solanaWall2 = _connector$solanaWall2.accounts) === null || _connector$solanaWall2 === void 0 || (_connector$solanaWall2 = _connector$solanaWall2[0]) === null || _connector$solanaWall2 === void 0 ? void 0 : _connector$solanaWall2.address;
    if (solanaAddress) {
      return solanaAddress;
    }
    if (!connector.provider) {
      return null;
    }
    const accounts = await connector.provider.request({
      method: "eth_accounts"
    });
    return (_accounts$ = accounts === null || accounts === void 0 ? void 0 : accounts[0]) !== null && _accounts$ !== void 0 ? _accounts$ : null;
  }
  async cacheConnectedLinkedWalletConnector(authConnector, walletConnector) {
    try {
      var _await$authConnector$2;
      const connectedWalletAddress = await this.getConnectedWalletAddress(walletConnector);
      if (!connectedWalletAddress) {
        return;
      }
      const linkedAccounts = (_await$authConnector$2 = await authConnector.getLinkedAccounts()) !== null && _await$authConnector$2 !== void 0 ? _await$authConnector$2 : [];
      const linkedAccount = this.findLinkedAccountByWalletAddress(linkedAccounts, connectedWalletAddress);
      if (linkedAccount && !linkedAccount.isPrimary) {
        const connectedWalletState = await this.resolveConnectedWalletConnectorState({
          connector: walletConnector,
          ethereumProvider: walletConnector.provider,
          solanaWallet: walletConnector.solanaWallet,
          usePrimaryProxy: false,
          account: linkedAccount
        });
        this.setConnectedWalletConnectorState(connectedWalletState, linkedAccount);
      }
    } catch (error) {
      log.debug("Failed to cache connected linked wallet connector", error);
    }
  }
  async cacheWallet(walletName, connectorNamespace) {
    await this.setState({
      cachedConnector: walletName,
      cachedConnectorNamespace: connectorNamespace
    });
  }
  async setCurrentChain(chainId) {
    const {
      currentChainId
    } = this.state;
    if (chainId === currentChainId) return;
    const newChain = this.coreOptions.chains.find(chain => chain.chainId === chainId);
    if (!newChain) throw WalletInitializationError.invalidParams(`Invalid chainId: ${chainId}`);
    await this.setState({
      currentChainId: chainId
    });
  }
  connectToPlugins(data) {
    Object.values(this.plugins).map(async plugin => {
      try {
        var _this$currentChain4;
        // skip if it's not compatible with the connector
        if (!plugin.SUPPORTED_CONNECTORS.includes(data.connector)) return;
        // skip if it's not compatible with the current chain
        if (plugin.pluginNamespace !== PLUGIN_NAMESPACES.MULTICHAIN && plugin.pluginNamespace !== ((_this$currentChain4 = this.currentChain) === null || _this$currentChain4 === void 0 ? void 0 : _this$currentChain4.chainNamespace)) return;
        // skip if it's already connected
        if (plugin.status === PLUGIN_STATUS.CONNECTED) return;
        await plugin.initWithWeb3Auth(this, this.coreOptions.uiConfig, this.analytics);
        await plugin.connect();
      } catch (error) {
        // swallow error if connector connector doesn't supports this plugin.
        if (error.code === 5211) {
          return;
        }
        log.error(error);
      }
    });
  }
  async bindPrimaryEthereumSigningProxy(ethereumProvider, connectorName) {
    var _this$primaryConnecto2, _this$currentChain5, _accountAbstractionCo;
    if (!this.commonJRPCProvider) throw WalletInitializationError.notFound(`CommonJrpcProvider not found`);
    const primaryConnectorProvider = connectorName === this.primaryConnectorName ? (_this$primaryConnecto2 = this.primaryConnector) === null || _this$primaryConnecto2 === void 0 ? void 0 : _this$primaryConnecto2.provider : null;
    const baseEthereumProvider = ethereumProvider === this.commonJRPCProvider || ethereumProvider === this.aaProvider ? primaryConnectorProvider !== null && primaryConnectorProvider !== void 0 ? primaryConnectorProvider : ethereumProvider : ethereumProvider;
    // For WalletConnect v2, bind the provider wrapper: its inner `.provider` is a
    // per-chain engine that is replaced on every chain switch and never emits events,
    // so binding it leaves commonJRPCProvider on the connect-time chain forever.
    let finalProvider = connectorName === WALLET_CONNECTORS.WALLET_CONNECT_V2 ? baseEthereumProvider : (baseEthereumProvider === null || baseEthereumProvider === void 0 ? void 0 : baseEthereumProvider.provider) || baseEthereumProvider;
    const {
      accountAbstractionConfig
    } = this.coreOptions;
    const is7702 = (accountAbstractionConfig === null || accountAbstractionConfig === void 0 ? void 0 : accountAbstractionConfig.smartAccountEipStandard) === SMART_ACCOUNT_EIP_STANDARD["EIP_7702"];
    const isAaSupportedForCurrentChain = ((_this$currentChain5 = this.currentChain) === null || _this$currentChain5 === void 0 ? void 0 : _this$currentChain5.chainNamespace) === CHAIN_NAMESPACES.EIP155 && (accountAbstractionConfig === null || accountAbstractionConfig === void 0 || (_accountAbstractionCo = accountAbstractionConfig.chains) === null || _accountAbstractionCo === void 0 ? void 0 : _accountAbstractionCo.some(chain => {
      var _this$currentChain6;
      return chain.chainId === ((_this$currentChain6 = this.currentChain) === null || _this$currentChain6 === void 0 ? void 0 : _this$currentChain6.chainId);
    }));

    // setup AA provider if AA is enabled (skip for EIP-7702; 7702 uses EOA + 5792/7702 RPC only)
    // Skip AA wrapping for Base Account as it's already a smart account provider
    if (!is7702 && isAaSupportedForCurrentChain && (connectorName === WALLET_CONNECTORS.AUTH || this.coreOptions.useAAWithExternalWallet && connectorName !== WALLET_CONNECTORS.BASE_ACCOUNT)) {
      var _accountAbstractionCo2;
      const {
        accountAbstractionProvider,
        toEoaProvider
      } = await import('./providers/account-abstraction-provider/index.js');
      const eoaProvider = connectorName === WALLET_CONNECTORS.AUTH ? await toEoaProvider(baseEthereumProvider) : baseEthereumProvider;
      const aaChainIds = new Set((accountAbstractionConfig === null || accountAbstractionConfig === void 0 || (_accountAbstractionCo2 = accountAbstractionConfig.chains) === null || _accountAbstractionCo2 === void 0 ? void 0 : _accountAbstractionCo2.map(chain => chain.chainId)) || []);
      const aaProvider = await accountAbstractionProvider({
        accountAbstractionConfig,
        provider: eoaProvider,
        chain: this.currentChain,
        chains: this.coreOptions.chains.filter(chain => aaChainIds.has(chain.chainId)),
        useProviderAsTransport: connectorName === WALLET_CONNECTORS.AUTH
      });
      this.aaProvider = aaProvider;
      if (connectorName !== WALLET_CONNECTORS.AUTH && this.coreOptions.useAAWithExternalWallet) {
        finalProvider = this.aaProvider;
      }
    }
    this.commonJRPCProvider.updateProviderEngineProxy(finalProvider);
  }
  getChainConfigForIsolatedConnector(chainId) {
    const chainConfig = this.coreOptions.chains.find(chain => chain.chainId === chainId);
    if (!chainConfig) {
      throw WalletInitializationError.invalidParams(`Chain config is not available for chain ${chainId}`);
    }
    return chainConfig;
  }
  async resolveInstalledDiscoveredWalletConnector(params) {
    const {
      connectorName,
      chainConfig,
      config,
      isMipdEnabled
    } = params;
    if (!isBrowser() || !isMipdEnabled) return null;
    if (chainConfig.chainNamespace === CHAIN_NAMESPACES.EIP155) {
      const {
        createMipd,
        injectedEvmConnector
      } = await import('./connectors/injected-evm-connector/index.js');
      const providerDetail = createMipd().getProviders().find(detail => normalizeWalletName(detail.info.name) === connectorName);
      if (providerDetail) {
        return injectedEvmConnector(providerDetail)(config);
      }
      return null;
    }
    if (chainConfig.chainNamespace === CHAIN_NAMESPACES.SOLANA) {
      const {
        createSolanaMipd,
        hasSolanaWalletStandardFeatures,
        walletStandardConnector
      } = await import('./connectors/injected-solana-connector/index.js');
      const wallet = createSolanaMipd().get().find(candidate => hasSolanaWalletStandardFeatures(candidate) && normalizeWalletName(candidate.name) === connectorName);
      if (wallet) {
        return walletStandardConnector(wallet)(config);
      }
    }
    return null;
  }
  async resolveDiscoveredWalletConnector(connectorName, chainId, config, effectiveProjectConfig) {
    var _this$coreOptions$mul2;
    const chainConfig = this.getChainConfigForIsolatedConnector(chainId);
    const isExternalWalletEnabled = Boolean(effectiveProjectConfig === null || effectiveProjectConfig === void 0 ? void 0 : effectiveProjectConfig.externalWalletAuth);
    const isMipdEnabled = isExternalWalletEnabled && ((_this$coreOptions$mul2 = this.coreOptions.multiInjectedProviderDiscovery) !== null && _this$coreOptions$mul2 !== void 0 ? _this$coreOptions$mul2 : true);
    const installedConnector = await this.resolveInstalledDiscoveredWalletConnector({
      connectorName,
      chainConfig,
      config,
      isMipdEnabled
    });
    if (installedConnector) {
      return installedConnector;
    }
    const isBuiltInConnectorName = Object.values(WALLET_CONNECTORS).includes(connectorName);
    const supportsWalletConnectFallback = chainConfig.chainNamespace === CHAIN_NAMESPACES.EIP155 || chainConfig.chainNamespace === CHAIN_NAMESPACES.SOLANA;

    // Named discovered wallets (for example Phantom) can reuse WalletConnect as a transport fallback
    // when an injected connector for the target chain namespace is unavailable.
    if (!isBuiltInConnectorName && isExternalWalletEnabled && supportsWalletConnectFallback) {
      const {
        walletConnectV2Connector
      } = await import('./connectors/wallet-connect-v2-connector/index.js');
      return walletConnectV2Connector()(config);
    }
    throw AccountLinkingError.unsupportedConnector(`Connector "${connectorName}" does not support automatic wallet linking. ` + `Use ${WALLET_CONNECTORS.METAMASK}, ${WALLET_CONNECTORS.WALLET_CONNECT_V2}, or an installed compatible wallet.`);
  }

  /**
   * Create a new connector instance that is NOT registered in this.connectors and NOT
   * subscribed to the main SDK event loop. Its lifecycle events are therefore isolated
   * and will not mutate any global SDK state (connectedConnectorName, connection, idToken).
   */
  async createIsolatedWalletConnector(connectorName, chainId, projectConfig) {
    var _ref8;
    const effectiveProjectConfig = (_ref8 = projectConfig !== null && projectConfig !== void 0 ? projectConfig : this.projectConfig) !== null && _ref8 !== void 0 ? _ref8 : undefined;
    const config = {
      projectConfig: effectiveProjectConfig,
      coreOptions: this.coreOptions,
      analytics: this.analytics
    };
    let connector;
    switch (connectorName) {
      case WALLET_CONNECTORS.METAMASK:
        connector = metaMaskConnector()(config);
        break;
      case WALLET_CONNECTORS.WALLET_CONNECT_V2:
        {
          const {
            walletConnectV2Connector
          } = await import('./connectors/wallet-connect-v2-connector/index.js');
          connector = walletConnectV2Connector()(config);
          break;
        }
      case WALLET_CONNECTORS.AUTH:
        throw AccountLinkingError.unsupportedConnector(`Connector "${connectorName}" does not support automatic wallet linking.`);
      default:
        {
          connector = await this.resolveDiscoveredWalletConnector(connectorName, chainId, config, effectiveProjectConfig);
          break;
        }
    }

    // Init the isolated connector WITHOUT subscribing to the main event loop.
    // This is the key difference from setupConnector(), which calls subscribeToConnectorEvents().
    // autoConnect: false ensures the connector does not attempt to rehydrate a previous session.
    await connector.init({
      chainId,
      autoConnect: false
    });
    return connector;
  }
  async setState(newState) {
    this.state = _objectSpread(_objectSpread({}, this.state), newState);
    await this.storage.set(WEB3AUTH_STATE_STORAGE_KEY, JSON.stringify(this.state));
  }
  async loadState(initialState) {
    if (initialState) {
      this.state = _objectSpread(_objectSpread({}, this.state), initialState);
      return;
    }
    const state = await this.storage.get(WEB3AUTH_STATE_STORAGE_KEY);
    if (!state) return;
    this.state = deserialize(state);
  }
  getStorageMethod() {
    var _this$coreOptions$sto;
    if ((_this$coreOptions$sto = this.coreOptions.storage) !== null && _this$coreOptions$sto !== void 0 && _this$coreOptions$sto.sessionId) return this.coreOptions.storage.sessionId;
    if (this.coreOptions.ssr) return new CookieStorage({
      maxAge: this.coreOptions.sessionTime
    });
    if (storageAvailable("localStorage")) return new LocalStorageAdapter();
    return new MemoryStorage();
  }
}

export { Web3AuthNoModal };