Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
8d8fbff51a
|
|||
| 369bd275c4 | |||
| 6d28653bb0 | |||
| aacb109e3f | |||
| 82e7c78a81 | |||
| c8fbf504e7 | |||
| 1e52adddf6 | |||
| 096522aa8a |
@@ -1 +1,3 @@
|
|||||||
PORT=3002
|
PORT=3002
|
||||||
|
REACT_APP_FORMBRICKS_ENV_ID=
|
||||||
|
REACT_APP_FORMBRICKS_APP_URL=
|
||||||
@@ -18,6 +18,8 @@ jobs:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
REACT_APP_BEE_HOST: https://api.test-node.staging.ethswarm.org/
|
REACT_APP_BEE_HOST: https://api.test-node.staging.ethswarm.org/
|
||||||
|
REACT_APP_FORMBRICKS_ENV_ID: ${{ secrets.REACT_APP_FORMBRICKS_ENV_ID }}
|
||||||
|
REACT_APP_FORMBRICKS_APP_URL: ${{ secrets.REACT_APP_FORMBRICKS_APP_URL }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
env:
|
||||||
|
REACT_APP_FORMBRICKS_ENV_ID: ${{ secrets.REACT_APP_FORMBRICKS_ENV_ID }}
|
||||||
|
REACT_APP_FORMBRICKS_APP_URL: ${{ secrets.REACT_APP_FORMBRICKS_APP_URL }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
env:
|
||||||
|
REACT_APP_FORMBRICKS_ENV_ID: ${{ secrets.REACT_APP_FORMBRICKS_ENV_ID }}
|
||||||
|
REACT_APP_FORMBRICKS_APP_URL: ${{ secrets.REACT_APP_FORMBRICKS_APP_URL }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ jobs:
|
|||||||
tests:
|
tests:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
env:
|
||||||
|
REACT_APP_FORMBRICKS_ENV_ID: ${{ secrets.REACT_APP_FORMBRICKS_ENV_ID }}
|
||||||
|
REACT_APP_FORMBRICKS_APP_URL: ${{ secrets.REACT_APP_FORMBRICKS_APP_URL }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [18.x]
|
node-version: [18.x]
|
||||||
|
|||||||
@@ -1,5 +1,26 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.33.3](https://github.com/ethersphere/bee-dashboard/compare/v0.33.2...v0.33.3) (2025-11-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add formbricks environment variables to workflow files ([#709](https://github.com/ethersphere/bee-dashboard/issues/709)) ([6d28653](https://github.com/ethersphere/bee-dashboard/commit/6d28653bb0b731a16d8adabbb9a8c9074387f769))
|
||||||
|
|
||||||
|
## [0.33.2](https://github.com/ethersphere/bee-dashboard/compare/v0.33.1...v0.33.2) (2025-11-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* clarify installation instructions in README ([#707](https://github.com/ethersphere/bee-dashboard/issues/707)) ([82e7c78](https://github.com/ethersphere/bee-dashboard/commit/82e7c78a818b46031b040f92e9a9491003c9bd92))
|
||||||
|
|
||||||
|
## [0.33.1](https://github.com/ethersphere/bee-dashboard/compare/v0.33.0...v0.33.1) (2025-11-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* put back external wallet balance context ([#704](https://github.com/ethersphere/bee-dashboard/issues/704)) ([096522a](https://github.com/ethersphere/bee-dashboard/commit/096522aa8a2f11afb0061a6fedbae241967408ef))
|
||||||
|
|
||||||
## [0.33.0](https://github.com/ethersphere/bee-dashboard/compare/v0.32.0...v0.33.0) (2025-11-12)
|
## [0.33.0](https://github.com/ethersphere/bee-dashboard/compare/v0.32.0...v0.33.0) (2025-11-12)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ Install globally with npm. We require Node.js's version of at least 12.x and npm
|
|||||||
npm install -g @ethersphere/bee-dashboard
|
npm install -g @ethersphere/bee-dashboard
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For the latest stable version, always use the official npm registry.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
:warning: To successfully connect to the Bee node, you will need to enable CORS. You can do so by setting
|
:warning: To successfully connect to the Bee node, you will need to enable CORS. You can do so by setting
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@ethersphere/bee-dashboard",
|
"name": "@ethersphere/bee-dashboard",
|
||||||
"version": "0.33.0",
|
"version": "0.33.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@ethersphere/bee-dashboard",
|
"name": "@ethersphere/bee-dashboard",
|
||||||
"version": "0.33.0",
|
"version": "0.33.3",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ethersphere/bee-js": "^10.1.1",
|
"@ethersphere/bee-js": "^10.1.1",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ethersphere/bee-dashboard",
|
"name": "@ethersphere/bee-dashboard",
|
||||||
"version": "0.33.0",
|
"version": "0.33.3",
|
||||||
"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",
|
||||||
|
|||||||
+23
-20
@@ -13,6 +13,7 @@ import { Provider as PlatformProvider } from './providers/Platform'
|
|||||||
import { Provider as SettingsProvider } from './providers/Settings'
|
import { Provider as SettingsProvider } from './providers/Settings'
|
||||||
import { Provider as StampsProvider } from './providers/Stamps'
|
import { Provider as StampsProvider } from './providers/Stamps'
|
||||||
import { Provider as TopUpProvider } from './providers/TopUp'
|
import { Provider as TopUpProvider } from './providers/TopUp'
|
||||||
|
import { Provider as BalanceProvider } from './providers/WalletBalance'
|
||||||
import BaseRouter from './routes'
|
import BaseRouter from './routes'
|
||||||
import { theme } from './theme'
|
import { theme } from './theme'
|
||||||
|
|
||||||
@@ -45,26 +46,28 @@ const App = ({
|
|||||||
>
|
>
|
||||||
<TopUpProvider>
|
<TopUpProvider>
|
||||||
<BeeProvider>
|
<BeeProvider>
|
||||||
<StampsProvider>
|
<BalanceProvider>
|
||||||
<FileProvider>
|
<StampsProvider>
|
||||||
<FileManagerProvider>
|
<FileProvider>
|
||||||
<FeedsProvider>
|
<FileManagerProvider>
|
||||||
<PlatformProvider>
|
<FeedsProvider>
|
||||||
<SnackbarProvider preventDuplicate anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}>
|
<PlatformProvider>
|
||||||
<Router>
|
<SnackbarProvider preventDuplicate anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}>
|
||||||
<>
|
<Router>
|
||||||
<CssBaseline />
|
<>
|
||||||
<Dashboard errorReporting={errorReporting}>
|
<CssBaseline />
|
||||||
<BaseRouter />
|
<Dashboard errorReporting={errorReporting}>
|
||||||
</Dashboard>
|
<BaseRouter />
|
||||||
</>
|
</Dashboard>
|
||||||
</Router>
|
</>
|
||||||
</SnackbarProvider>
|
</Router>
|
||||||
</PlatformProvider>
|
</SnackbarProvider>
|
||||||
</FeedsProvider>
|
</PlatformProvider>
|
||||||
</FileManagerProvider>
|
</FeedsProvider>
|
||||||
</FileProvider>
|
</FileManagerProvider>
|
||||||
</StampsProvider>
|
</FileProvider>
|
||||||
|
</StampsProvider>
|
||||||
|
</BalanceProvider>
|
||||||
</BeeProvider>
|
</BeeProvider>
|
||||||
</TopUpProvider>
|
</TopUpProvider>
|
||||||
</SettingsProvider>
|
</SettingsProvider>
|
||||||
|
|||||||
@@ -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)} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import FileManagerIcon from 'remixicon-react/FolderOpenLineIcon'
|
|||||||
import DocsIcon from 'remixicon-react/BookOpenLineIcon'
|
import DocsIcon from 'remixicon-react/BookOpenLineIcon'
|
||||||
import ExternalLinkIcon from 'remixicon-react/ExternalLinkLineIcon'
|
import ExternalLinkIcon from 'remixicon-react/ExternalLinkLineIcon'
|
||||||
import GithubIcon from 'remixicon-react/GithubFillIcon'
|
import GithubIcon from 'remixicon-react/GithubFillIcon'
|
||||||
|
import ExchangeDollarLineIcon from 'remixicon-react/ExchangeDollarLineIcon'
|
||||||
import HomeIcon from 'remixicon-react/Home3LineIcon'
|
import HomeIcon from 'remixicon-react/Home3LineIcon'
|
||||||
import SettingsIcon from 'remixicon-react/Settings2LineIcon'
|
import SettingsIcon from 'remixicon-react/Settings2LineIcon'
|
||||||
import AccountIcon from 'remixicon-react/Wallet3LineIcon'
|
import AccountIcon from 'remixicon-react/Wallet3LineIcon'
|
||||||
@@ -95,6 +96,11 @@ export default function SideBar(): ReactElement {
|
|||||||
icon: AccountIcon,
|
icon: AccountIcon,
|
||||||
pathMatcherSubstring: '/account/',
|
pathMatcherSubstring: '/account/',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Redistribution',
|
||||||
|
path: ROUTES.REDISTRIBUTION,
|
||||||
|
icon: ExchangeDollarLineIcon,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Settings',
|
label: 'Settings',
|
||||||
path: ROUTES.SETTINGS,
|
path: ROUTES.SETTINGS,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Box, Tooltip, Typography } from '@material-ui/core'
|
|
||||||
import { BZZ, DAI } from '@ethersphere/bee-js'
|
import { BZZ, DAI } from '@ethersphere/bee-js'
|
||||||
|
import { Box, Tooltip, Typography } from '@material-ui/core'
|
||||||
import { Wallet } from 'ethers'
|
import { Wallet } from 'ethers'
|
||||||
import { useSnackbar } from 'notistack'
|
import { useSnackbar } from 'notistack'
|
||||||
import { ReactElement, useContext, useEffect, useState } from 'react'
|
import { ReactElement, useContext, useEffect, useState } from 'react'
|
||||||
@@ -12,9 +12,9 @@ import ExpandableListItemKey from '../../components/ExpandableListItemKey'
|
|||||||
import { HistoryHeader } from '../../components/HistoryHeader'
|
import { HistoryHeader } from '../../components/HistoryHeader'
|
||||||
import { Loading } from '../../components/Loading'
|
import { Loading } from '../../components/Loading'
|
||||||
import { SwarmButton } from '../../components/SwarmButton'
|
import { SwarmButton } from '../../components/SwarmButton'
|
||||||
import { Context as BeeContext } from '../../providers/Bee'
|
|
||||||
import { Context as SettingsContext } from '../../providers/Settings'
|
import { Context as SettingsContext } from '../../providers/Settings'
|
||||||
import { Context as TopUpContext } from '../../providers/TopUp'
|
import { Context as TopUpContext } from '../../providers/TopUp'
|
||||||
|
import { Context as BalanceProvider } from '../../providers/WalletBalance'
|
||||||
import { createGiftWallet } from '../../utils/desktop'
|
import { createGiftWallet } from '../../utils/desktop'
|
||||||
import { ResolvedWallet } from '../../utils/wallet'
|
import { ResolvedWallet } from '../../utils/wallet'
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ const GIFT_WALLET_FUND_BZZ_AMOUNT = BZZ.fromDecimalString('0.5')
|
|||||||
export default function Index(): ReactElement {
|
export default function Index(): ReactElement {
|
||||||
const { giftWallets, addGiftWallet } = useContext(TopUpContext)
|
const { giftWallets, addGiftWallet } = useContext(TopUpContext)
|
||||||
const { rpcProvider, desktopUrl } = useContext(SettingsContext)
|
const { rpcProvider, desktopUrl } = useContext(SettingsContext)
|
||||||
const { walletBalance } = useContext(BeeContext)
|
const { balance } = useContext(BalanceProvider)
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [balances, setBalances] = useState<ResolvedWallet[]>([])
|
const [balances, setBalances] = useState<ResolvedWallet[]>([])
|
||||||
@@ -67,13 +67,12 @@ export default function Index(): ReactElement {
|
|||||||
navigate(-1)
|
navigate(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!walletBalance) {
|
if (!balance) {
|
||||||
return <Loading />
|
return <Loading />
|
||||||
}
|
}
|
||||||
|
|
||||||
const notEnoughFundsCheck =
|
const notEnoughFundsCheck =
|
||||||
walletBalance.nativeTokenBalance.lte(GIFT_WALLET_FUND_DAI_AMOUNT) ||
|
balance.dai.lte(GIFT_WALLET_FUND_DAI_AMOUNT) || balance.bzz.lt(GIFT_WALLET_FUND_BZZ_AMOUNT)
|
||||||
walletBalance.bzzBalance.lt(GIFT_WALLET_FUND_BZZ_AMOUNT)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -86,13 +85,10 @@ export default function Index(): ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box mb={0.25}>
|
<Box mb={0.25}>
|
||||||
<ExpandableListItem
|
<ExpandableListItem label="xDAI balance" value={`${balance.dai.toSignificantDigits(4)} xDAI`} />
|
||||||
label="xDAI balance"
|
|
||||||
value={`${walletBalance.nativeTokenBalance.toSignificantDigits(4)} xDAI`}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box mb={2}>
|
<Box mb={2}>
|
||||||
<ExpandableListItem label="xBZZ balance" value={`${walletBalance.bzzBalance.toSignificantDigits(4)} xBZZ`} />
|
<ExpandableListItem label="xBZZ balance" value={`${balance.bzz.toSignificantDigits(4)} xBZZ`} />
|
||||||
</Box>
|
</Box>
|
||||||
<Box mb={4}>
|
<Box mb={4}>
|
||||||
{balances.map((x, i) => (
|
{balances.map((x, i) => (
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import NodeInfoCard from './NodeInfoCard'
|
|||||||
import { WalletInfoCard } from './WalletInfoCard'
|
import { WalletInfoCard } from './WalletInfoCard'
|
||||||
|
|
||||||
export default function Status(): ReactElement {
|
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 { isDesktop, desktopUrl } = useContext(SettingsContext)
|
||||||
const { beeDesktopVersion } = useBeeDesktop(isDesktop, desktopUrl)
|
const { beeDesktopVersion } = useBeeDesktop(isDesktop, desktopUrl)
|
||||||
const { newBeeDesktopVersion } = useNewBeeDesktopVersion(isDesktop, desktopUrl, false)
|
const { newBeeDesktopVersion } = useNewBeeDesktopVersion(isDesktop, desktopUrl, false)
|
||||||
@@ -38,7 +38,10 @@ export default function Status(): ReactElement {
|
|||||||
<div style={{ height: '2px' }} />
|
<div style={{ height: '2px' }} />
|
||||||
<ExpandableListItem label="Connected peers" value={topology?.connected ?? '-'} />
|
<ExpandableListItem label="Connected peers" value={topology?.connected ?? '-'} />
|
||||||
<ExpandableListItem label="Population" value={topology?.population ?? '-'} />
|
<ExpandableListItem label="Population" value={topology?.population ?? '-'} />
|
||||||
|
<ExpandableListItem label="Pullsync rate" value={nodeStatus?.pullsyncRate} />
|
||||||
<ExpandableListItem label="Depth" value={topology?.depth ?? '-'} />
|
<ExpandableListItem label="Depth" value={topology?.depth ?? '-'} />
|
||||||
|
<ExpandableListItem label="Neighborhood size" value={nodeStatus?.neighborhoodSize} />
|
||||||
|
<ExpandableListItem label="Node is reachable" value={nodeStatus?.isReachable?.toString()} />
|
||||||
<ChainSync />
|
<ChainSync />
|
||||||
|
|
||||||
<div style={{ height: '16px' }} />
|
<div style={{ height: '16px' }} />
|
||||||
|
|||||||
@@ -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>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Box, Grid, Typography } from '@material-ui/core'
|
|
||||||
import { DAI } from '@ethersphere/bee-js'
|
import { DAI } from '@ethersphere/bee-js'
|
||||||
|
import { Box, Grid, Typography } from '@material-ui/core'
|
||||||
import { ReactElement, useContext } from 'react'
|
import { ReactElement, useContext } from 'react'
|
||||||
import { useNavigate } from 'react-router'
|
import { useNavigate } from 'react-router'
|
||||||
import Check from 'remixicon-react/CheckLineIcon'
|
import Check from 'remixicon-react/CheckLineIcon'
|
||||||
@@ -10,6 +10,7 @@ import { Loading } from '../../components/Loading'
|
|||||||
import { SwarmButton } from '../../components/SwarmButton'
|
import { SwarmButton } from '../../components/SwarmButton'
|
||||||
import { SwarmDivider } from '../../components/SwarmDivider'
|
import { SwarmDivider } from '../../components/SwarmDivider'
|
||||||
import { Context } from '../../providers/Bee'
|
import { Context } from '../../providers/Bee'
|
||||||
|
import { Context as BalanceProvider } from '../../providers/WalletBalance'
|
||||||
import { TopUpProgressIndicator } from './TopUpProgressIndicator'
|
import { TopUpProgressIndicator } from './TopUpProgressIndicator'
|
||||||
|
|
||||||
const MINIMUM_XDAI = DAI.fromDecimalString('0.5')
|
const MINIMUM_XDAI = DAI.fromDecimalString('0.5')
|
||||||
@@ -22,14 +23,15 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Index({ header, title, p, next }: Props): ReactElement {
|
export default function Index({ header, title, p, next }: Props): ReactElement {
|
||||||
const { nodeAddresses, walletBalance } = useContext(Context)
|
const { nodeAddresses } = useContext(Context)
|
||||||
|
const { balance } = useContext(BalanceProvider)
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
if (!walletBalance || !nodeAddresses) {
|
if (!balance || !nodeAddresses) {
|
||||||
return <Loading />
|
return <Loading />
|
||||||
}
|
}
|
||||||
|
|
||||||
const disabled = walletBalance.nativeTokenBalance.lt(MINIMUM_XDAI)
|
const disabled = balance.dai.lt(MINIMUM_XDAI)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -43,10 +45,10 @@ export default function Index({ header, title, p, next }: Props): ReactElement {
|
|||||||
<Box mb={4}>{p}</Box>
|
<Box mb={4}>{p}</Box>
|
||||||
<SwarmDivider mb={4} />
|
<SwarmDivider mb={4} />
|
||||||
<Box mb={0.25}>
|
<Box mb={0.25}>
|
||||||
<ExpandableListItemKey label="Funding wallet address" value={nodeAddresses.ethereum.toChecksum()} expanded />
|
<ExpandableListItemKey label="Funding wallet address" value={balance.address} expanded />
|
||||||
</Box>
|
</Box>
|
||||||
<Box mb={4}>
|
<Box mb={4}>
|
||||||
<ExpandableListItem label="xDAI balance" value={walletBalance.nativeTokenBalance.toSignificantDigits(4)} />
|
<ExpandableListItem label="xDAI balance" value={balance.dai.toSignificantDigits(4)} />
|
||||||
</Box>
|
</Box>
|
||||||
<Grid container direction="row" justifyContent="space-between">
|
<Grid container direction="row" justifyContent="space-between">
|
||||||
<SwarmButton iconType={Check} onClick={() => navigate(next)} disabled={disabled}>
|
<SwarmButton iconType={Check} onClick={() => navigate(next)} disabled={disabled}>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Box, Typography } from '@material-ui/core'
|
|
||||||
import { BeeModes } from '@ethersphere/bee-js'
|
import { BeeModes } from '@ethersphere/bee-js'
|
||||||
|
import { Box, Typography } from '@material-ui/core'
|
||||||
import { useSnackbar } from 'notistack'
|
import { useSnackbar } from 'notistack'
|
||||||
import { ReactElement, useContext, useEffect, useState } from 'react'
|
import { ReactElement, useContext, useEffect, useState } from 'react'
|
||||||
import { useNavigate, useParams } from 'react-router'
|
import { useNavigate, useParams } from 'react-router'
|
||||||
@@ -14,14 +14,16 @@ import { SwarmButton } from '../../components/SwarmButton'
|
|||||||
import { SwarmDivider } from '../../components/SwarmDivider'
|
import { SwarmDivider } from '../../components/SwarmDivider'
|
||||||
import { Context as BeeContext } from '../../providers/Bee'
|
import { Context as BeeContext } from '../../providers/Bee'
|
||||||
import { Context as SettingsContext } from '../../providers/Settings'
|
import { Context as SettingsContext } from '../../providers/Settings'
|
||||||
|
import { Context as BalanceProvider } from '../../providers/WalletBalance'
|
||||||
import { ROUTES } from '../../routes'
|
import { ROUTES } from '../../routes'
|
||||||
import { sleepMs } from '../../utils'
|
import { sleepMs } from '../../utils'
|
||||||
import { restartBeeNode, upgradeToLightNode } from '../../utils/desktop'
|
import { restartBeeNode, upgradeToLightNode } from '../../utils/desktop'
|
||||||
import { ResolvedWallet } from '../../utils/wallet'
|
import { ResolvedWallet } from '../../utils/wallet'
|
||||||
|
|
||||||
export function GiftCardFund(): ReactElement {
|
export function GiftCardFund(): ReactElement {
|
||||||
const { nodeAddresses, nodeInfo, walletBalance } = useContext(BeeContext)
|
const { nodeAddresses, nodeInfo } = useContext(BeeContext)
|
||||||
const { isDesktop, desktopUrl, rpcProvider, rpcProviderUrl } = useContext(SettingsContext)
|
const { isDesktop, desktopUrl, rpcProvider, rpcProviderUrl } = useContext(SettingsContext)
|
||||||
|
const { balance } = useContext(BalanceProvider)
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [wallet, setWallet] = useState<ResolvedWallet | null>(null)
|
const [wallet, setWallet] = useState<ResolvedWallet | null>(null)
|
||||||
@@ -39,7 +41,7 @@ export function GiftCardFund(): ReactElement {
|
|||||||
ResolvedWallet.make(privateKeyString, rpcProvider).then(setWallet)
|
ResolvedWallet.make(privateKeyString, rpcProvider).then(setWallet)
|
||||||
}, [privateKeyString, rpcProvider])
|
}, [privateKeyString, rpcProvider])
|
||||||
|
|
||||||
if (!wallet || !walletBalance) {
|
if (!wallet || !balance) {
|
||||||
return <Loading />
|
return <Loading />
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +96,7 @@ export function GiftCardFund(): ReactElement {
|
|||||||
</Box>
|
</Box>
|
||||||
<SwarmDivider mb={4} />
|
<SwarmDivider mb={4} />
|
||||||
<Box mb={0.25}>
|
<Box mb={0.25}>
|
||||||
<ExpandableListItemKey label="Gift wallet address" value={wallet.address || 'N/A'} />
|
<ExpandableListItemKey label="Gift wallet address" value={balance.address || 'N/A'} />
|
||||||
</Box>
|
</Box>
|
||||||
<Box mb={0.25}>
|
<Box mb={0.25}>
|
||||||
<ExpandableListItem label="xDAI balance" value={`${wallet.dai.toSignificantDigits(4)} xDAI`} />
|
<ExpandableListItem label="xDAI balance" value={`${wallet.dai.toSignificantDigits(4)} xDAI`} />
|
||||||
@@ -113,13 +115,10 @@ export function GiftCardFund(): ReactElement {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box mb={0.25}>
|
<Box mb={0.25}>
|
||||||
<ExpandableListItem
|
<ExpandableListItem label="xDAI balance" value={`${balance.dai.toSignificantDigits(4)} xDAI`} />
|
||||||
label="xDAI balance"
|
|
||||||
value={`${walletBalance.nativeTokenBalance.toSignificantDigits(4)} xDAI`}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box mb={2}>
|
<Box mb={2}>
|
||||||
<ExpandableListItem label="xBZZ balance" value={`${walletBalance.bzzBalance.toSignificantDigits(4)} xBZZ`} />
|
<ExpandableListItem label="xBZZ balance" value={`${balance.bzz.toSignificantDigits(4)} xBZZ`} />
|
||||||
</Box>
|
</Box>
|
||||||
<SwarmButton iconType={Check} onClick={onFund} disabled={loading} loading={loading}>
|
<SwarmButton iconType={Check} onClick={onFund} disabled={loading} loading={loading}>
|
||||||
{canUpgradeToLightNode ? 'Send all funds to your node and Upgrade' : 'Send all funds to your node'}
|
{canUpgradeToLightNode ? 'Send all funds to your node and Upgrade' : 'Send all funds to your node'}
|
||||||
|
|||||||
+16
-14
@@ -1,5 +1,5 @@
|
|||||||
import { Box, Typography } from '@material-ui/core'
|
|
||||||
import { BeeModes, BZZ, DAI } from '@ethersphere/bee-js'
|
import { BeeModes, BZZ, DAI } from '@ethersphere/bee-js'
|
||||||
|
import { Box, Typography } from '@material-ui/core'
|
||||||
import { useSnackbar } from 'notistack'
|
import { useSnackbar } from 'notistack'
|
||||||
import { ReactElement, useContext, useEffect, useState } from 'react'
|
import { ReactElement, useContext, useEffect, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router'
|
import { useNavigate } from 'react-router'
|
||||||
@@ -15,6 +15,7 @@ import { SwarmDivider } from '../../components/SwarmDivider'
|
|||||||
import { SwarmTextInput } from '../../components/SwarmTextInput'
|
import { SwarmTextInput } from '../../components/SwarmTextInput'
|
||||||
import { Context as BeeContext } from '../../providers/Bee'
|
import { Context as BeeContext } from '../../providers/Bee'
|
||||||
import { Context as SettingsContext } from '../../providers/Settings'
|
import { Context as SettingsContext } from '../../providers/Settings'
|
||||||
|
import { Context as BalanceProvider } from '../../providers/WalletBalance'
|
||||||
import { ROUTES } from '../../routes'
|
import { ROUTES } from '../../routes'
|
||||||
import { sleepMs } from '../../utils'
|
import { sleepMs } from '../../utils'
|
||||||
import { isSwapError, SwapError, wrapWithSwapError } from '../../utils/SwapError'
|
import { isSwapError, SwapError, wrapWithSwapError } from '../../utils/SwapError'
|
||||||
@@ -48,7 +49,8 @@ export function Swap({ header }: Props): ReactElement {
|
|||||||
const [daiAfterSwap, setDaiAfterSwap] = useState<DAI | null>(null)
|
const [daiAfterSwap, setDaiAfterSwap] = useState<DAI | null>(null)
|
||||||
|
|
||||||
const { rpcProviderUrl, isDesktop, desktopUrl } = useContext(SettingsContext)
|
const { rpcProviderUrl, isDesktop, desktopUrl } = useContext(SettingsContext)
|
||||||
const { nodeAddresses, nodeInfo, walletBalance } = useContext(BeeContext)
|
const { nodeAddresses, nodeInfo } = useContext(BeeContext)
|
||||||
|
const { balance } = useContext(BalanceProvider)
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { enqueueSnackbar } = useSnackbar()
|
const { enqueueSnackbar } = useSnackbar()
|
||||||
@@ -61,20 +63,20 @@ export function Swap({ header }: Props): ReactElement {
|
|||||||
|
|
||||||
// Set the initial xDAI to swap
|
// Set the initial xDAI to swap
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!walletBalance || userInputSwap) {
|
if (!balance || userInputSwap) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const minimumOptimalValue = DAI.fromDecimalString('1').plus(MINIMUM_XDAI)
|
const minimumOptimalValue = DAI.fromDecimalString('1').plus(MINIMUM_XDAI)
|
||||||
|
|
||||||
if (walletBalance.nativeTokenBalance.gte(minimumOptimalValue)) {
|
if (balance.dai.gte(minimumOptimalValue)) {
|
||||||
// Balance has at least 1 + MINIMUM_XDAI xDai
|
// Balance has at least 1 + MINIMUM_XDAI xDai
|
||||||
setDaiToSwap(walletBalance.nativeTokenBalance.minus(DAI.fromDecimalString('1')))
|
setDaiToSwap(balance.dai.minus(DAI.fromDecimalString('1')))
|
||||||
} else {
|
} else {
|
||||||
// Balance is low, halve the amount
|
// Balance is low, halve the amount
|
||||||
setDaiToSwap(walletBalance.nativeTokenBalance.divide(BigInt(2)))
|
setDaiToSwap(balance.dai.divide(BigInt(2)))
|
||||||
}
|
}
|
||||||
}, [walletBalance, userInputSwap])
|
}, [balance, userInputSwap])
|
||||||
|
|
||||||
// Set the xDAI to swap based on user input
|
// Set the xDAI to swap based on user input
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -95,13 +97,13 @@ export function Swap({ header }: Props): ReactElement {
|
|||||||
|
|
||||||
// Calculate the amount of tokens after swap
|
// Calculate the amount of tokens after swap
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!walletBalance || !daiToSwap || error) {
|
if (!balance || !daiToSwap || error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const daiAfterSwap = walletBalance.nativeTokenBalance.minus(daiToSwap)
|
const daiAfterSwap = balance.dai.minus(daiToSwap)
|
||||||
setDaiAfterSwap(daiAfterSwap)
|
setDaiAfterSwap(daiAfterSwap)
|
||||||
const tokensConverted = daiToSwap.exchangeToBZZ(price)
|
const tokensConverted = daiToSwap.exchangeToBZZ(price)
|
||||||
const bzzAfterSwap = tokensConverted.plus(walletBalance.bzzBalance)
|
const bzzAfterSwap = tokensConverted.plus(balance.bzz)
|
||||||
setBzzAfterSwap(bzzAfterSwap)
|
setBzzAfterSwap(bzzAfterSwap)
|
||||||
|
|
||||||
if (daiAfterSwap.lt(MINIMUM_XDAI)) {
|
if (daiAfterSwap.lt(MINIMUM_XDAI)) {
|
||||||
@@ -109,9 +111,9 @@ export function Swap({ header }: Props): ReactElement {
|
|||||||
} else if (bzzAfterSwap.lt(MINIMUM_XBZZ)) {
|
} else if (bzzAfterSwap.lt(MINIMUM_XBZZ)) {
|
||||||
setError(`Must have at least ${MINIMUM_XBZZ.toSignificantDigits(4)} xBZZ after swap!`)
|
setError(`Must have at least ${MINIMUM_XBZZ.toSignificantDigits(4)} xBZZ after swap!`)
|
||||||
}
|
}
|
||||||
}, [error, walletBalance, daiToSwap, price])
|
}, [error, balance, daiToSwap, price])
|
||||||
|
|
||||||
if (!walletBalance || !nodeAddresses || !daiToSwap || !bzzAfterSwap || !daiAfterSwap) {
|
if (!balance || !nodeAddresses || !daiToSwap || !bzzAfterSwap || !daiAfterSwap) {
|
||||||
return <Loading />
|
return <Loading />
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,8 +221,8 @@ export function Swap({ header }: Props): ReactElement {
|
|||||||
<SwarmDivider mb={4} />
|
<SwarmDivider mb={4} />
|
||||||
<Box mb={4}>
|
<Box mb={4}>
|
||||||
<Typography>
|
<Typography>
|
||||||
Your current balance is {walletBalance.nativeTokenBalance.toSignificantDigits(4)} xDAI and{' '}
|
Your current balance is {balance.dai.toSignificantDigits(4)} xDAI and {balance.bzz.toSignificantDigits(4)}{' '}
|
||||||
{walletBalance.bzzBalance.toSignificantDigits(4)} xBZZ.
|
xBZZ.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box mb={4}>
|
<Box mb={4}>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Box, createStyles, Grid, makeStyles, Typography } from '@material-ui/core'
|
|
||||||
import { BeeModes, BZZ, DAI } from '@ethersphere/bee-js'
|
import { BeeModes, BZZ, DAI } from '@ethersphere/bee-js'
|
||||||
|
import { Box, createStyles, Grid, makeStyles, Typography } from '@material-ui/core'
|
||||||
import { useSnackbar } from 'notistack'
|
import { useSnackbar } from 'notistack'
|
||||||
import { ReactElement, useContext, useState } from 'react'
|
import { ReactElement, useContext, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router'
|
import { useNavigate } from 'react-router'
|
||||||
@@ -15,6 +15,7 @@ import { SwarmButton } from '../../components/SwarmButton'
|
|||||||
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard'
|
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard'
|
||||||
import { Context as BeeContext, CheckState } from '../../providers/Bee'
|
import { Context as BeeContext, CheckState } from '../../providers/Bee'
|
||||||
import { Context as SettingsContext } from '../../providers/Settings'
|
import { Context as SettingsContext } from '../../providers/Settings'
|
||||||
|
import { Context as BalanceProvider } from '../../providers/WalletBalance'
|
||||||
import { ROUTES } from '../../routes'
|
import { ROUTES } from '../../routes'
|
||||||
import { restartBeeNode, upgradeToLightNode } from '../../utils/desktop'
|
import { restartBeeNode, upgradeToLightNode } from '../../utils/desktop'
|
||||||
|
|
||||||
@@ -39,7 +40,8 @@ export default function TopUp(): ReactElement {
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const styles = useStyles()
|
const styles = useStyles()
|
||||||
const { isDesktop, desktopUrl } = useContext(SettingsContext)
|
const { isDesktop, desktopUrl } = useContext(SettingsContext)
|
||||||
const { nodeInfo, status, walletBalance } = useContext(BeeContext)
|
const { nodeInfo, status } = useContext(BeeContext)
|
||||||
|
const { balance } = useContext(BalanceProvider)
|
||||||
const { rpcProviderUrl } = useContext(SettingsContext)
|
const { rpcProviderUrl } = useContext(SettingsContext)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const { enqueueSnackbar } = useSnackbar()
|
const { enqueueSnackbar } = useSnackbar()
|
||||||
@@ -47,8 +49,8 @@ export default function TopUp(): ReactElement {
|
|||||||
const canUpgradeToLightNode =
|
const canUpgradeToLightNode =
|
||||||
isDesktop &&
|
isDesktop &&
|
||||||
nodeInfo?.beeMode === BeeModes.ULTRA_LIGHT &&
|
nodeInfo?.beeMode === BeeModes.ULTRA_LIGHT &&
|
||||||
walletBalance?.nativeTokenBalance.gte(MINIMUM_XDAI) &&
|
balance?.dai.gte(MINIMUM_XDAI) &&
|
||||||
walletBalance?.bzzBalance.gte(MINIMUM_XBZZ)
|
balance?.bzz.gte(MINIMUM_XBZZ)
|
||||||
|
|
||||||
async function restart() {
|
async function restart() {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
@@ -65,7 +67,7 @@ export default function TopUp(): ReactElement {
|
|||||||
|
|
||||||
if (status.all === CheckState.ERROR) return <TroubleshootConnectionCard />
|
if (status.all === CheckState.ERROR) return <TroubleshootConnectionCard />
|
||||||
|
|
||||||
if (!walletBalance) {
|
if (!balance) {
|
||||||
return <Loading />
|
return <Loading />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ import {
|
|||||||
ChainState,
|
ChainState,
|
||||||
ChequebookAddressResponse,
|
ChequebookAddressResponse,
|
||||||
ChequebookBalanceResponse,
|
ChequebookBalanceResponse,
|
||||||
|
DebugStatus,
|
||||||
LastChequesResponse,
|
LastChequesResponse,
|
||||||
NodeAddresses,
|
NodeAddresses,
|
||||||
NodeInfo,
|
NodeInfo,
|
||||||
Peer,
|
Peer,
|
||||||
PeerBalance,
|
PeerBalance,
|
||||||
|
RedistributionState,
|
||||||
Topology,
|
Topology,
|
||||||
WalletBalance,
|
WalletBalance,
|
||||||
} from '@ethersphere/bee-js'
|
} from '@ethersphere/bee-js'
|
||||||
@@ -49,6 +51,7 @@ interface ContextInterface {
|
|||||||
apiHealth: boolean
|
apiHealth: boolean
|
||||||
nodeAddresses: NodeAddresses | null
|
nodeAddresses: NodeAddresses | null
|
||||||
nodeInfo: NodeInfo | null
|
nodeInfo: NodeInfo | null
|
||||||
|
nodeStatus: DebugStatus | null
|
||||||
topology: Topology | null
|
topology: Topology | null
|
||||||
chequebookAddress: ChequebookAddressResponse | null
|
chequebookAddress: ChequebookAddressResponse | null
|
||||||
peers: Peer[] | null
|
peers: Peer[] | null
|
||||||
@@ -59,6 +62,7 @@ interface ContextInterface {
|
|||||||
settlements: AllSettlements | null
|
settlements: AllSettlements | null
|
||||||
chainState: ChainState | null
|
chainState: ChainState | null
|
||||||
walletBalance: WalletBalance | null
|
walletBalance: WalletBalance | null
|
||||||
|
redistributionState: RedistributionState | null
|
||||||
latestBeeRelease: LatestBeeRelease | null
|
latestBeeRelease: LatestBeeRelease | null
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
lastUpdate: number | null
|
lastUpdate: number | null
|
||||||
@@ -79,6 +83,7 @@ const initialValues: ContextInterface = {
|
|||||||
apiHealth: false,
|
apiHealth: false,
|
||||||
nodeAddresses: null,
|
nodeAddresses: null,
|
||||||
nodeInfo: null,
|
nodeInfo: null,
|
||||||
|
nodeStatus: null,
|
||||||
topology: null,
|
topology: null,
|
||||||
chequebookAddress: null,
|
chequebookAddress: null,
|
||||||
stake: null,
|
stake: null,
|
||||||
@@ -89,6 +94,7 @@ const initialValues: ContextInterface = {
|
|||||||
settlements: null,
|
settlements: null,
|
||||||
chainState: null,
|
chainState: null,
|
||||||
walletBalance: null,
|
walletBalance: null,
|
||||||
|
redistributionState: null,
|
||||||
latestBeeRelease: null,
|
latestBeeRelease: null,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
lastUpdate: null,
|
lastUpdate: null,
|
||||||
@@ -172,6 +178,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
const [apiHealth, setApiHealth] = useState<boolean>(false)
|
const [apiHealth, setApiHealth] = useState<boolean>(false)
|
||||||
const [nodeAddresses, setNodeAddresses] = useState<NodeAddresses | null>(null)
|
const [nodeAddresses, setNodeAddresses] = useState<NodeAddresses | null>(null)
|
||||||
const [nodeInfo, setNodeInfo] = useState<NodeInfo | null>(null)
|
const [nodeInfo, setNodeInfo] = useState<NodeInfo | null>(null)
|
||||||
|
const [nodeStatus, setNodeStatus] = useState<DebugStatus | null>(null)
|
||||||
const [topology, setNodeTopology] = useState<Topology | null>(null)
|
const [topology, setNodeTopology] = useState<Topology | null>(null)
|
||||||
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)
|
||||||
@@ -182,6 +189,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
const [settlements, setSettlements] = useState<AllSettlements | null>(null)
|
const [settlements, setSettlements] = useState<AllSettlements | null>(null)
|
||||||
const [chainState, setChainState] = useState<ChainState | null>(null)
|
const [chainState, setChainState] = useState<ChainState | null>(null)
|
||||||
const [walletBalance, setWalletBalance] = useState<WalletBalance | null>(null)
|
const [walletBalance, setWalletBalance] = useState<WalletBalance | null>(null)
|
||||||
|
const [redistributionState, setRedistributionState] = useState<RedistributionState | null>(null)
|
||||||
const [startedAt] = useState(Date.now())
|
const [startedAt] = useState(Date.now())
|
||||||
|
|
||||||
const { latestBeeRelease } = useLatestBeeRelease()
|
const { latestBeeRelease } = useLatestBeeRelease()
|
||||||
@@ -257,6 +265,12 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
.then(setNodeInfo)
|
.then(setNodeInfo)
|
||||||
.catch(() => setNodeInfo(null)),
|
.catch(() => setNodeInfo(null)),
|
||||||
|
|
||||||
|
// NodeDebugInfo
|
||||||
|
beeApi
|
||||||
|
.getStatus({ timeout: TIMEOUT })
|
||||||
|
.then(setNodeStatus)
|
||||||
|
.catch(() => setNodeInfo(null)),
|
||||||
|
|
||||||
// Network Topology
|
// Network Topology
|
||||||
beeApi
|
beeApi
|
||||||
.getTopology({ timeout: TIMEOUT })
|
.getTopology({ timeout: TIMEOUT })
|
||||||
@@ -304,6 +318,12 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
.then(stake => setStake(stake))
|
.then(stake => setStake(stake))
|
||||||
.catch(() => setStake(null)),
|
.catch(() => setStake(null)),
|
||||||
|
|
||||||
|
// Redistribution stats
|
||||||
|
beeApi
|
||||||
|
.getRedistributionState({ timeout: TIMEOUT })
|
||||||
|
.then(setRedistributionState)
|
||||||
|
.catch(() => setRedistributionState(null)),
|
||||||
|
|
||||||
// Peer balances
|
// Peer balances
|
||||||
beeApi
|
beeApi
|
||||||
.getAllBalances({ timeout: TIMEOUT })
|
.getAllBalances({ timeout: TIMEOUT })
|
||||||
@@ -362,6 +382,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
apiHealth,
|
apiHealth,
|
||||||
nodeAddresses,
|
nodeAddresses,
|
||||||
nodeInfo,
|
nodeInfo,
|
||||||
|
nodeStatus,
|
||||||
topology,
|
topology,
|
||||||
chequebookAddress,
|
chequebookAddress,
|
||||||
peers,
|
peers,
|
||||||
@@ -372,6 +393,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
settlements,
|
settlements,
|
||||||
chainState,
|
chainState,
|
||||||
walletBalance,
|
walletBalance,
|
||||||
|
redistributionState,
|
||||||
latestBeeRelease,
|
latestBeeRelease,
|
||||||
isLoading,
|
isLoading,
|
||||||
lastUpdate,
|
lastUpdate,
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import { createContext, ReactChild, ReactElement, useContext, useEffect, useState } from 'react'
|
||||||
|
import { WalletAddress } from '../utils/wallet'
|
||||||
|
import { Context as BeeContext } from './Bee'
|
||||||
|
import { Context as SettingsContext } from './Settings'
|
||||||
|
|
||||||
|
interface ContextInterface {
|
||||||
|
balance: WalletAddress | null
|
||||||
|
error: Error | null
|
||||||
|
isLoading: boolean
|
||||||
|
lastUpdate: number | null
|
||||||
|
start: (frequency?: number) => void
|
||||||
|
stop: () => void
|
||||||
|
refresh: () => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialValues: ContextInterface = {
|
||||||
|
balance: null,
|
||||||
|
error: null,
|
||||||
|
isLoading: false,
|
||||||
|
lastUpdate: null,
|
||||||
|
start: () => {}, // eslint-disable-line
|
||||||
|
stop: () => {}, // eslint-disable-line
|
||||||
|
refresh: () => Promise.reject(),
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Context = createContext<ContextInterface>(initialValues)
|
||||||
|
export const Consumer = Context.Consumer
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: ReactChild
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Provider({ children }: Props): ReactElement {
|
||||||
|
const { rpcProvider } = useContext(SettingsContext)
|
||||||
|
const { nodeAddresses } = useContext(BeeContext)
|
||||||
|
const [balance, setBalance] = useState<WalletAddress | null>(initialValues.balance)
|
||||||
|
const [error, setError] = useState<Error | null>(initialValues.error)
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(initialValues.isLoading)
|
||||||
|
const [lastUpdate, setLastUpdate] = useState<number | null>(initialValues.lastUpdate)
|
||||||
|
const [frequency, setFrequency] = useState<number | null>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (nodeAddresses?.ethereum && rpcProvider) {
|
||||||
|
WalletAddress.make(nodeAddresses.ethereum.toHex(), rpcProvider).then(setBalance)
|
||||||
|
} else {
|
||||||
|
setBalance(null)
|
||||||
|
}
|
||||||
|
}, [nodeAddresses, rpcProvider])
|
||||||
|
|
||||||
|
const refresh = async () => {
|
||||||
|
// Don't want to refresh when already refreshing
|
||||||
|
if (isLoading) return
|
||||||
|
|
||||||
|
if (!balance) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true)
|
||||||
|
|
||||||
|
setBalance(await balance.refresh())
|
||||||
|
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 (
|
||||||
|
<Context.Provider value={{ balance, error, isLoading, lastUpdate, start, stop, refresh }}>
|
||||||
|
{children}
|
||||||
|
</Context.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ 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'
|
||||||
import { GiftCardTopUpIndex } from './pages/top-up/GiftCardTopUpIndex'
|
import { GiftCardTopUpIndex } from './pages/top-up/GiftCardTopUpIndex'
|
||||||
|
import RedistributionPage from './pages/redistribution'
|
||||||
import { Swap } from './pages/top-up/Swap'
|
import { Swap } from './pages/top-up/Swap'
|
||||||
import { Context as SettingsContext } from './providers/Settings'
|
import { Context as SettingsContext } from './providers/Settings'
|
||||||
import { FileManagerPage } from './pages/filemanager'
|
import { FileManagerPage } from './pages/filemanager'
|
||||||
@@ -37,6 +38,7 @@ export enum ROUTES {
|
|||||||
UPLOAD_IN_PROGRESS = '/files/upload/workflow',
|
UPLOAD_IN_PROGRESS = '/files/upload/workflow',
|
||||||
DOWNLOAD = '/files/download',
|
DOWNLOAD = '/files/download',
|
||||||
HASH = '/files/hash/:hash',
|
HASH = '/files/hash/:hash',
|
||||||
|
REDISTRIBUTION = '/redistribution',
|
||||||
SETTINGS = '/settings',
|
SETTINGS = '/settings',
|
||||||
STATUS = '/status',
|
STATUS = '/status',
|
||||||
TOP_UP = '/account/wallet/top-up',
|
TOP_UP = '/account/wallet/top-up',
|
||||||
@@ -82,6 +84,7 @@ const BaseRouter = (): ReactElement => {
|
|||||||
<Route path={ROUTES.SETTINGS} element={<Settings />} />
|
<Route path={ROUTES.SETTINGS} element={<Settings />} />
|
||||||
<Route path={ROUTES.STATUS} element={<Status />} />
|
<Route path={ROUTES.STATUS} element={<Status />} />
|
||||||
<Route path={ROUTES.INFO} element={<Info />} />
|
<Route path={ROUTES.INFO} element={<Info />} />
|
||||||
|
<Route path={ROUTES.REDISTRIBUTION} element={<RedistributionPage />} />
|
||||||
<Route path={ROUTES.TOP_UP} element={<TopUp />} />
|
<Route path={ROUTES.TOP_UP} element={<TopUp />} />
|
||||||
<Route path={ROUTES.TOP_UP_CRYPTO} element={<CryptoTopUpIndex />} />
|
<Route path={ROUTES.TOP_UP_CRYPTO} element={<CryptoTopUpIndex />} />
|
||||||
<Route path={ROUTES.TOP_UP_CRYPTO_SWAP} element={<Swap header="Top-up with cryptocurrencies" />} />
|
<Route path={ROUTES.TOP_UP_CRYPTO_SWAP} element={<Swap header="Top-up with cryptocurrencies" />} />
|
||||||
|
|||||||
@@ -2,6 +2,29 @@ import { BZZ, DAI, EthAddress } from '@ethersphere/bee-js'
|
|||||||
import { providers, Wallet } from 'ethers'
|
import { providers, Wallet } from 'ethers'
|
||||||
import { estimateNativeTransferTransactionCost, Rpc } from './rpc'
|
import { estimateNativeTransferTransactionCost, Rpc } from './rpc'
|
||||||
|
|
||||||
|
export class WalletAddress {
|
||||||
|
private constructor(
|
||||||
|
public address: string,
|
||||||
|
public bzz: BZZ,
|
||||||
|
public dai: DAI,
|
||||||
|
public provider: providers.JsonRpcProvider,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
static async make(address: string, provider: providers.JsonRpcProvider): Promise<WalletAddress> {
|
||||||
|
const bzz = await Rpc._eth_getBalanceERC20(address, provider)
|
||||||
|
const dai = await Rpc._eth_getBalance(address, provider)
|
||||||
|
|
||||||
|
return new WalletAddress(address, bzz, dai, provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async refresh(): Promise<WalletAddress> {
|
||||||
|
this.bzz = await Rpc._eth_getBalanceERC20(this.address, this.provider)
|
||||||
|
this.dai = await Rpc._eth_getBalance(this.address, this.provider)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class ResolvedWallet {
|
export class ResolvedWallet {
|
||||||
public address: string
|
public address: string
|
||||||
public privateKey: string
|
public privateKey: string
|
||||||
|
|||||||
Reference in New Issue
Block a user