added new page with node redistribution statistics

This commit is contained in:
2025-09-09 09:29:56 +08:00
committed by OpenCode
parent b3137fbef1
commit b5b0d37e94
6 changed files with 127 additions and 1 deletions
+71
View File
@@ -0,0 +1,71 @@
import { RedistributionState, BZZ, DAI } from '@ethersphere/bee-js'
import { useContext, useEffect, useState } from 'react'
import { Context } from '../providers/Settings'
import ExpandableListItem from './ExpandableListItem'
export function Redistribution() {
const { beeApi } = useContext(Context)
const [redistributionState, setRedistributionState] = useState<RedistributionState | null>(null)
useEffect(() => {
const interval = setInterval(() => {
if (!beeApi) {
return
}
beeApi.getRedistributionState().then(setRedistributionState).catch(console.error) // eslint-disable-line
}, 3_000)
return () => clearInterval(interval)
})
const formatDurationSeconds = (s?: number) => {
if (s === null || s === undefined) {
return '-'
} else {
return `${s} s`
}
}
const formatBzzAmount = (amount?: BZZ) => {
if (amount === null || amount === undefined) {
return '-'
} else {
return `${amount.toSignificantDigits(4)} xBZZ`
}
}
const formatDaiAmount = (amount?: DAI) => {
if (amount === null || amount === undefined) {
return '-'
} else {
return `${amount.toSignificantDigits(4)} xDAI`
}
}
return (
<>
<ExpandableListItem
label="Has sufficient funds"
value={redistributionState?.hasSufficientFunds?.toString() ?? '-'}
/>
<ExpandableListItem label="Fully synced" value={redistributionState?.isFullySynced?.toString() ?? '-'} />
<ExpandableListItem label="Frozen" value={redistributionState?.isFrozen?.toString() ?? '-'} />
<ExpandableListItem label="Phase" value={redistributionState?.phase ?? '-'} />
<ExpandableListItem label="Round" value={redistributionState?.round?.toString() ?? '-'} />
<ExpandableListItem
label="Last selected round"
value={redistributionState?.lastSelectedRound.toString() ?? '-'}
/>
<ExpandableListItem label="Last played round" value={redistributionState?.lastPlayedRound.toString() ?? '-'} />
<ExpandableListItem label="Last round won" value={redistributionState?.lastWonRound.toString() ?? '-'} />
<ExpandableListItem label="Last frozen round" value={redistributionState?.lastFrozenRound.toString() ?? '-'} />
<ExpandableListItem
label="Last sample duration"
value={formatDurationSeconds(redistributionState?.lastSampleDurationSeconds)}
/>
<ExpandableListItem label="Reward" value={formatBzzAmount(redistributionState?.reward)} />
<ExpandableListItem label="Fees" value={formatDaiAmount(redistributionState?.fees)} />
</>
)
}
+6
View File
@@ -7,6 +7,7 @@ import DocsIcon from 'remixicon-react/BookOpenLineIcon'
import ExternalLinkIcon from 'remixicon-react/ExternalLinkLineIcon'
import FileManagerIcon from 'remixicon-react/FolderOpenLineIcon'
import GithubIcon from 'remixicon-react/GithubFillIcon'
import ExchangeDollarLineIcon from 'remixicon-react/ExchangeDollarLineIcon'
import HomeIcon from 'remixicon-react/Home3LineIcon'
import MenuFoldIcon from 'remixicon-react/MenuFoldLineIcon'
import MenuUnfoldIcon from 'remixicon-react/MenuUnfoldLineIcon'
@@ -147,6 +148,11 @@ export default function SideBar(): ReactElement {
icon: AccountIcon,
pathMatcherSubstring: '/account/',
},
{
label: 'Redistribution',
path: ROUTES.REDISTRIBUTION,
icon: ExchangeDollarLineIcon,
},
{
label: 'Settings',
path: ROUTES.SETTINGS,
+4 -1
View File
@@ -15,7 +15,7 @@ import NodeInfoCard from './NodeInfoCard'
import { WalletInfoCard } from './WalletInfoCard'
export default function Status(): ReactElement {
const { beeVersion, status, topology, nodeInfo, walletBalance } = useContext(BeeContext)
const { beeVersion, status, topology, nodeInfo, nodeStatus, walletBalance } = useContext(BeeContext)
const { isDesktop, desktopUrl } = useContext(SettingsContext)
const { beeDesktopVersion } = useBeeDesktop(isDesktop, desktopUrl)
const { newBeeDesktopVersion } = useNewBeeDesktopVersion(isDesktop, desktopUrl, false)
@@ -40,7 +40,10 @@ export default function Status(): ReactElement {
<div style={{ height: '2px' }} />
<ExpandableListItem label="Connected peers" value={topology?.connected ?? '-'} />
<ExpandableListItem label="Population" value={topology?.population ?? '-'} />
<ExpandableListItem label="Pullsync rate" value={nodeStatus?.pullsyncRate} />
<ExpandableListItem label="Depth" value={topology?.depth ?? '-'} />
<ExpandableListItem label="Neighborhood size" value={nodeStatus?.neighborhoodSize} />
<ExpandableListItem label="Node is reachable" value={nodeStatus?.isReachable?.toString()} />
<ChainSync />
<div style={{ height: '16px' }} />
+25
View File
@@ -0,0 +1,25 @@
import CircularProgress from '@material-ui/core/CircularProgress'
import { ReactElement, useContext } from 'react'
import ExpandableList from '../../components/ExpandableList'
import { Redistribution } from '../../components/Redistribution'
import { Context as SettingsContext } from '../../providers/Settings'
export default function RedistributionPage(): ReactElement {
const { isLoading } = useContext(SettingsContext)
if (isLoading) {
return (
<div style={{ textAlign: 'center', width: '100%' }}>
<CircularProgress />
</div>
)
}
return (
<>
<ExpandableList label="Redistribution" defaultOpen>
<Redistribution />
</ExpandableList>
</>
)
}
+18
View File
@@ -5,11 +5,13 @@ import {
ChainState,
ChequebookAddressResponse,
ChequebookBalanceResponse,
DebugStatus,
LastChequesResponse,
NodeAddresses,
NodeInfo,
Peer,
PeerBalance,
RedistributionState,
Topology,
WalletBalance,
} from '@ethersphere/bee-js'
@@ -61,6 +63,7 @@ interface ContextInterface {
apiHealth: boolean
nodeAddresses: NodeAddresses | null
nodeInfo: NodeInfo | null
nodeStatus: DebugStatus | null
topology: Topology | null
chequebookAddress: ChequebookAddressResponse | null
peers: Peer[] | null
@@ -71,6 +74,7 @@ interface ContextInterface {
settlements: AllSettlements | null
chainState: ChainState | null
walletBalance: WalletBalance | null
redistributionState: RedistributionState | null
latestBeeRelease: LatestBeeRelease | null
isLoading: boolean
lastUpdate: number | null
@@ -91,6 +95,7 @@ const initialValues: ContextInterface = {
apiHealth: false,
nodeAddresses: null,
nodeInfo: null,
nodeStatus: null,
topology: null,
chequebookAddress: null,
stake: null,
@@ -101,6 +106,7 @@ const initialValues: ContextInterface = {
settlements: null,
chainState: null,
walletBalance: null,
redistributionState: null,
latestBeeRelease: null,
isLoading: true,
lastUpdate: null,
@@ -199,6 +205,7 @@ export function Provider({ children }: Props): ReactElement {
const [isWarmingUp, setIsWarmingUp] = useState<boolean>(true)
const [nodeAddresses, setNodeAddresses] = useState<NodeAddresses | null>(null)
const [nodeInfo, setNodeInfo] = useState<NodeInfo | null>(null)
const [nodeStatus, setNodeStatus] = useState<DebugStatus | null>(null)
const [topology, setNodeTopology] = useState<Topology | null>(null)
const [chequebookAddress, setChequebookAddress] = useState<ChequebookAddressResponse | null>(null)
const [peers, setPeers] = useState<Peer[] | null>(null)
@@ -209,6 +216,7 @@ export function Provider({ children }: Props): ReactElement {
const [settlements, setSettlements] = useState<AllSettlements | null>(null)
const [chainState, setChainState] = useState<ChainState | null>(null)
const [walletBalance, setWalletBalance] = useState<WalletBalance | null>(null)
const [redistributionState, setRedistributionState] = useState<RedistributionState | null>(null)
const [startedAt, setStartedAt] = useState(() => Date.now())
const { latestBeeRelease } = useLatestBeeRelease()
@@ -257,6 +265,7 @@ export function Provider({ children }: Props): ReactElement {
walletResult,
chequebookBalanceResult,
stakeResult,
redistributionStateResult,
peerBalancesResult,
settlementsResult,
] = await Promise.allSettled([
@@ -272,6 +281,7 @@ export function Provider({ children }: Props): ReactElement {
beeApi.getWalletBalance({ timeout: TIMEOUT }),
beeApi.getChequebookBalance({ timeout: TIMEOUT }),
beeApi.getStake({ timeout: TIMEOUT }),
beeApi.getRedistributionState({ timeout: TIMEOUT }),
beeApi.getAllBalances({ timeout: TIMEOUT }),
beeApi.getAllSettlements(),
])
@@ -282,6 +292,7 @@ export function Provider({ children }: Props): ReactElement {
setApiHealth(Boolean(health))
setIsWarmingUp(getFulfilledValue(statusResult)?.isWarmingUp ?? false)
setNodeStatus(getFulfilledValue(statusResult))
setNodeAddresses(getFulfilledValue(nodeAddressesResult))
setNodeInfo(getFulfilledValue(nodeInfoResult))
setNodeTopology(getFulfilledValue(topologyResult))
@@ -292,6 +303,7 @@ export function Provider({ children }: Props): ReactElement {
setWalletBalance(getFulfilledValue(walletResult))
setChequebookBalance(getFulfilledValue(chequebookBalanceResult))
setStake(getFulfilledValue(stakeResult))
setRedistributionState(getFulfilledValue(redistributionStateResult))
setPeerBalances(getFulfilledValue(peerBalancesResult)?.balances ?? null)
setSettlements(getFulfilledValue(settlementsResult))
setError(null)
@@ -332,6 +344,7 @@ export function Provider({ children }: Props): ReactElement {
setNodeAddresses(null)
setNodeTopology(null)
setNodeInfo(null)
setNodeStatus(null)
setPeers(null)
setChequebookAddress(null)
setChequebookBalance(null)
@@ -339,6 +352,7 @@ export function Provider({ children }: Props): ReactElement {
setPeerCheques(null)
setSettlements(null)
setChainState(null)
setRedistributionState(null)
if (beeApi !== null) {
refresh()
@@ -381,6 +395,7 @@ export function Provider({ children }: Props): ReactElement {
apiHealth,
nodeAddresses,
nodeInfo,
nodeStatus,
topology,
chequebookAddress,
peers,
@@ -391,6 +406,7 @@ export function Provider({ children }: Props): ReactElement {
settlements,
chainState,
walletBalance,
redistributionState,
latestBeeRelease,
isLoading,
lastUpdate,
@@ -405,6 +421,7 @@ export function Provider({ children }: Props): ReactElement {
apiHealth,
nodeAddresses,
nodeInfo,
nodeStatus,
topology,
chequebookAddress,
peers,
@@ -415,6 +432,7 @@ export function Provider({ children }: Props): ReactElement {
settlements,
chainState,
walletBalance,
redistributionState,
latestBeeRelease,
isLoading,
lastUpdate,
+3
View File
@@ -28,6 +28,7 @@ import { CryptoTopUpIndex } from './pages/topUp/CryptoTopUpIndex'
import { GiftCardFund } from './pages/topUp/GiftCardFund'
import { GiftCardTopUpIndex } from './pages/topUp/GiftCardTopUpIndex'
import { Swap } from './pages/topUp/Swap'
import RedistributionPage from './pages/redistribution'
import { Context as SettingsContext } from './providers/Settings'
export enum ROUTES {
@@ -38,6 +39,7 @@ export enum ROUTES {
UPLOAD_IN_PROGRESS = '/files/upload/workflow',
DOWNLOAD = '/files/download',
HASH = '/files/hash/:hash',
REDISTRIBUTION = '/redistribution',
SETTINGS = '/settings',
STATUS = '/status',
TOP_UP = '/account/wallet/top-up',
@@ -82,6 +84,7 @@ const BaseRouter = (): ReactElement => {
<Route path={ROUTES.SETTINGS} element={<Settings />} />
<Route path={ROUTES.STATUS} element={<Status />} />
<Route path={ROUTES.INFO} element={<Info />} />
<Route path={ROUTES.REDISTRIBUTION} element={<RedistributionPage />} />
<Route path={ROUTES.TOP_UP} element={<TopUp />} />
<Route path={ROUTES.TOP_UP_CRYPTO} element={<CryptoTopUpIndex />} />
<Route path={ROUTES.TOP_UP_CRYPTO_SWAP} element={<Swap header="Top-up with cryptocurrencies" />} />