feat: added tolerance to version check and warning if not exact to what we tested (#133)

* feat: added tolerance to version check and warning if not exact to what we expect

* chore: update to bee-js 0.10.0

* chore: updated interfaces that changed in bee-js 0.10.0
This commit is contained in:
Vojtech Simetka
2021-06-02 15:59:57 +02:00
committed by GitHub
parent bec84051a9
commit 353db10080
11 changed files with 137 additions and 48 deletions
+28 -11
View File
@@ -9,7 +9,7 @@
"version": "0.2.0", "version": "0.2.0",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"@ethersphere/bee-js": "^0.9.0", "@ethersphere/bee-js": "^0.10.0",
"@material-ui/core": "^4.11.4", "@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2", "@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.57", "@material-ui/lab": "^4.0.0-alpha.57",
@@ -31,6 +31,7 @@
"react-identicons": "^1.2.5", "react-identicons": "^1.2.5",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-syntax-highlighter": "^15.4.3", "react-syntax-highlighter": "^15.4.3",
"semver": "^7.3.2",
"serve-handler": "^6.1.3" "serve-handler": "^6.1.3"
}, },
"bin": { "bin": {
@@ -47,6 +48,7 @@
"@types/react-copy-to-clipboard": "^5.0.0", "@types/react-copy-to-clipboard": "^5.0.0",
"@types/react-dom": "^17.0.3", "@types/react-dom": "^17.0.3",
"@types/react-syntax-highlighter": "^13.5.0", "@types/react-syntax-highlighter": "^13.5.0",
"@types/semver": "^7.3.6",
"eslint": "^7.24.0", "eslint": "^7.24.0",
"eslint-config-prettier": "^8.2.0", "eslint-config-prettier": "^8.2.0",
"eslint-plugin-jest": "^24.3.5", "eslint-plugin-jest": "^24.3.5",
@@ -56,6 +58,11 @@
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
"typescript": "^4.2.4", "typescript": "^4.2.4",
"web-vitals": "^1.1.1" "web-vitals": "^1.1.1"
},
"engines": {
"bee": ">=0.6.0",
"node": ">=12.0.0",
"npm": ">=6.0.0"
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
@@ -1453,9 +1460,9 @@
} }
}, },
"node_modules/@ethersphere/bee-js": { "node_modules/@ethersphere/bee-js": {
"version": "0.9.0", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-0.9.0.tgz", "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-0.10.0.tgz",
"integrity": "sha512-C8lam7l+M5lLBOBKXyzIeSI2eE6R3jjBmP9bOJPZF8I42U5myNKp3t7QkIrdXZetrkAptVDISAZR0x0CZS2crQ==", "integrity": "sha512-j5HcrtN+LMmaqDNqdI5jUmU4YM039rV/vvOM2xsUX3+sFZBP00KVrpUsEMBzqQspU6U7//0y3BKx634V1hvpCA==",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
"elliptic": "^6.5.4", "elliptic": "^6.5.4",
@@ -1466,7 +1473,7 @@
"ws": "^7.4.4" "ws": "^7.4.4"
}, },
"engines": { "engines": {
"bee": "0.6.0-67cc8f24", "bee": "0.6.2-984dca0a",
"node": ">=12.0.0", "node": ">=12.0.0",
"npm": ">=6.0.0" "npm": ">=6.0.0"
} }
@@ -2803,6 +2810,12 @@
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz",
"integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==" "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA=="
}, },
"node_modules/@types/semver": {
"version": "7.3.6",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.6.tgz",
"integrity": "sha512-0caWDWmpCp0uifxFh+FaqK3CuZ2SkRR/ZRxAV5+zNdC3QVUi6wyOJnefhPvtNt8NQWXB5OA93BUvZsXpWat2Xw==",
"dev": true
},
"node_modules/@types/source-list-map": { "node_modules/@types/source-list-map": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
@@ -17283,7 +17296,6 @@
"version": "7.3.2", "version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
"dev": true,
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
}, },
@@ -22892,9 +22904,9 @@
} }
}, },
"@ethersphere/bee-js": { "@ethersphere/bee-js": {
"version": "0.9.0", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-0.9.0.tgz", "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-0.10.0.tgz",
"integrity": "sha512-C8lam7l+M5lLBOBKXyzIeSI2eE6R3jjBmP9bOJPZF8I42U5myNKp3t7QkIrdXZetrkAptVDISAZR0x0CZS2crQ==", "integrity": "sha512-j5HcrtN+LMmaqDNqdI5jUmU4YM039rV/vvOM2xsUX3+sFZBP00KVrpUsEMBzqQspU6U7//0y3BKx634V1hvpCA==",
"requires": { "requires": {
"axios": "^0.21.1", "axios": "^0.21.1",
"elliptic": "^6.5.4", "elliptic": "^6.5.4",
@@ -24029,6 +24041,12 @@
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz",
"integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==" "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA=="
}, },
"@types/semver": {
"version": "7.3.6",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.6.tgz",
"integrity": "sha512-0caWDWmpCp0uifxFh+FaqK3CuZ2SkRR/ZRxAV5+zNdC3QVUi6wyOJnefhPvtNt8NQWXB5OA93BUvZsXpWat2Xw==",
"dev": true
},
"@types/source-list-map": { "@types/source-list-map": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
@@ -36310,8 +36328,7 @@
"semver": { "semver": {
"version": "7.3.2", "version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
"dev": true
}, },
"send": { "send": {
"version": "0.17.1", "version": "0.17.1",
+8 -1
View File
@@ -24,7 +24,7 @@
"url": "https://github.com/ethersphere/bee-dashboard.git" "url": "https://github.com/ethersphere/bee-dashboard.git"
}, },
"dependencies": { "dependencies": {
"@ethersphere/bee-js": "^0.9.0", "@ethersphere/bee-js": "^0.10.0",
"@material-ui/core": "^4.11.4", "@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2", "@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.57", "@material-ui/lab": "^4.0.0-alpha.57",
@@ -46,6 +46,7 @@
"react-identicons": "^1.2.5", "react-identicons": "^1.2.5",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-syntax-highlighter": "^15.4.3", "react-syntax-highlighter": "^15.4.3",
"semver": "^7.3.2",
"serve-handler": "^6.1.3" "serve-handler": "^6.1.3"
}, },
"devDependencies": { "devDependencies": {
@@ -59,6 +60,7 @@
"@types/react-copy-to-clipboard": "^5.0.0", "@types/react-copy-to-clipboard": "^5.0.0",
"@types/react-dom": "^17.0.3", "@types/react-dom": "^17.0.3",
"@types/react-syntax-highlighter": "^13.5.0", "@types/react-syntax-highlighter": "^13.5.0",
"@types/semver": "^7.3.6",
"eslint": "^7.24.0", "eslint": "^7.24.0",
"eslint-config-prettier": "^8.2.0", "eslint-config-prettier": "^8.2.0",
"eslint-plugin-jest": "^24.3.5", "eslint-plugin-jest": "^24.3.5",
@@ -99,5 +101,10 @@
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
] ]
},
"engines": {
"node": ">=12.0.0",
"npm": ">=6.0.0",
"bee": ">=0.6.0"
} }
} }
+54
View File
@@ -0,0 +1,54 @@
import { ReactElement, useState } from 'react'
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'
import { Alert, AlertTitle } from '@material-ui/lab'
import Collapse from '@material-ui/core/Collapse'
import IconButton from '@material-ui/core/IconButton'
import CloseIcon from '@material-ui/icons/Close'
import { useStatusNodeVersion } from '../hooks/status'
import { SUPPORTED_BEE_VERSION_EXACT } from '@ethersphere/bee-js'
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
width: '100%',
marginBottom: theme.spacing(2),
},
}),
)
export default function VersionAlert(): ReactElement | null {
const classes = useStyles()
const { isLoading, userVersion } = useStatusNodeVersion()
const [open, setOpen] = useState<boolean>(true)
const isExactlySupportedBeeVersion = SUPPORTED_BEE_VERSION_EXACT === userVersion
if (isLoading) return null
return (
<Collapse in={!isExactlySupportedBeeVersion && open}>
<div className={classes.root}>
<Alert
severity="warning"
action={
<IconButton
aria-label="close"
color="inherit"
size="small"
onClick={() => {
setOpen(false)
}}
>
<CloseIcon fontSize="inherit" />
</IconButton>
}
>
<AlertTitle>Warning</AlertTitle>
Your Bee node version (<code>{userVersion}</code>) does not exactly match the Bee version we tested the Bee
Dashboard against (<code>{SUPPORTED_BEE_VERSION_EXACT}</code>). Please note that some functionality may not
work properly.
</Alert>
</div>
</Collapse>
)
}
+1 -1
View File
@@ -40,7 +40,7 @@ export default function DepositModal({ peerId, uncashedAmount }: Props): ReactEl
enqueueSnackbar( enqueueSnackbar(
<span> <span>
Successfully cashed out cheque. Transaction Successfully cashed out cheque. Transaction
<EthereumAddress hideBlockie transaction address={res.transactionHash} network={'goerli'} /> <EthereumAddress hideBlockie transaction address={res} network={'goerli'} />
</span>, </span>,
{ variant: 'success' }, { variant: 'success' },
) )
+2 -2
View File
@@ -18,7 +18,7 @@ interface Props {
label: string label: string
max?: BigNumber max?: BigNumber
min?: BigNumber min?: BigNumber
action: (amount: bigint) => Promise<{ transactionHash: string }> action: (amount: bigint) => Promise<string>
} }
export default function WithdrawModal({ export default function WithdrawModal({
@@ -48,7 +48,7 @@ export default function WithdrawModal({
if (amountToken === null) return if (amountToken === null) return
try { try {
const { transactionHash } = await action(amountToken.toBigInt as bigint) const transactionHash = await action(amountToken.toBigInt as bigint)
setOpen(false) setOpen(false)
enqueueSnackbar(`${successMessage} Transaction ${transactionHash}`, { variant: 'success' }) enqueueSnackbar(`${successMessage} Transaction ${transactionHash}`, { variant: 'success' })
} catch (e) { } catch (e) {
+22 -3
View File
@@ -9,6 +9,8 @@ import {
useDebugApiHealth, useDebugApiHealth,
useLatestBeeRelease, useLatestBeeRelease,
} from './apiHooks' } from './apiHooks'
import semver from 'semver'
import { engines } from '../../package.json'
export interface StatusChequebookHook extends StatusHookCommon { export interface StatusChequebookHook extends StatusHookCommon {
chequebookBalance: ChequebookBalance | null chequebookBalance: ChequebookBalance | null
@@ -19,12 +21,29 @@ export const useStatusNodeVersion = (): StatusNodeVersionHook => {
const { latestBeeRelease, isLoadingLatestBeeRelease } = useLatestBeeRelease() const { latestBeeRelease, isLoadingLatestBeeRelease } = useLatestBeeRelease()
const { nodeHealth, isLoadingNodeHealth } = useDebugApiHealth() const { nodeHealth, isLoadingNodeHealth } = useDebugApiHealth()
const latestVersion = semver.coerce(latestBeeRelease?.name)?.version
const latestUserVersion = semver.coerce(nodeHealth?.version)?.version
const isLatestBeeVersion = Boolean(
latestVersion &&
latestUserVersion &&
semver.satisfies(latestVersion, latestUserVersion, {
includePrerelease: true,
}),
)
return { return {
isLoading: isLoadingNodeHealth || isLoadingLatestBeeRelease, isLoading: isLoadingNodeHealth || isLoadingLatestBeeRelease,
isOk: Boolean(latestBeeRelease && latestBeeRelease.name === `v${nodeHealth?.version?.split('-')[0]}`), isOk: Boolean(
userVersion: nodeHealth?.version?.split('-')[0] || '-', nodeHealth &&
latestVersion: latestBeeRelease?.name.substring(1) || '-', semver.satisfies(nodeHealth.version, engines.bee, {
includePrerelease: true,
}),
),
userVersion: nodeHealth?.version,
latestVersion,
latestUrl: latestBeeRelease?.html_url || 'https://github.com/ethersphere/bee/releases/latest', latestUrl: latestBeeRelease?.html_url || 'https://github.com/ethersphere/bee/releases/latest',
isLatestBeeVersion,
} }
} }
+5 -16
View File
@@ -1,5 +1,6 @@
import { useState, useEffect, ReactElement } from 'react' import { useState, useEffect, ReactElement } from 'react'
import ErrorBoundary from '../components/ErrorBoundary' import ErrorBoundary from '../components/ErrorBoundary'
import AlertVersion from '../components/AlertVersion'
import { createStyles, Theme, makeStyles } from '@material-ui/core/styles' import { createStyles, Theme, makeStyles } from '@material-ui/core/styles'
@@ -11,7 +12,6 @@ import { RouteComponentProps } from 'react-router'
const useStyles = makeStyles((theme: Theme) => const useStyles = makeStyles((theme: Theme) =>
createStyles({ createStyles({
toolbar: theme.mixins.toolbar,
content: { content: {
marginLeft: '240px', marginLeft: '240px',
flexGrow: 1, flexGrow: 1,
@@ -19,20 +19,6 @@ const useStyles = makeStyles((theme: Theme) =>
padding: theme.spacing(3), padding: theme.spacing(3),
paddingBottom: '65px', paddingBottom: '65px',
}, },
footer: {
marginLeft: '240px',
backgroundColor: theme.palette.background.default,
position: 'fixed',
bottom: 0,
flexGrow: 1,
width: '-webkit-fill-available',
padding: theme.spacing(2),
textAlign: 'center',
},
logo: {
height: '20px',
marginRight: '7px',
},
}), }),
) )
@@ -73,7 +59,10 @@ const Dashboard = (props: Props): ReactElement => {
<SideBar {...props} themeMode={themeMode} health={health} nodeHealth={nodeHealth} /> <SideBar {...props} themeMode={themeMode} health={health} nodeHealth={nodeHealth} />
<NavBar themeMode={themeMode} /> <NavBar themeMode={themeMode} />
<ErrorBoundary> <ErrorBoundary>
<main className={classes.content}>{props.children}</main> <main className={classes.content}>
<AlertVersion />
{props.children}
</main>
</ErrorBoundary> </ErrorBoundary>
</div> </div>
) )
+9 -5
View File
@@ -23,17 +23,19 @@ const useStyles = makeStyles(() =>
interface Props { interface Props {
nodeAddresses: NodeAddresses | null nodeAddresses: NodeAddresses | null
nodeTopology: Topology | null nodeTopology: Topology | null
userBeeVersion: string | null userBeeVersion?: string
latestBeeVersion: string | null isLatestBeeVersion: boolean
isOk: boolean isOk: boolean
latestUrl: string
} }
function StatusCard({ function StatusCard({
userBeeVersion, userBeeVersion,
nodeAddresses, nodeAddresses,
nodeTopology, nodeTopology,
latestBeeVersion,
isOk, isOk,
isLatestBeeVersion,
latestUrl,
}: Props): ReactElement | null { }: Props): ReactElement | null {
const classes = useStyles() const classes = useStyles()
@@ -72,7 +74,7 @@ function StatusCard({
Bee Bee
</a>{' '} </a>{' '}
<span>{userBeeVersion || '-'}</span> <span>{userBeeVersion || '-'}</span>
{userBeeVersion && latestBeeVersion && userBeeVersion === latestBeeVersion ? ( {isLatestBeeVersion ? (
<Chip <Chip
style={{ marginLeft: '7px', color: '#2145a0' }} style={{ marginLeft: '7px', color: '#2145a0' }}
size="small" size="small"
@@ -80,7 +82,9 @@ function StatusCard({
className={classes.status} className={classes.status}
/> />
) : ( ) : (
<Typography variant="button">update</Typography> <Button size="small" variant="outlined" href={latestUrl}>
update
</Button>
)} )}
</Typography> </Typography>
<Typography component="div" variant="subtitle2" gutterBottom> <Typography component="div" variant="subtitle2" gutterBottom>
+2 -1
View File
@@ -49,9 +49,10 @@ export default function Status(): ReactElement {
<div className={classes.root}> <div className={classes.root}>
<StatusCard <StatusCard
userBeeVersion={nodeVersion.userVersion} userBeeVersion={nodeVersion.userVersion}
latestBeeVersion={nodeVersion.latestVersion} isLatestBeeVersion={nodeVersion.isLatestBeeVersion}
isOk={checks.every(c => c.isOk)} isOk={checks.every(c => c.isOk)}
nodeTopology={topology.topology} nodeTopology={topology.topology}
latestUrl={nodeVersion.latestUrl}
nodeAddresses={ethereumConnection.nodeAddresses} nodeAddresses={ethereumConnection.nodeAddresses}
/> />
{ethereumConnection.nodeAddresses && chequebook.chequebookAddress && ( {ethereumConnection.nodeAddresses && chequebook.chequebookAddress && (
+3 -2
View File
@@ -11,9 +11,10 @@ interface StatusHookCommon {
} }
interface StatusNodeVersionHook extends StatusHookCommon { interface StatusNodeVersionHook extends StatusHookCommon {
userVersion: string userVersion?: string
latestVersion: string latestVersion?: string
latestUrl: string latestUrl: string
isLatestBeeVersion: boolean
} }
interface StatusEthereumConnectionHook extends StatusHookCommon { interface StatusEthereumConnectionHook extends StatusHookCommon {
nodeAddresses: NodeAddresses | null nodeAddresses: NodeAddresses | null
+3 -6
View File
@@ -4,11 +4,9 @@ import {
BalanceResponse, BalanceResponse,
Bee, Bee,
BeeDebug, BeeDebug,
CashoutResponse,
ChequebookAddressResponse, ChequebookAddressResponse,
ChequebookBalanceResponse, ChequebookBalanceResponse,
Data, Data,
DepositTokensResponse,
FileData, FileData,
Health, Health,
LastCashoutActionResponse, LastCashoutActionResponse,
@@ -21,7 +19,6 @@ import {
PostageBatchOptions, PostageBatchOptions,
Reference, Reference,
Topology, Topology,
WithdrawTokensResponse,
} from '@ethersphere/bee-js' } from '@ethersphere/bee-js'
import { apiHost, debugApiHost } from '../constants' import { apiHost, debugApiHost } from '../constants'
@@ -88,7 +85,7 @@ export const beeDebugApi = {
getLastCheques(): Promise<LastChequesResponse> { getLastCheques(): Promise<LastChequesResponse> {
return beeJSDebugClient().getLastCheques() return beeJSDebugClient().getLastCheques()
}, },
peerCashout(peerId: string): Promise<CashoutResponse> { peerCashout(peerId: string): Promise<string> {
return beeJSDebugClient().cashoutLastCheque(peerId) return beeJSDebugClient().cashoutLastCheque(peerId)
}, },
getPeerLastCashout(peerId: string): Promise<LastCashoutActionResponse> { getPeerLastCashout(peerId: string): Promise<LastCashoutActionResponse> {
@@ -97,10 +94,10 @@ export const beeDebugApi = {
getPeerLastCheques(peerId: string): Promise<LastChequesForPeerResponse> { getPeerLastCheques(peerId: string): Promise<LastChequesForPeerResponse> {
return beeJSDebugClient().getLastChequesForPeer(peerId) return beeJSDebugClient().getLastChequesForPeer(peerId)
}, },
withdraw(amount: bigint): Promise<WithdrawTokensResponse> { withdraw(amount: bigint): Promise<string> {
return beeJSDebugClient().withdrawTokens(amount) return beeJSDebugClient().withdrawTokens(amount)
}, },
deposit(amount: bigint): Promise<DepositTokensResponse> { deposit(amount: bigint): Promise<string> {
return beeJSDebugClient().depositTokens(amount) return beeJSDebugClient().depositTokens(amount)
}, },
}, },