UNPKG

@web3auth/ui

Version:
274 lines (267 loc) 13.7 kB
'use strict'; var base = require('@web3auth/base'); var Bowser = require('bowser'); var React = require('react'); var reactI18next = require('react-i18next'); var interfaces = require('../interfaces.js'); var localeImport = require('../localeImport.js'); var ExternalWalletButton = require('./ExternalWallet/ExternalWalletButton.js'); var ExternalWalletDetails = require('./ExternalWallet/ExternalWalletDetails.js'); var ExternalWalletHeader = require('./ExternalWallet/ExternalWalletHeader.js'); var Loader = require('./Loader.js'); var jsxRuntime = require('react/jsx-runtime'); function formatIOSMobile(params) { const encodedUri = encodeURIComponent(params.uri); if (params.link.startsWith("http")) return `${params.link}/wc?uri=${encodedUri}`; if (params.link) return `${params.link}wc?uri=${encodedUri}`; return ""; } function ExternalWallet(props) { const { hideExternalWallets, handleExternalWalletClick, closeModal, config = {}, walletConnectUri, showBackButton, modalStatus, chainNamespace, walletRegistry } = props; const [externalButtons, setExternalButtons] = React.useState([]); const [totalExternalWallets, setTotalExternalWallets] = React.useState(0); const [selectedButton, setSelectedButton] = React.useState(null); const [walletSearch, setWalletSearch] = React.useState(""); const [t] = reactI18next.useTranslation(undefined, { i18n: localeImport }); const walletDiscoverySupported = React.useMemo(() => { const supported = walletRegistry && Object.keys(walletRegistry.default).length > 0 && Object.keys(walletRegistry.others).length > 0; return supported; }, [walletRegistry]); const deviceDetails = React.useMemo(() => { const browser = Bowser.getParser(window.navigator.userAgent); return { platform: browser.getPlatformType(), os: browser.getOSName(), browser: browser.getBrowserName().toLowerCase() }; }, []); const handleWalletSearch = e => { setWalletSearch(e.target.value); }; const adapterVisibilityMap = React.useMemo(() => { const canShowMap = {}; Object.keys(config).forEach(adapter => { const adapterConfig = config[adapter]; if (!adapterConfig.showOnModal) { canShowMap[adapter] = false; return; } if (deviceDetails.platform === "desktop" && adapterConfig.showOnDesktop) { canShowMap[adapter] = true; return; } if ((deviceDetails.platform === "mobile" || deviceDetails.platform === "tablet") && adapterConfig.showOnMobile) { canShowMap[adapter] = true; return; } canShowMap[adapter] = false; }); base.log.debug("adapter visibility map", canShowMap); return canShowMap; }, [config, deviceDetails.platform]); React.useEffect(() => { var _config$WALLET_ADAPTE; base.log.debug("loaded external wallets", config, walletConnectUri); const wcAvailable = (((_config$WALLET_ADAPTE = config[base.WALLET_ADAPTERS.WALLET_CONNECT_V2]) === null || _config$WALLET_ADAPTE === void 0 ? void 0 : _config$WALLET_ADAPTE.showOnModal) || false) !== false; if (wcAvailable && !walletConnectUri) { handleExternalWalletClick({ adapter: base.WALLET_ADAPTERS.WALLET_CONNECT_V2 }); } }, [config, handleExternalWalletClick, walletConnectUri]); React.useEffect(() => { if (walletDiscoverySupported) { const isWalletConnectAdapterIncluded = Object.keys(config).some(adapter => adapter === base.WALLET_ADAPTERS.WALLET_CONNECT_V2); const defaultButtonKeys = new Set(Object.keys(walletRegistry.default)); const generateWalletButtons = wallets => { return Object.keys(wallets).reduce((acc, wallet) => { var _config$wallet, _walletRegistryItem$w, _walletRegistryItem$c, _walletRegistryItem$i; if (adapterVisibilityMap[wallet] === false) return acc; const walletRegistryItem = wallets[wallet]; let href = ""; if (deviceDetails.platform === Bowser.PLATFORMS_MAP.mobile) { var _walletRegistryItem$m, _walletRegistryItem$m2; const universalLink = walletRegistryItem === null || walletRegistryItem === void 0 || (_walletRegistryItem$m = walletRegistryItem.mobile) === null || _walletRegistryItem$m === void 0 ? void 0 : _walletRegistryItem$m.universal; const deepLink = walletRegistryItem === null || walletRegistryItem === void 0 || (_walletRegistryItem$m2 = walletRegistryItem.mobile) === null || _walletRegistryItem$m2 === void 0 ? void 0 : _walletRegistryItem$m2.native; href = universalLink || deepLink; } const button = { name: wallet, displayName: walletRegistryItem.name, href, hasInjectedWallet: ((_config$wallet = config[wallet]) === null || _config$wallet === void 0 ? void 0 : _config$wallet.isInjected) || false, hasWalletConnect: isWalletConnectAdapterIncluded && ((_walletRegistryItem$w = walletRegistryItem.walletConnect) === null || _walletRegistryItem$w === void 0 || (_walletRegistryItem$w = _walletRegistryItem$w.sdks) === null || _walletRegistryItem$w === void 0 ? void 0 : _walletRegistryItem$w.includes("sign_v2")), hasInstallLinks: Object.keys(walletRegistryItem.app || {}).length > 0, walletRegistryItem, imgExtension: walletRegistryItem.imgExtension || "svg" }; // const isBrowserExtensionAvailable = walletRegistryItem.app?.chrome || walletRegistryItem.app?.firefox || walletRegistryItem.app?.edge; if (!button.hasInjectedWallet && !button.hasWalletConnect && !button.hasInstallLinks) return acc; const chainNamespaces = new Set((_walletRegistryItem$c = walletRegistryItem.chains) === null || _walletRegistryItem$c === void 0 ? void 0 : _walletRegistryItem$c.map(chain => chain.split(":")[0])); const injectedChainNamespaces = new Set((_walletRegistryItem$i = walletRegistryItem.injected) === null || _walletRegistryItem$i === void 0 ? void 0 : _walletRegistryItem$i.map(injected => injected.namespace)); if (!chainNamespaces.has(chainNamespace) && !injectedChainNamespaces.has(chainNamespace)) return acc; acc.push(button); return acc; }, []); }; // Generate buttons for default and other wallets const defaultButtons = generateWalletButtons(walletRegistry.default); const otherButtons = generateWalletButtons(walletRegistry.others); // Generate custom adapter buttons const customAdapterButtons = Object.keys(config).reduce((acc, adapter) => { if (![base.WALLET_ADAPTERS.WALLET_CONNECT_V2].includes(adapter) && !config[adapter].isInjected && adapterVisibilityMap[adapter]) { base.log.debug("custom adapter", adapter, config[adapter]); acc.push({ name: adapter, displayName: config[adapter].label || adapter, hasInjectedWallet: false, hasWalletConnect: false, hasInstallLinks: false }); } return acc; }, []); const allButtons = [...defaultButtons, ...otherButtons]; // Filter and set external buttons based on search input if (walletSearch) { const filteredList = allButtons.concat(customAdapterButtons).filter(button => button.name.toLowerCase().includes(walletSearch.toLowerCase())); base.log.debug("filteredLists", filteredList); setExternalButtons(filteredList); } else { const sortedButtons = [...allButtons.filter(button => button.hasInjectedWallet && defaultButtonKeys.has(button.name)), ...customAdapterButtons, ...allButtons.filter(button => !button.hasInjectedWallet && defaultButtonKeys.has(button.name))]; setExternalButtons(sortedButtons); } setTotalExternalWallets(allButtons.length + customAdapterButtons.length); base.log.debug("external buttons", allButtons); } else { const buttons = Object.keys(config).reduce((acc, adapter) => { base.log.debug("external buttons", adapter, adapterVisibilityMap[adapter]); if (![base.WALLET_ADAPTERS.WALLET_CONNECT_V2].includes(adapter) && adapterVisibilityMap[adapter]) { acc.push({ name: adapter, displayName: config[adapter].label || adapter, hasInjectedWallet: config[adapter].isInjected, hasWalletConnect: false, hasInstallLinks: false }); } return acc; }, []); setExternalButtons(buttons); setTotalExternalWallets(buttons.length); } }, [config, deviceDetails, adapterVisibilityMap, walletRegistry, walletSearch, chainNamespace, walletDiscoverySupported]); const handleWalletClick = button => { // if has injected wallet, connect to injected wallet // if doesn't have wallet connect & doesn't have install links, must be a custom adapter if (button.hasInjectedWallet || !button.hasWalletConnect && !button.hasInstallLinks) { handleExternalWalletClick({ adapter: button.name }); } else { // else, show wallet detail setSelectedButton(button); } }; return /*#__PURE__*/jsxRuntime.jsx("div", { className: `w3ajs-external-wallet w3a-group ${totalExternalWallets === 0 ? "w3a-group-loader-height" : ""}`, children: /*#__PURE__*/jsxRuntime.jsx("div", { className: "w3a-external-container w3ajs-external-container", children: totalExternalWallets === 0 ? /*#__PURE__*/jsxRuntime.jsx(Loader, { modalStatus: interfaces.MODAL_STATUS.CONNECTING, canEmit: false }) : modalStatus === interfaces.MODAL_STATUS.INITIALIZED && ( // All wallets !selectedButton ? /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [/*#__PURE__*/jsxRuntime.jsx(ExternalWalletHeader, { disableBackButton: !showBackButton, title: t("modal.external.connect-wallet"), goBack: hideExternalWallets, closeModal: closeModal }), totalExternalWallets > 15 && /*#__PURE__*/jsxRuntime.jsx("div", { className: "w3a--py-4", children: /*#__PURE__*/jsxRuntime.jsx("input", { className: "w3a--w-full w3a-text-field", name: "passwordless-input", required: true, value: walletSearch, placeholder: t("modal.external.search-wallet", { count: totalExternalWallets }), onFocus: e => { e.target.placeholder = ""; }, onBlur: e => { e.target.placeholder = t("modal.external.search-wallet", { count: totalExternalWallets }); }, onChange: e => handleWalletSearch(e) }) }), externalButtons.length === 0 ? /*#__PURE__*/jsxRuntime.jsx("div", { className: "w3a--w-full w3a--text-center w3a--text-app-gray-400 dark:w3a--text-app-gray-500 w3a--py-6 w3a--flex w3a--justify-center w3a--items-center", children: t("modal.external.no-wallets-found") }) : /*#__PURE__*/jsxRuntime.jsx("div", { className: `w3a-adapter-list-container ${totalExternalWallets < 15 ? "w3a--py-4" : ""}`, children: /*#__PURE__*/jsxRuntime.jsxs("ul", { className: "w3a-adapter-list w3ajs-wallet-adapters", children: [externalButtons.map(button => { return /*#__PURE__*/jsxRuntime.jsxs("li", { className: "w3a-adapter-item w3a-adapter-item--full", children: [deviceDetails.platform === "desktop" && /*#__PURE__*/jsxRuntime.jsx(ExternalWalletButton, { button: button, handleWalletClick: handleWalletClick }), deviceDetails.platform !== "desktop" && (button.href && button.hasWalletConnect && !button.hasInjectedWallet ? /*#__PURE__*/jsxRuntime.jsx("a", { href: button.href ? formatIOSMobile({ uri: walletConnectUri, link: button.href }) : walletConnectUri, target: "_blank", className: "w3a--w-full", rel: "noreferrer noopener", children: /*#__PURE__*/jsxRuntime.jsx(ExternalWalletButton, { button: button, handleWalletClick: handleWalletClick }) }) : /*#__PURE__*/jsxRuntime.jsx(ExternalWalletButton, { button: button, handleWalletClick: handleWalletClick }))] }, button.name + button.displayName); }), totalExternalWallets > 10 && !walletSearch && /*#__PURE__*/jsxRuntime.jsxs("li", { className: "w3a--flex w3a--flex-col w3a--items-center w3a--justify-center w3a--gap-y-0.5 w3a--my-4 w3a--w-full w3a--mx-auto w3a-adapter-item--full", children: [/*#__PURE__*/jsxRuntime.jsx("p", { className: "w3a--text-xs w3a--text-app-gray-500 dark:w3a--text-app-gray-400", children: t("modal.external.search-text") }), /*#__PURE__*/jsxRuntime.jsx("p", { className: "w3a--text-xs w3a--font-medium w3a--text-app-gray-900 dark:w3a--text-app-white", children: t("modal.external.search-subtext") })] })] }) })] }) : /*#__PURE__*/ // Wallet Detail jsxRuntime.jsx(ExternalWalletDetails, { connectButton: selectedButton, goBack: () => setSelectedButton(null), walletConnectUri: walletConnectUri, closeModal: closeModal })) }) }); } module.exports = ExternalWallet;