feat: changing API urls does not need the app refresh (#173)
* feat: changing API urls does not need the app refresh * fix: propagate beeDebugApi and beeApi change to the refresh interval * fix: any failed request on the Bee provider does not stop the execution of other requests * fix: error handling for incorrect bee and bee debug urls * fix: change debug API in the settings tab
This commit is contained in:
+125
-28
@@ -1,9 +1,9 @@
|
||||
import type { ChequebookBalance, Balance, Settlements } from '../types'
|
||||
import { createContext, ReactChild, ReactElement, useEffect, useState } from 'react'
|
||||
import { beeApi, beeDebugApi } from '../services/bee'
|
||||
import { createContext, ReactChild, ReactElement, useEffect, useState, useContext } from 'react'
|
||||
import { Token } from '../models/Token'
|
||||
import semver from 'semver'
|
||||
import { engines } from '../../package.json'
|
||||
import { Context as SettingsContext } from './Settings'
|
||||
|
||||
import type {
|
||||
NodeAddresses,
|
||||
@@ -125,6 +125,7 @@ function getStatus(
|
||||
}
|
||||
|
||||
export function Provider({ children }: Props): ReactElement {
|
||||
const { beeApi, beeDebugApi } = useContext(SettingsContext)
|
||||
const [apiHealth, setApiHealth] = useState<boolean>(false)
|
||||
const [debugApiHealth, setDebugApiHealth] = useState<Health | null>(null)
|
||||
const [nodeAddresses, setNodeAddresses] = useState<NodeAddresses | null>(null)
|
||||
@@ -147,47 +148,143 @@ export function Provider({ children }: Props): ReactElement {
|
||||
const latestUserVersion = semver.coerce(debugApiHealth?.version)?.version
|
||||
const latestUserVersionExact = debugApiHealth?.version
|
||||
|
||||
useEffect(() => {
|
||||
setIsLoading(true)
|
||||
|
||||
setApiHealth(false)
|
||||
|
||||
refresh()
|
||||
}, [beeApi])
|
||||
|
||||
useEffect(() => {
|
||||
setIsLoading(true)
|
||||
|
||||
setDebugApiHealth(null)
|
||||
setNodeAddresses(null)
|
||||
setNodeTopology(null)
|
||||
setPeers(null)
|
||||
setChequebookAddress(null)
|
||||
setChequebookBalance(null)
|
||||
setPeerBalances(null)
|
||||
setPeerCheques(null)
|
||||
setSettlements(null)
|
||||
|
||||
refresh()
|
||||
}, [beeDebugApi])
|
||||
|
||||
const refresh = async () => {
|
||||
// Don't want to refresh when already refreshing
|
||||
if (isRefreshing) return
|
||||
|
||||
// Not a valid bee api
|
||||
if (!beeApi || !beeDebugApi) {
|
||||
setIsLoading(false)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
setIsRefreshing(true)
|
||||
setError(null)
|
||||
|
||||
setApiHealth(await beeApi.status.health())
|
||||
setDebugApiHealth(await beeDebugApi.status.nodeHealth())
|
||||
setNodeAddresses(await beeDebugApi.connectivity.addresses())
|
||||
setNodeTopology(await beeDebugApi.connectivity.topology())
|
||||
setChequebookAddress(await beeDebugApi.chequebook.address())
|
||||
setPeers(await beeDebugApi.connectivity.listPeers())
|
||||
// Wrap the chequebook balance call to return BZZ values as Token object
|
||||
const chequeBalanceWrapper = async () => {
|
||||
const { totalBalance, availableBalance } = await beeDebugApi.getChequebookBalance()
|
||||
|
||||
const { totalBalance, availableBalance } = await beeDebugApi.chequebook.balance()
|
||||
setChequebookBalance({
|
||||
totalBalance: new Token(totalBalance),
|
||||
availableBalance: new Token(availableBalance),
|
||||
})
|
||||
return {
|
||||
totalBalance: new Token(totalBalance),
|
||||
availableBalance: new Token(availableBalance),
|
||||
}
|
||||
}
|
||||
|
||||
const { balances } = await beeDebugApi.balance.balances()
|
||||
setPeerBalances(balances.map(({ peer, balance }) => ({ peer, balance: new Token(balance) })))
|
||||
// Wrap the balances call to return BZZ values as Token object
|
||||
const peerBalanceWrapper = async () => {
|
||||
const { balances } = await beeDebugApi.getAllBalances()
|
||||
|
||||
setPeerCheques(await beeDebugApi.chequebook.getLastCheques())
|
||||
const { totalReceived, settlements, totalSent } = await beeDebugApi.settlements.getSettlements()
|
||||
setSettlements({
|
||||
totalReceived: new Token(totalReceived),
|
||||
totalSent: new Token(totalSent),
|
||||
settlements: settlements.map(({ peer, received, sent }) => ({
|
||||
peer,
|
||||
received: new Token(received),
|
||||
sent: new Token(sent),
|
||||
})),
|
||||
})
|
||||
return balances.map(({ peer, balance }) => ({ peer, balance: new Token(balance) }))
|
||||
}
|
||||
|
||||
setLastUpdate(Date.now())
|
||||
// Wrap the settlements call to return BZZ values as Token object
|
||||
const settlementsWrapper = async () => {
|
||||
const { totalReceived, settlements, totalSent } = await beeDebugApi.getAllSettlements()
|
||||
|
||||
return {
|
||||
totalReceived: new Token(totalReceived),
|
||||
totalSent: new Token(totalSent),
|
||||
settlements: settlements.map(({ peer, received, sent }) => ({
|
||||
peer,
|
||||
received: new Token(received),
|
||||
sent: new Token(sent),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
const promises = [
|
||||
// API health
|
||||
beeApi
|
||||
.isConnected()
|
||||
.then(setApiHealth)
|
||||
.catch(() => setApiHealth(false)),
|
||||
|
||||
// Debug API health
|
||||
beeDebugApi
|
||||
.getHealth()
|
||||
.then(setDebugApiHealth)
|
||||
.catch(() => setDebugApiHealth(null)),
|
||||
|
||||
// Node Addresses
|
||||
beeDebugApi
|
||||
.getNodeAddresses()
|
||||
.then(setNodeAddresses)
|
||||
.catch(() => setNodeAddresses(null)),
|
||||
|
||||
// Network Topology
|
||||
beeDebugApi
|
||||
.getTopology()
|
||||
.then(setNodeTopology)
|
||||
.catch(() => setNodeTopology(null)),
|
||||
|
||||
// Peers
|
||||
beeDebugApi
|
||||
.getPeers()
|
||||
.then(setPeers)
|
||||
.catch(() => setPeers(null)),
|
||||
|
||||
// Chequebook address
|
||||
beeDebugApi
|
||||
.getChequebookAddress()
|
||||
.then(setChequebookAddress)
|
||||
.catch(() => setChequebookAddress(null)),
|
||||
|
||||
// Cheques
|
||||
beeDebugApi
|
||||
.getLastCheques()
|
||||
.then(setPeerCheques)
|
||||
.catch(() => setPeerCheques(null)),
|
||||
|
||||
// Chequebook balance
|
||||
chequeBalanceWrapper()
|
||||
.then(setChequebookBalance)
|
||||
.catch(() => setChequebookBalance(null)),
|
||||
|
||||
// Peer balances
|
||||
peerBalanceWrapper()
|
||||
.then(setPeerBalances)
|
||||
.catch(() => setPeerBalances(null)),
|
||||
|
||||
// Settlements
|
||||
settlementsWrapper()
|
||||
.then(setSettlements)
|
||||
.catch(() => setSettlements(null)),
|
||||
]
|
||||
|
||||
await Promise.allSettled(promises)
|
||||
} catch (e) {
|
||||
setError(e)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
setIsRefreshing(false)
|
||||
setLastUpdate(Date.now())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +301,7 @@ export function Provider({ children }: Props): ReactElement {
|
||||
|
||||
return () => clearInterval(interval)
|
||||
}
|
||||
}, [frequency])
|
||||
}, [frequency, beeDebugApi, beeApi])
|
||||
|
||||
return (
|
||||
<Context.Provider
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { createContext, ReactChild, ReactElement, useState, useEffect } from 'react'
|
||||
import { Bee, BeeDebug } from '@ethersphere/bee-js'
|
||||
|
||||
interface ContextInterface {
|
||||
apiUrl: string
|
||||
apiDebugUrl: string
|
||||
beeApi: Bee | null
|
||||
beeDebugApi: BeeDebug | null
|
||||
setApiUrl: (url: string) => void
|
||||
setDebugApiUrl: (url: string) => void
|
||||
}
|
||||
|
||||
const initialValues: ContextInterface = {
|
||||
apiUrl: sessionStorage.getItem('api_host') || process.env.REACT_APP_BEE_HOST || 'http://localhost:1633',
|
||||
apiDebugUrl:
|
||||
sessionStorage.getItem('debug_api_host') || process.env.REACT_APP_BEE_DEBUG_HOST || 'http://localhost:1635',
|
||||
beeApi: null,
|
||||
beeDebugApi: null,
|
||||
setApiUrl: (url: string) => {}, // eslint-disable-line
|
||||
setDebugApiUrl: (url: string) => {}, // eslint-disable-line
|
||||
}
|
||||
|
||||
export const Context = createContext<ContextInterface>(initialValues)
|
||||
export const Consumer = Context.Consumer
|
||||
|
||||
interface Props {
|
||||
children: ReactChild
|
||||
}
|
||||
|
||||
export function Provider({ children }: Props): ReactElement {
|
||||
const [apiUrl, setApiUrl] = useState<string>(initialValues.apiUrl)
|
||||
const [apiDebugUrl, setDebugApiUrl] = useState<string>(initialValues.apiDebugUrl)
|
||||
const [beeApi, setBeeApi] = useState<Bee | null>(null)
|
||||
const [beeDebugApi, setBeeDebugApi] = useState<BeeDebug | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
setBeeApi(new Bee(apiUrl))
|
||||
sessionStorage.setItem('api_host', apiUrl)
|
||||
} catch (e) {
|
||||
setBeeApi(null)
|
||||
}
|
||||
}, [apiUrl])
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
setBeeDebugApi(new BeeDebug(apiDebugUrl))
|
||||
sessionStorage.setItem('debug_api_host', apiDebugUrl)
|
||||
} catch (e) {
|
||||
setBeeDebugApi(null)
|
||||
}
|
||||
}, [apiDebugUrl])
|
||||
|
||||
return (
|
||||
<Context.Provider value={{ apiUrl, apiDebugUrl, beeApi, beeDebugApi, setApiUrl, setDebugApiUrl }}>
|
||||
{children}
|
||||
</Context.Provider>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PostageBatch } from '@ethersphere/bee-js'
|
||||
import { createContext, ReactChild, ReactElement, useEffect, useState } from 'react'
|
||||
import { beeApi } from '../services/bee'
|
||||
import { createContext, ReactChild, ReactElement, useEffect, useState, useContext } from 'react'
|
||||
import { Context as SettingsContext } from './Settings'
|
||||
|
||||
export interface EnrichedPostageBatch extends PostageBatch {
|
||||
usage: number
|
||||
@@ -48,6 +48,7 @@ function enrichStamp(postageBatch: PostageBatch): EnrichedPostageBatch {
|
||||
}
|
||||
|
||||
export function Provider({ children }: Props): ReactElement {
|
||||
const { beeApi } = useContext(SettingsContext)
|
||||
const [stamps, setStamps] = useState<EnrichedPostageBatch[] | null>(initialValues.stamps)
|
||||
const [error, setError] = useState<Error | null>(initialValues.error)
|
||||
const [isLoading, setIsLoading] = useState<boolean>(initialValues.isLoading)
|
||||
@@ -58,9 +59,11 @@ export function Provider({ children }: Props): ReactElement {
|
||||
// Don't want to refresh when already refreshing
|
||||
if (isLoading) return
|
||||
|
||||
if (!beeApi) return
|
||||
|
||||
try {
|
||||
setIsLoading(true)
|
||||
const stamps = await beeApi.stamps.getPostageStamps()
|
||||
const stamps = await beeApi.getAllPostageBatch()
|
||||
|
||||
setStamps(stamps.map(enrichStamp))
|
||||
setLastUpdate(Date.now())
|
||||
|
||||
Reference in New Issue
Block a user