UNPKG

@web3auth/no-modal

Version:
582 lines (578 loc) 28.2 kB
'use strict'; var _objectSpread = require('@babel/runtime/helpers/objectSpread2'); var _defineProperty = require('@babel/runtime/helpers/defineProperty'); var connectEvm = require('@metamask/connect-evm'); var connectMultichain = require('@metamask/connect-multichain'); var connectSolana = require('@metamask/connect-solana'); var baseControllers = require('@toruslabs/base-controllers'); var metadataHelpers = require('@toruslabs/metadata-helpers'); var features = require('@wallet-standard/features'); var wsEmbed = require('@web3auth/ws-embed'); var siwe = require('viem/siwe'); var analytics = require('../../base/analytics.js'); var IChainInterface = require('../../base/chain/IChainInterface.js'); var baseConnector = require('../../base/connector/baseConnector.js'); require('../../base/connector/connectorStatus.js'); var constants = require('../../base/connector/constants.js'); require('@web3auth/auth'); require('jwt-decode'); require('../../base/constants.js'); var index$1 = require('../../base/errors/index.js'); var loglevel = require('../../base/loglevel.js'); require('../../base/plugin/errors.js'); require('../../base/plugin/IPlugin.js'); var utils = require('../../base/utils.js'); var index = require('../../base/wallet/index.js'); var utils$1 = require('../utils.js'); var solana = require('../../base/wallet/solana.js'); // `@metamask/connect-evm` announces its SDK-backed provider over EIP-6963 with this // RDNS value. Web3Auth uses the dedicated `metaMaskConnector` for MetaMask, so MIPD // discovery should ignore this provider to avoid treating the QR/deeplink transport // as a native injected wallet. const METAMASK_ERC_6963_PROVIDER_RDNS = "io.metamask.mmc"; class MetaMaskConnector extends baseConnector.BaseConnector { constructor(connectorOptions) { super(connectorOptions); _defineProperty(this, "connectorNamespace", IChainInterface.CONNECTOR_NAMESPACES.MULTICHAIN); _defineProperty(this, "currentChainNamespace", baseControllers.CHAIN_NAMESPACES.OTHER); _defineProperty(this, "type", constants.CONNECTOR_CATEGORY.EXTERNAL); _defineProperty(this, "name", index.WALLET_CONNECTORS.METAMASK); _defineProperty(this, "status", constants.CONNECTOR_STATUS.NOT_READY); _defineProperty(this, "evmClient", null); _defineProperty(this, "evmProvider", null); _defineProperty(this, "solanaClient", null); _defineProperty(this, "solanaProvider", null); _defineProperty(this, "initializationPromise", null); _defineProperty(this, "multichainClient", null); _defineProperty(this, "connectorSettings", void 0); _defineProperty(this, "analytics", void 0); this.connectorSettings = connectorOptions.connectorSettings; this.analytics = connectorOptions.analytics; } get provider() { if (this.status !== constants.CONNECTOR_STATUS.NOT_READY && this.evmProvider) { return this.evmProvider; } return null; } get solanaWallet() { return this.solanaProvider; } async init(options) { var _this$connectorSettin, _this$connectorSettin2, _this$connectorSettin3, _this$connectorSettin4, _this$connectorSettin5, _this$connectorSettin6, _this$connectorSettin7, _this$connectorSettin8, _this$connectorSettin9; const chainConfig = this.coreOptions.chains.find(x => x.chainId === options.chainId); super.checkInitializationRequirements({ chainConfig }); // Build supported networks in CAIP-2 format for multichain client const caipSupportedNetworks = {}; for (const chain of this.coreOptions.chains) { caipSupportedNetworks[utils.getCaipChainId(chain)] = chain.rpcTarget; } // Build supported networks in hex format for EVM client const hexSupportedNetworks = {}; for (const chain of this.coreOptions.chains) { if (chain.chainNamespace === baseControllers.CHAIN_NAMESPACES.EIP155) { hexSupportedNetworks[chain.chainId] = chain.rpcTarget; } } // Build supported networks for Solana client (MetaMask expects mainnet | testnet | devnet keys) const solanaSupportedNetworks = {}; for (const chain of this.coreOptions.chains) { if (chain.chainNamespace !== baseControllers.CHAIN_NAMESPACES.SOLANA) continue; const solanaChainId = solana.getSolanaChainByChainConfig(chain); if (!solanaChainId) continue; const networkName = solanaChainId.split(":")[1]; if (networkName) solanaSupportedNetworks[networkName] = chain.rpcTarget; } // Detect app metadata const appName = utils$1.getSiteName(window) || ((_this$connectorSettin = this.connectorSettings) === null || _this$connectorSettin === void 0 || (_this$connectorSettin = _this$connectorSettin.dapp) === null || _this$connectorSettin === void 0 ? void 0 : _this$connectorSettin.name) || "web3auth"; const appUrl = ((_this$connectorSettin2 = this.connectorSettings) === null || _this$connectorSettin2 === void 0 || (_this$connectorSettin2 = _this$connectorSettin2.dapp) === null || _this$connectorSettin2 === void 0 ? void 0 : _this$connectorSettin2.url) || window.location.origin || "https://web3auth.io"; const appIconUrl = (_this$connectorSettin3 = this.connectorSettings) === null || _this$connectorSettin3 === void 0 || (_this$connectorSettin3 = _this$connectorSettin3.dapp) === null || _this$connectorSettin3 === void 0 ? void 0 : _this$connectorSettin3.iconUrl; const dapp = _objectSpread({ name: appName, url: appUrl }, appIconUrl && { iconUrl: appIconUrl }); const ui = { preferExtension: (_this$connectorSettin4 = (_this$connectorSettin5 = this.connectorSettings) === null || _this$connectorSettin5 === void 0 || (_this$connectorSettin5 = _this$connectorSettin5.ui) === null || _this$connectorSettin5 === void 0 ? void 0 : _this$connectorSettin5.preferExtension) !== null && _this$connectorSettin4 !== void 0 ? _this$connectorSettin4 : true, showInstallModal: (_this$connectorSettin6 = (_this$connectorSettin7 = this.connectorSettings) === null || _this$connectorSettin7 === void 0 || (_this$connectorSettin7 = _this$connectorSettin7.ui) === null || _this$connectorSettin7 === void 0 ? void 0 : _this$connectorSettin7.showInstallModal) !== null && _this$connectorSettin6 !== void 0 ? _this$connectorSettin6 : false, headless: (_this$connectorSettin8 = (_this$connectorSettin9 = this.connectorSettings) === null || _this$connectorSettin9 === void 0 || (_this$connectorSettin9 = _this$connectorSettin9.ui) === null || _this$connectorSettin9 === void 0 ? void 0 : _this$connectorSettin9.headless) !== null && _this$connectorSettin8 !== void 0 ? _this$connectorSettin8 : true }; let initResolve; let initReject; this.initializationPromise = new Promise((resolve, reject) => { initResolve = resolve; initReject = reject; }); const hasEvmChains = Object.keys(hexSupportedNetworks).length > 0; const hasSolanaChains = Object.keys(solanaSupportedNetworks).length > 0; try { var _this$connectorSettin0; // Initialize the multichain client (singleton) first this.multichainClient = await connectMultichain.createMultichainClient({ dapp, api: { supportedNetworks: caipSupportedNetworks }, ui, debug: (_this$connectorSettin0 = this.connectorSettings) === null || _this$connectorSettin0 === void 0 ? void 0 : _this$connectorSettin0.debug, analytics: { integrationType: "web3auth", enabled: !this.coreOptions.disableAnalytics } }); // Listen for QR code URI from the multichain client (for mobile wallet connection) this.multichainClient.on("display_uri", uri => { if (uri) { this.updateConnectorData({ uri }); } }); // Create the EVM client only when EVM chains are configured // (createEVMClient requires at least one entry in supportedNetworks) if (hasEvmChains) { var _this$connectorSettin1; this.evmClient = await connectEvm.createEVMClient({ dapp, eventHandlers: { accountsChanged: _accounts => { if (_accounts.length === 0 && this.connected) { this.disconnect(); } }, chainChanged: _chainId => { // Keep Web3Auth state aligned with the wallet's actual EVM chain after connect/switch. this.updateConnectorData({ chainId: _chainId }); }, connect: _result => {}, disconnect: () => { if (this.connected) { this.disconnect(); } } }, api: { supportedNetworks: hexSupportedNetworks }, ui, debug: (_this$connectorSettin1 = this.connectorSettings) === null || _this$connectorSettin1 === void 0 ? void 0 : _this$connectorSettin1.debug, analytics: { integrationType: "web3auth", enabled: !this.coreOptions.disableAnalytics } }); this.evmProvider = this.evmClient.getProvider(); } // Create the Solana client only when Solana chains are configured if (hasSolanaChains) { this.solanaClient = await connectSolana.createSolanaClient({ dapp, api: { supportedNetworks: solanaSupportedNetworks }, skipAutoRegister: true, analytics: { integrationType: "web3auth", enabled: !this.coreOptions.disableAnalytics } }); this.solanaProvider = this.solanaClient.getWallet(); } this.isInjected = await connectMultichain.hasExtension(); initResolve(); } catch (error) { initReject(index$1.WalletLoginError.connectionError("Failed to initialize MetaMask Connect SDK", error)); } if (!this.multichainClient) { this.status = constants.CONNECTOR_STATUS.ERRORED; this.emit(constants.CONNECTOR_EVENTS.ERRORED, new Error("Failed to initialize MetaMask Connect.")); return; } const coreStatus = this.multichainClient.status; // only connect if the multichain client is connected and autoConnect is true (i.e during the rehydration) if (coreStatus === "connected" && options.autoConnect) { this.status = constants.CONNECTOR_STATUS.CONNECTED; this.rehydrated = true; // Force sync the chain state before connect with rehydrated state. // during rehydration, `createEVMClient` (from above) cause re-creating session for connected the evm provider, // triggering `switchChain` internally and unintentionally update the connector data with the new chain id. // This creates issue in rehydration flow, where Web3Auth connects to the incorrect chain id, not the rehydrated chain id. // Force sync the chain state with the rehydrated chain id to avoid this issue. await this.forceSyncChainState(chainConfig); this.emit(constants.CONNECTOR_EVENTS.CONNECTED, { connectorName: index.WALLET_CONNECTORS.METAMASK, reconnected: true, ethereumProvider: this.evmProvider, solanaWallet: this.solanaProvider, connectorNamespace: this.connectorNamespace }); try { await this.authorizeOrDisconnect(options.getAuthTokenInfo, options.chainId); } catch (error) { this.emit(constants.CONNECTOR_EVENTS.REHYDRATION_ERROR, error); } } else if (coreStatus === "connected" || coreStatus === "loaded" || coreStatus === "disconnected" || coreStatus === "pending") { this.status = constants.CONNECTOR_STATUS.READY; this.emit(constants.CONNECTOR_EVENTS.READY, index.WALLET_CONNECTORS.METAMASK); } else { // Something unexpected happened this.status = constants.CONNECTOR_STATUS.ERRORED; this.emit(constants.CONNECTOR_EVENTS.ERRORED, new Error("Failed to initialize MetaMask Connect.")); } } async connect({ chainId, getAuthTokenInfo, caipAccountIds: caipAccountIdsFromParams }) { super.checkConnectionRequirements(); await this.ensureInitialized(); const chainConfig = this.coreOptions.chains.find(x => x.chainId === chainId); if (!chainConfig) throw index$1.WalletLoginError.connectionError("Chain config is not available"); const scopes = this.coreOptions.chains.map(c => utils.getCaipChainId(c)); const caipAccountIds = caipAccountIdsFromParams || []; // Skip tracking for rehydration since only new connections are tracked const shouldTrack = !this.rehydrated; const startTime = Date.now(); const eventData = { connector: this.name, connector_type: this.type, is_injected: this.isInjected, chain_id: utils.getCaipChainId(chainConfig), chain_name: chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.displayName, chain_namespace: chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.chainNamespace }; try { if (this.status !== constants.CONNECTOR_STATUS.CONNECTING) { this.status = constants.CONNECTOR_STATUS.CONNECTING; this.emit(constants.CONNECTOR_EVENTS.CONNECTING, { connector: index.WALLET_CONNECTORS.METAMASK }); const evmConnectedPromise = new Promise(resolve => { if (this.evmClient.status === "connected") { resolve(); } else { var _this$evmProvider; // Wait for EVM provider to be ready (_this$evmProvider = this.evmProvider) === null || _this$evmProvider === void 0 || _this$evmProvider.once("connect", () => { resolve(); }); } }); // Connect using the multichain client await this.multichainClient.connect(scopes, caipAccountIds, { solana_accountChanged_notifications: true }); // Solana wallet-standard: `standard:events` change is not emitted from multichain // connect alone — MetamaskWallet syncs accounts via `standard:connect` → updateSession. if (this.solanaProvider) { await this.solanaProvider.features[features.StandardConnect].connect(); } // Wait for EVM provider to be ready if (this.evmProvider) { await evmConnectedPromise; } } // sync the chain state after connect // metamask might not be connected to the requested chain, so we need to sync the chain state to/from Web3Auth state after connect. await this.forceSyncChainState(chainConfig); // check if connected if (this.multichainClient.status !== "connected") { throw index$1.WalletLoginError.notConnectedError("Failed to connect with MetaMask wallet"); } this.status = constants.CONNECTOR_STATUS.CONNECTED; // Track connection events if (shouldTrack) { var _this$analytics, _this$analytics2; (_this$analytics = this.analytics) === null || _this$analytics === void 0 || _this$analytics.track(analytics.ANALYTICS_EVENTS.CONNECTION_STARTED, eventData); (_this$analytics2 = this.analytics) === null || _this$analytics2 === void 0 || _this$analytics2.track(analytics.ANALYTICS_EVENTS.CONNECTION_COMPLETED, _objectSpread(_objectSpread({}, eventData), {}, { duration: Date.now() - startTime })); } this.emit(constants.CONNECTOR_EVENTS.CONNECTED, { connectorName: index.WALLET_CONNECTORS.METAMASK, reconnected: this.rehydrated, ethereumProvider: this.evmProvider, solanaWallet: this.solanaProvider, connectorNamespace: this.connectorNamespace }); await this.authorizeOrDisconnect(getAuthTokenInfo, chainId); return { ethereumProvider: this.evmProvider, solanaWallet: this.solanaProvider, connectorName: this.name, connectorNamespace: this.connectorNamespace }; } catch (error) { // Ready again to be connected this.status = constants.CONNECTOR_STATUS.READY; if (!this.rehydrated) this.emit(constants.CONNECTOR_EVENTS.ERRORED, error); this.rehydrated = false; // Track connection events if (shouldTrack) { var _this$analytics3, _this$analytics4; (_this$analytics3 = this.analytics) === null || _this$analytics3 === void 0 || _this$analytics3.track(analytics.ANALYTICS_EVENTS.CONNECTION_STARTED, eventData); (_this$analytics4 = this.analytics) === null || _this$analytics4 === void 0 || _this$analytics4.track(analytics.ANALYTICS_EVENTS.CONNECTION_FAILED, _objectSpread(_objectSpread(_objectSpread({}, eventData), baseControllers.getErrorAnalyticsProperties(error)), {}, { duration: Date.now() - startTime })); } if (index$1.isUserRejectedError(error)) throw index$1.WalletOperationsError.userRejected(); if (error instanceof index$1.Web3AuthError) throw error; throw index$1.WalletLoginError.connectionError("Failed to login with MetaMask wallet", error); } } async disconnect(options = { cleanup: false }) { if (!this.multichainClient) throw index$1.WalletLoginError.connectionError("Multichain client is not available"); this.checkDisconnectionRequirements(); await this.clearMultichainWalletSessions(); // Disconnect using the multichain client if (this.multichainClient.status === "connected") { await this.multichainClient.disconnect(); } if (options.cleanup) { this.status = constants.CONNECTOR_STATUS.NOT_READY; this.initializationPromise = null; this.multichainClient = null; this.evmClient = null; this.evmProvider = null; this.solanaClient = null; this.solanaProvider = null; } else { // Ready to be connected again this.status = constants.CONNECTOR_STATUS.READY; } this.rehydrated = false; this.emit(constants.CONNECTOR_EVENTS.DISCONNECTED, { connector: index.WALLET_CONNECTORS.METAMASK }); } async getAuthTokenInfo(chainId) { if (!this.canAuthorize) throw index$1.WalletLoginError.notConnectedError(); // In multichain sessions both providers can exist at the same time, so auth must // follow the caller-selected chain instead of inferring from provider availability. const activeChainConfig = this.resolveAuthChainConfig(chainId); if (!activeChainConfig) throw index$1.WalletLoginError.connectionError("Chain config is not available"); const { chainNamespace } = activeChainConfig; const accounts = chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA && this.solanaProvider ? this.solanaProvider.accounts.map(a => a.address) : this.evmProvider ? await this.evmProvider.request({ method: wsEmbed.EVM_METHOD_TYPES.GET_ACCOUNTS }) : []; if (accounts && accounts.length > 0) { const cached = await this.getCachedOrNullAuthTokenInfo(accounts[0]); if (cached) return cached; } this.status = constants.CONNECTOR_STATUS.AUTHORIZING; this.emit(constants.CONNECTOR_EVENTS.AUTHORIZING, { connector: index.WALLET_CONNECTORS.METAMASK }); const authServer = utils.citadelServerUrl(this.coreOptions.authBuildEnv); const { challenge, signature } = await this.generateChallengeAndSign(authServer, accounts, activeChainConfig.chainId); return this.verifyAndAuthorize({ chainNamespace, signedMessage: signature, challenge, authServer }); } async getUserInfo() { if (!this.canAuthorize) throw index$1.WalletLoginError.notConnectedError("Not connected with wallet, Please login/connect first"); return {}; } async switchChain(params, init = false) { super.checkSwitchChainRequirements(params, init); await this.ensureInitialized(); const targetChainConfig = this.coreOptions.chains.find(c => c.chainId === params.chainId); if (!targetChainConfig) throw index$1.WalletLoginError.connectionError("Chain config is not available"); if (targetChainConfig.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA) { if (!this.solanaWallet) { throw index$1.WalletLoginError.unsupportedOperation("switchChain requires a Solana client, but no Solana chains are configured."); } // For solana case, we don't have the `switchChain` method like `evmClient`. // So, we just need to sync with the connected solana chain to the Web3Auth state. await this.forceSyncChainState(targetChainConfig); return; } if (!this.evmClient) { throw index$1.WalletLoginError.unsupportedOperation("switchChain requires an EVM client, but no EVM chains are configured."); } const chainConfiguration = targetChainConfig ? { chainId: params.chainId, chainName: targetChainConfig.displayName, rpcUrls: [targetChainConfig.rpcTarget], blockExplorerUrls: targetChainConfig.blockExplorerUrl ? [targetChainConfig.blockExplorerUrl] : undefined, nativeCurrency: { name: targetChainConfig.tickerName, symbol: targetChainConfig.ticker, decimals: targetChainConfig.decimals || 18 }, iconUrls: targetChainConfig.logo ? [targetChainConfig.logo] : undefined } : undefined; await this.evmClient.switchChain({ chainId: params.chainId, chainConfiguration }); this.updateConnectorData({ chainId: params.chainId }); } async generateChallengeAndSign(authServerUrl, accounts, chainId) { const activeChainConfig = this.resolveAuthChainConfig(chainId); if (!activeChainConfig) throw index$1.WalletLoginError.connectionError("Chain config is not available"); const { chainNamespace } = activeChainConfig; const accountsToUse = accounts || (chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA && this.solanaProvider ? this.solanaProvider.accounts.map(a => a.address) : this.evmProvider ? await this.evmProvider.request({ method: wsEmbed.EVM_METHOD_TYPES.GET_ACCOUNTS }) : []); if (!accountsToUse || accountsToUse.length === 0) { throw index$1.WalletLoginError.notConnectedError("Not connected with wallet, Please login/connect first"); } const authServer = authServerUrl || utils.citadelServerUrl(this.coreOptions.authBuildEnv); const payload = { domain: window.location.origin, uri: window.location.href, address: accountsToUse[0], chainId: parseInt(activeChainConfig.chainId, 16), version: "1", nonce: siwe.generateSiweNonce(), issuedAt: new Date().toISOString() }; const challenge = await baseControllers.signChallenge(payload, chainNamespace, authServer); let signedMessage; if (chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA && this.solanaProvider) { signedMessage = await solana.walletSignMessage(this.solanaProvider, challenge, accountsToUse[0]); } else if (this.evmProvider) { const hexChallenge = metadataHelpers.bytesToHexPrefixedString(metadataHelpers.utf8ToBytes(challenge)); signedMessage = await this.evmProvider.request({ method: wsEmbed.EVM_METHOD_TYPES.PERSONAL_SIGN, params: [hexChallenge, accountsToUse[0]] }); } else { throw index$1.WalletLoginError.notConnectedError("No provider available for signing"); } return { challenge, signature: signedMessage, chainNamespace }; } async enableMFA() { throw new Error("Method Not implemented"); } async manageMFA() { throw new Error("Method Not implemented"); } /** * Ensures the connector is initialized */ async ensureInitialized() { if (!this.initializationPromise) { throw index$1.WalletLoginError.notConnectedError("Connector is not initialized. Call init() first."); } await this.initializationPromise; } /** * Syncs the chain state with the Web3Auth state. * @param chainConfig - The chain config to sync. */ async forceSyncChainState(chainConfig) { var _this$evmProvider2; // EVM connectors can switch chains, so align the wallet with the requested chain // before Web3Auth persists the active chain in controller state. if (chainConfig.chainNamespace === baseControllers.CHAIN_NAMESPACES.EIP155 && ((_this$evmProvider2 = this.evmProvider) === null || _this$evmProvider2 === void 0 ? void 0 : _this$evmProvider2.chainId) !== chainConfig.chainId) { await this.switchChain({ chainId: chainConfig.chainId }, true); } else if (chainConfig.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA) { // For solana case, metamask connect the first available scope in priority order: mainnet > devnet > testnet. // So, if the user requested chain is different from the connected chain, // we need to update the connector data with the connected chain id to keep the Web3Auth state aligned. if ("scope" in this.solanaProvider && typeof this.solanaProvider.scope === "string") { var _this$coreOptions$cha; const connectedSolChain = this.solanaProvider.scope; const connectedChainConfig = (_this$coreOptions$cha = this.coreOptions.chains) === null || _this$coreOptions$cha === void 0 ? void 0 : _this$coreOptions$cha.find(chain => { return utils.getCaipChainId(chain) === connectedSolChain && chain.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA; }); if (!connectedChainConfig) { throw index$1.WalletLoginError.connectionError("Connected chain is not available in the chains config"); } this.updateConnectorData({ chainId: chainConfig.chainId }); } } } resolveAuthChainConfig(chainId) { var _this$evmProvider3, _this$coreOptions$cha2; if (chainId) { return this.coreOptions.chains.find(x => x.chainId === chainId); } const evmChainId = ((_this$evmProvider3 = this.evmProvider) === null || _this$evmProvider3 === void 0 ? void 0 : _this$evmProvider3.chainId) || ((_this$coreOptions$cha2 = this.coreOptions.chains.find(x => x.chainNamespace === baseControllers.CHAIN_NAMESPACES.EIP155)) === null || _this$coreOptions$cha2 === void 0 ? void 0 : _this$coreOptions$cha2.chainId); const isSolanaOnly = !this.evmProvider && !!this.solanaProvider; // Keep the old fallback for callers that do not pass a chainId yet. return isSolanaOnly ? this.coreOptions.chains.find(x => x.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA) : this.evmProvider ? this.coreOptions.chains.find(x => x.chainId === evmChainId) : undefined; } async clearMultichainWalletSessions() { const addresses = new Set(); if (this.evmProvider) { const evmAccounts = await this.evmProvider.request({ method: wsEmbed.EVM_METHOD_TYPES.GET_ACCOUNTS }); evmAccounts.forEach(account => addresses.add(account)); } if (this.solanaProvider) { this.solanaProvider.accounts.forEach(account => addresses.add(account.address)); } if (addresses.size === 0) { await this.clearWalletSession(); return; } // MetaMask can authorize both EVM and Solana accounts in one session, but BaseConnector // caches SIWW tokens under one address at a time. Clear every connected address on disconnect. for (const address of addresses) { this.initSessionManager(address); await this.clearWalletSession().catch(error => { loglevel.log.error("Failed to clear multichain wallet session", error); }); } } } /** * Factory function to create a MetaMask connector * * @param params - Configuration options for the MetaMask SDK * @returns A connector function that creates a MetaMaskConnector instance * * @example * ```typescript * const connector = metaMaskConnector({ * dapp: { name: 'My DApp', url: 'https://mydapp.com' }, * debug: true, * }); * ``` */ const metaMaskConnector = params => { return ({ coreOptions, analytics }) => { return new MetaMaskConnector({ connectorSettings: params, coreOptions, analytics }); }; }; exports.METAMASK_ERC_6963_PROVIDER_RDNS = METAMASK_ERC_6963_PROVIDER_RDNS; exports.metaMaskConnector = metaMaskConnector;