Refactor Node Page to spectreDao api endpoint
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import type NodeData from "@/app/api/types";
|
||||
import type { IObservatoryNode } from "@/app/api/types";
|
||||
import { DATA_OBSERVATORY_NODES_URL, NYM_NODES } from "@/app/api/urls";
|
||||
import { DATA_OBSERVATORY_NODES_URL } from "@/app/api/urls";
|
||||
import BlogArticlesCards from "@/components/blogs/BlogArticleCards";
|
||||
import ExplorerCard from "@/components/cards/ExplorerCard";
|
||||
import { ContentLayout } from "@/components/contentLayout/ContentLayout";
|
||||
@@ -36,32 +35,20 @@ export default async function NymNode({
|
||||
const observatoryNymNodes: IObservatoryNode[] =
|
||||
await observatoryResponse.json();
|
||||
|
||||
if (!observatoryNymNodes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const observatoryNymNode = observatoryNymNodes.find(
|
||||
(node) => node.node_id === id,
|
||||
);
|
||||
|
||||
console.log("observatorynNymNode :>> ", observatoryNymNode);
|
||||
|
||||
const response = await fetch(NYM_NODES, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
next: { revalidate: 60 },
|
||||
// refresh event list cache at given interval
|
||||
});
|
||||
|
||||
const nymNodes: NodeData[] = await response.json();
|
||||
|
||||
if (!nymNodes) {
|
||||
if (!observatoryNymNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nymNode = nymNodes.find((node) => node.node_id === id);
|
||||
|
||||
if (!nymNode) {
|
||||
return null;
|
||||
}
|
||||
const nodeDelegationsResponse = await fetch(
|
||||
`${DATA_OBSERVATORY_NODES_URL}/${id}/delegations`,
|
||||
{
|
||||
@@ -92,67 +79,66 @@ export default async function NymNode({
|
||||
{
|
||||
label: "Account",
|
||||
isSelected: false,
|
||||
link: `/account/${nymNode.bond_information.owner}`,
|
||||
link: `/account/${observatoryNymNode.bonding_address}`,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<NodeProfileCard
|
||||
bondInfo={nymNode.bond_information}
|
||||
nodeDescription={nymNode.description}
|
||||
nodeInfo={observatoryNymNode}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<BasicInfoCard
|
||||
bondInfo={nymNode.bond_information}
|
||||
nodeDescription={nymNode.description}
|
||||
rewardDetails={nymNode.rewarding_details}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<QualityIndicatorsCard
|
||||
nodeDescription={nymNode.description}
|
||||
nodeInfo={observatoryNymNode}
|
||||
/>
|
||||
</Grid>
|
||||
{observatoryNymNode && (
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<NodeProfileCard nodeInfo={observatoryNymNode} />
|
||||
</Grid>
|
||||
)}
|
||||
{observatoryNymNode && (
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<BasicInfoCard
|
||||
rewardDetails={observatoryNymNode.rewarding_details}
|
||||
nodeInfo={observatoryNymNode}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
{observatoryNymNode && (
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 4,
|
||||
}}
|
||||
>
|
||||
<QualityIndicatorsCard nodeInfo={observatoryNymNode} />
|
||||
</Grid>
|
||||
)}
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 6,
|
||||
}}
|
||||
>
|
||||
<NodeRewardsCard rewardDetails={nymNode.rewarding_details} />
|
||||
</Grid>
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 6,
|
||||
}}
|
||||
>
|
||||
<NodeMetricsCard
|
||||
nodeDescription={nymNode.description}
|
||||
nodeId={nymNode.bond_information.node_id}
|
||||
<NodeRewardsCard
|
||||
rewardDetails={observatoryNymNode.rewarding_details}
|
||||
nodeInfo={observatoryNymNode}
|
||||
/>
|
||||
</Grid>
|
||||
{observatoryNymNode && (
|
||||
<Grid
|
||||
size={{
|
||||
xs: 12,
|
||||
md: 6,
|
||||
}}
|
||||
>
|
||||
<NodeMetricsCard nodeInfo={observatoryNymNode} />
|
||||
</Grid>
|
||||
)}
|
||||
{delegations && (
|
||||
<Grid
|
||||
size={{
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import type {
|
||||
BondInformation,
|
||||
NodeDescription,
|
||||
RewardingDetails,
|
||||
} from "@/app/api/types";
|
||||
import type { IObservatoryNode, RewardingDetails } from "@/app/api/types";
|
||||
import { formatBigNum } from "@/utils/formatBigNumbers";
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
import { format } from "date-fns";
|
||||
@@ -11,17 +7,16 @@ import CopyToClipboard from "../copyToClipboard/CopyToClipboard";
|
||||
import ExplorerListItem from "../list/ListItem";
|
||||
|
||||
interface IBasicInfoCardProps {
|
||||
bondInfo: BondInformation;
|
||||
nodeDescription: NodeDescription;
|
||||
rewardDetails: RewardingDetails;
|
||||
nodeInfo: IObservatoryNode;
|
||||
}
|
||||
|
||||
export const BasicInfoCard = (props: IBasicInfoCardProps) => {
|
||||
const { bondInfo, nodeDescription, rewardDetails } = props;
|
||||
const { rewardDetails, nodeInfo } = props;
|
||||
|
||||
const timeBonded = nodeDescription
|
||||
const timeBonded = nodeInfo
|
||||
? format(
|
||||
new Date(nodeDescription.build_information.build_timestamp),
|
||||
new Date(nodeInfo.description.build_information.build_timestamp),
|
||||
"dd/MM/yyyy",
|
||||
)
|
||||
: "-";
|
||||
@@ -42,8 +37,10 @@ export const BasicInfoCard = (props: IBasicInfoCardProps) => {
|
||||
justifyContent="space-between"
|
||||
width="100%"
|
||||
>
|
||||
<Typography variant="body4">{bondInfo.owner}</Typography>
|
||||
<CopyToClipboard text={bondInfo.owner} />
|
||||
<Typography variant="body4">
|
||||
{nodeInfo.bonding_address}
|
||||
</Typography>
|
||||
<CopyToClipboard text={nodeInfo.bonding_address} />
|
||||
</Stack>
|
||||
}
|
||||
/>
|
||||
@@ -58,10 +55,8 @@ export const BasicInfoCard = (props: IBasicInfoCardProps) => {
|
||||
justifyContent="space-between"
|
||||
width="100%"
|
||||
>
|
||||
<Typography variant="body4">
|
||||
{bondInfo.node.identity_key}
|
||||
</Typography>
|
||||
<CopyToClipboard text={bondInfo.node.identity_key} />
|
||||
<Typography variant="body4">{nodeInfo.identity_key}</Typography>
|
||||
<CopyToClipboard text={nodeInfo.identity_key} />
|
||||
</Stack>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import type { ExplorerData } from "@/app/api";
|
||||
import type { IObservatoryNode, NodeDescription } from "@/app/api/types";
|
||||
import type { IObservatoryNode } from "@/app/api/types";
|
||||
import { CURRENT_EPOCH_REWARDS } from "@/app/api/urls";
|
||||
import ExplorerCard from "../cards/ExplorerCard";
|
||||
import ExplorerListItem from "../list/ListItem";
|
||||
|
||||
interface INodeMetricsCardProps {
|
||||
nodeDescription: NodeDescription;
|
||||
nodeId: number;
|
||||
nodeInfo?: IObservatoryNode;
|
||||
nodeInfo: IObservatoryNode;
|
||||
}
|
||||
|
||||
export const NodeMetricsCard = async (props: INodeMetricsCardProps) => {
|
||||
const { nodeDescription, nodeId, nodeInfo } = props;
|
||||
const { nodeInfo } = props;
|
||||
|
||||
const epochRewards = await fetch(CURRENT_EPOCH_REWARDS, {
|
||||
headers: {
|
||||
@@ -50,7 +48,7 @@ export const NodeMetricsCard = async (props: INodeMetricsCardProps) => {
|
||||
nodeInfo.total_stake,
|
||||
epochRewardsData.interval.stake_saturation_point,
|
||||
)
|
||||
: "";
|
||||
: "N/A";
|
||||
|
||||
return (
|
||||
<ExplorerCard label="Nym node metrics" sx={{ height: "100%" }}>
|
||||
@@ -58,24 +56,22 @@ export const NodeMetricsCard = async (props: INodeMetricsCardProps) => {
|
||||
row
|
||||
divider
|
||||
label="Node ID."
|
||||
value={nodeId.toString()}
|
||||
value={nodeInfo.node_id.toString()}
|
||||
/>
|
||||
{nodeDescription && (
|
||||
<>
|
||||
<ExplorerListItem
|
||||
row
|
||||
divider
|
||||
label="Host"
|
||||
value={nodeDescription.host_information.ip_address.toString()}
|
||||
/>
|
||||
<ExplorerListItem
|
||||
row
|
||||
divider
|
||||
label="Version"
|
||||
value={nodeDescription.build_information.build_version}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<>
|
||||
<ExplorerListItem
|
||||
row
|
||||
divider
|
||||
label="Host"
|
||||
value={nodeInfo.description.host_information.ip_address.toString()}
|
||||
/>
|
||||
<ExplorerListItem
|
||||
row
|
||||
divider
|
||||
label="Version"
|
||||
value={nodeInfo.description.build_information.build_version}
|
||||
/>
|
||||
</>
|
||||
{epochRewardsData && (
|
||||
<ExplorerListItem row label="Active set Prob." value={activeSetProb} />
|
||||
)}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
"use client";
|
||||
import type {
|
||||
BondInformation,
|
||||
IObservatoryNode,
|
||||
NodeDescription,
|
||||
} from "@/app/api/types";
|
||||
import type { IObservatoryNode } from "@/app/api/types";
|
||||
import { COSMOS_KIT_USE_CHAIN } from "@/config";
|
||||
import { useNymClient } from "@/hooks/useNymClient";
|
||||
import { useChain } from "@cosmos-kit/react";
|
||||
@@ -19,13 +15,11 @@ import { fee } from "../staking/schemas";
|
||||
import ConnectWallet from "../wallet/ConnectWallet";
|
||||
|
||||
interface INodeProfileCardProps {
|
||||
bondInfo: BondInformation;
|
||||
nodeDescription: NodeDescription;
|
||||
nodeInfo?: IObservatoryNode;
|
||||
nodeInfo: IObservatoryNode;
|
||||
}
|
||||
|
||||
export const NodeProfileCard = (props: INodeProfileCardProps) => {
|
||||
const { bondInfo, nodeDescription, nodeInfo } = props;
|
||||
const { nodeInfo } = props;
|
||||
const { isWalletConnected } = useChain(COSMOS_KIT_USE_CHAIN);
|
||||
const { nymClient } = useNymClient();
|
||||
const [infoModalProps, setInfoModalProps] = useState<InfoModalProps>({
|
||||
@@ -102,16 +96,16 @@ export const NodeProfileCard = (props: INodeProfileCardProps) => {
|
||||
return;
|
||||
}
|
||||
setSelectedNodeForStaking({
|
||||
nodeId: bondInfo.node_id,
|
||||
identityKey: bondInfo.node.identity_key,
|
||||
nodeId: nodeInfo.node_id,
|
||||
identityKey: nodeInfo.identity_key,
|
||||
});
|
||||
}, [isWalletConnected, bondInfo]);
|
||||
}, [isWalletConnected, nodeInfo]);
|
||||
|
||||
return (
|
||||
<ExplorerCard label="Nym Node" sx={{ height: "100%" }}>
|
||||
<Stack gap={1}>
|
||||
<Box display={"flex"} justifyContent={"flex-start"}>
|
||||
<RandomAvatar name={bondInfo.node.identity_key} size={80} square />
|
||||
<RandomAvatar name={nodeInfo.identity_key} size={80} square />
|
||||
</Box>
|
||||
<Typography
|
||||
variant="h3"
|
||||
@@ -121,10 +115,10 @@ export const NodeProfileCard = (props: INodeProfileCardProps) => {
|
||||
>
|
||||
{nodeInfo?.self_description.moniker || "Moniker"}
|
||||
</Typography>
|
||||
{nodeDescription && (
|
||||
{nodeInfo.description.auxiliary_details.location && (
|
||||
<CountryFlag
|
||||
countryCode={nodeDescription.auxiliary_details.location}
|
||||
countryName={nodeDescription.auxiliary_details.location}
|
||||
countryCode={nodeInfo.description.auxiliary_details.location}
|
||||
countryName={nodeInfo.description.auxiliary_details.location}
|
||||
/>
|
||||
)}
|
||||
{nodeInfo && (
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
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 INodeRewardsCardProps {
|
||||
rewardDetails: RewardingDetails;
|
||||
nodeInfo?: IObservatoryNode;
|
||||
}
|
||||
|
||||
export const NodeRewardsCard = (props: INodeRewardsCardProps) => {
|
||||
const { rewardDetails } = props;
|
||||
|
||||
const totalRewards = Number(rewardDetails.total_unit_reward) / 1000000;
|
||||
const totalRewardsFormated = `${totalRewards} NYM`;
|
||||
// const totalRewards = Number(rewardDetails.total_unit_reward) / 1000000;
|
||||
// const totalRewardsFormated = `${totalRewards} NYM`;
|
||||
|
||||
const operatorRewards = Number(rewardDetails.operator) / 1000000;
|
||||
const operatorRewardsFormated = `${operatorRewards} NYM`;
|
||||
|
||||
const stakerRewards = Number(rewardDetails.delegates) / 1000000;
|
||||
const stakerRewardsFormated = `${stakerRewards} NYM`;
|
||||
// const stakerRewards = Number(rewardDetails.delegates) / 1000000;
|
||||
// const stakerRewardsFormated = `${stakerRewards} NYM`;
|
||||
|
||||
const profitMarginPercent =
|
||||
Number(rewardDetails.cost_params.profit_margin_percent) * 100;
|
||||
|
||||
@@ -5,8 +5,7 @@ import ExplorerListItem from "../list/ListItem";
|
||||
import StarRating from "../starRating/StarRating";
|
||||
|
||||
interface IQualityIndicatorsCardProps {
|
||||
nodeDescription: NodeDescription;
|
||||
nodeInfo?: IObservatoryNode;
|
||||
nodeInfo: IObservatoryNode;
|
||||
}
|
||||
|
||||
type NodeDescriptionNotNull = NonNullable<NodeDescription>;
|
||||
@@ -31,13 +30,9 @@ function getNodeRoles(
|
||||
}
|
||||
|
||||
export const QualityIndicatorsCard = (props: IQualityIndicatorsCardProps) => {
|
||||
const { nodeDescription, nodeInfo } = props;
|
||||
const { nodeInfo } = props;
|
||||
|
||||
if (!nodeDescription) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nodeRoles = getNodeRoles(nodeDescription.declared_role);
|
||||
const nodeRoles = getNodeRoles(nodeInfo.description.declared_role);
|
||||
const NodeRoles = nodeRoles.map((role) => (
|
||||
<Stack key={role} direction="row" gap={1}>
|
||||
<Chip key={role} label={role} size="small" />
|
||||
@@ -45,19 +40,16 @@ export const QualityIndicatorsCard = (props: IQualityIndicatorsCardProps) => {
|
||||
));
|
||||
|
||||
function calculateQualityOfServiceStars(quality: number): number {
|
||||
if (quality < 0.2) {
|
||||
if (quality < 0.3) {
|
||||
return 1;
|
||||
}
|
||||
if (quality < 0.4) {
|
||||
if (quality < 0.5) {
|
||||
return 2;
|
||||
}
|
||||
if (quality < 0.6) {
|
||||
if (quality < 0.7) {
|
||||
return 3;
|
||||
}
|
||||
if (quality < 0.7) {
|
||||
return 4;
|
||||
}
|
||||
return 5;
|
||||
return 4;
|
||||
}
|
||||
const qualityOfServiceStars = nodeInfo?.uptime
|
||||
? calculateQualityOfServiceStars(nodeInfo?.uptime)
|
||||
@@ -78,12 +70,14 @@ export const QualityIndicatorsCard = (props: IQualityIndicatorsCardProps) => {
|
||||
</Stack>
|
||||
}
|
||||
/>
|
||||
<ExplorerListItem
|
||||
row
|
||||
divider
|
||||
label="Quality of service"
|
||||
value={<StarRating value={qualityOfServiceStars} />}
|
||||
/>
|
||||
{nodeIsMixNodeOnly && (
|
||||
<ExplorerListItem
|
||||
row
|
||||
divider
|
||||
label="Quality of service"
|
||||
value={<StarRating value={qualityOfServiceStars} />}
|
||||
/>
|
||||
)}
|
||||
{!nodeIsMixNodeOnly && (
|
||||
<ExplorerListItem
|
||||
row
|
||||
@@ -97,7 +91,7 @@ export const QualityIndicatorsCard = (props: IQualityIndicatorsCardProps) => {
|
||||
row
|
||||
divider
|
||||
label="Probe score"
|
||||
value={<StarRating value={5} />}
|
||||
value={<StarRating value={4} />}
|
||||
/>
|
||||
)}
|
||||
</ExplorerCard>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Rating } from "@mui/material";
|
||||
const StarRating = ({
|
||||
value,
|
||||
defaultValue,
|
||||
max = 5,
|
||||
max = 4,
|
||||
size = "medium",
|
||||
}: {
|
||||
value: number;
|
||||
|
||||
Reference in New Issue
Block a user