15c3012199
* explorer-api: add nym node endpoints + UI to show nym-nodes and account balances * explorer-api: add endpoints to get operator rewards explorer-ui: show delegations on nym-nodes, show operator rewards, bug fixes * explorer-ui: change summary screen to only show nym-node stats * explorer-api: add unstable routes to get legacy mixnodes and gateways from the contract instead of the Nym API explorer-ui: adapt front-end to show less information in legacy nodes with plain bond types * explorer-ui: fix up source of legacy mixnode data * explorer-ui: add more account page null and undefined checks * explorer-ui: filter out null gateway versions * explorer-ui: sanitise gateway versions * explorer-ui: add more guards on the balance parts to check that greater than 0 * explorer-api: make /tmp/unstable/gateways endpoint compatible with the current Harbour Master API * explorer-ui: fix typo * cargo fmt * Add node-id, total stake and links to nodes list --------- Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com> Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
147 lines
4.1 KiB
TypeScript
147 lines
4.1 KiB
TypeScript
import * as React from 'react'
|
|
import {
|
|
Link,
|
|
Paper,
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableContainer,
|
|
TableHead,
|
|
TableRow,
|
|
TableCellProps,
|
|
} from '@mui/material'
|
|
import { useTheme } from '@mui/material/styles'
|
|
import { Tooltip } from '@nymproject/react/tooltip/Tooltip'
|
|
import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard'
|
|
import { Box } from '@mui/system'
|
|
import { unymToNym } from '@/app/utils/currency'
|
|
import { GatewayEnrichedRowType } from './Gateways/Gateways'
|
|
import { MixnodeRowType } from './MixNodes'
|
|
import { StakeSaturationProgressBar } from './MixNodes/Economics/StakeSaturationProgressBar'
|
|
import {EXPLORER_FOR_ACCOUNTS} from "@/app/api/constants";
|
|
|
|
export type ColumnsType = {
|
|
field: string
|
|
title: string
|
|
headerAlign?: TableCellProps['align']
|
|
width?: string | number
|
|
tooltipInfo?: string
|
|
}
|
|
|
|
export interface UniversalTableProps<T = any> {
|
|
tableName: string
|
|
columnsData: ColumnsType[]
|
|
rows: T[]
|
|
}
|
|
|
|
function formatCellValues(val: string | number, field: string) {
|
|
if (field === 'identity_key' && typeof val === 'string') {
|
|
return (
|
|
<Box display="flex" justifyContent="flex-end">
|
|
<CopyToClipboard
|
|
sx={{ mr: 1, mt: 0.5, fontSize: '18px' }}
|
|
value={val}
|
|
tooltip={`Copy identity key ${val} to clipboard`}
|
|
/>
|
|
<span>{val}</span>
|
|
</Box>
|
|
)
|
|
}
|
|
|
|
if (field === 'bond') {
|
|
return unymToNym(val, 6)
|
|
}
|
|
|
|
if (field === 'owner') {
|
|
return (
|
|
<Link
|
|
underline="none"
|
|
color="inherit"
|
|
target="_blank"
|
|
href={`${EXPLORER_FOR_ACCOUNTS}/account/${val}`}
|
|
>
|
|
{val}
|
|
</Link>
|
|
)
|
|
}
|
|
|
|
if (field === 'stake_saturation') {
|
|
return <StakeSaturationProgressBar value={Number(val)} threshold={100} />
|
|
}
|
|
|
|
return val
|
|
}
|
|
|
|
export const DetailTable: FCWithChildren<{
|
|
tableName: string
|
|
columnsData: ColumnsType[]
|
|
rows: MixnodeRowType[] | GatewayEnrichedRowType[] | any[]
|
|
}> = ({ tableName, columnsData, rows }: UniversalTableProps) => {
|
|
const theme = useTheme()
|
|
return (
|
|
<TableContainer component={Paper}>
|
|
<Table sx={{ minWidth: 1080 }} aria-label={tableName}>
|
|
<TableHead>
|
|
<TableRow>
|
|
{columnsData?.map(({ field, title, width, tooltipInfo }) => (
|
|
<TableCell
|
|
key={field}
|
|
sx={{ fontSize: 14, fontWeight: 600, width }}
|
|
>
|
|
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
{tooltipInfo && (
|
|
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
<Tooltip
|
|
title={tooltipInfo}
|
|
id={field}
|
|
placement="top-start"
|
|
textColor={
|
|
theme.palette.nym.networkExplorer.tooltip.color
|
|
}
|
|
bgColor={
|
|
theme.palette.nym.networkExplorer.tooltip.background
|
|
}
|
|
maxWidth={230}
|
|
arrow
|
|
/>
|
|
</Box>
|
|
)}
|
|
{title}
|
|
</Box>
|
|
</TableCell>
|
|
))}
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{rows.map((eachRow) => (
|
|
<TableRow
|
|
key={eachRow.id}
|
|
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
|
|
>
|
|
{columnsData?.map((data, index) => (
|
|
<TableCell
|
|
key={data.title}
|
|
component="th"
|
|
scope="row"
|
|
variant="body"
|
|
sx={{
|
|
padding: 2,
|
|
width: 200,
|
|
fontSize: 14,
|
|
}}
|
|
data-testid={`${data.title.replace(/ /g, '-')}-value`}
|
|
>
|
|
{formatCellValues(
|
|
eachRow[columnsData[index].field],
|
|
columnsData[index].field
|
|
)}
|
|
</TableCell>
|
|
))}
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</TableContainer>
|
|
)
|
|
}
|