Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c9c4e7d7d1 | |||
| d97bc27c14 | |||
| e215c61ea1 | |||
| 8298d0bc66 | |||
| fac72b1299 | |||
| e780b971d9 | |||
| 90f9f91ddb | |||
| 01838dccd1 | |||
| 42b7f080b0 |
@@ -1,5 +1,27 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.23.0](https://github.com/ethersphere/bee-dashboard/compare/v0.22.0...v0.23.0) (2023-02-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add staking for full nodes ([#590](https://github.com/ethersphere/bee-dashboard/issues/590)) ([fac72b1](https://github.com/ethersphere/bee-dashboard/commit/fac72b1299353c104231aa038c1bab9df78c1355))
|
||||||
|
* upgrade bee-js to 5.2.0 ([#611](https://github.com/ethersphere/bee-dashboard/issues/611)) ([e215c61](https://github.com/ethersphere/bee-dashboard/commit/e215c61ea1619fc388fe8b1904d160b04a1a5c0d))
|
||||||
|
|
||||||
|
## [0.22.0](https://github.com/ethersphere/bee-dashboard/compare/v0.21.1...v0.22.0) (2023-01-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add node connecting status ([#603](https://github.com/ethersphere/bee-dashboard/issues/603)) ([90f9f91](https://github.com/ethersphere/bee-dashboard/commit/90f9f91ddbefb47b40c7e567125972b800d81972))
|
||||||
|
|
||||||
|
## [0.21.1](https://github.com/ethersphere/bee-dashboard/compare/v0.21.0...v0.21.1) (2022-12-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* do not require chequebook funding ([#599](https://github.com/ethersphere/bee-dashboard/issues/599)) ([42b7f08](https://github.com/ethersphere/bee-dashboard/commit/42b7f080b00a94f068d2fad4779d02ddcf58e27d))
|
||||||
|
|
||||||
## [0.21.0](https://github.com/ethersphere/bee-dashboard/compare/v0.20.2...v0.21.0) (2022-12-01)
|
## [0.21.0](https://github.com/ethersphere/bee-dashboard/compare/v0.20.2...v0.21.0) (2022-12-01)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
**Warning: This project is in alpha state. There might (and most probably will) be changes in the future to its API and
|
**Warning: This project is in alpha state. There might (and most probably will) be changes in the future to its API and
|
||||||
working. Also, no guarantees can be made about its stability, efficiency, and security at this stage.**
|
working. Also, no guarantees can be made about its stability, efficiency, and security at this stage.**
|
||||||
|
|
||||||
This project is intended to be used with **Bee version <!-- SUPPORTED_BEE_START -->1.9.0-13a47043<!-- SUPPORTED_BEE_END -->**.
|
This project is intended to be used with **Bee version <!-- SUPPORTED_BEE_START -->1.12.0-88c1d236<!-- SUPPORTED_BEE_END -->**.
|
||||||
Using it with older or newer Bee versions is not recommended and may not work. Stay up to date by joining the
|
Using it with older or newer Bee versions is not recommended and may not work. Stay up to date by joining the
|
||||||
[official Discord](https://discord.gg/GU22h2utj6) and by keeping an eye on the
|
[official Discord](https://discord.gg/GU22h2utj6) and by keeping an eye on the
|
||||||
[releases tab](https://github.com/ethersphere/bee-dashboard/releases).
|
[releases tab](https://github.com/ethersphere/bee-dashboard/releases).
|
||||||
|
|||||||
Generated
+168
-737
File diff suppressed because it is too large
Load Diff
+5
-5
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ethersphere/bee-dashboard",
|
"name": "@ethersphere/bee-dashboard",
|
||||||
"version": "0.21.0",
|
"version": "0.23.0",
|
||||||
"description": "An app which helps users to setup their Bee node and do actions like cash out cheques",
|
"description": "An app which helps users to setup their Bee node and do actions like cash out cheques",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"bee",
|
"bee",
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
"url": "https://github.com/ethersphere/bee-dashboard.git"
|
"url": "https://github.com/ethersphere/bee-dashboard.git"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ethersphere/bee-js": "^5.1.0",
|
"@ethersphere/bee-js": "^5.2.0",
|
||||||
"@ethersphere/manifest-js": "1.2.1",
|
"@ethersphere/manifest-js": "1.2.1",
|
||||||
"@ethersphere/swarm-cid": "^0.1.0",
|
"@ethersphere/swarm-cid": "^0.1.0",
|
||||||
"@material-ui/core": "4.12.3",
|
"@material-ui/core": "4.12.3",
|
||||||
@@ -48,9 +48,9 @@
|
|||||||
"notistack": "1.0.10",
|
"notistack": "1.0.10",
|
||||||
"opener": "1.5.2",
|
"opener": "1.5.2",
|
||||||
"qrcode.react": "1.0.1",
|
"qrcode.react": "1.0.1",
|
||||||
"react": ">=17.0.0 || >=18.0.0",
|
"react": ">= 17.0.2",
|
||||||
"react-copy-to-clipboard": "5.0.4",
|
"react-copy-to-clipboard": "5.0.4",
|
||||||
"react-dom": ">=17.0.0 || >=18.0.0",
|
"react-dom": ">= 17.0.2",
|
||||||
"react-identicons": "1.2.5",
|
"react-identicons": "1.2.5",
|
||||||
"react-router": "6.2.1",
|
"react-router": "6.2.1",
|
||||||
"react-router-dom": "6.2.1",
|
"react-router-dom": "6.2.1",
|
||||||
@@ -159,6 +159,6 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0",
|
"node": ">=14.0.0",
|
||||||
"npm": ">=6.9.0",
|
"npm": ">=6.9.0",
|
||||||
"bee": "1.9.0-13a47043"
|
"bee": "1.12.0-88c1d236"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { createStyles, makeStyles, Theme, Typography } from '@material-ui/core'
|
|||||||
import { ReactElement } from 'react'
|
import { ReactElement } from 'react'
|
||||||
import Check from 'remixicon-react/CheckLineIcon'
|
import Check from 'remixicon-react/CheckLineIcon'
|
||||||
import AlertCircle from 'remixicon-react/ErrorWarningFillIcon'
|
import AlertCircle from 'remixicon-react/ErrorWarningFillIcon'
|
||||||
|
import Connecting from 'remixicon-react/LinksLineIcon'
|
||||||
import RefreshLine from 'remixicon-react/RefreshLineIcon'
|
import RefreshLine from 'remixicon-react/RefreshLineIcon'
|
||||||
import { SwarmButton, SwarmButtonProps } from './SwarmButton'
|
import { SwarmButton, SwarmButtonProps } from './SwarmButton'
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ interface Props {
|
|||||||
title: string
|
title: string
|
||||||
subtitle: string
|
subtitle: string
|
||||||
buttonProps: SwarmButtonProps
|
buttonProps: SwarmButtonProps
|
||||||
status: 'ok' | 'error' | 'loading'
|
status: 'ok' | 'error' | 'loading' | 'connecting'
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = (backgroundColor: string) =>
|
const useStyles = (backgroundColor: string) =>
|
||||||
@@ -65,6 +66,8 @@ export default function Card({ buttonProps, icon, title, subtitle, status }: Pro
|
|||||||
statusIcon = <AlertCircle size="13" color="#f44336" />
|
statusIcon = <AlertCircle size="13" color="#f44336" />
|
||||||
} else if (status === 'loading') {
|
} else if (status === 'loading') {
|
||||||
statusIcon = <RefreshLine size="13" color="orange" />
|
statusIcon = <RefreshLine size="13" color="orange" />
|
||||||
|
} else if (status === 'connecting') {
|
||||||
|
statusIcon = <Connecting size="13" color="#0074D9" />
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { ReactElement, useContext } from 'react'
|
import { ReactElement, useContext } from 'react'
|
||||||
import { useLocation, matchPath } from 'react-router-dom'
|
import { matchPath, useLocation } from 'react-router-dom'
|
||||||
import ArrowRight from 'remixicon-react/ArrowRightLineIcon'
|
import ArrowRight from 'remixicon-react/ArrowRightLineIcon'
|
||||||
|
|
||||||
import { createStyles, Theme, makeStyles } from '@material-ui/core/styles'
|
import { ListItem, ListItemIcon, ListItemText, Typography } from '@material-ui/core'
|
||||||
import { ListItemText, ListItemIcon, ListItem, Typography } from '@material-ui/core'
|
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
|
||||||
import { Context } from '../providers/Bee'
|
import { Context } from '../providers/Bee'
|
||||||
import StatusIcon from './StatusIcon'
|
import StatusIcon from './StatusIcon'
|
||||||
|
|
||||||
@@ -44,6 +44,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
},
|
},
|
||||||
smallerText: {
|
smallerText: {
|
||||||
fontSize: '0.9rem',
|
fontSize: '0.9rem',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { ReactElement } from 'react'
|
|
||||||
import { CircularProgress } from '@material-ui/core'
|
import { CircularProgress } from '@material-ui/core'
|
||||||
|
import type { ReactElement } from 'react'
|
||||||
import { CheckState } from '../providers/Bee'
|
import { CheckState } from '../providers/Bee'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -28,6 +28,9 @@ export default function StatusIcon({ checkState, size, className, isLoading }: P
|
|||||||
case CheckState.STARTING:
|
case CheckState.STARTING:
|
||||||
backgroundColor = 'orange'
|
backgroundColor = 'orange'
|
||||||
break
|
break
|
||||||
|
case CheckState.CONNECTING:
|
||||||
|
backgroundColor = '#0074D9'
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
// Default is error
|
// Default is error
|
||||||
backgroundColor = '#ff3a52'
|
backgroundColor = '#ff3a52'
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { BigNumber } from 'bignumber.js'
|
||||||
|
import { ReactElement, useContext } from 'react'
|
||||||
|
import Download from 'remixicon-react/DownloadLineIcon'
|
||||||
|
import WithdrawDepositModal from '../components/WithdrawDepositModal'
|
||||||
|
import { Context as BeeContext } from '../providers/Bee'
|
||||||
|
import { Context as SettingsContext } from '../providers/Settings'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
onStarted: () => void
|
||||||
|
onFinished: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function StakeModal({ onStarted, onFinished }: Props): ReactElement {
|
||||||
|
const { beeDebugApi } = useContext(SettingsContext)
|
||||||
|
const { refresh } = useContext(BeeContext)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithdrawDepositModal
|
||||||
|
successMessage="Successfully deposited stake."
|
||||||
|
errorMessage="Error with depositing"
|
||||||
|
dialogMessage="Specify the amount of xBZZ you would like to stake. Your first stake must be at least 10 xBZZ. This will lock your tokens."
|
||||||
|
label="Stake"
|
||||||
|
icon={<Download size="1rem" />}
|
||||||
|
min={new BigNumber(0)}
|
||||||
|
action={async (amount: bigint) => {
|
||||||
|
if (!beeDebugApi) throw new Error('Bee Debug URL is not valid')
|
||||||
|
|
||||||
|
onStarted()
|
||||||
|
|
||||||
|
try {
|
||||||
|
await beeDebugApi.depositStake(amount.toString())
|
||||||
|
} finally {
|
||||||
|
refresh()
|
||||||
|
onFinished()
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'unknown'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
|
import { BeeModes } from '@ethersphere/bee-js'
|
||||||
import { createStyles, makeStyles, Tab, Tabs, Theme } from '@material-ui/core'
|
import { createStyles, makeStyles, Tab, Tabs, Theme } from '@material-ui/core'
|
||||||
import { ReactElement } from 'react'
|
import { ReactElement, useContext } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import { Context } from '../../providers/Bee'
|
||||||
import { ACCOUNT_TABS } from '../../routes'
|
import { ACCOUNT_TABS } from '../../routes'
|
||||||
|
|
||||||
const tabMap = {
|
const tabMap = {
|
||||||
@@ -8,10 +10,11 @@ const tabMap = {
|
|||||||
CHEQUEBOOK: 1,
|
CHEQUEBOOK: 1,
|
||||||
STAMPS: 2,
|
STAMPS: 2,
|
||||||
FEEDS: 3,
|
FEEDS: 3,
|
||||||
|
STAKING: 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
active: 'WALLET' | 'CHEQUEBOOK' | 'STAMPS' | 'FEEDS'
|
active: 'WALLET' | 'CHEQUEBOOK' | 'STAMPS' | 'FEEDS' | 'STAKING'
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
@@ -20,16 +23,12 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
marginBottom: theme.spacing(4),
|
marginBottom: theme.spacing(4),
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
|
marginLeft: theme.spacing(-0.25),
|
||||||
|
marginRight: theme.spacing(-0.25),
|
||||||
},
|
},
|
||||||
leftTab: {
|
tab: {
|
||||||
marginRight: theme.spacing(0.125),
|
marginLeft: theme.spacing(0.25),
|
||||||
},
|
marginRight: theme.spacing(0.25),
|
||||||
centerTab: {
|
|
||||||
marginLeft: theme.spacing(0.125),
|
|
||||||
marginRight: theme.spacing(0.125),
|
|
||||||
},
|
|
||||||
rightTab: {
|
|
||||||
marginLeft: theme.spacing(0.125),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@@ -37,6 +36,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
export function AccountNavigation({ active }: Props): ReactElement {
|
export function AccountNavigation({ active }: Props): ReactElement {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const { nodeInfo } = useContext(Context)
|
||||||
|
|
||||||
function onChange(event: React.ChangeEvent<Record<string, never>>, newValue: number) {
|
function onChange(event: React.ChangeEvent<Record<string, never>>, newValue: number) {
|
||||||
navigate(ACCOUNT_TABS[newValue])
|
navigate(ACCOUNT_TABS[newValue])
|
||||||
@@ -45,10 +45,11 @@ export function AccountNavigation({ active }: Props): ReactElement {
|
|||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<Tabs value={tabMap[active]} onChange={onChange} variant="fullWidth">
|
<Tabs value={tabMap[active]} onChange={onChange} variant="fullWidth">
|
||||||
<Tab className={classes.leftTab} key="WALLET" label="Wallet" />
|
<Tab className={classes.tab} key="WALLET" label="Wallet" />
|
||||||
<Tab className={classes.centerTab} key="CHEQUEBOOK" label="Chequebook" />
|
<Tab className={classes.tab} key="CHEQUEBOOK" label="Chequebook" />
|
||||||
<Tab className={classes.centerTab} key="STAMPS" label="Stamps" />
|
<Tab className={classes.tab} key="STAMPS" label="Stamps" />
|
||||||
<Tab className={classes.rightTab} key="FEEDS" label="Feeds" />
|
<Tab className={classes.tab} key="FEEDS" label="Feeds" />
|
||||||
|
{nodeInfo?.beeMode === BeeModes.FULL ? <Tab className={classes.tab} key="STAKING" label="Staking" /> : null}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { ReactElement, useContext, useState } from 'react'
|
||||||
|
import ExpandableList from '../../../components/ExpandableList'
|
||||||
|
import ExpandableListItem from '../../../components/ExpandableListItem'
|
||||||
|
import ExpandableListItemActions from '../../../components/ExpandableListItemActions'
|
||||||
|
import { Loading } from '../../../components/Loading'
|
||||||
|
import TroubleshootConnectionCard from '../../../components/TroubleshootConnectionCard'
|
||||||
|
import StakeModal from '../../../containers/StakeModal'
|
||||||
|
import { CheckState, Context as BeeContext } from '../../../providers/Bee'
|
||||||
|
import { Context as BalanceContext } from '../../../providers/WalletBalance'
|
||||||
|
import { AccountNavigation } from '../AccountNavigation'
|
||||||
|
import { Header } from '../Header'
|
||||||
|
|
||||||
|
export function AccountStaking(): ReactElement {
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
|
const { status, stake } = useContext(BeeContext)
|
||||||
|
const { balance } = useContext(BalanceContext)
|
||||||
|
|
||||||
|
if (status.all === CheckState.ERROR) return <TroubleshootConnectionCard />
|
||||||
|
|
||||||
|
function onStarted() {
|
||||||
|
setLoading(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFinished() {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header />
|
||||||
|
<AccountNavigation active="STAKING" />
|
||||||
|
<div>
|
||||||
|
{loading || stake?.toDecimal === undefined ? (
|
||||||
|
<Loading />
|
||||||
|
) : (
|
||||||
|
<ExpandableList label="Staking" defaultOpen>
|
||||||
|
<ExpandableListItem label="Staked BZZ" value={`${stake?.toSignificantDigits()} xBZZ`} />
|
||||||
|
{balance?.bzz ? (
|
||||||
|
<ExpandableListItem
|
||||||
|
label="Available xBZZ balance"
|
||||||
|
value={`${balance?.bzz.toSignificantDigits(4)} xBZZ`}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<ExpandableListItemActions>
|
||||||
|
<StakeModal onStarted={onStarted} onFinished={onFinished} />
|
||||||
|
</ExpandableListItemActions>
|
||||||
|
</ExpandableList>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -12,6 +12,18 @@ export default function NodeInfoCard(): ReactElement {
|
|||||||
const { status } = useContext(BeeContext)
|
const { status } = useContext(BeeContext)
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
if (status.all === CheckState.CONNECTING) {
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
buttonProps={{ iconType: Settings, children: 'Open node setup', onClick: () => navigate(ROUTES.STATUS) }}
|
||||||
|
icon={<Globe />}
|
||||||
|
title="Connecting..."
|
||||||
|
subtitle="Attempting to establish connection to your Bee node."
|
||||||
|
status="connecting"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (status.all === CheckState.STARTING) {
|
if (status.all === CheckState.STARTING) {
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
|
|||||||
@@ -19,16 +19,13 @@ const ChequebookDeployFund = (): ReactElement | null => {
|
|||||||
|
|
||||||
switch (checkState) {
|
switch (checkState) {
|
||||||
case CheckState.OK:
|
case CheckState.OK:
|
||||||
text = 'Your chequebook is deployed and funded'
|
|
||||||
break
|
|
||||||
case CheckState.WARNING:
|
|
||||||
text = (
|
text = (
|
||||||
<>
|
<>
|
||||||
Your chequebook is not funded. Please deposit some xBZZ to your chequebook address. You may need to aquire BZZ
|
Your chequebook is deployed. You may deposit some xBZZ to your chequebook to afford more traffic. You can
|
||||||
(e.g. <a href="https://bzz.exchange/">bzz.exchange</a>) and bridge it to the Gnosis Chain network through the{' '}
|
acquire BZZ (e.g. <a href="https://bzz.exchange/">bzz.exchange</a>) and bridge it to the Gnosis Chain network
|
||||||
<a href="https://omni.gnosischain.com/bridge">omni bridge</a>. To pay the transaction fees, you will also need
|
through the <a href="https://omni.gnosischain.com/bridge">omni bridge</a>. To pay the transaction fees, you
|
||||||
xDAI token. You can purchase DAI on the Ethereum mainnet network and bridge it to Gnosis Chain network through
|
will also need xDAI token. You can purchase DAI on the Ethereum mainnet network and bridge it to Gnosis Chain
|
||||||
the <a href="https://bridge.gnosischain.com">xDai Bridge</a>. See the{' '}
|
network through the <a href="https://bridge.gnosischain.com">xDai Bridge</a>. See the{' '}
|
||||||
<a href="https://www.gnosischain.com">official Gnosis Chain website</a> for more information.
|
<a href="https://www.gnosischain.com">official Gnosis Chain website</a> for more information.
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
+36
-13
@@ -13,15 +13,18 @@ import { createContext, ReactChild, ReactElement, useContext, useEffect, useStat
|
|||||||
import semver from 'semver'
|
import semver from 'semver'
|
||||||
import PackageJson from '../../package.json'
|
import PackageJson from '../../package.json'
|
||||||
import { useLatestBeeRelease } from '../hooks/apiHooks'
|
import { useLatestBeeRelease } from '../hooks/apiHooks'
|
||||||
|
import { BzzToken } from '../models/BzzToken'
|
||||||
import { Token } from '../models/Token'
|
import { Token } from '../models/Token'
|
||||||
import type { Balance, ChequebookBalance, Settlements } from '../types'
|
import type { Balance, ChequebookBalance, Settlements } from '../types'
|
||||||
import { Context as SettingsContext } from './Settings'
|
import { Context as SettingsContext } from './Settings'
|
||||||
|
|
||||||
|
const LAUNCH_GRACE_PERIOD = 15_000
|
||||||
const REFRESH_WHEN_OK = 30_000
|
const REFRESH_WHEN_OK = 30_000
|
||||||
const REFRESH_WHEN_ERROR = 5_000
|
const REFRESH_WHEN_ERROR = 5_000
|
||||||
const TIMEOUT = 3_000
|
const TIMEOUT = 3_000
|
||||||
|
|
||||||
export enum CheckState {
|
export enum CheckState {
|
||||||
|
CONNECTING = 'Connecting',
|
||||||
OK = 'OK',
|
OK = 'OK',
|
||||||
WARNING = 'Warning',
|
WARNING = 'Warning',
|
||||||
ERROR = 'Error',
|
ERROR = 'Error',
|
||||||
@@ -60,6 +63,7 @@ interface ContextInterface {
|
|||||||
chequebookAddress: ChequebookAddressResponse | null
|
chequebookAddress: ChequebookAddressResponse | null
|
||||||
peers: Peer[] | null
|
peers: Peer[] | null
|
||||||
chequebookBalance: ChequebookBalance | null
|
chequebookBalance: ChequebookBalance | null
|
||||||
|
stake: BzzToken | null
|
||||||
peerBalances: Balance[] | null
|
peerBalances: Balance[] | null
|
||||||
peerCheques: LastChequesResponse | null
|
peerCheques: LastChequesResponse | null
|
||||||
settlements: Settlements | null
|
settlements: Settlements | null
|
||||||
@@ -96,6 +100,7 @@ const initialValues: ContextInterface = {
|
|||||||
nodeInfo: null,
|
nodeInfo: null,
|
||||||
topology: null,
|
topology: null,
|
||||||
chequebookAddress: null,
|
chequebookAddress: null,
|
||||||
|
stake: null,
|
||||||
peers: null,
|
peers: null,
|
||||||
chequebookBalance: null,
|
chequebookBalance: null,
|
||||||
peerBalances: null,
|
peerBalances: null,
|
||||||
@@ -128,6 +133,7 @@ function getStatus(
|
|||||||
chequebookBalance: ChequebookBalance | null,
|
chequebookBalance: ChequebookBalance | null,
|
||||||
error: Error | null,
|
error: Error | null,
|
||||||
isDesktop: boolean,
|
isDesktop: boolean,
|
||||||
|
startedAt: number,
|
||||||
): Status {
|
): Status {
|
||||||
const status: Status = { ...initialValues.status }
|
const status: Status = { ...initialValues.status }
|
||||||
|
|
||||||
@@ -163,29 +169,37 @@ function getStatus(
|
|||||||
if (error || (nodeInfo && [BeeModes.FULL, BeeModes.LIGHT].includes(nodeInfo.beeMode))) {
|
if (error || (nodeInfo && [BeeModes.FULL, BeeModes.LIGHT].includes(nodeInfo.beeMode))) {
|
||||||
status.chequebook.isEnabled = true
|
status.chequebook.isEnabled = true
|
||||||
|
|
||||||
if (
|
if (chequebookAddress?.chequebookAddress && chequebookBalance !== null) {
|
||||||
chequebookAddress?.chequebookAddress &&
|
|
||||||
chequebookBalance !== null &&
|
|
||||||
chequebookBalance?.totalBalance.toBigNumber.isGreaterThan(0)
|
|
||||||
) {
|
|
||||||
status.chequebook.checkState = CheckState.OK
|
status.chequebook.checkState = CheckState.OK
|
||||||
} else if (chequebookAddress?.chequebookAddress) status.chequebook.checkState = CheckState.WARNING
|
} else status.chequebook.checkState = CheckState.OK
|
||||||
else status.chequebook.checkState = CheckState.OK
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status.all = determineOverallStatus(debugApiHealth, debugApiReadiness, status)
|
status.all = determineOverallStatus(debugApiHealth, debugApiReadiness, status, startedAt)
|
||||||
|
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineOverallStatus(debugApiHealth: Health | null, debugApiReadiness: boolean, status: Status): CheckState {
|
function determineOverallStatus(
|
||||||
|
debugApiHealth: Health | null,
|
||||||
|
debugApiReadiness: boolean,
|
||||||
|
status: Status,
|
||||||
|
startedAt: number,
|
||||||
|
): CheckState {
|
||||||
|
const hasErrors = Object.values(status).some(
|
||||||
|
({ isEnabled, checkState }) => isEnabled && checkState === CheckState.ERROR,
|
||||||
|
)
|
||||||
|
const hasWarnings = Object.values(status).some(
|
||||||
|
({ isEnabled, checkState }) => isEnabled && checkState === CheckState.WARNING,
|
||||||
|
)
|
||||||
|
const isInGracePeriod = Date.now() - startedAt < LAUNCH_GRACE_PERIOD
|
||||||
|
|
||||||
if (debugApiHealth?.status === 'ok' && !debugApiReadiness) {
|
if (debugApiHealth?.status === 'ok' && !debugApiReadiness) {
|
||||||
return CheckState.STARTING
|
return CheckState.STARTING
|
||||||
} else if (Object.values(status).some(({ isEnabled, checkState }) => isEnabled && checkState === CheckState.ERROR)) {
|
} else if (hasErrors && isInGracePeriod) {
|
||||||
|
return CheckState.CONNECTING
|
||||||
|
} else if (hasErrors) {
|
||||||
return CheckState.ERROR
|
return CheckState.ERROR
|
||||||
} else if (
|
} else if (hasWarnings) {
|
||||||
Object.values(status).some(({ isEnabled, checkState }) => isEnabled && checkState === CheckState.WARNING)
|
|
||||||
) {
|
|
||||||
return CheckState.WARNING
|
return CheckState.WARNING
|
||||||
} else {
|
} else {
|
||||||
return CheckState.OK
|
return CheckState.OK
|
||||||
@@ -214,11 +228,13 @@ export function Provider({ children, isDesktop }: Props): ReactElement {
|
|||||||
const [chequebookAddress, setChequebookAddress] = useState<ChequebookAddressResponse | null>(null)
|
const [chequebookAddress, setChequebookAddress] = useState<ChequebookAddressResponse | null>(null)
|
||||||
const [peers, setPeers] = useState<Peer[] | null>(null)
|
const [peers, setPeers] = useState<Peer[] | null>(null)
|
||||||
const [chequebookBalance, setChequebookBalance] = useState<ChequebookBalance | null>(null)
|
const [chequebookBalance, setChequebookBalance] = useState<ChequebookBalance | null>(null)
|
||||||
|
const [stake, setStake] = useState<BzzToken | null>(null)
|
||||||
const [peerBalances, setPeerBalances] = useState<Balance[] | null>(null)
|
const [peerBalances, setPeerBalances] = useState<Balance[] | null>(null)
|
||||||
const [peerCheques, setPeerCheques] = useState<LastChequesResponse | null>(null)
|
const [peerCheques, setPeerCheques] = useState<LastChequesResponse | null>(null)
|
||||||
const [settlements, setSettlements] = useState<Settlements | null>(null)
|
const [settlements, setSettlements] = useState<Settlements | null>(null)
|
||||||
const [chainState, setChainState] = useState<ChainState | null>(null)
|
const [chainState, setChainState] = useState<ChainState | null>(null)
|
||||||
const [chainId, setChainId] = useState<number | null>(null)
|
const [chainId, setChainId] = useState<number | null>(null)
|
||||||
|
const [startedAt] = useState(Date.now())
|
||||||
|
|
||||||
const { latestBeeRelease } = useLatestBeeRelease()
|
const { latestBeeRelease } = useLatestBeeRelease()
|
||||||
|
|
||||||
@@ -376,6 +392,11 @@ export function Provider({ children, isDesktop }: Props): ReactElement {
|
|||||||
.then(setChequebookBalance)
|
.then(setChequebookBalance)
|
||||||
.catch(() => setChequebookBalance(null)),
|
.catch(() => setChequebookBalance(null)),
|
||||||
|
|
||||||
|
beeDebugApi
|
||||||
|
.getStake({ timeout: TIMEOUT })
|
||||||
|
.then(stake => setStake(new BzzToken(stake)))
|
||||||
|
.catch(() => setStake(null)),
|
||||||
|
|
||||||
// Peer balances
|
// Peer balances
|
||||||
peerBalanceWrapper()
|
peerBalanceWrapper()
|
||||||
.then(setPeerBalances)
|
.then(setPeerBalances)
|
||||||
@@ -413,6 +434,7 @@ export function Provider({ children, isDesktop }: Props): ReactElement {
|
|||||||
chequebookBalance,
|
chequebookBalance,
|
||||||
error,
|
error,
|
||||||
Boolean(isDesktop),
|
Boolean(isDesktop),
|
||||||
|
startedAt,
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -458,6 +480,7 @@ export function Provider({ children, isDesktop }: Props): ReactElement {
|
|||||||
chequebookAddress,
|
chequebookAddress,
|
||||||
peers,
|
peers,
|
||||||
chequebookBalance,
|
chequebookBalance,
|
||||||
|
stake,
|
||||||
peerBalances,
|
peerBalances,
|
||||||
peerCheques,
|
peerCheques,
|
||||||
settlements,
|
settlements,
|
||||||
|
|||||||
+5
-1
@@ -2,6 +2,7 @@ import { ReactElement, useContext } from 'react'
|
|||||||
import { Route, Routes } from 'react-router-dom'
|
import { Route, Routes } from 'react-router-dom'
|
||||||
import { AccountChequebook } from './pages/account/chequebook/AccountChequebook'
|
import { AccountChequebook } from './pages/account/chequebook/AccountChequebook'
|
||||||
import { AccountFeeds } from './pages/account/feeds/AccountFeeds'
|
import { AccountFeeds } from './pages/account/feeds/AccountFeeds'
|
||||||
|
import { AccountStaking } from './pages/account/staking/AccountStaking'
|
||||||
import { AccountStamps } from './pages/account/stamps/AccountStamps'
|
import { AccountStamps } from './pages/account/stamps/AccountStamps'
|
||||||
import { AccountWallet } from './pages/account/wallet/AccountWallet'
|
import { AccountWallet } from './pages/account/wallet/AccountWallet'
|
||||||
import CreateNewFeed from './pages/feeds/CreateNewFeed'
|
import CreateNewFeed from './pages/feeds/CreateNewFeed'
|
||||||
@@ -14,10 +15,10 @@ import { UploadLander } from './pages/files/UploadLander'
|
|||||||
import GiftCards from './pages/gift-code'
|
import GiftCards from './pages/gift-code'
|
||||||
import Info from './pages/info'
|
import Info from './pages/info'
|
||||||
import LightModeRestart from './pages/restart/LightModeRestart'
|
import LightModeRestart from './pages/restart/LightModeRestart'
|
||||||
import TopUp from './pages/top-up'
|
|
||||||
import Settings from './pages/settings'
|
import Settings from './pages/settings'
|
||||||
import { CreatePostageStampPage } from './pages/stamps/CreatePostageStampPage'
|
import { CreatePostageStampPage } from './pages/stamps/CreatePostageStampPage'
|
||||||
import Status from './pages/status'
|
import Status from './pages/status'
|
||||||
|
import TopUp from './pages/top-up'
|
||||||
import { BankCardTopUpIndex } from './pages/top-up/BankCardTopUpIndex'
|
import { BankCardTopUpIndex } from './pages/top-up/BankCardTopUpIndex'
|
||||||
import { CryptoTopUpIndex } from './pages/top-up/CryptoTopUpIndex'
|
import { CryptoTopUpIndex } from './pages/top-up/CryptoTopUpIndex'
|
||||||
import { GiftCardFund } from './pages/top-up/GiftCardFund'
|
import { GiftCardFund } from './pages/top-up/GiftCardFund'
|
||||||
@@ -51,6 +52,7 @@ export enum ROUTES {
|
|||||||
ACCOUNT_FEEDS_UPDATE = '/account/feeds/update/:hash',
|
ACCOUNT_FEEDS_UPDATE = '/account/feeds/update/:hash',
|
||||||
ACCOUNT_FEEDS_VIEW = '/account/feeds/:uuid',
|
ACCOUNT_FEEDS_VIEW = '/account/feeds/:uuid',
|
||||||
ACCOUNT_INVITATIONS = '/account/invitations',
|
ACCOUNT_INVITATIONS = '/account/invitations',
|
||||||
|
ACCOUNT_STAKING = '/account/staking',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ACCOUNT_TABS = [
|
export const ACCOUNT_TABS = [
|
||||||
@@ -58,6 +60,7 @@ export const ACCOUNT_TABS = [
|
|||||||
ROUTES.ACCOUNT_CHEQUEBOOK,
|
ROUTES.ACCOUNT_CHEQUEBOOK,
|
||||||
ROUTES.ACCOUNT_STAMPS,
|
ROUTES.ACCOUNT_STAMPS,
|
||||||
ROUTES.ACCOUNT_FEEDS,
|
ROUTES.ACCOUNT_FEEDS,
|
||||||
|
ROUTES.ACCOUNT_STAKING,
|
||||||
]
|
]
|
||||||
|
|
||||||
const BaseRouter = (): ReactElement => {
|
const BaseRouter = (): ReactElement => {
|
||||||
@@ -88,6 +91,7 @@ const BaseRouter = (): ReactElement => {
|
|||||||
<Route path={ROUTES.ACCOUNT_FEEDS_NEW} element={<CreateNewFeed />} />
|
<Route path={ROUTES.ACCOUNT_FEEDS_NEW} element={<CreateNewFeed />} />
|
||||||
<Route path={ROUTES.ACCOUNT_FEEDS_UPDATE} element={<UpdateFeed />} />
|
<Route path={ROUTES.ACCOUNT_FEEDS_UPDATE} element={<UpdateFeed />} />
|
||||||
<Route path={ROUTES.ACCOUNT_FEEDS_VIEW} element={<FeedSubpage />} />
|
<Route path={ROUTES.ACCOUNT_FEEDS_VIEW} element={<FeedSubpage />} />
|
||||||
|
<Route path={ROUTES.ACCOUNT_STAKING} element={<AccountStaking />} />
|
||||||
{isDesktop && <Route path={ROUTES.ACCOUNT_INVITATIONS} element={<GiftCards />} />}
|
{isDesktop && <Route path={ROUTES.ACCOUNT_INVITATIONS} element={<GiftCards />} />}
|
||||||
</Routes>
|
</Routes>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user