diff --git a/package.json b/package.json index 5f0e0218b6..e58ead5c2b 100644 --- a/package.json +++ b/package.json @@ -44,11 +44,9 @@ "dependencies": { "@0xsquid/sdk": "^2.8.1", "@apollo/client": "^3.7.1", - "@blocto/web3-react-connector": "^1.0.7", - "@coinbase/wallet-sdk": "^3.0.4", + "@blocto/wagmi-connector": "^2.0.4", "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@holdstation/paymaster-helper": "^2.0.20", - "@kyberswap/krystal-walletconnect-v2": "0.0.1", "@kyberswap/ks-sdk-classic": "^1.0.3", "@kyberswap/ks-sdk-core": "1.1.5", "@kyberswap/ks-sdk-elastic": "^1.1.2", @@ -63,16 +61,8 @@ "@reduxjs/toolkit": "1.9.3", "@sentry/react": "^7.18.0", "@sentry/tracing": "^7.18.0", + "@tanstack/react-query": "^5.52.1", "@use-gesture/react": "^10.2.27", - "@web3-react/coinbase-wallet": "8.2.0", - "@web3-react/core": "8.2.0", - "@web3-react/eip1193": "8.2.0", - "@web3-react/empty": "8.2.0", - "@web3-react/gnosis-safe": "8.2.0", - "@web3-react/metamask": "8.2.1", - "@web3-react/network": "8.2.0", - "@web3-react/types": "8.2.0", - "@web3-react/walletconnect-v2": "^8.3.3", "@zkmelabs/widget": "^0.1.3", "aos": "^2.3.4", "axios": "1.2.1", @@ -130,7 +120,9 @@ "swiper": "^8.4.4", "ua-parser-js": "^1.0.33", "util": "^0.12.5", + "viem": "^2.20.0", "vite-plugin-env-compatible": "^1.1.1", + "wagmi": "^2.12.7", "walktour": "^5.2.0", "wcag-contrast": "^3.0.0", "workbox-core": "^6.5.4", @@ -202,7 +194,7 @@ "prom-client": "^14.2.0", "storybook": "^7.6.2", "ts-node": "^10.9.1", - "typescript": "4.8.4", + "typescript": "5.3.3", "vite": "^4.3.9", "vite-plugin-checker": "^0.5.6", "vite-plugin-svgr": "^2.4.0", diff --git a/patches/@web3-react+coinbase-wallet+8.2.0.patch b/patches/@web3-react+coinbase-wallet+8.2.0.patch deleted file mode 100644 index 27d52f63a8..0000000000 --- a/patches/@web3-react+coinbase-wallet+8.2.0.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/node_modules/@web3-react/coinbase-wallet/dist/index.js b/node_modules/@web3-react/coinbase-wallet/dist/index.js -index f38d06e..584c5a5 100644 ---- a/node_modules/@web3-react/coinbase-wallet/dist/index.js -+++ b/node_modules/@web3-react/coinbase-wallet/dist/index.js -@@ -136,7 +136,7 @@ class CoinbaseWallet extends types_1.Connector { - params: [{ chainId: desiredChainIdHex }], - }) - .catch((error) => __awaiter(this, void 0, void 0, function* () { -- if (error.code === 4902 && typeof desiredChainIdOrChainParameters !== 'number') { -+ if ((error.code === 4902 || error.code === -32603) && typeof desiredChainIdOrChainParameters !== 'number') { - if (!this.provider) - throw new Error('No provider'); - // if we're here, we can try to add a new network -@@ -166,7 +166,7 @@ class CoinbaseWallet extends types_1.Connector { - method: 'wallet_switchEthereumChain', - params: [{ chainId: desiredChainIdHex }], - }).catch((error) => __awaiter(this, void 0, void 0, function* () { -- if (error.code === 4902 && typeof desiredChainIdOrChainParameters !== 'number') { -+ if ((error.code === 4902 || error.code === -32603) && typeof desiredChainIdOrChainParameters !== 'number') { - if (!this.provider) - throw new Error('No provider'); - // if we're here, we can try to add a new network diff --git a/patches/@web3-react+metamask+8.2.1.patch b/patches/@web3-react+metamask+8.2.1.patch deleted file mode 100644 index 8b23dd9630..0000000000 --- a/patches/@web3-react+metamask+8.2.1.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/node_modules/@web3-react/metamask/dist/index.js b/node_modules/@web3-react/metamask/dist/index.js -index c8476dd..a613ed1 100644 ---- a/node_modules/@web3-react/metamask/dist/index.js -+++ b/node_modules/@web3-react/metamask/dist/index.js -@@ -64,7 +64,14 @@ class MetaMask extends types_1.Connector { - this.provider = (_b = this.provider.providers.find((p) => p.isMetaMask)) !== null && _b !== void 0 ? _b : this.provider.providers[0]; - } - this.provider.on('connect', ({ chainId }) => { -- this.actions.update({ chainId: parseChainId(chainId) }); -+ this.provider -+ .request({ method: 'eth_chainId' }) -+ .then(chainId => { -+ this.actions.update({ chainId: parseChainId(chainId) }) -+ }) -+ .catch(() => { -+ this.actions.update({ chainId: parseChainId(chainId) }) -+ }) - }); - this.provider.on('disconnect', (error) => { - var _a; diff --git a/patches/@web3modal+core+2.4.7.patch b/patches/@web3modal+core+2.4.7.patch deleted file mode 100644 index 35050b9ecd..0000000000 --- a/patches/@web3modal+core+2.4.7.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/node_modules/@web3modal/core/dist/_types/src/types/controllerTypes.d.ts b/node_modules/@web3modal/core/dist/_types/src/types/controllerTypes.d.ts -index 57a1c75..c8d5687 100644 ---- a/node_modules/@web3modal/core/dist/_types/src/types/controllerTypes.d.ts -+++ b/node_modules/@web3modal/core/dist/_types/src/types/controllerTypes.d.ts -@@ -172,6 +172,7 @@ export interface ThemeCtrlState { - '--w3m-accent-fill-color'?: string; - '--w3m-background-color'?: string; - '--w3m-background-image-url'?: string; -+ '--w3m-color-bg-1'?: string; - '--w3m-logo-image-url'?: string; - '--w3m-background-border-radius'?: string; - '--w3m-container-border-radius'?: string; diff --git a/public/.well-known/walletconnect.txt b/public/.well-known/walletconnect.txt index 72cd48d316..6da45abf2c 100644 --- a/public/.well-known/walletconnect.txt +++ b/public/.well-known/walletconnect.txt @@ -1 +1 @@ -b52e5f7a-d705-4e20-8eff-1dc8676996d6=489d0fca236bddfb749f13dcf60bc4686ab33803a980874f43f99e36c3f48518 \ No newline at end of file +b52e5f7a-d705-4e20-8eff-1dc8676996d6=489d0fca236bddfb749f13dcf60bc4686ab33803a980874f43f99e36c3f48518 diff --git a/src/components/AddToMetamask/index.tsx b/src/components/AddToMetamask/index.tsx index da2b5efd60..3a96967906 100644 --- a/src/components/AddToMetamask/index.tsx +++ b/src/components/AddToMetamask/index.tsx @@ -1,9 +1,9 @@ import { Token } from '@kyberswap/ks-sdk-core' -import { getConnection } from 'connection' import styled from 'styled-components' import { ButtonEmpty } from 'components/Button' import { RowFixed } from 'components/Row' +import { CONNECTOR_ICON_OVERRIDE_MAP } from 'components/Web3Provider' import { useActiveWeb3React, useWeb3React } from 'hooks' import { getTokenLogoURL } from 'utils' @@ -15,7 +15,6 @@ const StyledLogo = styled.img` export default function AddTokenToMetaMask({ token }: { token: Token }) { const { chainId, walletKey } = useActiveWeb3React() const { connector } = useWeb3React() - const connection = getConnection(connector) async function addToMetaMask() { const tokenAddress = token.address @@ -40,14 +39,15 @@ export default function AddTokenToMetaMask({ token }: { token: Token }) { console.error(error) } } - const { icon } = connection.getProviderInfo() + const icon = CONNECTOR_ICON_OVERRIDE_MAP[connector?.id || ''] ?? connector?.icon + if (!walletKey || !icon) return null - if (walletKey === 'WALLET_CONNECT') return null + if (walletKey === 'WalletConnect') return null if (walletKey === 'COINBASE') return null // Coinbase wallet no need to add since it automatically track token return ( - + ) diff --git a/src/components/DownloadWalletModal/index.tsx b/src/components/DownloadWalletModal/index.tsx index 1fe76d7921..42bb8e9450 100644 --- a/src/components/DownloadWalletModal/index.tsx +++ b/src/components/DownloadWalletModal/index.tsx @@ -4,10 +4,19 @@ import { X } from 'react-feather' import { Image, Text } from 'rebass' import styled from 'styled-components' +import bloctoIcon from 'assets/wallets-connect/bocto.svg' +import braveIcon from 'assets/wallets-connect/brave.svg' +import coin98Icon from 'assets/wallets-connect/coin98.svg' +import coinbaseIcon from 'assets/wallets-connect/coinbase.svg' +import krystalIcon from 'assets/wallets-connect/krystal.svg' +import metaMaskIcon from 'assets/wallets-connect/metamask.svg' +import rabbyIcon from 'assets/wallets-connect/rabby.svg' +import safeIcon from 'assets/wallets-connect/safe.svg' +import trustWalletIcon from 'assets/wallets-connect/trust-wallet.svg' +import zerionIcon from 'assets/wallets-connect/zerion.svg' import Column from 'components/Column' import Modal from 'components/Modal' import Row, { RowBetween } from 'components/Row' -import { connections } from 'constants/wallets' import useTheme from 'hooks/useTheme' import { ApplicationModal } from 'state/application/actions' import { useCloseModal, useModalOpen } from 'state/application/hooks' @@ -37,6 +46,49 @@ const DownloadWalletRow = styled.a` } ` +const wallets = [ + { + name: 'Krystal', + icon: krystalIcon, + installLink: 'https://wallet.krystal.app', + }, + + { + name: 'Rabby', + icon: rabbyIcon, + installLink: 'https://rabby.io', + }, + + { + name: 'Zerion', + icon: zerionIcon, + installLink: 'https://zerion.io', + }, + + { + name: 'Trust Wallet', + icon: trustWalletIcon, + installLink: 'https://trustwallet.com/vi/deeplink', + }, + + { + name: 'Brave Wallet', + icon: braveIcon, + installLink: 'https://brave.com/download', + }, + + { name: 'Safe Wallet', icon: safeIcon, installLink: 'https://safe.global/wallet' }, + + { name: 'Coinbase', icon: coinbaseIcon, installLink: 'https://www.coinbase.com/wallet' }, + { name: 'Coin98', icon: coin98Icon, installLink: 'https://wallet.coin98.com/' }, + { name: 'Blocto', icon: bloctoIcon, installLink: 'https://blocto.io/download' }, + { + name: 'MetaMask', + icon: metaMaskIcon, + installLink: 'https://metamask.io/download', + }, +] + export default function DownloadWalletModal() { const theme = useTheme() const isOpen = useModalOpen(ApplicationModal.DOWNLOAD_WALLET) @@ -55,7 +107,7 @@ export default function DownloadWalletModal() { - {Object.values(connections) + {wallets .filter(e => e.installLink) .map(item => ( (null) const dragControls = useDragControls() @@ -290,9 +288,9 @@ const DraggableNetworkButton = ({ )} {selected && !walletKey && } - {account && walletKey && connection.getProviderInfo().icon && ( + {account && walletKey && connector?.icon && ( - + )} diff --git a/src/components/Header/web3/SelectWallet.tsx b/src/components/Header/web3/SelectWallet.tsx index 1cbd84e0e4..54ff81d3dc 100644 --- a/src/components/Header/web3/SelectWallet.tsx +++ b/src/components/Header/web3/SelectWallet.tsx @@ -1,7 +1,6 @@ import { Trans } from '@lingui/macro' -import { getConnection } from 'connection' import { darken, lighten } from 'polished' -import { useEffect, useMemo } from 'react' +import { useMemo } from 'react' import { Activity } from 'react-feather' import { useMedia } from 'react-use' import styled from 'styled-components' @@ -14,17 +13,16 @@ import Loader from 'components/Loader' import { RowBetween } from 'components/Row' import { MouseoverTooltip } from 'components/Tooltip' import { TutorialIds } from 'components/Tutorial/TutorialSwap/constant' +import { CONNECTOR_ICON_OVERRIDE_MAP } from 'components/Web3Provider' import { useActiveWeb3React, useWeb3React } from 'hooks' import useENSName from 'hooks/useENSName' import useLogin from 'hooks/useLogin' import useMixpanel, { MIXPANEL_TYPE } from 'hooks/useMixpanel' import useTheme from 'hooks/useTheme' import { useNetworkModalToggle, useWalletModalToggle } from 'state/application/hooks' -import { useAppDispatch } from 'state/hooks' import { useSignedAccountInfo } from 'state/profile/hooks' import { isTransactionRecent, newTransactionsFirst, useAllTransactions } from 'state/transactions/hooks' import { TransactionDetails } from 'state/transactions/type' -import { updateRecentConnectionMeta } from 'state/user/actions' import { MEDIA_WIDTHS } from 'theme' import { shortenAddress } from 'utils' @@ -106,14 +104,12 @@ const AccountElement = styled.div` function Web3StatusInner() { const { chainId, account, walletKey, isWrongNetwork } = useActiveWeb3React() + const { connector } = useWeb3React() const { mixpanelHandler } = useMixpanel() const uptoMedium = useMedia(`(max-width: ${MEDIA_WIDTHS.upToMedium}px)`) const { signIn } = useLogin() const { ENSName } = useENSName(account ?? undefined) const theme = useTheme() - const { connector } = useWeb3React() - const connection = getConnection(connector) - const dispatch = useAppDispatch() const allTransactions = useAllTransactions() @@ -126,20 +122,13 @@ function Web3StatusInner() { const pendingLength = sortedRecentTransactions.filter(tx => !tx.receipt).length - useEffect(() => { - if (account || ENSName) { - const { rdns } = connection.getProviderInfo() - dispatch( - updateRecentConnectionMeta({ type: connection.type, address: account, ENSName: ENSName ?? undefined, rdns }), - ) - } - }, [ENSName, account, connection, dispatch]) - const hasPendingTransactions = !!pendingLength const toggleWalletModal = useWalletModalToggle() const toggleNetworkModal = useNetworkModalToggle() const { isSignInDifferentWallet } = useSignedAccountInfo() + const icon = CONNECTOR_ICON_OVERRIDE_MAP[connector?.id || ''] ?? connector?.icon + if (isWrongNetwork) { return ( @@ -196,7 +185,7 @@ function Web3StatusInner() { ) : ( walletKey && ( - + ) )} diff --git a/src/components/Header/web3/WalletModal/Option.tsx b/src/components/Header/web3/WalletModal/Option.tsx index 6874d51113..324935d8c8 100644 --- a/src/components/Header/web3/WalletModal/Option.tsx +++ b/src/components/Header/web3/WalletModal/Option.tsx @@ -1,9 +1,9 @@ -import { ActivationStatus, useActivationState } from 'connection/activate' -import { Connection } from 'connection/types' import { darken } from 'polished' import React from 'react' import styled, { css } from 'styled-components' +import { Connector, useConnect } from 'wagmi' +import { CONNECTOR_ICON_OVERRIDE_MAP } from 'components/Web3Provider' import { useActiveWeb3React } from 'hooks' import { useCloseModal } from 'state/application/hooks' import { ApplicationModal } from 'state/application/types' @@ -98,33 +98,41 @@ const OptionCardLeft = styled.div` // } // ` -const Option = ({ connection }: { connection: Connection }) => { - const { activationState, tryActivation } = useActivationState() +const Option = ({ connector }: { connector: Connector }) => { const [isAcceptedTerm] = useIsAcceptedTerm() const { chainId } = useActiveWeb3React() - const { name, icon } = connection.getProviderInfo() - - const isSomeOptionPending = activationState.status === ActivationStatus.PENDING - const isCurrentOptionPending = isSomeOptionPending && activationState.connection === connection + const { name } = connector + const icon = CONNECTOR_ICON_OVERRIDE_MAP[connector.id] ?? connector.icon const closeWalletModal = useCloseModal(ApplicationModal.WALLET) + const { + variables, + isPending: isSomeOptionPending, + connect, + } = useConnect({ + mutation: { + onSuccess: () => { + closeWalletModal() + }, + onError: e => { + console.log(e) + }, + }, + }) + + const isCurrentOptionPending = isSomeOptionPending && variables.connector === connector const content = ( - isAcceptedTerm && - tryActivation( - connection, - () => { - closeWalletModal() - }, - chainId, - ) - } + id={`connect-${name}`} + onClick={() => { + if (isAcceptedTerm) { + connect({ connector, chainId: chainId as any }) + } + }} connected={isCurrentOptionPending} isDisabled={!isAcceptedTerm} > diff --git a/src/components/Header/web3/WalletModal/PendingView.tsx b/src/components/Header/web3/WalletModal/PendingView.tsx deleted file mode 100644 index b9b73f7d80..0000000000 --- a/src/components/Header/web3/WalletModal/PendingView.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { Trans } from '@lingui/macro' -import { ActivationStatus, useActivationState } from 'connection/activate' -import { darken } from 'polished' -import styled from 'styled-components' - -import Loader from 'components/Loader' -import { useActiveWeb3React } from 'hooks' -import { useCloseModal } from 'state/application/hooks' -import { ApplicationModal } from 'state/application/types' - -const PendingSection = styled.div` - ${({ theme }) => theme.flexColumnNoWrap}; - align-items: center; - justify-content: center; - width: 100%; - & > * { - width: 100%; - } -` - -const StyledLoader = styled(Loader)` - margin-right: 1rem; -` - -const LoadingMessage = styled.div<{ hasError?: boolean }>` - ${({ theme }) => theme.flexRowNoWrap}; - align-items: center; - justify-content: flex-start; - border-radius: 16px; - color: ${({ theme, hasError }) => (hasError ? theme.red1 : 'inherit')}; - border: 1px solid ${({ theme, hasError }) => (hasError ? theme.red1 : theme.text4)}; - width: 100%; - & > * { - padding: 1rem; - } -` - -const ErrorGroup = styled.div` - ${({ theme }) => theme.flexRowNoWrap}; - align-items: center; - justify-content: space-between; - display: flex; - width: 100%; - ${({ theme }) => theme.mediaWidth.upToExtraSmall` - font-size:14px; - `} -` - -const ErrorButton = styled.div` - border-radius: 8px; - font-size: 12px; - color: ${({ theme }) => theme.primary}; - background-color: rgba(49, 203, 158, 0.2); - padding: 0.5rem; - font-weight: 600; - user-select: none; - min-width: 70px; - &:hover { - cursor: pointer; - background-color: ${({ theme }) => darken(0.1, theme.bg5)}; - } -` - -const LoadingWrapper = styled.div` - ${({ theme }) => theme.flexRowNoWrap}; - align-items: center; - width: 100%; -` - -export default function PendingView() { - const { activationState, tryActivation } = useActivationState() - - const { chainId } = useActiveWeb3React() - const closeWalletModal = useCloseModal(ApplicationModal.WALLET) - if (activationState.status === ActivationStatus.IDLE) return null - - const { name } = activationState.connection.getProviderInfo() - - return ( - - - - {activationState.status === ActivationStatus.ERROR ? ( - -
- Error connecting to {name}. -
- - tryActivation( - activationState.connection, - () => { - closeWalletModal() - }, - chainId, - ) - } - > - Try Again - -
- ) : ( - <> - - Initializing with {name}... - - )} -
-
-
- ) -} diff --git a/src/components/Header/web3/WalletModal/WarningBox.tsx b/src/components/Header/web3/WalletModal/WarningBox.tsx deleted file mode 100644 index 2c17974f9d..0000000000 --- a/src/components/Header/web3/WalletModal/WarningBox.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useState } from 'react' -import { AlertTriangle, ChevronUp } from 'react-feather' -import { Flex, Text } from 'rebass' -import styled from 'styled-components' - -import { ReactComponent as WarningIcon } from 'assets/images/warning.svg' -import { SUPPORTED_WALLET, SUPPORTED_WALLETS } from 'constants/wallets' -import useTheme from 'hooks/useTheme' -import { ExternalLink } from 'theme' -import checkForBraveBrowser from 'utils/checkForBraveBrowser' - -const WarningBoxWrapper = styled.div` - width: 100%; - background-color: ${({ theme }) => theme.buttonBlack}; - margin-top: 24px; - color: ${({ theme }) => theme.subText}; - margin-bottom: 12px; - border-radius: 8px; - padding: 16px 24px; - font-size: 12px; - line-height: 16px; -` -const InfoWrapper = styled.div` - width: 100%; - display: flex; - gap: 12px; - align-items: center; -` -const StepsWrapper = styled.div` - border-top: 1px solid ${({ theme }) => theme.border}; - display: flex; - flex-direction: column; - gap: 12px; - padding-top: 16px; - margin-top: 16px; -` -const StyledAlert = styled(WarningIcon)` - height: 64px; - width: 64px; -` -const IconWrapper = styled.div<{ show: boolean }>` - padding: 0 8px; - transform: rotate(${({ show }) => (show ? '0deg' : '180deg')}); - transition: transform 300ms; - cursor: pointer; -` -const Step = styled.div` - width: 24px; - height: 24px; - background-color: rgba(49, 203, 158, 0.2); - border-radius: 50%; - color: ${({ theme }) => theme.primary}; - display: flex; - justify-content: center; - align-items: center; - margin-right: 8px; -` -const StepContainer = styled.div` - display: flex; - color: ${({ theme }) => theme.subText}; - align-items: center; -` - -export const C98OverrideGuide = ({ - walletKey, - isOpened = true, -}: { - walletKey?: SUPPORTED_WALLET - isOpened?: boolean -}) => { - const theme = useTheme() - const [show, setShow] = useState(false) - - if (!walletKey) return null - - const walletName = SUPPORTED_WALLETS[walletKey].name - // TODO: remove - const injectedName = 'BRAVE' - - const isSelectCoin98 = walletKey === 'COIN98' - return ( - - - - {!isOpened ? ( - - {walletName} is not available. In order to use {walletName}, please follow the steps below to disable{' '} - {injectedName} Wallet: - - ) : ( - - If {injectedName} wallet opens instead of {walletName}, please close the {injectedName} popup then follow - the steps below to disable {injectedName} Wallet: - - )} - setShow(prev => !prev)}> - - - - {show && ( - - - 1 - Open C98 Browser Extension - - - 2 - Click on the Settings icon - - - 3 - Select Override Wallets - - - 4 - {isSelectCoin98 ? Enable Metamask in C98 : Disable Metamask in C98} - - - 5 - Refresh the page then try to connect to {walletName} again - - - )} - - ) -} - -export const WarningBox = ({ walletKey }: { walletKey?: SUPPORTED_WALLET }) => { - const theme = useTheme() - - const isBraveBrowser = checkForBraveBrowser() - - if (!walletKey) return null - - if (!isBraveBrowser && walletKey === 'BRAVE') { - return ( - - - - - - - Brave wallet can only be used in Brave Browser. Download it{' '} - - here - - - - ) - } - - return null -} diff --git a/src/components/Header/web3/WalletModal/index.tsx b/src/components/Header/web3/WalletModal/index.tsx index 667003c03a..33b8df91c7 100644 --- a/src/components/Header/web3/WalletModal/index.tsx +++ b/src/components/Header/web3/WalletModal/index.tsx @@ -1,12 +1,11 @@ import { Trans } from '@lingui/macro' -import { ActivationStatus, useActivationState } from 'connection/activate' -import { ConnectionType } from 'connection/types' import dayjs from 'dayjs' import { rgba } from 'polished' import { useEffect, useState } from 'react' import { ChevronLeft } from 'react-feather' import { Text } from 'rebass' import styled from 'styled-components' +import { useConnect } from 'wagmi' import { ReactComponent as Close } from 'assets/images/x.svg' import Modal from 'components/Modal' @@ -24,13 +23,11 @@ import { useOpenNetworkModal, useWalletModalToggle, } from 'state/application/hooks' -import { useAppDispatch } from 'state/hooks' -import { clearRecentConnectionMeta } from 'state/user/actions' import { useIsAcceptedTerm } from 'state/user/hooks' import { ExternalLink } from 'theme' -import PendingView from './PendingView' -import { useConnections } from './useConnections' +import Option from './Option' +import { useOrderedConnections } from './useConnections' const CloseIcon = styled.div` height: 24px; @@ -108,10 +105,7 @@ const HoverText = styled.div` export default function WalletModal() { const { isWrongNetwork, account } = useActiveWeb3React() - const { activationState, cancelActivation } = useActivationState() - const theme = useTheme() - const dispatch = useAppDispatch() const walletModalOpen = useModalOpen(ApplicationModal.WALLET) const toggleWalletModal = useWalletModalToggle() @@ -119,8 +113,9 @@ export default function WalletModal() { const openWalletModal = useOpenModal(ApplicationModal.WALLET) const openNetworkModal = useOpenNetworkModal() + const { isPending: isSomeOptionPending, isIdle, isError, reset } = useConnect() const onDismiss = () => { - cancelActivation() + reset() closeWalletModal() } @@ -134,20 +129,18 @@ export default function WalletModal() { } }, [isWrongNetwork, openNetworkModal]) - const { orderedConnections } = useConnections() + const connectors = useOrderedConnections() const [isPinnedPopupWallet, setPinnedPopupWallet] = useState(false) - const isSomeOptionPending = activationState.status === ActivationStatus.PENDING - function getModalContent() { return ( - {(isSomeOptionPending || activationState.status === ActivationStatus.ERROR) && ( + {(isSomeOptionPending || isError) && ( { - cancelActivation() + reset() }} style={{ marginRight: '1rem', flex: 1 }} > @@ -159,20 +152,18 @@ export default function WalletModal() { { - cancelActivation() + reset() toggleWalletModal() }} > - {activationState.status === ActivationStatus.IDLE && ( + {isIdle && ( { if (!isAcceptedTerm) { mixpanelHandler(MIXPANEL_TYPE.WALLET_CONNECT_ACCEPT_TERM_CLICK) - } else { - dispatch(clearRecentConnectionMeta()) } setIsAcceptedTerm(!isAcceptedTerm) }} @@ -200,11 +191,11 @@ export default function WalletModal() { )} - {activationState.status !== ActivationStatus.IDLE ? ( - - ) : ( - {orderedConnections} - )} + + {connectors.map(c => ( + ) @@ -229,9 +220,15 @@ export default function WalletModal() { minHeight={false} maxHeight={90} maxWidth={600} - bypassScrollLock={isSomeOptionPending && activationState.connection.type === ConnectionType.WALLET_CONNECT_V2} + bypassScrollLock={ + true + //isSomeOptionPending + //&& activationState.connection.type === ConnectionType.WALLET_CONNECT_V2 + } bypassFocusLock={ - isSomeOptionPending && activationState.connection.type === ConnectionType.WALLET_CONNECT_V2 + true + //isSomeOptionPending + //&& activationState.connection.type === ConnectionType.WALLET_CONNECT_V2 // walletView === WALLET_VIEWS.PENDING && ['WALLET_CONNECT', 'KRYSTAL_WC', 'BLOCTO'].includes(pendingWalletKey) } > diff --git a/src/components/Header/web3/WalletModal/useConnections.tsx b/src/components/Header/web3/WalletModal/useConnections.tsx index 8e5e3c5263..0a2e6546b8 100644 --- a/src/components/Header/web3/WalletModal/useConnections.tsx +++ b/src/components/Header/web3/WalletModal/useConnections.tsx @@ -1,69 +1,71 @@ -import { connections, eip6963Connection } from 'connection' -import { useInjectedProviderDetails } from 'connection/eip6963/providers' -import { Connection, ConnectionType, RecentConnectionMeta } from 'connection/types' -import { shouldUseDeprecatedInjector } from 'connection/utils' import { useMemo } from 'react' +import { isMobile } from 'react-device-detect' +import { Connector, useConnect } from 'wagmi' + +import { CONNECTION, getConnectorWithId } from 'components/Web3Provider' + +function getInjectedConnectors(connectors: readonly Connector[]) { + let isCoinbaseWalletBrowser = false + const injectedConnectors = connectors.filter(c => { + // Special-case: Ignore coinbase eip6963-injected connector; coinbase connection is handled via the SDK connector. + if (c.id === CONNECTION.COINBASE_RDNS) { + if (isMobile) { + isCoinbaseWalletBrowser = true + } + return false + } + + return c.type === CONNECTION.INJECTED_CONNECTOR_TYPE && c.id !== CONNECTION.INJECTED_CONNECTOR_ID + }) + + // Special-case: Return deprecated window.ethereum connector when no eip6963 injectors are present. + const fallbackInjector = getConnectorWithId(connectors, CONNECTION.INJECTED_CONNECTOR_ID, { shouldThrow: true }) + if (!injectedConnectors.length && Boolean(window.ethereum)) { + return { injectedConnectors: [fallbackInjector], isCoinbaseWalletBrowser } + } -import { useAppSelector } from 'state/hooks' - -import Option from './Option' - -function useEIP6963Connections() { - const eip6963Injectors = useInjectedProviderDetails() - const eip6963Enabled = true - - return useMemo(() => { - if (!eip6963Enabled) return { eip6963Connections: [], showDeprecatedMessage: false } - - const eip6963Connections = eip6963Injectors.flatMap(injector => eip6963Connection.wrap(injector.info) ?? []) - - // Displays ui to activate window.ethereum for edge-case where we detect window.ethereum !== one of the eip6963 providers - const showDeprecatedMessage = eip6963Connections.length > 0 && shouldUseDeprecatedInjector(eip6963Injectors) - - return { eip6963Connections, showDeprecatedMessage } - }, [eip6963Injectors, eip6963Enabled]) + return { injectedConnectors, isCoinbaseWalletBrowser } } -function mergeConnections(connections: Connection[], eip6963Connections: Connection[]) { - const hasEip6963Connections = eip6963Connections.length > 0 - const displayedConnections = connections.filter(c => c.shouldDisplay()) +type InjectableConnector = Connector & { isInjected?: boolean } +export function useOrderedConnections(): InjectableConnector[] { + const { connectors } = useConnect() - if (!hasEip6963Connections) return displayedConnections + return useMemo(() => { + const { injectedConnectors: injectedConnectorsBase, isCoinbaseWalletBrowser } = getInjectedConnectors(connectors) + const injectedConnectors = injectedConnectorsBase.map(c => ({ ...c, isInjected: true })) - const allConnections = [...displayedConnections.filter(c => c.type !== ConnectionType.INJECTED)] - // By default, injected options should appear second in the list (below Uniswap wallet) - allConnections.splice(1, 0, ...eip6963Connections) + const coinbaseSdkConnector = getConnectorWithId(connectors, CONNECTION.COINBASE_SDK_CONNECTOR_ID) + const walletConnectConnector = getConnectorWithId(connectors, CONNECTION.WALLET_CONNECT_CONNECTOR_ID) + const bloctoConnector = getConnectorWithId(connectors, CONNECTION.BLOCTO_ID) - return allConnections -} + if (!coinbaseSdkConnector || !walletConnectConnector) { + throw new Error('Expected connector(s) missing from wagmi context.') + } -// TODO(WEB-3244) Improve ordering logic to make less brittle, as it is spread across connections/index.ts and here -/** Returns an array of all connection Options that should be displayed, where the recent connection is first in the array */ -function getOrderedConnections(connections: Connection[], recentConnection: RecentConnectionMeta | undefined) { - const list: JSX.Element[] = [] - for (const connection of connections) { - if (!connection.shouldDisplay()) continue - const { name, rdns } = connection.getProviderInfo() + // Special-case: Only display the injected connector for in-wallet browsers. + if (isMobile && injectedConnectors.length === 1) { + return injectedConnectors + } - // For eip6963 injectors, we need to check rdns in addition to connection type to ensure it's the recent connection - const isRecent = connection.type === recentConnection?.type && (!rdns || rdns === recentConnection.rdns) + // Special-case: Only display the Coinbase connector in the Coinbase Wallet. + if (isCoinbaseWalletBrowser) { + return [coinbaseSdkConnector] + } - const option =