import _objectSpread from '@babel/runtime/helpers/objectSpread2';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import { serializeError } from '@web3auth/auth';
import { Web3AuthNoModal, cloneDeep, WALLET_CONNECTORS, LOGIN_MODE, log, CONNECTOR_STATUS, sdkVersion, ANALYTICS_SDK_TYPE, withAbort, CONNECTOR_EVENTS, ANALYTICS_EVENTS, getErrorAnalyticsProperties, WalletInitializationError, fetchProjectConfig, fetchWalletRegistry, WALLET_REGISTRY_URL, CONNECTOR_CATEGORY, CONNECTOR_NAMES, CONNECTOR_NAMESPACES } from '@web3auth/no-modal';
import deepmerge from 'deepmerge';
import { defaultConnectorsModalConfig } from './config.js';
import { AUTH_PROVIDERS_NAMES, AUTH_PROVIDERS, capitalizeFirstLetter } from './ui/config.js';
import { LOGIN_MODAL_EVENTS } from './ui/interfaces.js';
import { LoginModal } from './ui/loginModal.js';
import { getUserLanguage } from './ui/utils.js';

class Web3Auth extends Web3AuthNoModal {
  constructor(options, initialState) {
    super(options, initialState);
    _defineProperty(this, "loginModal", void 0);
    _defineProperty(this, "options", void 0);
    _defineProperty(this, "modalConfig", cloneDeep(defaultConnectorsModalConfig));
    _defineProperty(this, "onInitExternalWallets", async params => {
      if (params.externalWalletsInitialized) return;
      // initialize WC connector only as other external wallets are initialized in initModal
      await this.initExternalConnectors(this.connectors.filter(x => x.name === WALLET_CONNECTORS.WALLET_CONNECT_V2), {
        externalWalletsInitialized: true,
        externalWalletsVisibility: true
      });
    });
    _defineProperty(this, "onSocialLogin", async params => {
      try {
        await this.connectTo(WALLET_CONNECTORS.AUTH, params.loginParams, LOGIN_MODE.MODAL);
      } catch (error) {
        log.error(`Error while connecting to connector: ${params.connector}`, error);
      }
    });
    _defineProperty(this, "onExternalWalletLogin", async params => {
      try {
        var _params$loginParams;
        const connector = this.getConnector(params.connector, (_params$loginParams = params.loginParams) === null || _params$loginParams === void 0 ? void 0 : _params$loginParams.chainNamespace);
        // auto-connect WalletConnect in background to generate QR code URI without interfering with user's selected connection
        const shouldStartConnectionInBackground = connector.name === WALLET_CONNECTORS.WALLET_CONNECT_V2;
        if (shouldStartConnectionInBackground) {
          const initialChain = this.getInitialChainIdForConnector(connector);
          await connector.connect({
            chainId: initialChain.chainId
          });
        } else {
          await this.connectTo(params.connector, params.loginParams, LOGIN_MODE.MODAL);
        }
      } catch (error) {
        log.error(`Error while connecting to connector: ${params.connector}`, error);
      }
    });
    _defineProperty(this, "onModalVisibility", async visibility => {
      log.debug("is login modal visible", visibility);
      this.emit(LOGIN_MODAL_EVENTS.MODAL_VISIBILITY, visibility);

      // handle WC session refresh
      const wcConnector = this.getConnector(WALLET_CONNECTORS.WALLET_CONNECT_V2);
      if (wcConnector) {
        const walletConnectStatus = wcConnector === null || wcConnector === void 0 ? void 0 : wcConnector.status;
        log.debug("trying refreshing wc session", visibility, walletConnectStatus);
        if (visibility && (walletConnectStatus === CONNECTOR_STATUS.READY || walletConnectStatus === CONNECTOR_STATUS.CONNECTING)) {
          log.debug("refreshing wc session");

          // refreshing session for wallet connect whenever modal is opened.
          try {
            const initialChain = this.getInitialChainIdForConnector(wcConnector);
            wcConnector.connect({
              chainId: initialChain.chainId
            });
          } catch (error) {
            log.error(`Error while disconnecting to wallet connect in core`, error);
          }
        }
        if (!visibility && this.status === CONNECTOR_STATUS.CONNECTED && (walletConnectStatus === CONNECTOR_STATUS.READY || walletConnectStatus === CONNECTOR_STATUS.CONNECTING)) {
          log.debug("this stops wc connector from trying to reconnect once proposal expires");
          wcConnector.status = CONNECTOR_STATUS.READY;
        }
      }
    });
    _defineProperty(this, "getChainNamespaces", () => {
      var _this$coreOptions$cha;
      return [...new Set(((_this$coreOptions$cha = this.coreOptions.chains) === null || _this$coreOptions$cha === void 0 ? void 0 : _this$coreOptions$cha.map(x => x.chainNamespace)) || [])];
    });
    this.options = _objectSpread({}, options);
    if (!this.options.uiConfig) this.options.uiConfig = {};
    if (this.options.modalConfig) this.modalConfig = this.options.modalConfig;
    log.info("modalConfig", this.modalConfig);
  }
  async init(options) {
    // init analytics
    const startTime = Date.now();
    this.analytics.init();
    this.analytics.identify(this.options.clientId, {
      web3auth_client_id: this.options.clientId,
      web3auth_network: this.options.web3AuthNetwork
    });
    this.analytics.setGlobalProperties({
      dapp_url: window.location.origin,
      sdk_name: ANALYTICS_SDK_TYPE.WEB_MODAL,
      sdk_version: sdkVersion,
      // Required for organization analytics
      web3auth_client_id: this.options.clientId,
      web3auth_network: this.options.web3AuthNetwork
    });
    let trackData = {};
    try {
      var _authConnector$authIn, _this$coreOptions$uiC;
      const {
        signal
      } = options || {};
      super.checkInitRequirements();
      // get project config and wallet registry
      const {
        projectConfig,
        walletRegistry
      } = await this.getProjectAndWalletConfig();

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

      // init login modal
      const {
        filteredWalletRegistry,
        disabledExternalWallets
      } = this.filterWalletRegistry(walletRegistry, projectConfig);
      this.loginModal = new LoginModal(_objectSpread(_objectSpread({}, this.options.uiConfig), {}, {
        connectorListener: this,
        web3authClientId: this.options.clientId,
        web3authNetwork: this.options.web3AuthNetwork,
        authBuildEnv: this.options.authBuildEnv,
        chainNamespaces: this.getChainNamespaces(),
        walletRegistry: filteredWalletRegistry,
        analytics: this.analytics
      }), {
        onInitExternalWallets: this.onInitExternalWallets,
        onSocialLogin: this.onSocialLogin,
        onExternalWalletLogin: this.onExternalWalletLogin,
        onModalVisibility: this.onModalVisibility
      });
      await withAbort(() => this.loginModal.initModal(), signal);

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

      // initialize connectors
      this.on(CONNECTOR_EVENTS.CONNECTORS_UPDATED, ({
        connectors: newConnectors
      }) => {
        const onAbortHandler = () => {
          var _this$connectors;
          log.debug("init aborted");
          if (((_this$connectors = this.connectors) === null || _this$connectors === void 0 ? void 0 : _this$connectors.length) > 0) {
            super.cleanup();
          }
        };
        withAbort(() => this.initConnectors({
          connectors: newConnectors,
          projectConfig,
          disabledExternalWallets
        }), signal, onAbortHandler);
      });
      await withAbort(() => super.loadConnectors({
        projectConfig,
        modalMode: true
      }), signal);

      // initialize plugins
      await withAbort(() => super.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;
    }
  }
  async connect() {
    if (!this.loginModal) throw WalletInitializationError.notReady("Login modal is not initialized");
    // if already connected return provider
    if (this.connectedConnectorName && this.status === CONNECTOR_STATUS.CONNECTED && this.provider) return this.provider;
    this.loginModal.open();
    return new Promise((resolve, reject) => {
      // remove all listeners when promise is resolved or rejected.
      // this is to prevent memory leaks if user clicks connect button multiple times.
      const handleConnected = () => {
        this.removeListener(CONNECTOR_EVENTS.ERRORED, handleError);
        this.removeListener(LOGIN_MODAL_EVENTS.MODAL_VISIBILITY, handleVisibility);
        return resolve(this.provider);
      };
      const handleError = err => {
        this.removeListener(CONNECTOR_EVENTS.CONNECTED, handleConnected);
        this.removeListener(LOGIN_MODAL_EVENTS.MODAL_VISIBILITY, handleVisibility);
        return reject(err);
      };
      const handleVisibility = visibility => {
        // modal is closed but user is not connected to any wallet.
        if (!visibility && this.status !== CONNECTOR_STATUS.CONNECTED) {
          this.removeListener(CONNECTOR_EVENTS.CONNECTED, handleConnected);
          this.removeListener(CONNECTOR_EVENTS.ERRORED, handleError);
          return reject(new Error("User closed the modal"));
        }
      };
      this.once(CONNECTOR_EVENTS.CONNECTED, handleConnected);
      this.once(CONNECTOR_EVENTS.ERRORED, handleError);
      this.once(LOGIN_MODAL_EVENTS.MODAL_VISIBILITY, handleVisibility);
    });
  }
  initUIConfig(projectConfig) {
    super.initUIConfig(projectConfig);
    this.options.uiConfig = deepmerge(cloneDeep(projectConfig.whitelabel || {}), this.options.uiConfig || {});
    if (!this.options.uiConfig.defaultLanguage) this.options.uiConfig.defaultLanguage = getUserLanguage(this.options.uiConfig.defaultLanguage);
    if (!this.options.uiConfig.mode) this.options.uiConfig.mode = "light";
    this.options.uiConfig = deepmerge(projectConfig.loginModal || {}, this.options.uiConfig, {
      arrayMerge: (_, sourceArray) => sourceArray
    });

    // merge login methods order from project config and user config, with user config taking precedence
    const defaultAuthConnections = projectConfig.embeddedWalletAuth.filter(x => x.isDefault).map(x => x.authConnection);
    const mergedAuthConnections = [...(this.options.uiConfig.loginMethodsOrder || []), ...defaultAuthConnections];
    const loginMethodsOrder = [];
    const authConnectionSet = new Set();
    for (const authConnection of mergedAuthConnections) {
      if (authConnectionSet.has(authConnection)) continue;
      authConnectionSet.add(authConnection);
      loginMethodsOrder.push(authConnection);
    }
    this.options.uiConfig.loginMethodsOrder = loginMethodsOrder;
  }
  getInitializationTrackData() {
    var _this$modalConfig, _this$modalConfig2, _this$modalConfig3, _this$options$uiConfi, _this$options$uiConfi2, _this$options$uiConfi3, _this$options$uiConfi4, _this$options$uiConfi5, _this$options$uiConfi6, _this$options$uiConfi7, _this$options$uiConfi8, _this$options$uiConfi9, _this$options$uiConfi0, _this$options$uiConfi1, _this$options$uiConfi10, _this$options$uiConfi11, _this$options$uiConfi12;
    return _objectSpread(_objectSpread({}, super.getInitializationTrackData()), {}, {
      modal_hide_wallet_discovery: (_this$modalConfig = this.modalConfig) === null || _this$modalConfig === void 0 ? void 0 : _this$modalConfig.hideWalletDiscovery,
      modal_connectors: Object.keys(((_this$modalConfig2 = this.modalConfig) === null || _this$modalConfig2 === void 0 ? void 0 : _this$modalConfig2.connectors) || {}),
      modal_auth_connector_login_methods: Object.keys(((_this$modalConfig3 = this.modalConfig) === null || _this$modalConfig3 === void 0 || (_this$modalConfig3 = _this$modalConfig3.connectors) === null || _this$modalConfig3 === void 0 || (_this$modalConfig3 = _this$modalConfig3[WALLET_CONNECTORS.AUTH]) === null || _this$modalConfig3 === void 0 ? void 0 : _this$modalConfig3.loginMethods) || {}),
      // UI config
      ui_login_methods_order: (_this$options$uiConfi = this.options.uiConfig) === null || _this$options$uiConfi === void 0 ? void 0 : _this$options$uiConfi.loginMethodsOrder,
      ui_modal_z_index: (_this$options$uiConfi2 = this.options.uiConfig) === null || _this$options$uiConfi2 === void 0 ? void 0 : _this$options$uiConfi2.modalZIndex,
      ui_display_errors_on_modal: (_this$options$uiConfi3 = this.options.uiConfig) === null || _this$options$uiConfi3 === void 0 ? void 0 : _this$options$uiConfi3.displayErrorsOnModal,
      ui_login_grid_col: (_this$options$uiConfi4 = this.options.uiConfig) === null || _this$options$uiConfi4 === void 0 ? void 0 : _this$options$uiConfi4.loginGridCol,
      ui_primary_button: (_this$options$uiConfi5 = this.options.uiConfig) === null || _this$options$uiConfi5 === void 0 ? void 0 : _this$options$uiConfi5.primaryButton,
      ui_modal_widget_type: (_this$options$uiConfi6 = this.options.uiConfig) === null || _this$options$uiConfi6 === void 0 ? void 0 : _this$options$uiConfi6.widgetType,
      ui_modal_target_id_used: Boolean((_this$options$uiConfi7 = this.options.uiConfig) === null || _this$options$uiConfi7 === void 0 ? void 0 : _this$options$uiConfi7.targetId),
      ui_modal_logo_alignment: (_this$options$uiConfi8 = this.options.uiConfig) === null || _this$options$uiConfi8 === void 0 ? void 0 : _this$options$uiConfi8.logoAlignment,
      ui_modal_border_radius_type: (_this$options$uiConfi9 = this.options.uiConfig) === null || _this$options$uiConfi9 === void 0 ? void 0 : _this$options$uiConfi9.borderRadiusType,
      ui_modal_button_radius_type: (_this$options$uiConfi0 = this.options.uiConfig) === null || _this$options$uiConfi0 === void 0 ? void 0 : _this$options$uiConfi0.buttonRadiusType,
      ui_modal_sign_in_methods: (_this$options$uiConfi1 = this.options.uiConfig) === null || _this$options$uiConfi1 === void 0 ? void 0 : _this$options$uiConfi1.signInMethods,
      ui_modal_add_previous_login_hint: (_this$options$uiConfi10 = this.options.uiConfig) === null || _this$options$uiConfi10 === void 0 ? void 0 : _this$options$uiConfi10.addPreviousLoginHint,
      ui_modal_display_installed_external_wallets: (_this$options$uiConfi11 = this.options.uiConfig) === null || _this$options$uiConfi11 === void 0 ? void 0 : _this$options$uiConfi11.displayInstalledExternalWallets,
      ui_modal_display_external_wallets_count: (_this$options$uiConfi12 = this.options.uiConfig) === null || _this$options$uiConfi12 === void 0 ? void 0 : _this$options$uiConfi12.displayExternalWalletsCount
    });
  }
  filterWalletRegistry(walletRegistry, projectConfig) {
    const {
      disableAllRecommendedWallets,
      disableAllOtherWallets,
      disabledWallets
    } = projectConfig.externalWalletAuth || {};

    // add disabled wallets to set
    const disabledExternalWallets = new Set(disabledWallets || []);
    if (disableAllRecommendedWallets) {
      Object.keys(walletRegistry.default).forEach(wallet => disabledExternalWallets.add(wallet));
    }
    if (disableAllOtherWallets) {
      Object.keys(walletRegistry.others).forEach(wallet => disabledExternalWallets.add(wallet));
    }
    // always show MetaMask, force enable it
    disabledExternalWallets.delete(WALLET_CONNECTORS.METAMASK);

    // remove wallets that are disabled in project config from wallet registry
    const filteredWalletRegistry = cloneDeep(walletRegistry);
    disabledExternalWallets.forEach(wallet => {
      delete filteredWalletRegistry.default[wallet];
      delete filteredWalletRegistry.others[wallet];
    });
    return {
      disabledExternalWallets,
      filteredWalletRegistry
    };
  }
  async getProjectAndWalletConfig() {
    var _this$options$account, _this$modalConfig4;
    const [projectConfigResult, walletRegistryResult] = await Promise.allSettled([fetchProjectConfig({
      clientId: this.options.clientId,
      web3AuthNetwork: this.options.web3AuthNetwork,
      aaProvider: (_this$options$account = this.options.accountAbstractionConfig) === null || _this$options$account === void 0 ? void 0 : _this$options$account.smartAccountType,
      authBuildEnv: this.options.authBuildEnv
    }), fetchWalletRegistry(WALLET_REGISTRY_URL)]);

    // handle project config result
    if (projectConfigResult.status === "rejected") {
      const error = await serializeError(projectConfigResult.reason);
      log.error("Failed to fetch project configurations", error);
      throw WalletInitializationError.notReady("failed to fetch project configurations", error);
    }
    const projectConfig = projectConfigResult.value;

    // handle wallet registry result
    let walletRegistry = {
      others: {},
      default: {}
    };
    const isExternalWalletEnabled = Boolean(projectConfig.externalWalletAuth);
    if (isExternalWalletEnabled && !((_this$modalConfig4 = this.modalConfig) !== null && _this$modalConfig4 !== void 0 && _this$modalConfig4.hideWalletDiscovery)) {
      if (walletRegistryResult.status === "fulfilled") {
        walletRegistry = walletRegistryResult.value;
      } else {
        log.error("Failed to fetch wallet registry", walletRegistryResult.reason);
      }
    }
    return {
      projectConfig,
      walletRegistry
    };
  }
  async initConnectors({
    connectors,
    projectConfig,
    disabledExternalWallets
  }) {
    // filter connectors based on config
    const filteredConnectorNames = await this.filterConnectors({
      projectConfig,
      disabledExternalWallets
    });

    // initialize connectors based on availability
    const {
      hasInAppConnectors,
      hasExternalConnectors
    } = await this.checkConnectorAvailability(filteredConnectorNames);
    const filteredConnectors = connectors.filter(x => filteredConnectorNames.includes(x.name));

    // initialize in-app and cached connector (if there are only external connectors enabled)
    await this.initInAppAndCachedConnectors(filteredConnectors);
    if (hasExternalConnectors) {
      if (hasInAppConnectors) {
        // show connect button if both in-app and external wallets are available
        this.loginModal.initExternalWalletContainer();
        // initialize installed external wallets (except WC), don't mark external wallets as fully initialized
        this.initExternalConnectors(filteredConnectors.filter(x => x.type === CONNECTOR_CATEGORY.EXTERNAL && x.name !== WALLET_CONNECTORS.WALLET_CONNECT_V2), {
          externalWalletsInitialized: false,
          showExternalWalletsOnly: false,
          externalWalletsVisibility: false
        });
      } else {
        // if no in app wallet is available then initialize all external wallets in modal
        await this.initExternalConnectors(filteredConnectors.filter(x => x.type === CONNECTOR_CATEGORY.EXTERNAL), {
          externalWalletsInitialized: true,
          showExternalWalletsOnly: true,
          externalWalletsVisibility: true
        });
      }
    }

    // emit ready event if connector is ready
    if (this.status === CONNECTOR_STATUS.NOT_READY) {
      this.status = CONNECTOR_STATUS.READY;
      this.emit(CONNECTOR_EVENTS.READY);
    }
  }
  async filterConnectors({
    projectConfig,
    disabledExternalWallets
  }) {
    var _this$modalConfig5;
    // Auth connector config: populate this with the default config for auth connectors.
    const loginMethods = {};
    const embedWalletConfigMap = new Map();
    for (const authConnectionConfig of projectConfig.embeddedWalletAuth || []) {
      const {
        isDefault,
        authConnection,
        groupedAuthConnectionId,
        authConnectionId
      } = authConnectionConfig;
      if (isDefault) {
        loginMethods[authConnection] = {
          name: AUTH_PROVIDERS_NAMES[authConnection],
          authConnection: authConnection,
          authConnectionId: authConnectionId,
          groupedAuthConnectionId: groupedAuthConnectionId,
          extraLoginOptions: authConnectionConfig.jwtParameters,
          isDefault: true,
          showOnModal: true
        };
      }
      const id = this.getCombinedConnectionId(authConnectionId, groupedAuthConnectionId);
      embedWalletConfigMap.set(id, authConnectionConfig);
    }
    const dashboardConnectorConfig = {
      [WALLET_CONNECTORS.AUTH]: {
        label: WALLET_CONNECTORS.AUTH,
        loginMethods
      }
    };

    // populate the user config data with the dashboard config.
    if ((_this$modalConfig5 = this.modalConfig) !== null && _this$modalConfig5 !== void 0 && (_this$modalConfig5 = _this$modalConfig5.connectors) !== null && _this$modalConfig5 !== void 0 && _this$modalConfig5[WALLET_CONNECTORS.AUTH]) {
      if (!this.modalConfig.connectors[WALLET_CONNECTORS.AUTH].loginMethods) this.modalConfig.connectors[WALLET_CONNECTORS.AUTH].loginMethods = {};
    }
    const authProviders = new Set(AUTH_PROVIDERS);
    Object.keys(this.modalConfig.connectors[WALLET_CONNECTORS.AUTH].loginMethods).forEach(key => {
      const userConfig = this.modalConfig.connectors[WALLET_CONNECTORS.AUTH].loginMethods[key];
      const {
        authConnectionId,
        groupedAuthConnectionId
      } = userConfig;
      if (!authProviders.has(key)) {
        throw WalletInitializationError.invalidParams(`Invalid auth connection: ${key}`);
      }

      // only throw error if one of them is defined in the config.
      if (groupedAuthConnectionId || authConnectionId) {
        const id = this.getCombinedConnectionId(authConnectionId, groupedAuthConnectionId);
        if (!embedWalletConfigMap.has(id)) throw WalletInitializationError.invalidParams(`Invalid auth connection config, authConnection: ${key}. Missing AuthConnectionConfig from the dashboard.`);
        const configFromDashboard = embedWalletConfigMap.get(id);
        this.modalConfig.connectors[WALLET_CONNECTORS.AUTH].loginMethods[key] = _objectSpread(_objectSpread({}, userConfig), {}, {
          authConnection: configFromDashboard.authConnection,
          authConnectionId: configFromDashboard.authConnectionId,
          groupedAuthConnectionId: configFromDashboard.groupedAuthConnectionId,
          isDefault: configFromDashboard.isDefault || false,
          extraLoginOptions: _objectSpread(_objectSpread({}, configFromDashboard.jwtParameters), userConfig.extraLoginOptions)
        });
      }
    });
    this.modalConfig.connectors = deepmerge(dashboardConnectorConfig, cloneDeep(this.modalConfig.connectors || {}));

    // merge default connectors with the custom configured connectors.
    const allConnectorNames = [...new Set([...Object.keys(this.modalConfig.connectors || {}), ...this.connectors.map(connector => connector.name)])];
    const connectorNames = allConnectorNames.map(connectorName => {
      var _this$modalConfig6, _this$modalConfig$con, _this$modalConfig$con2;
      // start with the default config of connector.
      const defaultConnectorConfig = {
        label: CONNECTOR_NAMES[connectorName] || connectorName.split("-").map(capitalizeFirstLetter).join(" "),
        showOnModal: true
      };
      this.modalConfig.connectors[connectorName] = _objectSpread(_objectSpread({}, defaultConnectorConfig), ((_this$modalConfig6 = this.modalConfig) === null || _this$modalConfig6 === void 0 || (_this$modalConfig6 = _this$modalConfig6.connectors) === null || _this$modalConfig6 === void 0 ? void 0 : _this$modalConfig6[connectorName]) || {});

      // check if connector is configured/added by user and exist in connectors map.
      const connector = this.getConnector(connectorName);
      log.debug("connector config", connectorName, (_this$modalConfig$con = this.modalConfig.connectors) === null || _this$modalConfig$con === void 0 || (_this$modalConfig$con = _this$modalConfig$con[connectorName]) === null || _this$modalConfig$con === void 0 ? void 0 : _this$modalConfig$con.showOnModal, connector);

      // check if connector is configured/added by user and exist in connectors map.
      const connectorConfig = (_this$modalConfig$con2 = this.modalConfig.connectors) === null || _this$modalConfig$con2 === void 0 ? void 0 : _this$modalConfig$con2[connectorName];
      if (!connector) {
        if (connectorConfig.showOnModal) throw WalletInitializationError.invalidParams(`Connector ${connectorName} is not configured`);
        return;
      }

      // skip connector if it is hidden by user
      if (!connectorConfig.showOnModal) return;

      // skip external connector if external wallets are disabled except for MetaMask
      const isExternalWalletEnabled = Boolean(projectConfig.externalWalletAuth);
      if (connector.type === CONNECTOR_CATEGORY.EXTERNAL && connector.name !== WALLET_CONNECTORS.METAMASK) {
        if (!isExternalWalletEnabled) return;
        if (disabledExternalWallets.has(connectorName)) return;
      }

      // skip WC connector if external wallets are disabled or hideWalletDiscovery is true
      if (connectorName === WALLET_CONNECTORS.WALLET_CONNECT_V2) {
        var _this$modalConfig7;
        if (!isExternalWalletEnabled) return;
        if ((_this$modalConfig7 = this.modalConfig) !== null && _this$modalConfig7 !== void 0 && _this$modalConfig7.hideWalletDiscovery) return;
      }
      this.modalConfig.connectors[connectorName] = connectorConfig;
      return connectorName;
    });
    // const connectorNames = await Promise.all(connectorConfigurationPromises);
    return connectorNames.filter(name => name !== undefined);
  }
  async checkConnectorAvailability(connectorNames) {
    // currently all default in app and external wallets can be hidden or shown based on config.
    // check if in app connectors are available
    const hasInAppConnectors = this.connectors.some(connector => {
      var _this$modalConfig$con3, _this$modalConfig$con4;
      if (connector.type !== CONNECTOR_CATEGORY.IN_APP) return false;
      if (((_this$modalConfig$con3 = this.modalConfig.connectors) === null || _this$modalConfig$con3 === void 0 || (_this$modalConfig$con3 = _this$modalConfig$con3[connector.name]) === null || _this$modalConfig$con3 === void 0 ? void 0 : _this$modalConfig$con3.showOnModal) !== true) return false;
      if (!((_this$modalConfig$con4 = this.modalConfig.connectors) !== null && _this$modalConfig$con4 !== void 0 && (_this$modalConfig$con4 = _this$modalConfig$con4[connector.name]) !== null && _this$modalConfig$con4 !== void 0 && _this$modalConfig$con4.loginMethods)) return true;
      if (Object.values(this.modalConfig.connectors[connector.name].loginMethods).some(method => method.showOnModal)) return true;
      return false;
    });
    log.debug(hasInAppConnectors, this.connectors, connectorNames, "hasInAppWallets");

    // check if external connectors are available
    const hasExternalConnectors = connectorNames.some(connectorName => {
      var _this$getConnector, _this$modalConfig$con5;
      if (connectorName === WALLET_CONNECTORS.WALLET_CONNECT_V2) return true;
      return ((_this$getConnector = this.getConnector(connectorName)) === null || _this$getConnector === void 0 ? void 0 : _this$getConnector.type) === CONNECTOR_CATEGORY.EXTERNAL && ((_this$modalConfig$con5 = this.modalConfig.connectors) === null || _this$modalConfig$con5 === void 0 || (_this$modalConfig$con5 = _this$modalConfig$con5[connectorName]) === null || _this$modalConfig$con5 === void 0 ? void 0 : _this$modalConfig$con5.showOnModal);
    });
    return {
      hasInAppConnectors,
      hasExternalConnectors
    };
  }
  async initInAppAndCachedConnectors(connectors) {
    await Promise.all(connectors.map(async connector => {
      const connectorName = connector.name;
      try {
        // skip if connector is already initialized
        if (connector.status !== CONNECTOR_STATUS.NOT_READY) return;

        // only initialize a external connectors here if it is a cached connector.
        if (this.cachedConnector !== connectorName && connector.type === CONNECTOR_CATEGORY.EXTERNAL) return;

        // in-app wallets or cached wallet (being connected or already connected) are initialized first.
        // if connector is configured then only initialize in app or cached connector.
        // external wallets are initialized on INIT_EXTERNAL_WALLET event.
        this.subscribeToConnectorEvents(connector);
        const initialChain = this.getInitialChainIdForConnector(connector);
        const autoConnect = super.checkIfAutoConnect(connector);
        await connector.init({
          autoConnect,
          chainId: initialChain.chainId
        });

        // note: not adding cachedWallet to modal if it is external wallet.
        // adding it later if no in-app wallets are available.
        if (connector.type === CONNECTOR_CATEGORY.IN_APP) {
          var _this$modalConfig$con6, _this$options$uiConfi13, _this$options$uiConfi14, _this$options$uiConfi15;
          log.info("connectorInitResults", connectorName);
          const loginMethods = ((_this$modalConfig$con6 = this.modalConfig.connectors[connectorName]) === null || _this$modalConfig$con6 === void 0 ? void 0 : _this$modalConfig$con6.loginMethods) || {};
          this.loginModal.addSocialLogins(connectorName, loginMethods, ((_this$options$uiConfi13 = this.options.uiConfig) === null || _this$options$uiConfi13 === void 0 ? void 0 : _this$options$uiConfi13.loginMethodsOrder) || AUTH_PROVIDERS, _objectSpread(_objectSpread({}, this.options.uiConfig), {}, {
            loginGridCol: ((_this$options$uiConfi14 = this.options.uiConfig) === null || _this$options$uiConfi14 === void 0 ? void 0 : _this$options$uiConfi14.loginGridCol) || 3,
            primaryButton: ((_this$options$uiConfi15 = this.options.uiConfig) === null || _this$options$uiConfi15 === void 0 ? void 0 : _this$options$uiConfi15.primaryButton) || "socialLogin"
          }));
        }
      } catch (error) {
        log.error(error, "error while initializing connector ", connectorName);
      }
    }));
  }
  async initExternalConnectors(externalConnectors, options) {
    const connectorsConfig = {};
    const connectorChainNamespaceMap = {};

    // we do it like this because we don't want one slow connector to delay the load of the entire external wallet section.
    externalConnectors.forEach(async connector => {
      const connectorName = connector.name;
      log.debug("init external wallet", this.cachedConnector, connectorName, connector.status);

      // a wallet can support multiple chain namespaces e.g. Phantom has EvmInjected connector and WalletStandard connector.
      if (!connectorChainNamespaceMap[connectorName]) connectorChainNamespaceMap[connectorName] = new Set();
      if (connector.connectorNamespace === CONNECTOR_NAMESPACES.MULTICHAIN) {
        this.getChainNamespaces().forEach(x => connectorChainNamespaceMap[connectorName].add(x));
      } else {
        connectorChainNamespaceMap[connectorName].add(connector.connectorNamespace);
      }

      // initialize connectors
      // skip initializing cached connector here as it is already being initialized in initModal before.
      if (connector.status === CONNECTOR_STATUS.NOT_READY && this.cachedConnector !== connectorName) {
        try {
          this.subscribeToConnectorEvents(connector);
          const initialChain = this.getInitialChainIdForConnector(connector);
          await connector.init({
            autoConnect: this.cachedConnector === connectorName,
            chainId: initialChain.chainId
          });
        } catch (error) {
          log.error(error, "error while initializing connector", connectorName);
        }
      }

      // update connector config
      if ([CONNECTOR_STATUS.NOT_READY, CONNECTOR_STATUS.READY, CONNECTOR_STATUS.CONNECTING, CONNECTOR_STATUS.CONNECTED].includes(connector.status)) {
        const connectorModalConfig = this.modalConfig.connectors[connectorName];
        connectorsConfig[connectorName] = _objectSpread(_objectSpread({}, connectorModalConfig), {}, {
          isInjected: connector.isInjected,
          icon: connector.icon,
          chainNamespaces: Array.from(connectorChainNamespaceMap[connectorName])
        });
        this.loginModal.addWalletLogins(connectorsConfig, {
          showExternalWalletsOnly: !!options.showExternalWalletsOnly,
          externalWalletsVisibility: !!options.externalWalletsVisibility,
          externalWalletsInitialized: !!options.externalWalletsInitialized
        });
      }
    });
  }
  getCombinedConnectionId(authConnectionId, groupedAuthConnectionId) {
    let id = authConnectionId;
    if (groupedAuthConnectionId) {
      id = `${groupedAuthConnectionId}_${authConnectionId}`;
    }
    return id;
  }
}

export { Web3Auth };
