diff --git a/demo/vue-app-new/package-lock.json b/demo/vue-app-new/package-lock.json index 5f43c0d3c..198966700 100644 --- a/demo/vue-app-new/package-lock.json +++ b/demo/vue-app-new/package-lock.json @@ -209,6 +209,9 @@ "version": "9.0.0-alpha.5", "license": "ISC", "dependencies": { + "@walletconnect/sign-client": "^2.16.1", + "@walletconnect/types": "^2.16.1", + "@walletconnect/utils": "^2.16.1", "@web3auth/auth": "^9.3.3", "@web3auth/base": "^9.0.0-alpha.4", "@web3auth/base-evm-adapter": "^9.0.0-alpha.4", @@ -216,20 +219,12 @@ "@web3auth/ethereum-provider": "^9.0.0-alpha.5", "deepmerge": "^4.3.1" }, - "devDependencies": { - "@walletconnect/sign-client": "^2.16.1", - "@walletconnect/types": "^2.16.1", - "@walletconnect/utils": "^2.16.1" - }, "engines": { "node": ">=18.x", "npm": ">=9.x" }, "peerDependencies": { - "@babel/runtime": "^7.x", - "@walletconnect/sign-client": "^2.x", - "@walletconnect/types": "^2.x", - "@walletconnect/utils": "^2.x" + "@babel/runtime": "^7.x" } }, "../../packages/base": { diff --git a/packages/adapters/coinbase-adapter/src/coinbaseAdapter.ts b/packages/adapters/coinbase-adapter/src/coinbaseAdapter.ts index 2affe3749..d46e08221 100644 --- a/packages/adapters/coinbase-adapter/src/coinbaseAdapter.ts +++ b/packages/adapters/coinbase-adapter/src/coinbaseAdapter.ts @@ -72,7 +72,7 @@ class CoinbaseAdapter extends BaseEvmAdapter { ...this.coinbaseOptions, appChainIds: [Number.parseInt(this.chainConfig.chainId, 16)], }); - this.coinbaseProvider = this.coinbaseInstance.makeWeb3Provider({ options: this.coinbaseOptions.options || "all" }); + this.coinbaseProvider = this.coinbaseInstance.makeWeb3Provider({ options: this.coinbaseOptions.options || "smartWalletOnly" }); this.status = ADAPTER_STATUS.READY; this.emit(ADAPTER_EVENTS.READY, WALLET_ADAPTERS.COINBASE); try { diff --git a/packages/base/src/utils.ts b/packages/base/src/utils.ts index fdaf62aed..b68cbbb77 100644 --- a/packages/base/src/utils.ts +++ b/packages/base/src/utils.ts @@ -37,9 +37,10 @@ export interface WalletRegistryItem { universal?: string; inAppBrowser?: string; }; + primaryColor?: string; } -export type WalletRegistry = Record; +export type WalletRegistry = { others: Record; default: Record }; export function storageAvailable(type: "sessionStorage" | "localStorage"): boolean { let storageExists = false; diff --git a/packages/base/src/wallet/index.ts b/packages/base/src/wallet/index.ts index 5dc302830..9ab5b147a 100644 --- a/packages/base/src/wallet/index.ts +++ b/packages/base/src/wallet/index.ts @@ -30,5 +30,5 @@ export const ADAPTER_NAMES = { [MULTI_CHAIN_ADAPTERS.SFA]: "SFA", [SOLANA_ADAPTERS.TORUS_SOLANA]: "Torus", [EVM_ADAPTERS.TORUS_EVM]: "Torus", - [EVM_ADAPTERS.COINBASE]: "Coinbase", + [EVM_ADAPTERS.COINBASE]: "Coinbase Smart Wallet", }; diff --git a/packages/modal/src/modalManager.ts b/packages/modal/src/modalManager.ts index 943c25834..502371553 100644 --- a/packages/modal/src/modalManager.ts +++ b/packages/modal/src/modalManager.ts @@ -2,6 +2,7 @@ import { AuthAdapter, AuthOptions, getAuthDefaultOptions, LOGIN_PROVIDER, LoginC import { ADAPTER_CATEGORY, ADAPTER_EVENTS, + ADAPTER_NAMES, ADAPTER_STATUS, BaseAdapterConfig, cloneDeep, @@ -85,7 +86,7 @@ export class Web3Auth extends Web3AuthNoModal implements IWeb3AuthModal { if (!this.options.uiConfig.defaultLanguage) this.options.uiConfig.defaultLanguage = getUserLanguage(this.options.uiConfig.defaultLanguage); if (!this.options.uiConfig.mode) this.options.uiConfig.mode = "light"; - let walletRegistry: WalletRegistry = {}; + let walletRegistry: WalletRegistry = { others: {}, default: {} }; try { walletRegistry = await fetchWalletRegistry(walletRegistryUrl); } catch (e) { @@ -126,7 +127,7 @@ export class Web3Auth extends Web3AuthNoModal implements IWeb3AuthModal { const adapterConfigurationPromises = allAdapters.map(async (adapterName) => { // start with the default config of adapter. let adapterConfig = this.modalConfig.adapters?.[adapterName] || { - label: adapterName.split("-").map(capitalizeFirstLetter).join(" "), + label: ADAPTER_NAMES[adapterName] || adapterName.split("-").map(capitalizeFirstLetter).join(" "), showOnModal: true, showOnMobile: true, showOnDesktop: true, diff --git a/packages/ui/src/components/Button/styles.css b/packages/ui/src/components/Button/styles.css index 3fc36ab1d..e68aea957 100644 --- a/packages/ui/src/components/Button/styles.css +++ b/packages/ui/src/components/Button/styles.css @@ -41,7 +41,7 @@ a.t-btn:not(.t-btn-text) { } #w3a-modal .size-xl { height: 52px; - @apply px-6 py-3.5 text-base; + @apply px-4 py-3.5 text-base; } /* #w3a-modal .icon { @apply rounded-full; @@ -160,14 +160,14 @@ a.t-btn:not(.t-btn-text) { #w3a-modal .btn-link { @apply no-underline; } -#w3a-modal button.t-btn:hover>.hover-icon { +#w3a-modal button.t-btn:hover > .hover-icon { display: block; transition: display 150ms; transition-timing-function: cubic-bezier(0, 0.54, 0.63, 0.99); } -#w3a-modal button.t-btn:hover>.image-icon { +#w3a-modal button.t-btn:hover > .image-icon { display: none; transition: display 150ms; transition-timing-function: cubic-bezier(0, 0.54, 0.63, 0.99); -} \ No newline at end of file +} diff --git a/packages/ui/src/components/ExternalWallet/ExternalWalletButton.tsx b/packages/ui/src/components/ExternalWallet/ExternalWalletButton.tsx index 0205319a0..ac033ab2b 100644 --- a/packages/ui/src/components/ExternalWallet/ExternalWalletButton.tsx +++ b/packages/ui/src/components/ExternalWallet/ExternalWalletButton.tsx @@ -1,4 +1,3 @@ -import { BaseAdapterConfig } from "@web3auth/base"; import { useTranslation } from "react-i18next"; import { ExternalButton } from "../../interfaces"; @@ -8,12 +7,11 @@ import Image from "../Image"; interface ExternalWalletButtonProps { button: ExternalButton; - adapterConfig?: BaseAdapterConfig; handleWalletClick: (button: ExternalButton) => void; } export default function ExternalWalletButton(props: ExternalWalletButtonProps) { - const { adapterConfig, button, handleWalletClick } = props; + const { button, handleWalletClick } = props; const [t] = useTranslation(undefined, { i18n }); return ( @@ -21,12 +19,12 @@ export default function ExternalWalletButton(props: ExternalWalletButtonProps) { variant="tertiary" type="button" onClick={() => handleWalletClick(button)} - className="w-full rounded-xl size-xl flex !justify-between items-center bg-app-gray-100 hover:bg-app-gray-200 dark:bg-app-gray-700 dark:hover:bg-app-gray-800 !px-2" - title={adapterConfig?.label || button.name} + className="w-full rounded-xl size-xl flex !justify-between items-center wallet-btn" + title={button.name} >
- -

{adapterConfig?.label || button.displayName}

+ +

{button.displayName}

{button.hasInjectedWallet && ( diff --git a/packages/ui/src/components/ExternalWallet/ExternalWalletConnect.tsx b/packages/ui/src/components/ExternalWallet/ExternalWalletConnect.tsx index e128fb296..b455d716f 100644 --- a/packages/ui/src/components/ExternalWallet/ExternalWalletConnect.tsx +++ b/packages/ui/src/components/ExternalWallet/ExternalWalletConnect.tsx @@ -42,12 +42,16 @@ export default function ExternalWalletConnect(props: ExternalWalletConnectProps) {!walletConnectUri ? ( ) : ( - + )} {/* Install links */} {connectButton.hasInstallLinks && ( -
+
{t("modal.external.dont-have")} {connectButton.displayName}? diff --git a/packages/ui/src/components/ExternalWallet/ExternalWalletDetails.tsx b/packages/ui/src/components/ExternalWallet/ExternalWalletDetails.tsx new file mode 100644 index 000000000..b5f8cbfa7 --- /dev/null +++ b/packages/ui/src/components/ExternalWallet/ExternalWalletDetails.tsx @@ -0,0 +1,26 @@ +import { ExternalButton } from "../../interfaces"; +import ExternalWalletConnect from "./ExternalWalletConnect"; +import ExternalWalletInstall from "./ExternalWalletInstall"; + +interface ExternalWalletDetailProps { + connectButton: ExternalButton; + walletConnectUri: string; + goBack: () => void; + closeModal: () => void; +} + +export default function ExternalWalletDetail(props: ExternalWalletDetailProps) { + const { connectButton, walletConnectUri, goBack, closeModal } = props; + + return ( +
+ {connectButton.hasWalletConnect ? ( + // Wallet Connect + + ) : ( + // Download wallets + + )} +
+ ); +} diff --git a/packages/ui/src/components/ExternalWallets.tsx b/packages/ui/src/components/ExternalWallets.tsx index a8743f46e..524cf9657 100644 --- a/packages/ui/src/components/ExternalWallets.tsx +++ b/packages/ui/src/components/ExternalWallets.tsx @@ -1,4 +1,4 @@ -import { BaseAdapterConfig, ChainNamespaceType, log, WALLET_ADAPTERS, WalletRegistry } from "@web3auth/base"; +import { BaseAdapterConfig, ChainNamespaceType, log, WALLET_ADAPTERS, WalletRegistry, WalletRegistryItem } from "@web3auth/base"; import bowser from "bowser"; import { ChangeEvent, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -6,7 +6,7 @@ import { useTranslation } from "react-i18next"; import { ExternalButton, MODAL_STATUS, ModalStatusType } from "../interfaces"; import i18n from "../localeImport"; import ExternalWalletButton from "./ExternalWallet/ExternalWalletButton"; -import ExternalWalletConnect from "./ExternalWallet/ExternalWalletConnect"; +import ExternalWalletDetail from "./ExternalWallet/ExternalWalletDetails"; import ExternalWalletHeader from "./ExternalWallet/ExternalWalletHeader"; import Loader from "./Loader"; @@ -26,10 +26,10 @@ type os = "iOS" | "Android"; type platform = "mobile" | "desktop" | "tablet"; type browser = "chrome" | "firefox" | "edge" | "brave" | "safari"; -function formatIOSMobile(params: { uri: string; universalLink?: string; deepLink?: string }) { +function formatIOSMobile(params: { uri: string; link?: string }) { const encodedUri: string = encodeURIComponent(params.uri); - if (params.universalLink) return `${params.universalLink}/wc?uri=${encodedUri}`; - if (params.deepLink) return `${params.deepLink}wc?uri=${encodedUri}`; + if (params.link.startsWith("http")) return `${params.link}/wc?uri=${encodedUri}`; + if (params.link) return `${params.link}wc?uri=${encodedUri}`; return ""; } @@ -43,20 +43,19 @@ export default function ExternalWallet(props: ExternalWalletsProps) { showBackButton, modalStatus, chainNamespace, - walletRegistry = {}, + walletRegistry, } = props; const [externalButtons, setExternalButtons] = useState([]); - const [adapterVisibilityMap, setAdapterVisibilityMap] = useState>({}); const [totalExternalWallets, setTotalExternalWallets] = useState(0); const [selectedButton, setSelectedButton] = useState(null); const [walletSearch, setWalletSearch] = useState(""); const [t] = useTranslation(undefined, { i18n }); - const [isWalletDiscoveryReady, isWalletDiscoveryNotReady] = useMemo(() => { + const walletDiscoverySupported = useMemo(() => { const walletConnectSupported = Object.keys(config || {}).some((adapter) => adapter === WALLET_ADAPTERS.WALLET_CONNECT_V2); - const walletDiscoverySupported = walletRegistry && Object.keys(walletRegistry).length > 0 && walletConnectSupported; - return [walletDiscoverySupported && walletConnectUri, walletDiscoverySupported && !walletConnectUri]; - }, [config, walletConnectUri, walletRegistry]); + const supported = walletRegistry && Object.keys(walletRegistry).length > 0 && walletConnectSupported; + return supported; + }, [config, walletRegistry]); const deviceDetails = useMemo<{ platform: platform; os: os; browser: browser }>(() => { const browser = bowser.getParser(window.navigator.userAgent); @@ -71,13 +70,7 @@ export default function ExternalWallet(props: ExternalWalletsProps) { setWalletSearch(e.target.value); }; - useEffect(() => { - log.debug("loaded external wallets", config, walletConnectUri, deviceDetails.platform); - const wcAvailable = (config[WALLET_ADAPTERS.WALLET_CONNECT_V2]?.showOnModal || false) !== false; - if (wcAvailable && !walletConnectUri) { - handleExternalWalletClick({ adapter: WALLET_ADAPTERS.WALLET_CONNECT_V2 }); - } - + const adapterVisibilityMap = useMemo(() => { const canShowMap: Record = {}; Object.keys(config).forEach((adapter) => { const adapterConfig = config[adapter]; @@ -96,43 +89,62 @@ export default function ExternalWallet(props: ExternalWalletsProps) { canShowMap[adapter] = false; }); log.debug("adapter visibility map", canShowMap); - setAdapterVisibilityMap(canShowMap); - }, [config, handleExternalWalletClick, walletConnectUri, deviceDetails]); + return canShowMap; + }, [config, deviceDetails.platform]); useEffect(() => { - if (isWalletDiscoveryReady) { + log.debug("loaded external wallets", config, walletConnectUri); + const wcAvailable = (config[WALLET_ADAPTERS.WALLET_CONNECT_V2]?.showOnModal || false) !== false; + if (wcAvailable && !walletConnectUri) { + handleExternalWalletClick({ adapter: WALLET_ADAPTERS.WALLET_CONNECT_V2 }); + } + }, [config, handleExternalWalletClick, walletConnectUri]); + + useEffect(() => { + if (walletDiscoverySupported) { const isWalletConnectAdapterIncluded = Object.keys(config).some((adapter) => adapter === WALLET_ADAPTERS.WALLET_CONNECT_V2); - const buttons: ExternalButton[] = Object.keys(walletRegistry).reduce((acc, wallet) => { - if (adapterVisibilityMap[wallet] !== false) { - const walletRegistryItem = walletRegistry[wallet]; - // don't include wallets that don't support sign v2 - if (!walletRegistryItem.walletConnect?.sdks?.includes("sign_v2")) return acc; + const defaultButtonKeys = new Set(Object.keys(walletRegistry.default)); + + const generateWalletButtons = (wallets: Record): ExternalButton[] => { + return Object.keys(wallets).reduce((acc, wallet) => { + if (adapterVisibilityMap[wallet] === false) return acc; + + const walletRegistryItem: WalletRegistryItem = wallets[wallet]; let href = ""; - if (deviceDetails.platform === bowser.PLATFORMS_MAP.mobile && walletConnectUri) { + if (deviceDetails.platform === bowser.PLATFORMS_MAP.mobile) { const universalLink = walletRegistryItem?.mobile?.universal; const deepLink = walletRegistryItem?.mobile?.native; - href = universalLink || deepLink ? formatIOSMobile({ uri: walletConnectUri, universalLink, deepLink }) : walletConnectUri; + href = universalLink || deepLink; } - // All injected wallets are present in wallet registry + const button = { name: wallet, displayName: walletRegistryItem.name, href, hasInjectedWallet: config[wallet]?.isInjected || false, - hasWalletConnect: isWalletConnectAdapterIncluded, + hasWalletConnect: isWalletConnectAdapterIncluded && walletRegistryItem.walletConnect?.sdks?.includes("sign_v2"), hasInstallLinks: Object.keys(walletRegistryItem.app || {}).length > 0, walletRegistryItem, }; + if (!button.hasInjectedWallet && !button.hasWalletConnect && !button.hasInstallLinks) return acc; + const chainNamespaces = new Set(walletRegistryItem.chains?.map((chain) => chain.split(":")[0])); if (!chainNamespaces.has(chainNamespace)) return acc; + acc.push(button); - } - return acc; - }, [] as ExternalButton[]); + return acc; + }, [] as ExternalButton[]); + }; + + // Generate buttons for default and other wallets + const defaultButtons = generateWalletButtons(walletRegistry.default); + const otherButtons = generateWalletButtons(walletRegistry.others); + + // Generate custom adapter buttons const customAdapterButtons: ExternalButton[] = Object.keys(config).reduce((acc, adapter) => { - log.debug("external adapter installed buttons", adapter, adapterVisibilityMap[adapter]); if (![WALLET_ADAPTERS.WALLET_CONNECT_V2].includes(adapter) && !config[adapter].isInjected && adapterVisibilityMap[adapter]) { + log.debug("custom adapter", adapter, config[adapter]); acc.push({ name: adapter, displayName: config[adapter].label || adapter, @@ -143,21 +155,27 @@ export default function ExternalWallet(props: ExternalWalletsProps) { } return acc; }, [] as ExternalButton[]); - setTotalExternalWallets(buttons.length + customAdapterButtons.length); - // sort wallets so that injected wallets come first and then ones without wallet connect and then rest - const injectedWallets = buttons.filter((button) => button.hasInjectedWallet); - const nonInjectedWallets = buttons.filter((button) => !button.hasInjectedWallet); - const filteredButtons = injectedWallets - .concat(customAdapterButtons) - .concat(nonInjectedWallets) - .filter((button) => { - if (!walletSearch) return true; - return button.displayName.toLowerCase().includes(walletSearch.toLowerCase()); - }) - .slice(0, 15); // show at most 15 wallets - log.debug("external buttons", buttons, filteredButtons); - setExternalButtons(filteredButtons); + 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())); + 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); + + log.debug("external buttons", allButtons); } else { const buttons: ExternalButton[] = Object.keys(config).reduce((acc, adapter) => { log.debug("external buttons", adapter, adapterVisibilityMap[adapter]); @@ -173,26 +191,30 @@ export default function ExternalWallet(props: ExternalWalletsProps) { return acc; }, [] as ExternalButton[]); setExternalButtons(buttons); + setTotalExternalWallets(buttons.length); } - }, [config, deviceDetails, walletConnectUri, adapterVisibilityMap, isWalletDiscoveryReady, walletRegistry, walletSearch, chainNamespace]); + }, [config, deviceDetails, adapterVisibilityMap, walletRegistry, walletSearch, chainNamespace, walletDiscoverySupported]); const handleWalletClick = (button: ExternalButton) => { if (deviceDetails.platform === "desktop") { // if has injected wallet, connect to injected wallet - if (!button.hasInjectedWallet && button.hasWalletConnect) { + if (button.hasInjectedWallet) { + handleExternalWalletClick({ adapter: button.name }); + } else { // else, show wallet detail setSelectedButton(button); - return; } + } else if (!button.href && button.hasInjectedWallet) { + // on mobile, if href is not available, connect to injected wallet + handleExternalWalletClick({ adapter: button.name }); } - handleExternalWalletClick({ adapter: button.name }); }; return ( -
+
{/* Loader */} - {isWalletDiscoveryNotReady ? ( + {totalExternalWallets === 0 ? ( ) : ( modalStatus === MODAL_STATUS.INITIALIZED && @@ -208,8 +230,8 @@ export default function ExternalWallet(props: ExternalWalletsProps) { /> {/* Search */} - {isWalletDiscoveryReady && ( -
+ {totalExternalWallets > 15 && ( +
) : ( -
-
    +
    +
      {externalButtons.map((button) => { return ( -
    • +
    • {deviceDetails.platform === "desktop" ? ( - + ) : ( - - + + )}
    • @@ -254,10 +281,10 @@ export default function ExternalWallet(props: ExternalWalletsProps) { ) : ( // Wallet Detail - setSelectedButton(null)} + walletConnectUri={walletConnectUri} closeModal={closeModal} /> )) diff --git a/packages/ui/src/components/Image.tsx b/packages/ui/src/components/Image.tsx index 1d63c19e1..b72dcc8a5 100644 --- a/packages/ui/src/components/Image.tsx +++ b/packages/ui/src/components/Image.tsx @@ -15,7 +15,7 @@ export default function Image(props: ImageProps) { height={height} width={width} alt={imageId} - className="image-icon" + className="image-icon object-contain rounded" onError={({ currentTarget }) => { if (fallbackImageId) { // eslint-disable-next-line no-param-reassign @@ -26,7 +26,13 @@ export default function Image(props: ImageProps) { }} /> {isButton ? ( - {hoverImageId} + {hoverImageId} ) : null} ); diff --git a/packages/ui/src/components/SelfCustodyViaWeb3Auth.tsx b/packages/ui/src/components/SelfCustodyViaWeb3Auth.tsx index 1514a2b8b..24184a345 100644 --- a/packages/ui/src/components/SelfCustodyViaWeb3Auth.tsx +++ b/packages/ui/src/components/SelfCustodyViaWeb3Auth.tsx @@ -6,7 +6,7 @@ export default function SelfCustodyViaWeb3Auth() { const [t] = useTranslation(undefined, { i18n }); return ( -
      +
      {t("modal.footer.message-new")}
      Web3Auth Logo Light Web3Auth Logo Dark diff --git a/packages/ui/src/components/WalletConnect.tsx b/packages/ui/src/components/WalletConnect.tsx index c772f7f11..5b04b4121 100644 --- a/packages/ui/src/components/WalletConnect.tsx +++ b/packages/ui/src/components/WalletConnect.tsx @@ -10,10 +10,11 @@ import i18n from "../localeImport"; interface WalletConnectProps { walletConnectUri: string; logoImage?: string; + primaryColor?: string; } function WalletConnect(props: WalletConnectProps) { - const { walletConnectUri, logoImage } = props; + const { walletConnectUri, logoImage, primaryColor } = props; const isDesktop = useMemo(() => { const browser = Bowser.getParser(window.navigator.userAgent); @@ -36,9 +37,9 @@ function WalletConnect(props: WalletConnectProps) {
      -
      {t("modal.external.walletconnect-subtitle")}
      + {/*
      {t("modal.external.walletconnect-subtitle")}
      */}
      -
      {t("modal.external.walletconnect-copy")}
      +
      {t("modal.external.walletconnect-copy")}
      diff --git a/packages/ui/src/css/web3auth.css b/packages/ui/src/css/web3auth.css index e5cc94f53..85cb7cb49 100644 --- a/packages/ui/src/css/web3auth.css +++ b/packages/ui/src/css/web3auth.css @@ -267,13 +267,13 @@ /* Adapter List */ #w3a-modal div.w3a-adapter-list-container { - height: calc(100dvh - 450px); + height: 380px; scrollbar-width: none; overflow-y: auto; } #w3a-modal ul.w3a-adapter-list { - @apply grid grid-cols-6 overflow-y-auto gap-x-2 gap-y-2 h-[294px]; + @apply grid grid-cols-6 overflow-y-auto gap-x-2 gap-y-2; padding: 1px; transition: height 0.35s; transition-timing-function: cubic-bezier(0.92, 0, 0.74, 1); @@ -612,7 +612,7 @@ } #w3a-modal .w3a-modal__loader-social-logo { - @apply bg-app-gray-100 dark:bg-app-gray-50 w-14 h-14 flex rounded-full items-center justify-center p-1; + @apply w-14 h-14 flex rounded-full items-center justify-center p-1; } #w3a-modal .w3a-modal__loader-social-logo img { @@ -672,6 +672,10 @@ animation: beat5 2.4s infinite; } +.wallet-btn { + @apply !bg-app-gray-100 hover:!bg-app-gray-200 dark:!bg-app-gray-700 dark:hover:bg-app-gray-800; +} + @keyframes beat1 { 0% { transform: scale(0);