Skip to content

Commit 3dbb9c5

Browse files
committed
added new page with node redistribution statistics
1 parent 1249c0d commit 3dbb9c5

File tree

6 files changed

+172
-1
lines changed

6 files changed

+172
-1
lines changed

src/components/Redistribution.tsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { RedistributionState, BZZ, DAI } from '@ethersphere/bee-js'
2+
import { useContext, useEffect, useState } from 'react'
3+
import { Context } from '../providers/Settings'
4+
import ExpandableListItem from './ExpandableListItem'
5+
6+
export function Redistribution() {
7+
const { beeApi } = useContext(Context)
8+
const [redistributionState, setRedistributionState] = useState<RedistributionState | null>(null)
9+
10+
useEffect(() => {
11+
const interval = setInterval(() => {
12+
if (!beeApi) {
13+
return
14+
}
15+
16+
beeApi.getRedistributionState().then(setRedistributionState).catch(console.error) // eslint-disable-line
17+
}, 3_000)
18+
19+
return () => clearInterval(interval)
20+
})
21+
22+
const formatDurationSeconds = (s?: number) => {
23+
if (s === null || s === undefined) {
24+
return '-'
25+
} else {
26+
return `${s} s`
27+
}
28+
}
29+
30+
const formatBzzAmount = (amount?: BZZ) => {
31+
if (amount === null || amount === undefined) {
32+
return '-'
33+
} else {
34+
return `${amount.toSignificantDigits(4)} xBZZ`
35+
}
36+
}
37+
38+
const formatDaiAmount = (amount?: DAI) => {
39+
if (amount === null || amount === undefined) {
40+
return '-'
41+
} else {
42+
return `${amount.toSignificantDigits(4)} xDAI`
43+
}
44+
}
45+
46+
return (
47+
<>
48+
<ExpandableListItem
49+
label="Has sufficient funds"
50+
value={redistributionState?.hasSufficientFunds?.toString() ?? '-'}
51+
/>
52+
<ExpandableListItem label="Fully synced" value={redistributionState?.isFullySynced?.toString() ?? '-'} />
53+
<ExpandableListItem label="Frozen" value={redistributionState?.isFrozen?.toString() ?? '-'} />
54+
<ExpandableListItem label="Phase" value={redistributionState?.phase ?? '-'} />
55+
<ExpandableListItem label="Round" value={redistributionState?.round?.toString() ?? '-'} />
56+
<ExpandableListItem
57+
label="Last selected round"
58+
value={redistributionState?.lastSelectedRound.toString() ?? '-'}
59+
/>
60+
<ExpandableListItem label="Last played round" value={redistributionState?.lastPlayedRound.toString() ?? '-'} />
61+
<ExpandableListItem label="Last round won" value={redistributionState?.lastWonRound.toString() ?? '-'} />
62+
<ExpandableListItem label="Last frozen round" value={redistributionState?.lastFrozenRound.toString() ?? '-'} />
63+
<ExpandableListItem label="Last sample duration" value={redistributionState?.lastSampleDurationSeconds ?? '-'} />
64+
<ExpandableListItem label="Reward" value={formatBzzAmount(redistributionState?.reward)} />
65+
<ExpandableListItem label="Fees" value={formatDaiAmount(redistributionState?.fees)} />
66+
</>
67+
)
68+
}

src/components/SideBar.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import { ReactElement, useContext } from 'react'
55
import { Link } from 'react-router-dom'
66
import FilesIcon from 'remixicon-react/ArrowUpDownLineIcon'
77
import DocsIcon from 'remixicon-react/BookOpenLineIcon'
8+
import ExchangeFundsLineIcon from 'remixicon-react/ExchangeFundsLineIcon'
89
import ExternalLinkIcon from 'remixicon-react/ExternalLinkLineIcon'
910
import GithubIcon from 'remixicon-react/GithubFillIcon'
11+
import ExchangeDollarLineIcon from 'remixicon-react/ExchangeDollarLineIcon'
1012
import HomeIcon from 'remixicon-react/Home3LineIcon'
1113
import SettingsIcon from 'remixicon-react/Settings2LineIcon'
1214
import AccountIcon from 'remixicon-react/Wallet3LineIcon'
@@ -88,6 +90,11 @@ export default function SideBar(): ReactElement {
8890
icon: AccountIcon,
8991
pathMatcherSubstring: '/account/',
9092
},
93+
{
94+
label: 'Redistribution',
95+
path: ROUTES.REDISTRIBUTION,
96+
icon: ExchangeDollarLineIcon,
97+
},
9198
{
9299
label: 'Settings',
93100
path: ROUTES.SETTINGS,

src/pages/info/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import NodeInfoCard from './NodeInfoCard'
1313
import { WalletInfoCard } from './WalletInfoCard'
1414

1515
export default function Status(): ReactElement {
16-
const { beeVersion, status, topology, nodeInfo, walletBalance } = useContext(BeeContext)
16+
const { beeVersion, status, topology, nodeInfo, nodeStatus, walletBalance } = useContext(BeeContext)
1717
const { isDesktop, desktopUrl } = useContext(SettingsContext)
1818
const { beeDesktopVersion } = useBeeDesktop(isDesktop, desktopUrl)
1919
const { newBeeDesktopVersion } = useNewBeeDesktopVersion(isDesktop, desktopUrl, false)
@@ -38,7 +38,10 @@ export default function Status(): ReactElement {
3838
<div style={{ height: '2px' }} />
3939
<ExpandableListItem label="Connected peers" value={topology?.connected ?? '-'} />
4040
<ExpandableListItem label="Population" value={topology?.population ?? '-'} />
41+
<ExpandableListItem label="Pullsync rate" value={nodeStatus?.pullsyncRate} />
4142
<ExpandableListItem label="Depth" value={topology?.depth ?? '-'} />
43+
<ExpandableListItem label="Neighborhood size" value={nodeStatus?.neighborhoodSize} />
44+
<ExpandableListItem label="Node is reachable" value={nodeStatus?.isReachable?.toString()} />
4245
<ChainSync />
4346

4447
<div style={{ height: '16px' }} />

src/pages/redistribution/index.tsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import CircularProgress from '@material-ui/core/CircularProgress'
2+
import { useSnackbar } from 'notistack'
3+
import { ReactElement, useContext } from 'react'
4+
import ExpandableList from '../../components/ExpandableList'
5+
import ExpandableListItemInput from '../../components/ExpandableListItemInput'
6+
import { Redistribution } from '../../components/Redistribution'
7+
import { Context as BeeContext } from '../../providers/Bee'
8+
import { Context as SettingsContext } from '../../providers/Settings'
9+
import { getDesktopConfiguration, restartBeeNode, setJsonRpcInDesktop } from '../../utils/desktop'
10+
11+
export default function RedistributionPage(): ReactElement {
12+
const {
13+
apiUrl,
14+
setApiUrl,
15+
lockedApiSettings,
16+
cors,
17+
dataDir,
18+
ensResolver,
19+
rpcProviderUrl,
20+
isLoading,
21+
isDesktop,
22+
desktopUrl,
23+
setAndPersistJsonRpcProvider,
24+
} = useContext(SettingsContext)
25+
const { refresh } = useContext(BeeContext)
26+
const { enqueueSnackbar, closeSnackbar } = useSnackbar()
27+
28+
async function handleSetRpcUrl(value: string) {
29+
try {
30+
setAndPersistJsonRpcProvider(value)
31+
32+
const shouldUpdateDesktop = isDesktop && (await getDesktopConfiguration(desktopUrl))['blockchain-rpc-endpoint']
33+
34+
if (shouldUpdateDesktop) {
35+
await setJsonRpcInDesktop(desktopUrl, value)
36+
const snackKey = enqueueSnackbar('RPC endpoint successfully changed, restarting Bee node...', {
37+
variant: 'success',
38+
})
39+
await restartBeeNode(desktopUrl)
40+
closeSnackbar(snackKey)
41+
enqueueSnackbar('Bee node restarted', { variant: 'success' })
42+
} else {
43+
enqueueSnackbar('RPC endpoint successfully changed', { variant: 'success' })
44+
}
45+
46+
await refresh()
47+
} catch (e) {
48+
console.error(e) //eslint-disable-line
49+
enqueueSnackbar(`Failed to change RPC endpoint. ${e}`, { variant: 'error' })
50+
}
51+
}
52+
53+
if (isLoading) {
54+
return (
55+
<div style={{ textAlign: 'center', width: '100%' }}>
56+
<CircularProgress />
57+
</div>
58+
)
59+
}
60+
61+
return (
62+
<>
63+
<ExpandableList label="Redistribution" defaultOpen>
64+
<Redistribution />
65+
</ExpandableList>
66+
</>
67+
)
68+
}

src/providers/Bee.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import {
55
ChainState,
66
ChequebookAddressResponse,
77
ChequebookBalanceResponse,
8+
DebugStatus,
89
LastChequesResponse,
910
NodeAddresses,
1011
NodeInfo,
1112
Peer,
1213
PeerBalance,
14+
RedistributionState,
1315
Topology,
1416
WalletBalance,
1517
} from '@ethersphere/bee-js'
@@ -49,6 +51,7 @@ interface ContextInterface {
4951
apiHealth: boolean
5052
nodeAddresses: NodeAddresses | null
5153
nodeInfo: NodeInfo | null
54+
nodeStatus: DebugStatus | null
5255
topology: Topology | null
5356
chequebookAddress: ChequebookAddressResponse | null
5457
peers: Peer[] | null
@@ -59,6 +62,7 @@ interface ContextInterface {
5962
settlements: AllSettlements | null
6063
chainState: ChainState | null
6164
walletBalance: WalletBalance | null
65+
redistributionState: RedistributionState | null
6266
latestBeeRelease: LatestBeeRelease | null
6367
isLoading: boolean
6468
lastUpdate: number | null
@@ -79,6 +83,7 @@ const initialValues: ContextInterface = {
7983
apiHealth: false,
8084
nodeAddresses: null,
8185
nodeInfo: null,
86+
nodeStatus: null,
8287
topology: null,
8388
chequebookAddress: null,
8489
stake: null,
@@ -89,6 +94,7 @@ const initialValues: ContextInterface = {
8994
settlements: null,
9095
chainState: null,
9196
walletBalance: null,
97+
redistributionState: null,
9298
latestBeeRelease: null,
9399
isLoading: true,
94100
lastUpdate: null,
@@ -172,6 +178,7 @@ export function Provider({ children }: Props): ReactElement {
172178
const [apiHealth, setApiHealth] = useState<boolean>(false)
173179
const [nodeAddresses, setNodeAddresses] = useState<NodeAddresses | null>(null)
174180
const [nodeInfo, setNodeInfo] = useState<NodeInfo | null>(null)
181+
const [nodeStatus, setNodeStatus] = useState<DebugStatus | null>(null)
175182
const [topology, setNodeTopology] = useState<Topology | null>(null)
176183
const [chequebookAddress, setChequebookAddress] = useState<ChequebookAddressResponse | null>(null)
177184
const [peers, setPeers] = useState<Peer[] | null>(null)
@@ -182,6 +189,7 @@ export function Provider({ children }: Props): ReactElement {
182189
const [settlements, setSettlements] = useState<AllSettlements | null>(null)
183190
const [chainState, setChainState] = useState<ChainState | null>(null)
184191
const [walletBalance, setWalletBalance] = useState<WalletBalance | null>(null)
192+
const [redistributionState, setRedistributionState] = useState<RedistributionState | null>(null)
185193
const [startedAt] = useState(Date.now())
186194

187195
const { latestBeeRelease } = useLatestBeeRelease()
@@ -257,6 +265,12 @@ export function Provider({ children }: Props): ReactElement {
257265
.then(setNodeInfo)
258266
.catch(() => setNodeInfo(null)),
259267

268+
// NodeDebugInfo
269+
beeApi
270+
.getStatus({ timeout: TIMEOUT })
271+
.then(setNodeStatus)
272+
.catch(() => setNodeInfo(null)),
273+
260274
// Network Topology
261275
beeApi
262276
.getTopology({ timeout: TIMEOUT })
@@ -304,6 +318,12 @@ export function Provider({ children }: Props): ReactElement {
304318
.then(stake => setStake(stake))
305319
.catch(() => setStake(null)),
306320

321+
// Redistribution stats
322+
beeApi
323+
.getRedistributionState({ timeout: TIMEOUT })
324+
.then(setRedistributionState)
325+
.catch(() => setRedistributionState(null)),
326+
307327
// Peer balances
308328
beeApi
309329
.getAllBalances({ timeout: TIMEOUT })
@@ -362,6 +382,7 @@ export function Provider({ children }: Props): ReactElement {
362382
apiHealth,
363383
nodeAddresses,
364384
nodeInfo,
385+
nodeStatus,
365386
topology,
366387
chequebookAddress,
367388
peers,
@@ -372,6 +393,7 @@ export function Provider({ children }: Props): ReactElement {
372393
settlements,
373394
chainState,
374395
walletBalance,
396+
redistributionState,
375397
latestBeeRelease,
376398
isLoading,
377399
lastUpdate,

src/routes.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { BankCardTopUpIndex } from './pages/top-up/BankCardTopUpIndex'
2525
import { CryptoTopUpIndex } from './pages/top-up/CryptoTopUpIndex'
2626
import { GiftCardFund } from './pages/top-up/GiftCardFund'
2727
import { GiftCardTopUpIndex } from './pages/top-up/GiftCardTopUpIndex'
28+
import RedistributionPage from './pages/redistribution'
2829
import { Swap } from './pages/top-up/Swap'
2930
import { Context as SettingsContext } from './providers/Settings'
3031

@@ -35,6 +36,7 @@ export enum ROUTES {
3536
UPLOAD_IN_PROGRESS = '/files/upload/workflow',
3637
DOWNLOAD = '/files/download',
3738
HASH = '/files/hash/:hash',
39+
REDISTRIBUTION = '/redistribution',
3840
SETTINGS = '/settings',
3941
STATUS = '/status',
4042
TOP_UP = '/account/wallet/top-up',
@@ -79,6 +81,7 @@ const BaseRouter = (): ReactElement => {
7981
<Route path={ROUTES.SETTINGS} element={<Settings />} />
8082
<Route path={ROUTES.STATUS} element={<Status />} />
8183
<Route path={ROUTES.INFO} element={<Info />} />
84+
<Route path={ROUTES.REDISTRIBUTION} element={<RedistributionPage />} />
8285
<Route path={ROUTES.TOP_UP} element={<TopUp />} />
8386
<Route path={ROUTES.TOP_UP_CRYPTO} element={<CryptoTopUpIndex />} />
8487
<Route path={ROUTES.TOP_UP_CRYPTO_SWAP} element={<Swap header="Top-up with cryptocurrencies" />} />

0 commit comments

Comments
 (0)