feat(wallet-connect): make v2 the default walletconnect method (#6785)

* explicitly enumerate all supported wcv2 methods as optional ?

* use only sign methods in optionalMethods

* rename class

* feat(wallet-connect): make v2 the default

* fix loader and menu button occlusion

* fix test

* pr feedback from zzmp

* update connector name

* add slack convo link from x-walletconnect
This commit is contained in:
Jordan Frankfurt 2023-06-16 11:33:37 -05:00 committed by GitHub
parent 1a634c350a
commit 2d61c72588
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 44 deletions

@ -3,7 +3,7 @@ import { BrowserEvent, InterfaceElementName, InterfaceEventName } from '@uniswap
import { useAccountDrawer } from 'components/AccountDrawer'
import { ButtonEmphasis, ButtonSize, ThemeButton } from 'components/Button'
import Loader from 'components/Icons/LoadingSpinner'
import { walletConnectV2Connection } from 'connection'
import { walletConnectV1Connection } from 'connection'
import { ActivationStatus, useActivationState } from 'connection/activate'
import { Connection, ConnectionType } from 'connection/types'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
@ -63,7 +63,7 @@ const IconWrapper = styled.div`
align-items: flex-end;
`};
`
const WCv2PopoverContent = styled(ThemeButton)`
const WCv1PopoverContent = styled(ThemeButton)`
background: ${({ theme }) => theme.backgroundSurface};
border: 1px solid ${({ theme }) => theme.backgroundOutline};
border-radius: 12px;
@ -77,7 +77,7 @@ const WCv2PopoverContent = styled(ThemeButton)`
z-index: ${Z_INDEX.popover};
`
const TOGGLE_SIZE = 24
const WCv2PopoverToggle = styled.button`
const WCv1PopoverToggle = styled.button`
align-items: center;
background-color: transparent;
border: none;
@ -117,15 +117,15 @@ const Wrapper = styled.div<{ disabled: boolean }>`
}
`
const WCv2Icon = styled.img`
const WCv1Icon = styled.img`
height: 20px !important;
width: 20px !important;
`
const WCv2BodyText = styled(ThemedText.BodyPrimary)`
margin-bottom: 4px;
const WCv1BodyText = styled(ThemedText.BodyPrimary)`
margin-bottom: 4px !important;
text-align: left;
`
const WCv2Caption = styled(ThemedText.Caption)`
const WCv1Caption = styled(ThemedText.Caption)`
text-align: left;
`
@ -141,15 +141,15 @@ function PopupButtonContent({ connection, isDarkMode, show, onClick, onClose }:
useOnClickOutside(popoverElement, onClose)
if (!show) return null
return (
<WCv2PopoverContent onClick={onClick} ref={popoverElement} size={ButtonSize.small} emphasis={ButtonEmphasis.medium}>
<WCv1PopoverContent onClick={onClick} ref={popoverElement} size={ButtonSize.small} emphasis={ButtonEmphasis.medium}>
<IconWrapper>
<WCv2Icon src={connection.getIcon?.(isDarkMode)} alt={connection.getName()} />
<WCv1Icon src={connection.getIcon?.(isDarkMode)} alt={connection.getName()} />
</IconWrapper>
<div>
<WCv2BodyText>Connect with v2</WCv2BodyText>
<WCv2Caption color="textSecondary">Under development and unsupported by most wallets</WCv2Caption>
<WCv1BodyText>Connect with v1</WCv1BodyText>
<WCv1Caption color="textSecondary">Support for v1 will be discontinued very soon.</WCv1Caption>
</div>
</WCv2PopoverContent>
</WCv1PopoverContent>
)
}
@ -158,30 +158,32 @@ interface OptionProps {
}
export default function Option({ connection }: OptionProps) {
const { activationState, tryActivation } = useActivationState()
const [WC2PromptOpen, setWC2PromptOpen] = useState(false)
const [WC1PromptOpen, setWC1PromptOpen] = useState(false)
const [accountDrawerOpen, toggleAccountDrawerOpen] = useAccountDrawer()
const activate = () => tryActivation(connection, toggleAccountDrawerOpen)
useEffect(() => {
if (!accountDrawerOpen) setWC2PromptOpen(false)
if (!accountDrawerOpen) setWC1PromptOpen(false)
}, [accountDrawerOpen])
const isSomeOptionPending = activationState.status === ActivationStatus.PENDING
const isCurrentOptionPending = isSomeOptionPending && activationState.connection.type === connection.type
const isDarkMode = useIsDarkMode()
const handleClickConnectViaWCv2 = (e: MouseEvent<HTMLButtonElement>) => {
const handleClickConnectViaWCv1 = (e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation()
tryActivation(walletConnectV2Connection, () => {
setWC2PromptOpen(false)
tryActivation(walletConnectV1Connection, () => {
setWC1PromptOpen(false)
toggleAccountDrawerOpen()
})
}
const handleClickOpenWCv2Tooltip = (e: MouseEvent<HTMLButtonElement>) => {
const handleClickOpenWCv1Tooltip = (e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation()
setWC2PromptOpen(true)
setWC1PromptOpen(true)
}
const showExtraMenuToggle = connection.type === ConnectionType.WALLET_CONNECT_V2 && !isCurrentOptionPending
return (
<Wrapper disabled={isSomeOptionPending}>
<TraceEvent
@ -207,17 +209,17 @@ export default function Option({ connection }: OptionProps) {
</OptionCardClickable>
</TraceEvent>
{connection.type === ConnectionType.WALLET_CONNECT && (
{showExtraMenuToggle && (
<>
<WCv2PopoverToggle onClick={handleClickOpenWCv2Tooltip} onMouseDown={handleClickOpenWCv2Tooltip}>
<WCv1PopoverToggle onClick={handleClickOpenWCv1Tooltip} onMouseDown={handleClickOpenWCv1Tooltip}>
<MoreHorizontal />
</WCv2PopoverToggle>
</WCv1PopoverToggle>
<PopupButtonContent
connection={connection}
isDarkMode={isDarkMode}
show={WC2PromptOpen}
onClick={handleClickConnectViaWCv2}
onClose={() => setWC2PromptOpen(false)}
show={WC1PromptOpen}
onClick={handleClickConnectViaWCv1}
onClose={() => setWC1PromptOpen(false)}
/>
</>
)}

@ -14,7 +14,7 @@ const RPC_URLS_WITHOUT_FALLBACKS = Object.entries(RPC_URLS).reduce(
{}
)
export class WalletConnectPopup extends WalletConnect {
export class WalletConnectV1 extends WalletConnect {
ANALYTICS_EVENT = 'Wallet Connect QR Scan'
constructor({
actions,
@ -31,7 +31,7 @@ export class WalletConnectPopup extends WalletConnect {
}
// Custom class for Uniswap Wallet specific functionality
export class UniwalletConnect extends WalletConnectPopup {
export class UniwalletConnect extends WalletConnectV1 {
ANALYTICS_EVENT = 'Uniswap Wallet QR Scan'
static UNI_URI_AVAILABLE = 'uni_uri_available'

@ -16,7 +16,7 @@ const RPC_URLS_WITHOUT_FALLBACKS = Object.entries(RPC_URLS).reduce(
)
const optionalChains = [...L1_CHAIN_IDS, ...L2_CHAIN_IDS].filter((x) => x !== SupportedChainId.MAINNET)
export class WalletConnectV2Popup extends WalletConnect {
export class WalletConnectV2 extends WalletConnect {
ANALYTICS_EVENT = 'Wallet Connect QR Scan'
constructor({
actions,
@ -32,6 +32,10 @@ export class WalletConnectV2Popup extends WalletConnect {
chains: [SupportedChainId.MAINNET],
showQrModal: qrcode,
rpcMap: RPC_URLS_WITHOUT_FALLBACKS,
// as of 6/16/2023 there are no docs for `optionalMethods`
// this set of optional methods fixes a bug we encountered where permit2 signatures were never received from the connected wallet
// source: https://uniswapteam.slack.com/archives/C03R5G8T8BH/p1686858618164089?thread_ts=1686778867.145689&cid=C03R5G8T8BH
optionalMethods: ['eth_signTypedData', 'eth_signTypedData_v4', 'eth_sign'],
qrModalOptions: {
chainImages: undefined,
desktopWallets: undefined,

@ -23,7 +23,7 @@ describe('connection utility/metadata tests', () => {
const injected = getConnection(ConnectionType.INJECTED)
const coinbase = getConnection(ConnectionType.COINBASE_WALLET)
const uniswap = getConnection(ConnectionType.UNISWAP_WALLET)
const walletconnect = getConnection(ConnectionType.WALLET_CONNECT)
const walletconnect = getConnection(ConnectionType.WALLET_CONNECT_V2)
return { displayed, injected, coinbase, uniswap, walletconnect }
}

@ -16,8 +16,8 @@ import { RPC_URLS } from '../constants/networks'
import { RPC_PROVIDERS } from '../constants/providers'
import { Connection, ConnectionType } from './types'
import { getInjection, getIsCoinbaseWallet, getIsInjected, getIsMetaMaskWallet } from './utils'
import { UniwalletConnect, WalletConnectPopup } from './WalletConnect'
import { WalletConnectV2Popup } from './WalletConnectV2'
import { UniwalletConnect, WalletConnectV1 } from './WalletConnect'
import { WalletConnectV2 } from './WalletConnectV2'
function onError(error: Error) {
console.debug(`web3-react error: ${error}`)
@ -70,28 +70,28 @@ export const gnosisSafeConnection: Connection = {
shouldDisplay: () => false,
}
const [web3WalletConnect, web3WalletConnectHooks] = initializeConnector<WalletConnectPopup>(
(actions) => new WalletConnectPopup({ actions, onError })
const [web3WalletConnect, web3WalletConnectHooks] = initializeConnector<WalletConnectV1>(
(actions) => new WalletConnectV1({ actions, onError })
)
export const walletConnectConnection: Connection = {
getName: () => 'WalletConnect',
export const walletConnectV1Connection: Connection = {
getName: () => 'WalletConnectV1',
connector: web3WalletConnect,
hooks: web3WalletConnectHooks,
type: ConnectionType.WALLET_CONNECT,
getIcon: () => WALLET_CONNECT_ICON,
shouldDisplay: () => !getIsInjectedMobileBrowser(),
shouldDisplay: () => false,
}
const [web3WalletConnectV2, web3WalletConnectV2Hooks] = initializeConnector<WalletConnectV2Popup>(
(actions) => new WalletConnectV2Popup({ actions, onError })
const [web3WalletConnectV2, web3WalletConnectV2Hooks] = initializeConnector<WalletConnectV2>(
(actions) => new WalletConnectV2({ actions, onError })
)
export const walletConnectV2Connection: Connection = {
getName: () => 'WalletConnectV2',
getName: () => 'WalletConnect',
connector: web3WalletConnectV2,
hooks: web3WalletConnectV2Hooks,
type: ConnectionType.WALLET_CONNECT_V2,
getIcon: () => WALLET_CONNECT_ICON,
shouldDisplay: () => false,
shouldDisplay: () => !getIsInjectedMobileBrowser(),
}
const [web3UniwalletConnect, web3UniwalletConnectHooks] = initializeConnector<UniwalletConnect>(
@ -143,8 +143,8 @@ export function getConnections() {
return [
uniwalletConnectConnection,
injectedConnection,
walletConnectConnection,
walletConnectV2Connection,
walletConnectV1Connection,
coinbaseWalletConnection,
gnosisSafeConnection,
networkConnection,
@ -165,7 +165,7 @@ export function getConnection(c: Connector | ConnectionType) {
case ConnectionType.COINBASE_WALLET:
return coinbaseWalletConnection
case ConnectionType.WALLET_CONNECT:
return walletConnectConnection
return walletConnectV1Connection
case ConnectionType.WALLET_CONNECT_V2:
return walletConnectV2Connection
case ConnectionType.UNIWALLET:

@ -2,7 +2,7 @@ import { Connector } from '@web3-react/types'
import {
networkConnection,
uniwalletConnectConnection,
walletConnectConnection,
walletConnectV1Connection,
walletConnectV2Connection,
} from 'connection'
import { getChainInfo } from 'constants/chainInfo'
@ -28,8 +28,8 @@ export const switchChain = async (connector: Connector, chainId: SupportedChainI
throw new Error(`Chain ${chainId} not supported for connector (${typeof connector})`)
} else if (
[
walletConnectV1Connection.connector,
walletConnectV2Connection.connector,
walletConnectConnection.connector,
uniwalletConnectConnection.connector,
networkConnection.connector,
].includes(connector)