import React, {useState, useContext} from 'react' import {useQuery, useQueryClient} from 'react-query' import {useInterval} from '../hooks/use-interval' import {EpochPeriod} from '../types' import useNodeTiming from '../hooks/use-node-timing' import {useSettingsState} from './settings-context' import {fetchEpoch} from '../api' const EpochContext = React.createContext() const shouldRefetchEpoch = (epochData, timing) => { const {flipLottery, shortSession, longSession} = timing const {currentPeriod, nextValidation} = epochData const nextValidationTime = new Date(nextValidation).getTime() const currentDate = new Date().getTime() if ( currentDate > nextValidationTime + (shortSession + longSession) * 1000 && (currentPeriod === EpochPeriod.LongSession || currentPeriod === EpochPeriod.AfterLongSession) ) { return true } if ( currentDate > nextValidationTime + shortSession * 1000 && currentPeriod === EpochPeriod.ShortSession ) { return true } if ( currentDate > nextValidationTime && currentPeriod === EpochPeriod.FlipLottery ) { return true } if ( currentDate > nextValidationTime - flipLottery * 1000 && currentPeriod === EpochPeriod.None ) { return true } return false } export function EpochProvider(props) { const queryClient = useQueryClient() const {apiKey, url} = useSettingsState() const timing = useNodeTiming() const [lastModifiedEpochTime, setLastModifiedEpochTime] = useState(0) const {data: epochData} = useQuery( ['get-epoch', apiKey, url], () => fetchEpoch(), { retryDelay: 5 * 1000, initialData: null, } ) useInterval(() => { if (!epochData || !timing) return if (shouldRefetchEpoch(epochData, timing)) { const currentTime = new Date().getTime() if (Math.abs(currentTime - lastModifiedEpochTime > 15 * 1000)) { queryClient.invalidateQueries('get-epoch') setLastModifiedEpochTime(currentTime) } } }, 1000) return <EpochContext.Provider {...props} value={epochData ?? null} /> } export function useEpoch() { const context = useContext(EpochContext) if (context === undefined) { throw new Error('useEpoch must be used within a EpochProvider') } return context }