@web3auth/ui
Version:
Ui modal for web3Auth
274 lines (267 loc) • 13.7 kB
JavaScript
'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;