Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔬 Make useRawLogs more efficient and responsive #1151

Merged
merged 25 commits into from
May 27, 2024
Merged
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5b4f0fd
Make useRawLogs more efficient and responsive
TylerEther Apr 21, 2024
620bdba
Improve useRawLogs
TylerEther Apr 30, 2024
5e10010
Fix and simplify nullish checking in deepEqual
TylerEther May 9, 2024
0611e13
Remove comment in deepEqual
TylerEther May 9, 2024
9450e66
Cleanup useResolvedFilter
TylerEther May 9, 2024
2617464
Move isPrimitive and deepEqual to common helper
TylerEther May 9, 2024
33d7551
Fix bug in deepEqual
TylerEther May 9, 2024
1bade54
Add comment to deepEqual
TylerEther May 9, 2024
5526c85
Make slight deepEqual performance improvement
TylerEther May 9, 2024
68a2aec
Add tests for deepEqual and isPrimitive
TylerEther May 9, 2024
cc92969
Export common in helpers
TylerEther May 9, 2024
3fdef33
Extract useResolvedFilter to useResolvedPromise
TylerEther May 9, 2024
5287f89
Add tests for useResolvedPromise
TylerEther May 9, 2024
adb11a6
Remove unused import
TylerEther May 9, 2024
7c429dd
Fix code smell
TylerEther May 9, 2024
3e05b97
Disable unused var linting
TylerEther May 9, 2024
99c4639
Improve performance of useResolvedPromise
TylerEther May 9, 2024
7447756
Fix staleness issue
TylerEther May 9, 2024
8501c3e
Fix bugs in useResolvedPromise
TylerEther May 9, 2024
53c335b
Disable buggy optimization
TylerEther May 9, 2024
548d973
Merge branch 'TrueFiEng:master' into use-raw-logs-improvements
TylerEther May 13, 2024
2363153
Merge branch 'master' into use-raw-logs-improvements
JustynaBroniszewska May 15, 2024
17d24e4
Merge branch 'master' into use-raw-logs-improvements
nezouse May 17, 2024
3371c32
Create hot-pots-tap.md
nezouse May 17, 2024
af09026
Merge branch 'master' into use-raw-logs-improvements
nezouse May 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 69 additions & 7 deletions packages/core/src/hooks/useRawLogs.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useEffect, useMemo, useState } from 'react'
import { useMemo, useState } from 'react'
import { useEthers } from './useEthers'
import { useReadonlyNetworks } from '../providers/network/readonlyNetworks'
import { useBlockNumbers, useBlockNumber } from '../hooks'
import { useBlockNumbers, useBlockNumber, useConfig } from '../hooks'
import { QueryParams } from '../constants/type/QueryParams'
import type { Filter, FilterByBlockHash, Log } from '@ethersproject/abstract-provider'
import { Falsy } from '../model/types'
import { ChainId } from '../constants'

/**
* Returns all blockchain logs given a block filter.
Expand All @@ -16,7 +17,7 @@ import { Falsy } from '../model/types'
* @public
*/
export function useRawLogs(
filter: Filter | FilterByBlockHash | Promise<Filter | FilterByBlockHash> | Falsy,
filter: Filter | FilterByBlockHash | Falsy,
queryParams: QueryParams = {}
): Log[] | undefined {
const { library } = useEthers()
Expand All @@ -25,21 +26,82 @@ export function useRawLogs(
const blockNumbers = useBlockNumbers()

const [logs, setLogs] = useState<Log[] | undefined>()
const [lastContractAddress, setLastContractAddress] = useState<string | undefined>()
const [lastTopics, setLastTopics] = useState<string | undefined>()
const [lastChainId, setLastChainId] = useState<ChainId | undefined>()
const [lastBlockNumber, setLastBlockNumber] = useState<number | undefined>()
const [isLoading, setIsLoading] = useState<boolean>(false)

const { chainId } = queryParams
const { chainId, isStatic } = queryParams
const config = useConfig()
const refresh = queryParams?.refresh ?? config.refresh

const [provider, blockNumber] = useMemo(
() => (chainId ? [providers[chainId], blockNumbers[chainId]] : [library, _blockNumber]),
[providers, library, blockNumbers, _blockNumber, chainId]
)

const deps: any[] = [provider]

const filterTopicsAsJson = filter && JSON.stringify(filter.topics)

// Push the filter elements to the dependencies. We do this individually b/c hook dependency checks are shallow
deps.push(filter && filter.address)
deps.push(filterTopicsAsJson)
deps.push(filter && (filter as FilterByBlockHash).blockHash)
deps.push(filter && (filter as Filter).fromBlock)
deps.push(filter && (filter as Filter).toBlock)

// Push the block number if we are not static
deps.push(!isStatic && refresh !== 'never' ? blockNumber : 0)

async function updateLogs() {
setLogs(!filter ? undefined : await provider?.getLogs(filter))
if (isLoading) {
// We are already loading, don't start another request
return
}

setIsLoading(true)
try {
let filterChanged = true
if (
chainId === lastChainId &&
filter &&
lastContractAddress === filter.address &&
lastTopics === filterTopicsAsJson
) {
// The filter did not change
filterChanged = false
} else {
// Filter changed. Reset logs
setLogs(undefined)
}

if (!filterChanged) {
if (isStatic || refresh === 'never') {
// Only update logs if contract address or topics changed
return
} else if (typeof refresh === 'number') {
// Only update logs if the block number has increased by the refresh interval
if (blockNumber && lastBlockNumber && blockNumber - lastBlockNumber < refresh) {
return
}
}
}

setLogs(!filter ? undefined : await provider?.getLogs(filter))
setLastContractAddress(!filter ? undefined : filter.address)
setLastTopics(!filter ? undefined : JSON.stringify(filter.topics))
setLastChainId(chainId)
setLastBlockNumber(blockNumber)
} finally {
setIsLoading(false)
}
}

useEffect(() => {
useMemo(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Also shouldn't useEffect behave the same as useMemo here. Why the change ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. I was playing around with what worked best. I've switched back to useEffect as they behave the same and to also handle cleanup procedures.

void updateLogs()
}, [provider, blockNumber])
}, deps)

return logs
}