Commit 984c742d authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

fix: use context for block number (#3708)

* fix: use context for block number

* fix: check for valid BlockNumberContext
parent 00b151d7
...@@ -3,7 +3,7 @@ import 'inter-ui' ...@@ -3,7 +3,7 @@ import 'inter-ui'
import 'polyfills' import 'polyfills'
import 'components/analytics' import 'components/analytics'
import { BlockUpdater } from 'lib/hooks/useBlockNumber' import { BlockNumberProvider } from 'lib/hooks/useBlockNumber'
import { MulticallUpdater } from 'lib/state/multicall' import { MulticallUpdater } from 'lib/state/multicall'
import { StrictMode } from 'react' import { StrictMode } from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
...@@ -40,7 +40,6 @@ function Updaters() { ...@@ -40,7 +40,6 @@ function Updaters() {
<UserUpdater /> <UserUpdater />
<ApplicationUpdater /> <ApplicationUpdater />
<TransactionUpdater /> <TransactionUpdater />
<BlockUpdater />
<MulticallUpdater /> <MulticallUpdater />
<LogsUpdater /> <LogsUpdater />
</> </>
...@@ -55,11 +54,13 @@ ReactDOM.render( ...@@ -55,11 +54,13 @@ ReactDOM.render(
<Web3ReactProvider getLibrary={getLibrary}> <Web3ReactProvider getLibrary={getLibrary}>
<Web3ProviderNetwork getLibrary={getLibrary}> <Web3ProviderNetwork getLibrary={getLibrary}>
<Blocklist> <Blocklist>
<BlockNumberProvider>
<Updaters /> <Updaters />
<ThemeProvider> <ThemeProvider>
<ThemedGlobalStyle /> <ThemedGlobalStyle />
<App /> <App />
</ThemeProvider> </ThemeProvider>
</BlockNumberProvider>
</Blocklist> </Blocklist>
</Web3ProviderNetwork> </Web3ProviderNetwork>
</Web3ReactProvider> </Web3ReactProvider>
......
...@@ -4,7 +4,7 @@ import { DEFAULT_LOCALE, SUPPORTED_LOCALES, SupportedLocale } from 'constants/lo ...@@ -4,7 +4,7 @@ import { DEFAULT_LOCALE, SUPPORTED_LOCALES, SupportedLocale } from 'constants/lo
import { Provider as AtomProvider } from 'jotai' import { Provider as AtomProvider } from 'jotai'
import { TransactionsUpdater } from 'lib/hooks/transactions' import { TransactionsUpdater } from 'lib/hooks/transactions'
import { ActiveWeb3Provider } from 'lib/hooks/useActiveWeb3React' import { ActiveWeb3Provider } from 'lib/hooks/useActiveWeb3React'
import { BlockUpdater } from 'lib/hooks/useBlockNumber' import { BlockNumberProvider } from 'lib/hooks/useBlockNumber'
import { Provider as I18nProvider } from 'lib/i18n' import { Provider as I18nProvider } from 'lib/i18n'
import { MulticallUpdater, store as multicallStore } from 'lib/state/multicall' import { MulticallUpdater, store as multicallStore } from 'lib/state/multicall'
import styled, { keyframes, Theme, ThemeProvider } from 'lib/theme' import styled, { keyframes, Theme, ThemeProvider } from 'lib/theme'
...@@ -83,7 +83,6 @@ const DialogWrapper = styled.div` ...@@ -83,7 +83,6 @@ const DialogWrapper = styled.div`
function Updaters() { function Updaters() {
return ( return (
<> <>
<BlockUpdater />
<MulticallUpdater /> <MulticallUpdater />
<TransactionsUpdater /> <TransactionsUpdater />
</> </>
...@@ -130,8 +129,10 @@ export default function Widget(props: PropsWithChildren<WidgetProps>) { ...@@ -130,8 +129,10 @@ export default function Widget(props: PropsWithChildren<WidgetProps>) {
<ReduxProvider store={multicallStore}> <ReduxProvider store={multicallStore}>
<AtomProvider> <AtomProvider>
<ActiveWeb3Provider provider={provider} jsonRpcEndpoint={jsonRpcEndpoint}> <ActiveWeb3Provider provider={provider} jsonRpcEndpoint={jsonRpcEndpoint}>
<BlockNumberProvider>
<Updaters /> <Updaters />
{children} {children}
</BlockNumberProvider>
</ActiveWeb3Provider> </ActiveWeb3Provider>
</AtomProvider> </AtomProvider>
</ReduxProvider> </ReduxProvider>
......
import useActiveWeb3React from 'hooks/useActiveWeb3React' import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useIsWindowVisible from 'hooks/useIsWindowVisible' import useIsWindowVisible from 'hooks/useIsWindowVisible'
import { atom } from 'jotai' import { createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { useAtomValue, useUpdateAtom } from 'jotai/utils'
import { useCallback, useEffect } from 'react'
interface ChainBlock { const MISSING_PROVIDER = Symbol()
chainId?: number const BlockNumberContext = createContext<
block?: number | {
value?: number
fastForward(block: number): void
}
| typeof MISSING_PROVIDER
>(MISSING_PROVIDER)
function useBlockNumberContext() {
const blockNumber = useContext(BlockNumberContext)
if (blockNumber === MISSING_PROVIDER) {
throw new Error('BlockNumber hooks must be wrapped in a <BlockNumberProvider>')
}
return blockNumber
} }
const chainBlockAtom = atom<ChainBlock>({})
function useUpdateChainBlock() { /** Requires that BlockUpdater be installed in the DOM tree. */
const { chainId, library } = useActiveWeb3React() export default function useBlockNumber(): number | undefined {
const windowVisible = useIsWindowVisible() return useBlockNumberContext().value
const setChainBlock = useUpdateAtom(chainBlockAtom) }
export function useFastForwardBlockNumber(): (block: number) => void {
return useBlockNumberContext().fastForward
}
export function BlockNumberProvider({ children }: { children: ReactNode }) {
const { chainId: activeChainId, library } = useActiveWeb3React()
const [{ chainId, block }, setChainBlock] = useState<{ chainId?: number; block?: number }>({ chainId: activeChainId })
const onBlock = useCallback( const onBlock = useCallback(
(block: number) => { (block: number) => {
setChainBlock((chainBlock) => { setChainBlock((chainBlock) => {
if (chainBlock.chainId === chainId) { if (chainBlock.chainId === activeChainId) {
if (!chainBlock.block || chainBlock.block < block) { if (!chainBlock.block || chainBlock.block < block) {
return { chainId, block } return { chainId: activeChainId, block }
} }
} }
return chainBlock return chainBlock
}) })
}, },
[chainId, setChainBlock] [activeChainId, setChainBlock]
) )
const windowVisible = useIsWindowVisible()
useEffect(() => { useEffect(() => {
if (library && chainId && windowVisible) { if (library && activeChainId && windowVisible) {
// If chainId hasn't changed, don't clear the block. This prevents re-fetching still valid data. // If chainId hasn't changed, don't clear the block. This prevents re-fetching still valid data.
setChainBlock((chainBlock) => (chainBlock.chainId === chainId ? chainBlock : { chainId })) setChainBlock((chainBlock) => (chainBlock.chainId === activeChainId ? chainBlock : { chainId: activeChainId }))
library library
.getBlockNumber() .getBlockNumber()
.then(onBlock) .then(onBlock)
.catch((error) => { .catch((error) => {
console.error(`Failed to get block number for chainId ${chainId}`, error) console.error(`Failed to get block number for chainId ${activeChainId}`, error)
}) })
library.on('block', onBlock) library.on('block', onBlock)
...@@ -47,23 +65,14 @@ function useUpdateChainBlock() { ...@@ -47,23 +65,14 @@ function useUpdateChainBlock() {
} }
} }
return undefined return undefined
}, [chainId, library, onBlock, setChainBlock, windowVisible]) }, [activeChainId, library, onBlock, setChainBlock, windowVisible])
}
export function BlockUpdater() {
useUpdateChainBlock()
return null
}
/** Requires that BlockUpdater be installed in the DOM tree. */
export default function useBlockNumber(): number | undefined {
const { chainId: activeChainId } = useActiveWeb3React()
const { chainId, block } = useAtomValue(chainBlockAtom)
return activeChainId === chainId ? block : undefined
}
export function useFastForwardBlockNumber(): (block: number) => void { const value = useMemo(
const { chainId } = useActiveWeb3React() () => ({
const setChainBlock = useUpdateAtom(chainBlockAtom) value: chainId === activeChainId ? block : undefined,
return useCallback((block: number) => setChainBlock({ chainId, block }), [chainId, setChainBlock]) fastForward: (block: number) => setChainBlock({ chainId: activeChainId, block }),
}),
[activeChainId, block, chainId]
)
return <BlockNumberContext.Provider value={value}>{children}</BlockNumberContext.Provider>
} }
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