178 lines
4.7 KiB
TypeScript
178 lines
4.7 KiB
TypeScript
import { ChevronRight } from "@mui/icons-material";
|
|
import { Card, IconButton, Typography } from "@mui/material";
|
|
import { Box } from "@mui/system";
|
|
import {
|
|
createColumnHelper,
|
|
getCoreRowModel,
|
|
getExpandedRowModel,
|
|
Row,
|
|
useReactTable,
|
|
} from "@tanstack/react-table";
|
|
import { ReactElement, useMemo } from "react";
|
|
import useLatestObservations, {
|
|
ObservationsResponse,
|
|
} from "../hooks/useLatestObservations";
|
|
import useLatestVAAs, { VAAsResponse } from "../hooks/useLatestVAAs";
|
|
import * as vaa from "../utils/vaa";
|
|
import Table from "./Table";
|
|
|
|
const columnHelper = createColumnHelper<VAAsResponse>();
|
|
|
|
// TODO: parse once
|
|
|
|
const columns = [
|
|
columnHelper.display({
|
|
id: "_expand",
|
|
cell: ({ row }) =>
|
|
row.getCanExpand() ? (
|
|
<IconButton
|
|
size="small"
|
|
{...{
|
|
onClick: row.getToggleExpandedHandler(),
|
|
style: { cursor: "pointer" },
|
|
}}
|
|
>
|
|
<ChevronRight
|
|
sx={{
|
|
transition: ".2s",
|
|
transform: row.getIsExpanded() ? "rotate(90deg)" : undefined,
|
|
}}
|
|
/>
|
|
</IconButton>
|
|
) : null,
|
|
}),
|
|
columnHelper.accessor("_id", {
|
|
id: "sequence",
|
|
header: () => "Sequence",
|
|
cell: (info) => info.getValue().split("/")[2],
|
|
}),
|
|
columnHelper.accessor("vaas", {
|
|
id: "type",
|
|
header: () => "Type",
|
|
cell: (info) =>
|
|
vaa.parse(Buffer.from(info.getValue(), "base64")).payload.type,
|
|
}),
|
|
columnHelper.accessor("vaas", {
|
|
id: "chain",
|
|
header: () => "Chain",
|
|
cell: (info) =>
|
|
(vaa.parse(Buffer.from(info.getValue(), "base64")).payload as any)
|
|
.chain || "",
|
|
}),
|
|
columnHelper.accessor("vaas", {
|
|
id: "address",
|
|
header: () => "Address",
|
|
cell: (info) =>
|
|
(vaa.parse(Buffer.from(info.getValue(), "base64")).payload as any)
|
|
.address || "",
|
|
}),
|
|
columnHelper.accessor("vaas", {
|
|
id: "module",
|
|
header: () => "Module",
|
|
cell: (info) =>
|
|
(vaa.parse(Buffer.from(info.getValue(), "base64")).payload as any)
|
|
.module || "",
|
|
}),
|
|
columnHelper.accessor("updatedAt", {
|
|
header: () => "Observed At",
|
|
cell: (info) => new Date(info.getValue()).toLocaleString(),
|
|
}),
|
|
];
|
|
|
|
const obsColumnHelper = createColumnHelper<CollatedObservation>();
|
|
|
|
const obsColumns = [
|
|
obsColumnHelper.accessor("_id", {
|
|
header: () => "Sequence",
|
|
cell: (info) => info.getValue().split("/")[2],
|
|
}),
|
|
obsColumnHelper.accessor("count", {
|
|
header: () => "Count",
|
|
cell: (info) => info.getValue(),
|
|
}),
|
|
];
|
|
|
|
function VAADetails({ row }: { row: Row<VAAsResponse> }): ReactElement {
|
|
return (
|
|
<Typography variant="body2" sx={{ wordBreak: "break-all" }}>
|
|
{Buffer.from(row.original.vaas, "base64").toString("hex")}
|
|
</Typography>
|
|
);
|
|
}
|
|
|
|
type CollatedObservation = {
|
|
_id: string;
|
|
count: number;
|
|
observations: ObservationsResponse[];
|
|
};
|
|
|
|
function Governance() {
|
|
const vaas = useLatestVAAs(
|
|
"1/0000000000000000000000000000000000000000000000000000000000000004"
|
|
);
|
|
const obs = useLatestObservations(
|
|
"1/0000000000000000000000000000000000000000000000000000000000000004"
|
|
);
|
|
const collatedObservations: CollatedObservation[] = useMemo(
|
|
() =>
|
|
// NOTE: this ignores differing digests
|
|
Object.entries(
|
|
obs.reduce((obvsById, o) => {
|
|
if (!obvsById[o.messageId]) {
|
|
obvsById[o.messageId] = [];
|
|
}
|
|
obvsById[o.messageId].push(o);
|
|
return obvsById;
|
|
}, {} as any)
|
|
).map(([key, val]: [string, any]) => ({
|
|
_id: key,
|
|
count: val.length,
|
|
observations: val,
|
|
})),
|
|
[obs]
|
|
);
|
|
const table = useReactTable({
|
|
columns,
|
|
data: vaas,
|
|
getRowId: (vaa) => vaa._id,
|
|
getRowCanExpand: () => true,
|
|
getCoreRowModel: getCoreRowModel(),
|
|
getExpandedRowModel: getExpandedRowModel(),
|
|
enableSorting: false,
|
|
});
|
|
const obsTable = useReactTable({
|
|
columns: obsColumns,
|
|
data: collatedObservations,
|
|
getRowId: (o) => o._id,
|
|
getCoreRowModel: getCoreRowModel(),
|
|
enableSorting: false,
|
|
});
|
|
return (
|
|
<>
|
|
<Box m={2}>
|
|
<Card>
|
|
<Box m={2}>
|
|
<Typography variant="h5">Latest Governance VAAs</Typography>
|
|
<Table<VAAsResponse>
|
|
table={table}
|
|
renderSubComponent={VAADetails}
|
|
/>
|
|
</Box>
|
|
</Card>
|
|
</Box>
|
|
<Box m={2}>
|
|
<Card>
|
|
<Box m={2}>
|
|
<Typography variant="h5">Latest Governance Observations</Typography>
|
|
<Typography variant="caption">
|
|
Collated from the latest 100 governance observations
|
|
</Typography>
|
|
<Table<CollatedObservation> table={obsTable} />
|
|
</Box>
|
|
</Card>
|
|
</Box>
|
|
</>
|
|
);
|
|
}
|
|
export default Governance;
|