Skip to content

Commit

Permalink
fix: downstream referential equality errors (#144)
Browse files Browse the repository at this point in the history
* improve key logic

* address comments

* fix e2e tests

* style(lint): lint action with ESLint

Co-authored-by: Jordan Frankfurt <jordanwfrankfurt@gmail.com>
Co-authored-by: Lint Action <lint-action@uniswap.org>
  • Loading branch information
3 people authored Aug 15, 2022
1 parent 133ed89 commit efe8d19
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 49 deletions.
72 changes: 28 additions & 44 deletions e2e/connect.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,88 +5,72 @@
import '@ethersproject/providers'
import 'jest-environment-hardhat'

import { render, RenderResult, waitFor } from '@testing-library/react'
import { waitFor } from '@testing-library/react'
import { tokens } from '@uniswap/default-token-list'
import React from 'react'

import { SwapWidget } from '../src'
import { renderWidget } from '../src/test'

const HARDHAT_ACCOUNT_DISPLAY_STRING = `${hardhat.account.address?.substring(
0,
6
)}...${hardhat.account.address?.substring(hardhat.account.address.length - 4)}`

describe('connect', () => {
let component: RenderResult
let account: HTMLElement
let connectWallet: HTMLElement
let toolbar: HTMLElement
let tokenSelect: HTMLElement

beforeEach(async () => {
component = render(<SwapWidget tokenList={tokens} />)
connectWallet = await component.findByTestId('connect-wallet')
toolbar = await component.findByTestId('toolbar')
tokenSelect = (await component.findAllByTestId('token-select'))[0]
})

describe('with no params, using fallback JSON RPC URL', () => {
it('prompts for wallet connection in the Wallet and Toolbar', async () => {
expect(toolbar.textContent).toBe('Connecting…')
await waitFor(() => expect(toolbar.textContent).not.toBe('Connecting…'))
expect(connectWallet.textContent).toBe('Connect wallet to swap')
const component = renderWidget(<SwapWidget tokenList={tokens} />)
const toolbar = await component.findByTestId('toolbar')
expect(toolbar.textContent).toBe('Connect wallet to swap')
const connectWallet = await component.findByTestId('connect-wallet')
expect(connectWallet.textContent).toBe('Connect wallet to swap')
})

it('expects widget not to be disabled', async () => {
expect(tokenSelect).toHaveProperty('disabled', true)
await waitFor(() => expect(toolbar.textContent).not.toBe('Connecting…'))
expect(tokenSelect).toHaveProperty('disabled', false)
const component = renderWidget(<SwapWidget tokenList={tokens} />)
const tokenSelect = (await component.findAllByTestId('token-select'))[0]
await waitFor(() => {
expect(tokenSelect).toHaveProperty('disabled', false)
})
})
})

describe('with valid jsonRpcUrlMap', () => {
it('prompts for wallet connection in the Wallet and Toolbar', async () => {
component = render(<SwapWidget tokenList={tokens} jsonRpcUrlMap={{ 1: [hardhat.url] }} />)
expect(connectWallet.textContent).toBe('Connect wallet to swap')
expect(toolbar.textContent).toBe('Connecting…')
await waitFor(() => expect(toolbar.textContent).not.toBe('Connecting…'))
const component = renderWidget(<SwapWidget tokenList={tokens} jsonRpcUrlMap={{ 1: [hardhat.url] }} />)
const connectWallet = await component.findByTestId('connect-wallet')
const toolbar = await component.findByTestId('toolbar')
expect(connectWallet.textContent).toBe('Connect wallet to swap')
expect(toolbar.textContent).toBe('Connect wallet to swap')
})

it('expects widget not to be disabled', async () => {
component = render(<SwapWidget tokenList={tokens} jsonRpcUrlMap={{ 1: [hardhat.url] }} />)
const component = renderWidget(<SwapWidget tokenList={tokens} jsonRpcUrlMap={{ 1: [hardhat.url] }} />)
let tokenSelect = (await component.findAllByTestId('token-select'))[0]
expect(tokenSelect).toHaveProperty('disabled', true)
const toolbar = await component.findByTestId('toolbar')
await waitFor(() => expect(toolbar.textContent).not.toBe('Connecting…'))
expect(tokenSelect).toHaveProperty('disabled', false)
tokenSelect = (await component.findAllByTestId('token-select'))[0]
await waitFor(() => expect(tokenSelect).toHaveProperty('disabled', false))
})
})

describe('with wallet provider', () => {
it('displays connected account chip', async () => {
component = render(<SwapWidget tokenList={tokens} provider={hardhat.provider} />)
const component = renderWidget(<SwapWidget tokenList={tokens} provider={hardhat.provider} />)
const toolbar = await component.findByTestId('toolbar')
await waitFor(() => expect(toolbar.textContent).not.toBe('Connecting…'))
account = await component.findByTestId('account')
expect(account.textContent?.toLowerCase()).toBe(HARDHAT_ACCOUNT_DISPLAY_STRING)
})

it('does not prompt for wallet connection in toolbar', async () => {
component = render(<SwapWidget tokenList={tokens} provider={hardhat.provider} />)
expect(toolbar.textContent).toBe('Connecting…')
await waitFor(
async () => {
toolbar = (await component.findAllByTestId('toolbar'))[1]
expect(toolbar.textContent).toBe('Enter an amount')
},
{ timeout: 10000 }
)
const account = await component.findByTestId('account')
await waitFor(() => expect(account.textContent?.toLowerCase()).toBe(HARDHAT_ACCOUNT_DISPLAY_STRING))
})

it('expects widget not to be disabled', async () => {
component = render(<SwapWidget tokenList={tokens} provider={hardhat.provider} />)
expect(tokenSelect).toHaveProperty('disabled', true)
const component = renderWidget(<SwapWidget tokenList={tokens} provider={hardhat.provider} />)
const toolbar = await component.findByTestId('toolbar')
await waitFor(() => expect(toolbar.textContent).not.toBe('Connecting…'))
expect(tokenSelect).toHaveProperty('disabled', false)
const tokenSelect = (await component.findAllByTestId('token-select'))[0]
await waitFor(() => expect(tokenSelect).toHaveProperty('disabled', false))
})
})
})
28 changes: 23 additions & 5 deletions src/hooks/connectWeb3/useWeb3React.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Connector, Provider as Eip1193Provider, Web3ReactStore } from '@web3-re
import { WalletConnect } from '@web3-react/walletconnect'
import { SupportedChainId } from 'constants/chains'
import { atom, useAtom } from 'jotai'
import { PropsWithChildren, useEffect, useMemo } from 'react'
import { PropsWithChildren, useEffect, useMemo, useRef } from 'react'
import JsonRpcConnector from 'utils/JsonRpcConnector'

export type Web3Connection = [Connector, Web3ReactHooks]
Expand Down Expand Up @@ -104,12 +104,30 @@ export function ActiveWeb3Provider({
[jsonRpcUrlMap, defaultChainId]
)

connections = [metaMaskConnection, walletConnectConnectionQR, walletConnectConnectionPopup, networkConnection]
if (integratorConnection) connections = [integratorConnection, ...connections]
const key = useRef(0)
connections = useMemo(() => {
// while react warns against triggering side effects in useMemo,
// in this instance we're only using the mutated value to generate a key,
// so tightly coupling the key update with the memo update shouldn't cause any issues,
// and most clearly expresses the intent
key.current += 1
return [
integratorConnection,
metaMaskConnection,
walletConnectConnectionQR,
walletConnectConnectionPopup,
networkConnection,
].filter((connection): connection is Web3Connection => Boolean(connection))
}, [
integratorConnection,
metaMaskConnection,
walletConnectConnectionQR,
walletConnectConnectionPopup,
networkConnection,
])

const key = `${connections.length}+${Object.entries(jsonRpcUrlMap)}+${propsDefaultChainId}+${defaultChainId}`
return (
<Web3ReactProvider connectors={connections} key={key}>
<Web3ReactProvider connectors={connections} key={key.current}>
{children}
</Web3ReactProvider>
)
Expand Down

1 comment on commit efe8d19

@vercel
Copy link

@vercel vercel bot commented on efe8d19 Aug 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

widgets – ./

widgets-uniswap.vercel.app
widgets-git-main-uniswap.vercel.app
widgets-seven-tau.vercel.app

Please sign in to comment.