Skip to content

Commit

Permalink
Feat/network status (#514)
Browse files Browse the repository at this point in the history
* feat: add new api endpoint to appConfig

* feat: add NetworkStatus component

* chore: better logging

* fix: destructuring of response data

* feat: update status message

* chore(content): fix typo

* chore: update api endpoint

* chore: update network status api endpoint

* chore: remove workaround

* refactor: network alert config
  • Loading branch information
moritzkirstein authored Mar 17, 2024
1 parent 03ae65d commit fdedf02
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 7 deletions.
13 changes: 12 additions & 1 deletion app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,16 @@ module.exports = {
},

// Display alert banner for the developer preview deployment
showPreviewAlert: process.env.NEXT_PUBLIC_SHOW_PREVIEW_ALERT || 'false'
showPreviewAlert: process.env.NEXT_PUBLIC_SHOW_PREVIEW_ALERT || 'false',

networkAlertConfig: {
// Refresh interval for network status - 30 sec
refreshInterval: 30000,
// Margin of error for block count (how much difference between min / max block numbers before showing an alert)
errorMargin: 10,
// Map chainIds to their respective status endpoints
statusEndpoints: {
100: 'https://status.genx.delta-dao.com/api/check-blocks'
}
}
}
10 changes: 10 additions & 0 deletions src/@context/MarketMetadata/_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ export interface AppConfig {
roughTxGasEstimate: number
}
showPreviewAlert: string
networkAlertConfig: {
// Refresh interval for network status - 30 sec
refreshInterval: number
// Margin of error for block count (how much difference between min / max block numbers before showing an alert)
errorMargin: number
// Map chainIds to their respective status endpoints
statusEndpoints: {
[chainId: number]: string
}
}
}
export interface SiteContent {
siteTitle: string
Expand Down
84 changes: 84 additions & 0 deletions src/components/@shared/NetworkStatus/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { ReactElement, useCallback, useEffect, useState } from 'react'
import { useNetwork } from 'wagmi'
import { useMarketMetadata } from '../../../@context/MarketMetadata'
import Alert from '../atoms/Alert'
import axios from 'axios'
import { LoggerInstance } from '@oceanprotocol/lib'

export default function NetworkStatus({
className
}: {
className?: string
}): ReactElement {
const [showNetworkAlert, setShowNetworkAlert] = useState(true)
const [network, setNetwork] = useState<string>()
const { appConfig } = useMarketMetadata()
const { chain } = useNetwork()

const { networkAlertConfig } = appConfig

const fetchNetworkStatus = useCallback(
async (chainId: number) => {
if (!chainId) return
setNetwork(chain?.name)
const apiEndpoint = networkAlertConfig.statusEndpoints[chainId]
if (!apiEndpoint) return
LoggerInstance.log(`[NetworkStatus] retrieving network status`, {
apiEndpoint
})
try {
const result = await axios.get(apiEndpoint)
const { Nodes } = result.data
const { nodes }: { nodes: { [node: string]: number } } = Nodes
let minBlock: number
let maxBlock: number
Object.values(nodes).forEach((block) => {
if (!minBlock || block < minBlock) minBlock = block
if (!maxBlock || block > maxBlock) maxBlock = block
})
const hasError = maxBlock - minBlock > networkAlertConfig.errorMargin
setShowNetworkAlert(hasError)
LoggerInstance.log(`[NetworkStatus] network status updated:`, {
minBlock,
maxBlock,
hasError
})
} catch (error) {
LoggerInstance.error(
`[NetworkStatus] could not retrieve network status:`,
error.message
)
}
},
[networkAlertConfig, chain]
)

useEffect(() => {
if (!chain?.id) return

fetchNetworkStatus(chain?.id)

// init periodic refresh for network status
const networkStatusInterval = setInterval(
() => fetchNetworkStatus(chain?.id),
networkAlertConfig.refreshInterval
)

return () => {
clearInterval(networkStatusInterval)
}
}, [chain, fetchNetworkStatus])

return (
showNetworkAlert && (
<Alert
state="warning"
text="The network is currently undergoing maintenance, which may cause instabilities or transaction delays. Please try again later if you run into issues."
title="Network Status"
badge={network || chain?.id.toString()}
onDismiss={() => setShowNetworkAlert(false)}
className={className}
/>
)
)
}
5 changes: 4 additions & 1 deletion src/components/@shared/Page/PageHeader.module.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.header {
margin-bottom: var(--spacer);
max-width: 50rem;
}

.title {
Expand Down Expand Up @@ -81,3 +80,7 @@
margin-top: calc(var(--spacer) / 2);
max-width: 30rem;
}

.networkAlert {
margin: var(--spacer) auto;
}
14 changes: 9 additions & 5 deletions src/components/@shared/Page/PageHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ReactElement } from 'react'
import classNames from 'classnames/bind'
import styles from './PageHeader.module.css'
import Markdown from '@shared/Markdown'
import SearchBar from '@components/Header/SearchBar'
import BrandLogo from '@images/brand-logo.svg'
import GaiaXLogo from '@images/gaia-x-logo.svg'
import Markdown from '@shared/Markdown'
import classNames from 'classnames/bind'
import { ReactElement } from 'react'
import NetworkStatus from '../NetworkStatus'
import styles from './PageHeader.module.css'

const cx = classNames.bind(styles)

Expand Down Expand Up @@ -46,7 +47,10 @@ export default function PageHeader({
</div>
</div>
) : (
<h1 className={styles.title}>{title}</h1>
<div>
<h1 className={styles.title}>{title}</h1>
<NetworkStatus className={styles.networkAlert} />
</div>
)}
{description && !isHome && (
<Markdown text={description} className={styles.description} />
Expand Down

0 comments on commit fdedf02

Please sign in to comment.