Refactor Node page to accept identity_key in params
This commit is contained in:
@@ -15,8 +15,6 @@ export default async function Account({
|
||||
try {
|
||||
const address = (await params).address;
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<ContentLayout>
|
||||
<Grid container columnSpacing={5} rowSpacing={5}>
|
||||
|
||||
@@ -17,8 +17,10 @@ export default async function NymNode({
|
||||
params: Promise<{ id: string }>; // node_id or identity_key
|
||||
}) {
|
||||
try {
|
||||
const paramsId = (await params).id;
|
||||
const id = Number(paramsId);
|
||||
const paramId = (await params).id;
|
||||
const id = Number(paramId);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<ContentLayout>
|
||||
@@ -26,7 +28,7 @@ export default async function NymNode({
|
||||
<Grid size={12}>
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between" }}>
|
||||
<SectionHeading title="Nym Node Details" />
|
||||
<NodePageButtonGroup paramId={id.toString()} />
|
||||
<NodePageButtonGroup paramId={paramId} />
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid
|
||||
@@ -35,7 +37,7 @@ export default async function NymNode({
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<NodeProfileCard id={id} />
|
||||
<NodeProfileCard paramId={paramId} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
@@ -43,7 +45,7 @@ export default async function NymNode({
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<BasicInfoCard id={id} />
|
||||
<BasicInfoCard paramId={paramId} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
@@ -51,7 +53,7 @@ export default async function NymNode({
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<NodeRoleCard id={id} />
|
||||
<NodeRoleCard paramId={paramId} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
@@ -59,7 +61,7 @@ export default async function NymNode({
|
||||
md: 6,
|
||||
}}
|
||||
>
|
||||
<NodeParametersCard id={id} />
|
||||
<NodeParametersCard paramId={paramId} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
@@ -67,14 +69,14 @@ export default async function NymNode({
|
||||
md: 6,
|
||||
}}
|
||||
>
|
||||
<NodeDataCard id={id} />
|
||||
<NodeDataCard paramId={paramId} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
}}
|
||||
>
|
||||
<NodeDelegationsCard id={id} />
|
||||
<NodeDelegationsCard paramId={paramId} />
|
||||
</Grid>
|
||||
{/*
|
||||
<Grid
|
||||
|
||||
@@ -53,16 +53,6 @@ export const fetchGatewayStatus = async (
|
||||
return response.json();
|
||||
};
|
||||
|
||||
|
||||
|
||||
// export const fetchNodeIdByIdentityKey = async (
|
||||
// identity_key: string,
|
||||
// ): Promise<number> => {
|
||||
// const nodes = await fetchObservatoryNodes();
|
||||
// const node = nodes?.find((node) => node.identity_key === identity_key);
|
||||
// return node?.node_id || 0;
|
||||
// };
|
||||
|
||||
export const fetchNodeDelegations = async (
|
||||
id: number,
|
||||
): Promise<NodeRewardDetails[]> => {
|
||||
|
||||
@@ -7,12 +7,15 @@ import { formatBigNum } from "../../utils/formatBigNumbers";
|
||||
import ExplorerCard from "../cards/ExplorerCard";
|
||||
import CopyToClipboard from "../copyToClipboard/CopyToClipboard";
|
||||
import ExplorerListItem from "../list/ListItem";
|
||||
import { IObservatoryNode } from "@/app/api/types";
|
||||
|
||||
interface IBasicInfoCardProps {
|
||||
id: number;
|
||||
}
|
||||
type Props = {
|
||||
paramId: string;
|
||||
};
|
||||
|
||||
export const BasicInfoCard = ({ paramId }: Props) => {
|
||||
let nodeInfo: IObservatoryNode | undefined
|
||||
|
||||
export const BasicInfoCard = ({ id }: IBasicInfoCardProps) => {
|
||||
const {
|
||||
data: nymNodes,
|
||||
isLoading,
|
||||
@@ -50,7 +53,14 @@ export const BasicInfoCard = ({ id }: IBasicInfoCardProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
const nodeInfo = nymNodes.find((node) => node.node_id === id);
|
||||
// get node info based on wether it's dentity_key or node_id
|
||||
|
||||
if (paramId.length > 10) {
|
||||
nodeInfo = nymNodes.find((node) => node.identity_key === paramId);
|
||||
|
||||
} else {
|
||||
nodeInfo = nymNodes.find((node) => node.node_id === Number(paramId));
|
||||
}
|
||||
|
||||
if (!nodeInfo) return null;
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ import {
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useMemo } from "react";
|
||||
import type { NodeRewardDetails } from "../../app/api/types";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchNodeDelegations } from "@/app/api";
|
||||
|
||||
const ColumnHeading = ({
|
||||
children,
|
||||
@@ -27,13 +29,30 @@ const getNymsFormated = (unyms: string) => {
|
||||
return balance.toFixed();
|
||||
};
|
||||
|
||||
const DelegationsTable = ({
|
||||
delegations,
|
||||
}: {
|
||||
delegations: NodeRewardDetails[];
|
||||
}) => {
|
||||
type Props = {
|
||||
id: number;
|
||||
};
|
||||
|
||||
const DelegationsTable = ({ id }: Props) => {
|
||||
const router = useRouter();
|
||||
|
||||
const {
|
||||
data: delegations = [],
|
||||
isLoading,
|
||||
isError,
|
||||
} = useQuery({
|
||||
queryKey: ["nodeDelegations", id],
|
||||
queryFn: () => fetchNodeDelegations(id),
|
||||
staleTime: 10 * 60 * 1000, // 10 minutes
|
||||
refetchOnWindowFocus: false, // Prevents unnecessary refetching
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
});
|
||||
|
||||
|
||||
|
||||
if (isError) return null;
|
||||
|
||||
const columns: MRT_ColumnDef<NodeRewardDetails>[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
|
||||
@@ -6,12 +6,15 @@ import { Skeleton, Typography } from "@mui/material";
|
||||
import { format } from "date-fns";
|
||||
import ExplorerCard from "../cards/ExplorerCard";
|
||||
import ExplorerListItem from "../list/ListItem";
|
||||
import { IObservatoryNode } from "@/app/api/types";
|
||||
|
||||
interface INodeMetricsCardProps {
|
||||
id: number; // Node ID
|
||||
}
|
||||
type Props = {
|
||||
paramId: string;
|
||||
};
|
||||
|
||||
export const NodeDataCard = ({ paramId }: Props) => {
|
||||
let nodeInfo: IObservatoryNode | undefined
|
||||
|
||||
export const NodeDataCard = ({ id }: INodeMetricsCardProps) => {
|
||||
const {
|
||||
data: epochRewardsData,
|
||||
isLoading: isEpochLoading,
|
||||
@@ -61,7 +64,14 @@ export const NodeDataCard = ({ id }: INodeMetricsCardProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
const nodeInfo = nymNodes.find((node) => node.node_id === id);
|
||||
// get node info based on wether it's dentity_key or node_id
|
||||
|
||||
if (paramId.length > 10) {
|
||||
nodeInfo = nymNodes.find((node) => node.identity_key === paramId);
|
||||
|
||||
} else {
|
||||
nodeInfo = nymNodes.find((node) => node.node_id === Number(paramId));
|
||||
}
|
||||
|
||||
if (!nodeInfo) return null;
|
||||
|
||||
|
||||
@@ -1,30 +1,45 @@
|
||||
"use client";
|
||||
|
||||
import { fetchNodeDelegations } from "@/app/api";
|
||||
import { fetchObservatoryNodes } from "@/app/api";
|
||||
import { Skeleton, Typography } from "@mui/material";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import ExplorerCard from "../cards/ExplorerCard";
|
||||
import DelegationsTable from "./DelegationsTable";
|
||||
import { IObservatoryNode } from "@/app/api/types";
|
||||
|
||||
interface NodeDelegationsCardProps {
|
||||
id: number; // Node ID
|
||||
}
|
||||
type Props = {
|
||||
paramId: string;
|
||||
};
|
||||
|
||||
const NodeDelegationsCard = ({ paramId }: Props) => {
|
||||
let nodeInfo: IObservatoryNode | undefined
|
||||
|
||||
const NodeDelegationsCard = ({ id }: NodeDelegationsCardProps) => {
|
||||
const {
|
||||
data: delegations = [],
|
||||
isLoading,
|
||||
data: nymNodes,
|
||||
isError,
|
||||
isLoading
|
||||
} = useQuery({
|
||||
queryKey: ["nodeDelegations", id],
|
||||
queryFn: () => fetchNodeDelegations(id),
|
||||
queryKey: ["nymNodes"],
|
||||
queryFn: fetchObservatoryNodes,
|
||||
staleTime: 10 * 60 * 1000, // 10 minutes
|
||||
refetchOnWindowFocus: false, // Prevents unnecessary refetching
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
if (paramId.length > 10) {
|
||||
nodeInfo = nymNodes?.find((node) => node.identity_key === paramId);
|
||||
|
||||
} else {
|
||||
nodeInfo = nymNodes?.find((node) => node.node_id === Number(paramId));
|
||||
}
|
||||
|
||||
if (!nodeInfo) return null;
|
||||
|
||||
const id = nodeInfo.node_id
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<ExplorerCard label="Delegations" sx={{ height: "100%" }}>
|
||||
@@ -48,7 +63,7 @@ const NodeDelegationsCard = ({ id }: NodeDelegationsCardProps) => {
|
||||
|
||||
return (
|
||||
<ExplorerCard label="Delegations" sx={{ height: "100%" }}>
|
||||
<DelegationsTable delegations={delegations} />
|
||||
<DelegationsTable id={id} />
|
||||
</ExplorerCard>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,26 +3,15 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchObservatoryNodes } from "@/app/api";
|
||||
import ExplorerButtonGroup from "@/components/toggleButton/ToggleButton";
|
||||
import { IObservatoryNode } from "@/app/api/types";
|
||||
|
||||
type Props = {
|
||||
paramId: string;
|
||||
};
|
||||
|
||||
// const resolveNodeId = async (paramId: string) => {
|
||||
// if (paramId.length > 10) {
|
||||
// return await fetchNodeIdByIdentityKey(paramId);
|
||||
// }
|
||||
// return Number(paramId);
|
||||
// };
|
||||
|
||||
// const fetchResolvedNodeInfo = async (paramId: string) => {
|
||||
// const id = await resolveNodeId(paramId);
|
||||
// const node = await fetchNodeInfo(id);
|
||||
// return { node, id };
|
||||
// };
|
||||
|
||||
export default function NodePageButtonGroup({ paramId }: Props) {
|
||||
const id = Number(paramId)
|
||||
let nodeInfo: IObservatoryNode | undefined
|
||||
|
||||
const {
|
||||
data: nymNodes,
|
||||
isError,
|
||||
@@ -38,7 +27,16 @@ export default function NodePageButtonGroup({ paramId }: Props) {
|
||||
|
||||
if (!nymNodes || isError) return null;
|
||||
|
||||
const nodeInfo = nymNodes.find((node) => node.node_id === id);
|
||||
|
||||
// get node info based on wether it's dentity_key or node_id
|
||||
|
||||
if (paramId.length > 10) {
|
||||
nodeInfo = nymNodes.find((node) => node.identity_key === paramId);
|
||||
|
||||
} else {
|
||||
nodeInfo = nymNodes.find((node) => node.node_id === Number(paramId));
|
||||
}
|
||||
|
||||
|
||||
if (!nodeInfo) return null;
|
||||
|
||||
|
||||
@@ -4,15 +4,17 @@ import { formatBigNum } from "@/utils/formatBigNumbers";
|
||||
import { Skeleton, Typography } from "@mui/material";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchEpochRewards, fetchObservatoryNodes } from "../../app/api";
|
||||
import type { RewardingDetails } from "../../app/api/types";
|
||||
import type { IObservatoryNode, RewardingDetails } from "../../app/api/types";
|
||||
import ExplorerCard from "../cards/ExplorerCard";
|
||||
import ExplorerListItem from "../list/ListItem";
|
||||
|
||||
interface INodeParametersCardProps {
|
||||
id: number; // Node ID
|
||||
}
|
||||
type Props = {
|
||||
paramId: string;
|
||||
};
|
||||
|
||||
export const NodeParametersCard = ({ paramId }: Props) => {
|
||||
let nodeInfo: IObservatoryNode | undefined
|
||||
|
||||
export const NodeParametersCard = ({ id }: INodeParametersCardProps) => {
|
||||
// Fetch epoch rewards
|
||||
const {
|
||||
data: epochRewardsData,
|
||||
@@ -62,9 +64,17 @@ export const NodeParametersCard = ({ id }: INodeParametersCardProps) => {
|
||||
</ExplorerCard>
|
||||
);
|
||||
}
|
||||
const nodeInfo = nymNodes.find((node) => node.node_id === id);
|
||||
// get node info based on wether it's dentity_key or node_id
|
||||
|
||||
if (paramId.length > 10) {
|
||||
nodeInfo = nymNodes.find((node) => node.identity_key === paramId);
|
||||
|
||||
} else {
|
||||
nodeInfo = nymNodes.find((node) => node.node_id === Number(paramId));
|
||||
}
|
||||
|
||||
if (!nodeInfo) return null;
|
||||
|
||||
const totalStake = formatBigNum(Number(nodeInfo.total_stake) / 1_000_000);
|
||||
const totalStakeFormatted = `${totalStake} NYM`;
|
||||
|
||||
|
||||
@@ -17,12 +17,15 @@ import InfoModal, { type InfoModalProps } from "../modal/InfoModal";
|
||||
import StakeModal from "../staking/StakeModal";
|
||||
import { fee } from "../staking/schemas";
|
||||
import ConnectWallet from "../wallet/ConnectWallet";
|
||||
import { IObservatoryNode } from "@/app/api/types";
|
||||
|
||||
interface INodeProfileCardProps {
|
||||
id: number; // Node ID
|
||||
}
|
||||
type Props = {
|
||||
paramId: string;
|
||||
};
|
||||
|
||||
export const NodeProfileCard = ({ paramId }: Props) => {
|
||||
let nodeInfo: IObservatoryNode | undefined
|
||||
|
||||
export const NodeProfileCard = ({ id }: INodeProfileCardProps) => {
|
||||
const { isWalletConnected } = useChain(COSMOS_KIT_USE_CHAIN);
|
||||
const { nymClient } = useNymClient();
|
||||
const [infoModalProps, setInfoModalProps] = useState<InfoModalProps>({
|
||||
@@ -49,7 +52,15 @@ export const NodeProfileCard = ({ id }: INodeProfileCardProps) => {
|
||||
});
|
||||
|
||||
|
||||
const nodeInfo = nymNodes?.find((node) => node.node_id === id);
|
||||
|
||||
// get node info based on wether it's dentity_key or node_id
|
||||
|
||||
if (paramId.length > 10) {
|
||||
nodeInfo = nymNodes?.find((node) => node.identity_key === paramId);
|
||||
|
||||
} else {
|
||||
nodeInfo = nymNodes?.find((node) => node.node_id === Number(paramId));
|
||||
}
|
||||
|
||||
const handleOnSelectStake = useCallback(() => {
|
||||
if (!nodeInfo) return;
|
||||
@@ -80,6 +91,15 @@ export const NodeProfileCard = ({ id }: INodeProfileCardProps) => {
|
||||
}
|
||||
}, [isWalletConnected, nodeInfo]);
|
||||
|
||||
if (isLoadingNymNodes) {
|
||||
return (
|
||||
<ExplorerCard label="Nym Node" sx={{ height: "100%" }}>
|
||||
<Skeleton variant="rectangular" height={80} width={80} />
|
||||
<Skeleton variant="text" />
|
||||
<Skeleton variant="text" height={200} />
|
||||
</ExplorerCard>
|
||||
);
|
||||
}
|
||||
if (isError || !nymNodes) {
|
||||
return (
|
||||
<ExplorerCard label="Nym Node" sx={{ height: "100%" }}>
|
||||
@@ -90,15 +110,6 @@ export const NodeProfileCard = ({ id }: INodeProfileCardProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (isLoadingNymNodes) {
|
||||
return (
|
||||
<ExplorerCard label="Nym Node" sx={{ height: "100%" }}>
|
||||
<Skeleton variant="rectangular" height={80} width={80} />
|
||||
<Skeleton variant="text" />
|
||||
<Skeleton variant="text" height={200} />
|
||||
</ExplorerCard>
|
||||
);
|
||||
}
|
||||
|
||||
const handleStakeOnNode = async ({
|
||||
nodeId,
|
||||
|
||||
@@ -7,14 +7,14 @@ import {
|
||||
fetchGatewayStatus,
|
||||
fetchObservatoryNodes,
|
||||
} from "../../app/api";
|
||||
import type { LastProbeResult, NodeDescription } from "../../app/api/types";
|
||||
import type { IObservatoryNode, LastProbeResult, NodeDescription } from "../../app/api/types";
|
||||
import ExplorerCard from "../cards/ExplorerCard";
|
||||
import ExplorerListItem from "../list/ListItem";
|
||||
import StarRating from "../starRating/StarRating";
|
||||
|
||||
interface INodeRoleCardProps {
|
||||
id: number; // Node ID
|
||||
}
|
||||
type Props = {
|
||||
paramId: string;
|
||||
};
|
||||
|
||||
type NodeDescriptionNotNull = NonNullable<NodeDescription>;
|
||||
type DeclaredRoleKey = keyof NodeDescriptionNotNull["declared_role"];
|
||||
@@ -143,7 +143,9 @@ function calculateWireguardPerformance(probeResult: LastProbeResult): number {
|
||||
}
|
||||
}
|
||||
|
||||
export const NodeRoleCard = ({ id }: INodeRoleCardProps) => {
|
||||
export const NodeRoleCard = ({ paramId }: Props) => {
|
||||
let nodeInfo: IObservatoryNode | undefined
|
||||
|
||||
// Fetch node info
|
||||
const {
|
||||
data: nymNodes,
|
||||
@@ -171,8 +173,13 @@ export const NodeRoleCard = ({ id }: INodeRoleCardProps) => {
|
||||
|
||||
});
|
||||
|
||||
const nodeInfo = nymNodes?.find((node) => node.node_id === id);
|
||||
// Extract node roles once `nodeInfo` is available
|
||||
|
||||
if (paramId.length > 10) {
|
||||
nodeInfo = nymNodes?.find((node) => node.identity_key === paramId);
|
||||
|
||||
} else {
|
||||
nodeInfo = nymNodes?.find((node) => node.node_id === Number(paramId));
|
||||
} // Extract node roles once `nodeInfo` is available
|
||||
const nodeRoles = nodeInfo
|
||||
? getNodeRoles(nodeInfo.description.declared_role)
|
||||
: [];
|
||||
|
||||
Reference in New Issue
Block a user