Commit 2d61c725 authored by Jordan Frankfurt's avatar Jordan Frankfurt Committed by GitHub

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
parent 1a634c35
...@@ -3,7 +3,7 @@ import { BrowserEvent, InterfaceElementName, InterfaceEventName } from '@uniswap ...@@ -3,7 +3,7 @@ import { BrowserEvent, InterfaceElementName, InterfaceEventName } from '@uniswap
import { useAccountDrawer } from 'components/AccountDrawer' import { useAccountDrawer } from 'components/AccountDrawer'
import { ButtonEmphasis, ButtonSize, ThemeButton } from 'components/Button' import { ButtonEmphasis, ButtonSize, ThemeButton } from 'components/Button'
import Loader from 'components/Icons/LoadingSpinner' import Loader from 'components/Icons/LoadingSpinner'
import { walletConnectV2Connection } from 'connection' import { walletConnectV1Connection } from 'connection'
import { ActivationStatus, useActivationState } from 'connection/activate' import { ActivationStatus, useActivationState } from 'connection/activate'
import { Connection, ConnectionType } from 'connection/types' import { Connection, ConnectionType } from 'connection/types'
import { useOnClickOutside } from 'hooks/useOnClickOutside' import { useOnClickOutside } from 'hooks/useOnClickOutside'
...@@ -63,7 +63,7 @@ const IconWrapper = styled.div` ...@@ -63,7 +63,7 @@ const IconWrapper = styled.div`
align-items: flex-end; align-items: flex-end;
`}; `};
` `
const WCv2PopoverContent = styled(ThemeButton)` const WCv1PopoverContent = styled(ThemeButton)`
background: ${({ theme }) => theme.backgroundSurface}; background: ${({ theme }) => theme.backgroundSurface};
border: 1px solid ${({ theme }) => theme.backgroundOutline}; border: 1px solid ${({ theme }) => theme.backgroundOutline};
border-radius: 12px; border-radius: 12px;
...@@ -77,7 +77,7 @@ const WCv2PopoverContent = styled(ThemeButton)` ...@@ -77,7 +77,7 @@ const WCv2PopoverContent = styled(ThemeButton)`
z-index: ${Z_INDEX.popover}; z-index: ${Z_INDEX.popover};
` `
const TOGGLE_SIZE = 24 const TOGGLE_SIZE = 24
const WCv2PopoverToggle = styled.button` const WCv1PopoverToggle = styled.button`
align-items: center; align-items: center;
background-color: transparent; background-color: transparent;
border: none; border: none;
...@@ -117,15 +117,15 @@ const Wrapper = styled.div<{ disabled: boolean }>` ...@@ -117,15 +117,15 @@ const Wrapper = styled.div<{ disabled: boolean }>`
} }
` `
const WCv2Icon = styled.img` const WCv1Icon = styled.img`
height: 20px !important; height: 20px !important;
width: 20px !important; width: 20px !important;
` `
const WCv2BodyText = styled(ThemedText.BodyPrimary)` const WCv1BodyText = styled(ThemedText.BodyPrimary)`
margin-bottom: 4px; margin-bottom: 4px !important;
text-align: left; text-align: left;
` `
const WCv2Caption = styled(ThemedText.Caption)` const WCv1Caption = styled(ThemedText.Caption)`
text-align: left; text-align: left;
` `
...@@ -141,15 +141,15 @@ function PopupButtonContent({ connection, isDarkMode, show, onClick, onClose }: ...@@ -141,15 +141,15 @@ function PopupButtonContent({ connection, isDarkMode, show, onClick, onClose }:
useOnClickOutside(popoverElement, onClose) useOnClickOutside(popoverElement, onClose)
if (!show) return null if (!show) return null
return ( return (
<WCv2PopoverContent onClick={onClick} ref={popoverElement} size={ButtonSize.small} emphasis={ButtonEmphasis.medium}> <WCv1PopoverContent onClick={onClick} ref={popoverElement} size={ButtonSize.small} emphasis={ButtonEmphasis.medium}>
<IconWrapper> <IconWrapper>
<WCv2Icon src={connection.getIcon?.(isDarkMode)} alt={connection.getName()} /> <WCv1Icon src={connection.getIcon?.(isDarkMode)} alt={connection.getName()} />
</IconWrapper> </IconWrapper>
<div> <div>
<WCv2BodyText>Connect with v2</WCv2BodyText> <WCv1BodyText>Connect with v1</WCv1BodyText>
<WCv2Caption color="textSecondary">Under development and unsupported by most wallets</WCv2Caption> <WCv1Caption color="textSecondary">Support for v1 will be discontinued very soon.</WCv1Caption>
</div> </div>
</WCv2PopoverContent> </WCv1PopoverContent>
) )
} }
...@@ -158,30 +158,32 @@ interface OptionProps { ...@@ -158,30 +158,32 @@ interface OptionProps {
} }
export default function Option({ connection }: OptionProps) { export default function Option({ connection }: OptionProps) {
const { activationState, tryActivation } = useActivationState() const { activationState, tryActivation } = useActivationState()
const [WC2PromptOpen, setWC2PromptOpen] = useState(false) const [WC1PromptOpen, setWC1PromptOpen] = useState(false)
const [accountDrawerOpen, toggleAccountDrawerOpen] = useAccountDrawer() const [accountDrawerOpen, toggleAccountDrawerOpen] = useAccountDrawer()
const activate = () => tryActivation(connection, toggleAccountDrawerOpen) const activate = () => tryActivation(connection, toggleAccountDrawerOpen)
useEffect(() => { useEffect(() => {
if (!accountDrawerOpen) setWC2PromptOpen(false) if (!accountDrawerOpen) setWC1PromptOpen(false)
}, [accountDrawerOpen]) }, [accountDrawerOpen])
const isSomeOptionPending = activationState.status === ActivationStatus.PENDING const isSomeOptionPending = activationState.status === ActivationStatus.PENDING
const isCurrentOptionPending = isSomeOptionPending && activationState.connection.type === connection.type const isCurrentOptionPending = isSomeOptionPending && activationState.connection.type === connection.type
const isDarkMode = useIsDarkMode() const isDarkMode = useIsDarkMode()
const handleClickConnectViaWCv2 = (e: MouseEvent<HTMLButtonElement>) => { const handleClickConnectViaWCv1 = (e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation() e.stopPropagation()
tryActivation(walletConnectV2Connection, () => { tryActivation(walletConnectV1Connection, () => {
setWC2PromptOpen(false) setWC1PromptOpen(false)
toggleAccountDrawerOpen() toggleAccountDrawerOpen()
}) })
} }
const handleClickOpenWCv2Tooltip = (e: MouseEvent<HTMLButtonElement>) => { const handleClickOpenWCv1Tooltip = (e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation() e.stopPropagation()
setWC2PromptOpen(true) setWC1PromptOpen(true)
} }
const showExtraMenuToggle = connection.type === ConnectionType.WALLET_CONNECT_V2 && !isCurrentOptionPending
return ( return (
<Wrapper disabled={isSomeOptionPending}> <Wrapper disabled={isSomeOptionPending}>
<TraceEvent <TraceEvent
...@@ -207,17 +209,17 @@ export default function Option({ connection }: OptionProps) { ...@@ -207,17 +209,17 @@ export default function Option({ connection }: OptionProps) {
</OptionCardClickable> </OptionCardClickable>
</TraceEvent> </TraceEvent>
{connection.type === ConnectionType.WALLET_CONNECT && ( {showExtraMenuToggle && (
<> <>
<WCv2PopoverToggle onClick={handleClickOpenWCv2Tooltip} onMouseDown={handleClickOpenWCv2Tooltip}> <WCv1PopoverToggle onClick={handleClickOpenWCv1Tooltip} onMouseDown={handleClickOpenWCv1Tooltip}>
<MoreHorizontal /> <MoreHorizontal />
</WCv2PopoverToggle> </WCv1PopoverToggle>
<PopupButtonContent <PopupButtonContent
connection={connection} connection={connection}
isDarkMode={isDarkMode} isDarkMode={isDarkMode}
show={WC2PromptOpen} show={WC1PromptOpen}
onClick={handleClickConnectViaWCv2} onClick={handleClickConnectViaWCv1}
onClose={() => setWC2PromptOpen(false)} onClose={() => setWC1PromptOpen(false)}
/> />
</> </>
)} )}
......
...@@ -14,7 +14,7 @@ const RPC_URLS_WITHOUT_FALLBACKS = Object.entries(RPC_URLS).reduce( ...@@ -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' ANALYTICS_EVENT = 'Wallet Connect QR Scan'
constructor({ constructor({
actions, actions,
...@@ -31,7 +31,7 @@ export class WalletConnectPopup extends WalletConnect { ...@@ -31,7 +31,7 @@ export class WalletConnectPopup extends WalletConnect {
} }
// Custom class for Uniswap Wallet specific functionality // Custom class for Uniswap Wallet specific functionality
export class UniwalletConnect extends WalletConnectPopup { export class UniwalletConnect extends WalletConnectV1 {
ANALYTICS_EVENT = 'Uniswap Wallet QR Scan' ANALYTICS_EVENT = 'Uniswap Wallet QR Scan'
static UNI_URI_AVAILABLE = 'uni_uri_available' static UNI_URI_AVAILABLE = 'uni_uri_available'
......
...@@ -16,7 +16,7 @@ const RPC_URLS_WITHOUT_FALLBACKS = Object.entries(RPC_URLS).reduce( ...@@ -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) 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' ANALYTICS_EVENT = 'Wallet Connect QR Scan'
constructor({ constructor({
actions, actions,
...@@ -32,6 +32,10 @@ export class WalletConnectV2Popup extends WalletConnect { ...@@ -32,6 +32,10 @@ export class WalletConnectV2Popup extends WalletConnect {
chains: [SupportedChainId.MAINNET], chains: [SupportedChainId.MAINNET],
showQrModal: qrcode, showQrModal: qrcode,
rpcMap: RPC_URLS_WITHOUT_FALLBACKS, 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: { qrModalOptions: {
chainImages: undefined, chainImages: undefined,
desktopWallets: undefined, desktopWallets: undefined,
......
...@@ -23,7 +23,7 @@ describe('connection utility/metadata tests', () => { ...@@ -23,7 +23,7 @@ describe('connection utility/metadata tests', () => {
const injected = getConnection(ConnectionType.INJECTED) const injected = getConnection(ConnectionType.INJECTED)
const coinbase = getConnection(ConnectionType.COINBASE_WALLET) const coinbase = getConnection(ConnectionType.COINBASE_WALLET)
const uniswap = getConnection(ConnectionType.UNISWAP_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 } return { displayed, injected, coinbase, uniswap, walletconnect }
} }
......
...@@ -16,8 +16,8 @@ import { RPC_URLS } from '../constants/networks' ...@@ -16,8 +16,8 @@ import { RPC_URLS } from '../constants/networks'
import { RPC_PROVIDERS } from '../constants/providers' import { RPC_PROVIDERS } from '../constants/providers'
import { Connection, ConnectionType } from './types' import { Connection, ConnectionType } from './types'
import { getInjection, getIsCoinbaseWallet, getIsInjected, getIsMetaMaskWallet } from './utils' import { getInjection, getIsCoinbaseWallet, getIsInjected, getIsMetaMaskWallet } from './utils'
import { UniwalletConnect, WalletConnectPopup } from './WalletConnect' import { UniwalletConnect, WalletConnectV1 } from './WalletConnect'
import { WalletConnectV2Popup } from './WalletConnectV2' import { WalletConnectV2 } from './WalletConnectV2'
function onError(error: Error) { function onError(error: Error) {
console.debug(`web3-react error: ${error}`) console.debug(`web3-react error: ${error}`)
...@@ -70,28 +70,28 @@ export const gnosisSafeConnection: Connection = { ...@@ -70,28 +70,28 @@ export const gnosisSafeConnection: Connection = {
shouldDisplay: () => false, shouldDisplay: () => false,
} }
const [web3WalletConnect, web3WalletConnectHooks] = initializeConnector<WalletConnectPopup>( const [web3WalletConnect, web3WalletConnectHooks] = initializeConnector<WalletConnectV1>(
(actions) => new WalletConnectPopup({ actions, onError }) (actions) => new WalletConnectV1({ actions, onError })
) )
export const walletConnectConnection: Connection = { export const walletConnectV1Connection: Connection = {
getName: () => 'WalletConnect', getName: () => 'WalletConnectV1',
connector: web3WalletConnect, connector: web3WalletConnect,
hooks: web3WalletConnectHooks, hooks: web3WalletConnectHooks,
type: ConnectionType.WALLET_CONNECT, type: ConnectionType.WALLET_CONNECT,
getIcon: () => WALLET_CONNECT_ICON, getIcon: () => WALLET_CONNECT_ICON,
shouldDisplay: () => !getIsInjectedMobileBrowser(), shouldDisplay: () => false,
} }
const [web3WalletConnectV2, web3WalletConnectV2Hooks] = initializeConnector<WalletConnectV2Popup>( const [web3WalletConnectV2, web3WalletConnectV2Hooks] = initializeConnector<WalletConnectV2>(
(actions) => new WalletConnectV2Popup({ actions, onError }) (actions) => new WalletConnectV2({ actions, onError })
) )
export const walletConnectV2Connection: Connection = { export const walletConnectV2Connection: Connection = {
getName: () => 'WalletConnectV2', getName: () => 'WalletConnect',
connector: web3WalletConnectV2, connector: web3WalletConnectV2,
hooks: web3WalletConnectV2Hooks, hooks: web3WalletConnectV2Hooks,
type: ConnectionType.WALLET_CONNECT_V2, type: ConnectionType.WALLET_CONNECT_V2,
getIcon: () => WALLET_CONNECT_ICON, getIcon: () => WALLET_CONNECT_ICON,
shouldDisplay: () => false, shouldDisplay: () => !getIsInjectedMobileBrowser(),
} }
const [web3UniwalletConnect, web3UniwalletConnectHooks] = initializeConnector<UniwalletConnect>( const [web3UniwalletConnect, web3UniwalletConnectHooks] = initializeConnector<UniwalletConnect>(
...@@ -143,8 +143,8 @@ export function getConnections() { ...@@ -143,8 +143,8 @@ export function getConnections() {
return [ return [
uniwalletConnectConnection, uniwalletConnectConnection,
injectedConnection, injectedConnection,
walletConnectConnection,
walletConnectV2Connection, walletConnectV2Connection,
walletConnectV1Connection,
coinbaseWalletConnection, coinbaseWalletConnection,
gnosisSafeConnection, gnosisSafeConnection,
networkConnection, networkConnection,
...@@ -165,7 +165,7 @@ export function getConnection(c: Connector | ConnectionType) { ...@@ -165,7 +165,7 @@ export function getConnection(c: Connector | ConnectionType) {
case ConnectionType.COINBASE_WALLET: case ConnectionType.COINBASE_WALLET:
return coinbaseWalletConnection return coinbaseWalletConnection
case ConnectionType.WALLET_CONNECT: case ConnectionType.WALLET_CONNECT:
return walletConnectConnection return walletConnectV1Connection
case ConnectionType.WALLET_CONNECT_V2: case ConnectionType.WALLET_CONNECT_V2:
return walletConnectV2Connection return walletConnectV2Connection
case ConnectionType.UNIWALLET: case ConnectionType.UNIWALLET:
......
...@@ -2,7 +2,7 @@ import { Connector } from '@web3-react/types' ...@@ -2,7 +2,7 @@ import { Connector } from '@web3-react/types'
import { import {
networkConnection, networkConnection,
uniwalletConnectConnection, uniwalletConnectConnection,
walletConnectConnection, walletConnectV1Connection,
walletConnectV2Connection, walletConnectV2Connection,
} from 'connection' } from 'connection'
import { getChainInfo } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
...@@ -28,8 +28,8 @@ export const switchChain = async (connector: Connector, chainId: SupportedChainI ...@@ -28,8 +28,8 @@ export const switchChain = async (connector: Connector, chainId: SupportedChainI
throw new Error(`Chain ${chainId} not supported for connector (${typeof connector})`) throw new Error(`Chain ${chainId} not supported for connector (${typeof connector})`)
} else if ( } else if (
[ [
walletConnectV1Connection.connector,
walletConnectV2Connection.connector, walletConnectV2Connection.connector,
walletConnectConnection.connector,
uniwalletConnectConnection.connector, uniwalletConnectConnection.connector,
networkConnection.connector, networkConnection.connector,
].includes(connector) ].includes(connector)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment