1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00
market/src/hooks/useGraphSyncStatus.ts
Norbi b8247c7ef4
The Graph sync status (#466)
* WIP

* query update

* quick fix

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* get blocks number when no provider, added threshold

* format code

* naming fix

* show graph out of sync message inside announcement banner

* added loader

* moved sync component

* refactor all the things

* new atoms/AnnouncementBanner : banner component reduced to presentation only, where its content is always passed as props

* revised molecules/NetworkBanner: the former AnnouncementBanner now holds all the specific network detection logic, in the end also returns the atoms/AnnouncementBanner

* new hook hooks/useGraphSyncStatus: move all the graph fetching logic in there so we can use its status in multiple places in the app without all this props passing. This also decouples the SyncStatus component in footer from its logic

* in App.tsx, add the graph sync warning banner in another atoms/AnnouncementBanner, getting its values from the hook

* data flow refactor

* .env.example tweak

* race condition fighting

* subgraph loading

* polygon fallback fix

* no interval fetching

* turn around logic for adding infura ID

* removed graphNotSynched

Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro>
Co-authored-by: Norbi <katunanorbert@gmai.com>
Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
2021-04-13 10:57:59 +02:00

105 lines
3.5 KiB
TypeScript

import { useState, useEffect } from 'react'
import fetch from 'cross-fetch'
import { useOcean } from '../providers/Ocean'
import { useWeb3 } from '../providers/Web3'
import { Logger } from '@oceanprotocol/lib'
import Web3 from 'web3'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
const blockDifferenceThreshold = 30
const ethGraphUrl = `https://api.thegraph.com/subgraphs/name/blocklytics/ethereum-blocks`
const ethGraphQuery =
'{"query":" query Blocks{ blocks(first: 1, skip: 0, orderBy: number, orderDirection: desc, where: {number_gt: 9300000}) { id number timestamp author difficulty gasUsed gasLimit } }","variables":{},"operationName":"Blocks"}'
const graphQuery =
'{"query":" query Meta { _meta { block { hash number } deployment hasIndexingErrors } }","variables":{},"operationName":"Meta"}'
export interface UseGraphSyncStatus {
isGraphSynced: boolean
blockHead: number
blockGraph: number
}
async function fetchGraph(url: string, queryBody: string): Promise<Response> {
try {
const response = await fetch(url, {
method: 'POST',
body: queryBody
})
return await response.json()
} catch (error) {
console.error('Error parsing json: ' + error.message)
}
}
async function getBlockHead(config: ConfigHelperConfig) {
// for ETH main, get block from graph fetch
if (config.network === 'mainnet') {
const response: any = await fetchGraph(ethGraphUrl, ethGraphQuery)
return Number(response.data.blocks[0].number)
}
// for everything else, create new web3 instance with infura
const web3Instance = new Web3(config.nodeUri)
const blockHead = await web3Instance.eth.getBlockNumber()
return blockHead
}
async function getBlockSubgraph(subgraphUri: string) {
const response: any = await fetchGraph(
`${subgraphUri}/subgraphs/name/oceanprotocol/ocean-subgraph`,
graphQuery
)
const blockNumberGraph = Number(response.data._meta.block.number)
return blockNumberGraph
}
export function useGraphSyncStatus(): UseGraphSyncStatus {
const { config } = useOcean()
const { block, web3Loading } = useWeb3()
const [blockGraph, setBlockGraph] = useState<number>()
const [blockHead, setBlockHead] = useState<number>()
const [isGraphSynced, setIsGraphSynced] = useState(true)
const [subgraphLoading, setSubgraphLoading] = useState(false)
// Get and set head block
useEffect(() => {
if (!config || !config.nodeUri || web3Loading) return
async function initBlockHead() {
const blockHead = block || (await getBlockHead(config))
setBlockHead(blockHead)
Logger.log('[GraphStatus] Head block: ', blockHead)
}
initBlockHead()
}, [web3Loading, block, config.nodeUri])
// Get and set subgraph block
useEffect(() => {
if (!config || !config.subgraphUri) return
async function initBlockSubgraph() {
setSubgraphLoading(true)
const blockGraph = await getBlockSubgraph(config.subgraphUri)
setBlockGraph(blockGraph)
setSubgraphLoading(false)
Logger.log('[GraphStatus] Latest block from subgraph: ', blockGraph)
}
initBlockSubgraph()
}, [config.subgraphUri])
// Set sync status
useEffect(() => {
if ((!blockGraph && !blockHead) || web3Loading || subgraphLoading) return
const difference = blockHead - blockGraph
if (difference > blockDifferenceThreshold) {
setIsGraphSynced(false)
return
}
setIsGraphSynced(true)
}, [blockGraph, blockHead])
return { blockHead, blockGraph, isGraphSynced }
}