Commit 34a22ef9 authored by Charles Bachmeier's avatar Charles Bachmeier Committed by GitHub

fix: chain query parameter doesn't block you from switching chains (#6926)

* useSearchParams

* delete old param

* properly handle a connected wallet

* update chain query via network switcher

* updated tests

* working test

* comment typo

* don't overwrite current params

* change chain based on user wallet interaction

* one instance of set

* update chainIdRef on account load

* useeffect

* set chainIdRef when isActive

* remove logging

* update comment

* make condition else if
parent 5e86cf7b
...@@ -111,6 +111,7 @@ describe('network switching', () => { ...@@ -111,6 +111,7 @@ describe('network switching', () => {
cy.wait('@wallet_switchEthereumChain') cy.wait('@wallet_switchEthereumChain')
waitsForActiveChain('Polygon') waitsForActiveChain('Polygon')
cy.get(getTestSelector('web3-status-connected')) cy.get(getTestSelector('web3-status-connected'))
cy.url().should('contain', 'chain=polygon')
// Verify that the input/output fields were reset // Verify that the input/output fields were reset
cy.get('#swap-currency-input .token-amount-input').should('have.value', '') cy.get('#swap-currency-input .token-amount-input').should('have.value', '')
...@@ -127,4 +128,17 @@ describe('network switching from URL param', () => { ...@@ -127,4 +128,17 @@ describe('network switching from URL param', () => {
cy.wait('@wallet_switchEthereumChain') cy.wait('@wallet_switchEthereumChain')
waitsForActiveChain('Polygon') waitsForActiveChain('Polygon')
}) })
it('should be able to switch network after loading from URL param', () => {
cy.visit('/swap?chain=polygon', { ethereum: 'hardhat' })
cy.get(getTestSelector('web3-status-connected'))
cy.wait('@wallet_switchEthereumChain')
waitsForActiveChain('Polygon')
// switching to another chain clears query param
switchChain('Ethereum')
cy.wait('@wallet_switchEthereumChain')
waitsForActiveChain('Ethereum')
cy.url().should('not.contain', 'chain=polygon')
})
}) })
...@@ -2,7 +2,9 @@ import { ChainId } from '@uniswap/sdk-core' ...@@ -2,7 +2,9 @@ import { ChainId } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { getConnection } from 'connection' import { getConnection } from 'connection'
import { didUserReject } from 'connection/utils' import { didUserReject } from 'connection/utils'
import { CHAIN_IDS_TO_NAMES, isSupportedChain } from 'constants/chains'
import { useCallback } from 'react' import { useCallback } from 'react'
import { useSearchParams } from 'react-router-dom'
import { addPopup, PopupType } from 'state/application/reducer' import { addPopup, PopupType } from 'state/application/reducer'
import { useAppDispatch } from 'state/hooks' import { useAppDispatch } from 'state/hooks'
...@@ -12,6 +14,7 @@ export default function useSelectChain() { ...@@ -12,6 +14,7 @@ export default function useSelectChain() {
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const { connector } = useWeb3React() const { connector } = useWeb3React()
const switchChain = useSwitchChain() const switchChain = useSwitchChain()
const [searchParams, setSearchParams] = useSearchParams()
return useCallback( return useCallback(
async (targetChain: ChainId) => { async (targetChain: ChainId) => {
...@@ -21,6 +24,10 @@ export default function useSelectChain() { ...@@ -21,6 +24,10 @@ export default function useSelectChain() {
try { try {
await switchChain(connector, targetChain) await switchChain(connector, targetChain)
if (isSupportedChain(targetChain)) {
searchParams.set('chain', CHAIN_IDS_TO_NAMES[targetChain])
setSearchParams(searchParams)
}
} catch (error) { } catch (error) {
if (!didUserReject(connection, error) && error.code !== -32002 /* request already pending */) { if (!didUserReject(connection, error) && error.code !== -32002 /* request already pending */) {
console.error('Failed to switch networks', error) console.error('Failed to switch networks', error)
...@@ -33,6 +40,6 @@ export default function useSelectChain() { ...@@ -33,6 +40,6 @@ export default function useSelectChain() {
} }
} }
}, },
[connector, dispatch, switchChain] [connector, dispatch, searchParams, setSearchParams, switchChain]
) )
} }
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { CHAIN_IDS_TO_NAMES } from 'constants/chains' import { CHAIN_IDS_TO_NAMES, isSupportedChain } from 'constants/chains'
import { ParsedQs } from 'qs' import { ParsedQs } from 'qs'
import { useEffect } from 'react' import { useEffect, useRef } from 'react'
import { useSearchParams } from 'react-router-dom' import { useSearchParams } from 'react-router-dom'
import useParsedQueryString from './useParsedQueryString' import useParsedQueryString from './useParsedQueryString'
...@@ -21,8 +21,18 @@ function getParsedChainId(parsedQs?: ParsedQs) { ...@@ -21,8 +21,18 @@ function getParsedChainId(parsedQs?: ParsedQs) {
} }
export default function useSyncChainQuery() { export default function useSyncChainQuery() {
const { chainId, isActive } = useWeb3React() const { chainId, isActive, account } = useWeb3React()
const parsedQs = useParsedQueryString() const parsedQs = useParsedQueryString()
const chainIdRef = useRef(chainId)
const accountRef = useRef(account)
useEffect(() => {
// Update chainIdRef when the account is retrieved from Web3React
if (account && account !== accountRef.current) {
chainIdRef.current = chainId
accountRef.current = account
}
}, [account, chainId])
const urlChainId = getParsedChainId(parsedQs) const urlChainId = getParsedChainId(parsedQs)
...@@ -31,8 +41,22 @@ export default function useSyncChainQuery() { ...@@ -31,8 +41,22 @@ export default function useSyncChainQuery() {
const [searchParams, setSearchParams] = useSearchParams() const [searchParams, setSearchParams] = useSearchParams()
useEffect(() => { useEffect(() => {
if (isActive && urlChainId && chainId !== urlChainId) { // Change a user's chain on pageload if the connected chainId does not match the query param chain
if (isActive && urlChainId && chainIdRef.current === chainId && chainId !== urlChainId) {
selectChain(urlChainId) selectChain(urlChainId)
} }
}, [urlChainId, selectChain, searchParams, setSearchParams, isActive, chainId]) // If a user has a connected wallet and has manually changed their chain, update the query parameter if it's supported
else if (account && chainIdRef.current !== chainId && chainId !== urlChainId) {
if (isSupportedChain(chainId)) {
searchParams.set('chain', CHAIN_IDS_TO_NAMES[chainId])
} else {
searchParams.delete('chain')
}
setSearchParams(searchParams)
}
// If a user has a connected wallet and the chainId matches the query param chain, update the chainIdRef
else if (isActive && chainId === urlChainId) {
chainIdRef.current = urlChainId
}
}, [urlChainId, selectChain, searchParams, isActive, chainId, account, setSearchParams])
} }
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