import { PostageBatch } from '@ethersphere/bee-js' import { createContext, ReactChild, ReactElement, useContext, useEffect, useState } from 'react' import { Context as SettingsContext } from './Settings' export interface EnrichedPostageBatch extends PostageBatch { usage: number usageText: string } interface ContextInterface { stamps: EnrichedPostageBatch[] | null error: Error | null isLoading: boolean lastUpdate: number | null start: (frequency?: number) => void stop: () => void refresh: () => Promise } const initialValues: ContextInterface = { stamps: null, error: null, isLoading: false, lastUpdate: null, start: () => {}, // eslint-disable-line stop: () => {}, // eslint-disable-line refresh: () => Promise.reject(), } export const Context = createContext(initialValues) export const Consumer = Context.Consumer interface Props { children: ReactChild } export function enrichStamp(postageBatch: PostageBatch): EnrichedPostageBatch { const { depth, bucketDepth, utilization } = postageBatch const usage = utilization / Math.pow(2, depth - bucketDepth) const usageText = `${Math.ceil(usage * 100)}%` return { ...postageBatch, usage, usageText, } } export function Provider({ children }: Props): ReactElement { const { beeDebugApi } = useContext(SettingsContext) const [stamps, setStamps] = useState(initialValues.stamps) const [error, setError] = useState(initialValues.error) const [isLoading, setIsLoading] = useState(initialValues.isLoading) const [lastUpdate, setLastUpdate] = useState(initialValues.lastUpdate) const [frequency, setFrequency] = useState(null) const refresh = async () => { // Don't want to refresh when already refreshing if (isLoading) return if (!beeDebugApi) return try { setIsLoading(true) const stamps = await beeDebugApi.getAllPostageBatch() setStamps(stamps.filter(x => x.exists).map(enrichStamp)) setLastUpdate(Date.now()) } catch (e) { setError(e as Error) } finally { setIsLoading(false) } } const start = (freq = 30000) => setFrequency(freq) const stop = () => setFrequency(null) // Start the update loop useEffect(() => { refresh() // Start autorefresh only if the frequency is set if (frequency) { const interval = setInterval(refresh, frequency) return () => clearInterval(interval) } }, [frequency]) // eslint-disable-line react-hooks/exhaustive-deps return ( {children} ) }