fix build

This commit is contained in:
Yana
2025-04-15 20:54:37 +03:00
parent 433cac8c58
commit 32a4bf1172
8 changed files with 12109 additions and 39798 deletions
+20 -18
View File
@@ -1,29 +1,29 @@
import { countryCodeMap } from "@/assets/countryCodes";
import { addSeconds } from "date-fns";
/* eslint-disable @typescript-eslint/no-explicit-any */
import type {
CountryDataResponse,
CurrentEpochData,
ExplorerData,
GatewayStatus,
IAccountBalancesInfo,
IObservatoryNode,
IPacketsAndStakingData,
NodeRewardDetails,
NS_NODE,
NodeRewardDetails,
NymTokenomics,
ObservatoryBalance,
CountryDataResponse,
} from "./types";
import {
CURRENT_EPOCH,
CURRENT_EPOCH_REWARDS,
DATA_OBSERVATORY_BALANCES_URL,
DATA_OBSERVATORY_NODES_URL,
NS_API_NODES,
NYM_ACCOUNT_ADDRESS,
NYM_PRICES_API,
OBSERVATORY_GATEWAYS_URL,
NS_API_NODES,
} from "./urls";
import { countryCodeMap } from "@/assets/countryCodes";
// Fetch function for epoch rewards
export const fetchEpochRewards = async (): Promise<
@@ -46,7 +46,7 @@ export const fetchEpochRewards = async (): Promise<
// Fetch gateway status based on identity key
export const fetchGatewayStatus = async (
identityKey: string
identityKey: string,
): Promise<GatewayStatus | null> => {
const response = await fetch(`${OBSERVATORY_GATEWAYS_URL}/${identityKey}`);
@@ -58,7 +58,7 @@ export const fetchGatewayStatus = async (
};
export const fetchNodeDelegations = async (
id: number
id: number,
): Promise<NodeRewardDetails[]> => {
const response = await fetch(
`${DATA_OBSERVATORY_NODES_URL}/${id}/delegations`,
@@ -67,7 +67,7 @@ export const fetchNodeDelegations = async (
Accept: "application/json",
"Content-Type": "application/json; charset=utf-8",
},
}
},
);
if (!response.ok) {
@@ -93,7 +93,7 @@ export const fetchCurrentEpoch = async () => {
const data: CurrentEpochData = await response.json();
const epochEndTime = addSeconds(
new Date(data.current_epoch_start),
data.epoch_length.secs
data.epoch_length.secs,
).toISOString();
return { ...data, current_epoch_end: epochEndTime };
@@ -122,7 +122,9 @@ export const fetchBalances = async (address: string): Promise<number> => {
};
// Fetch function to get total staker rewards
export const fetchTotalStakerRewards = async (address: string): Promise<number> => {
export const fetchTotalStakerRewards = async (
address: string,
): Promise<number> => {
const response = await fetch(`${DATA_OBSERVATORY_BALANCES_URL}/${address}`, {
headers: {
Accept: "application/json",
@@ -162,7 +164,7 @@ export const fetchOriginalStake = async (address: string): Promise<number> => {
export const fetchNoise = async (): Promise<IPacketsAndStakingData[]> => {
if (!process.env.NEXT_PUBLIC_NS_API_MIXNODES_STATS) {
throw new Error(
"NEXT_PUBLIC_NS_API_MIXNODES_STATS environment variable is not defined"
"NEXT_PUBLIC_NS_API_MIXNODES_STATS environment variable is not defined",
);
}
const response = await fetch(process.env.NEXT_PUBLIC_NS_API_MIXNODES_STATS, {
@@ -178,7 +180,7 @@ export const fetchNoise = async (): Promise<IPacketsAndStakingData[]> => {
// Fetch Account Balance
export const fetchAccountBalance = async (
address: string
address: string,
): Promise<IAccountBalancesInfo> => {
const res = await fetch(`${NYM_ACCOUNT_ADDRESS}/${address}`, {
headers: {
@@ -208,7 +210,7 @@ export const fetchObservatoryNodes = async (): Promise<IObservatoryNode[]> => {
Accept: "application/json",
"Content-Type": "application/json; charset=utf-8",
},
}
},
);
if (!response.ok) {
@@ -261,12 +263,12 @@ export const fetchNSApiNodes = async (): Promise<NS_NODE[]> => {
Accept: "application/json",
"Content-Type": "application/json; charset=utf-8",
},
}
},
);
if (!response.ok) {
throw new Error(
`Failed to fetch NS API nodes (page ${page}): ${response.statusText}`
`Failed to fetch NS API nodes (page ${page}): ${response.statusText}`,
);
}
@@ -297,7 +299,7 @@ export const fetchWorldMapCountries =
const countryCounts: Record<string, number> = {};
// Process each node
nodes.forEach((node: NS_NODE) => {
for (const node of nodes) {
// Get the 2-letter country code from the node's geoip data
const twoLetterCode = node.geoip?.country;
@@ -309,17 +311,17 @@ export const fetchWorldMapCountries =
countryCounts[threeLetterCode] =
(countryCounts[threeLetterCode] || 0) + 1;
}
});
}
// Convert the counts to the required format
const result: CountryDataResponse = {};
Object.entries(countryCounts).forEach(([threeLetterCode, count]) => {
for (const [threeLetterCode, count] of Object.entries(countryCounts)) {
result[threeLetterCode] = {
ISO3: threeLetterCode,
nodes: count,
};
});
}
return result;
};
+1 -1
View File
@@ -1,3 +1,4 @@
import { WorldMap } from "@/components/worldMap/WorldMap";
import { Stack } from "@mui/material";
import Grid from "@mui/material/Grid2";
import BlogArticlesCards from "../components/blogs/BlogArticleCards";
@@ -10,7 +11,6 @@ import { StakersNumberCard } from "../components/landingPageComponents/StakersNu
import { TokenomicsCard } from "../components/landingPageComponents/TokenomicsCard";
import NodeTable from "../components/nodeTable/NodeTableWithAction";
import NodeAndAddressSearch from "../components/search/NodeAndAddressSearch";
import { WorldMap } from "@/components/worldMap/WorldMap";
export default async function Home() {
return (
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
"use client";
import { fetchNSApiNodes, fetchObservatoryNodes } from "@/app/api";
import { fetchObservatoryNodes } from "@/app/api";
import type { IObservatoryNode } from "@/app/api/types";
import { Skeleton, Typography, useTheme } from "@mui/material";
import { useQuery } from "@tanstack/react-query";
@@ -19,21 +19,6 @@ export const StakersNumberCard = () => {
refetchOnMount: false,
});
const {
data: nsNodes,
isLoading: loadingNsNodes,
isError: errorNsNodes,
} = useQuery({
queryKey: ["nsNodes"],
queryFn: () => fetchNSApiNodes(),
staleTime: 10 * 60 * 1000, // 10 minutes
refetchOnWindowFocus: false, // Prevents unnecessary refetching
refetchOnReconnect: false,
refetchOnMount: false,
});
console.log("nsNodes", nsNodes);
const theme = useTheme();
const isDarkMode = theme.palette.mode === "dark";
@@ -61,7 +46,7 @@ export const StakersNumberCard = () => {
const getActiveStakersNumber = (nodes: IObservatoryNode[]): number => {
return nodes.reduce(
(sum, node) => sum + node.rewarding_details.unique_delegations,
0
0,
);
};
const allStakers = getActiveStakersNumber(nymNodes);
@@ -1,5 +1,6 @@
"use client";
import type { IObservatoryNode } from "@/app/api/types";
import { NYM_ACCOUNT_ADDRESS } from "@/app/api/urls";
import { Search } from "@mui/icons-material";
import {
Autocomplete,
@@ -13,7 +14,6 @@ import { useQuery } from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { fetchObservatoryNodes } from "../../app/api";
import { NYM_ACCOUNT_ADDRESS } from "@/app/api/urls";
const NodeAndAddressSearch = () => {
const router = useRouter();
@@ -50,7 +50,7 @@ const NodeAndAddressSearch = () => {
}
} catch {
setErrorText(
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again."
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again.",
);
setIsLoading(false); // Stop loading
@@ -58,7 +58,7 @@ const NodeAndAddressSearch = () => {
}
} else {
setErrorText(
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again."
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again.",
);
setIsLoading(false); // Stop loading
@@ -68,7 +68,7 @@ const NodeAndAddressSearch = () => {
// Check if it's a node identity key
if (nymNodes) {
const matchingNode = nymNodes.find(
(node) => node.identity_key === inputValue
(node) => node.identity_key === inputValue,
);
if (matchingNode) {
@@ -77,13 +77,13 @@ const NodeAndAddressSearch = () => {
}
}
setErrorText(
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again."
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again.",
);
setIsLoading(false);
}
} catch (error) {
setErrorText(
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again."
"No node found with the provided Name, Node ID or Identity Key. Please check your input and try again.",
);
console.error(error);
setIsLoading(false); // Stop loading
@@ -92,7 +92,7 @@ const NodeAndAddressSearch = () => {
// Handle search input change
const handleSearchInputChange = (
event: React.ChangeEvent<HTMLInputElement>
event: React.ChangeEvent<HTMLInputElement>,
) => {
const value = event.target.value;
setInputValue(value);
@@ -107,7 +107,7 @@ const NodeAndAddressSearch = () => {
const filteredNodes = nymNodes.filter((node) =>
node.self_description?.moniker
?.toLowerCase()
.includes(value.toLowerCase())
.includes(value.toLowerCase()),
);
setSearchOptions(filteredNodes);
} else {
@@ -118,7 +118,7 @@ const NodeAndAddressSearch = () => {
// Handle node selection from dropdown
const handleNodeSelect = (
event: React.SyntheticEvent,
value: string | IObservatoryNode | null
value: string | IObservatoryNode | null,
) => {
if (value && typeof value !== "string") {
setIsLoading(true); // Show loading spinner
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
import { scaleLinear } from "d3-scale";
import * as React from "react";
import {
ComposableMap,
Geographies,
@@ -10,18 +10,17 @@ import {
} from "react-simple-maps";
import { Tooltip } from "react-tooltip";
import "react-tooltip/dist/react-tooltip.css";
import { Skeleton, Stack, Typography, IconButton } from "@mui/material";
import { useTheme } from "@mui/material/styles";
import { CountryDataResponse } from "../../app/api/types";
import MAP_TOPOJSON from "../../assets/world-110m.json";
import { useQuery } from "@tanstack/react-query";
import { fetchWorldMapCountries } from "@/app/api";
import ExplorerCard from "../cards/ExplorerCard";
import AddIcon from "@mui/icons-material/Add";
import RemoveIcon from "@mui/icons-material/Remove";
import RestartAltIcon from "@mui/icons-material/RestartAlt";
import { IconButton, Skeleton, Stack, Typography } from "@mui/material";
import { useTheme } from "@mui/material/styles";
import { useQuery } from "@tanstack/react-query";
import type { CountryDataResponse } from "../../app/api/types";
import MAP_TOPOJSON from "../../assets/world-110m.json";
export const WorldMap = ({}): JSX.Element => {
export const WorldMap = (): JSX.Element => {
const theme = useTheme();
const isDarkMode = theme.palette.mode === "dark";
const [position, setPosition] = React.useState<{
@@ -42,14 +41,19 @@ export const WorldMap = ({}): JSX.Element => {
refetchOnMount: false,
});
const [tooltipContent, setTooltipContent] = React.useState<string | null>(
null
);
const [tooltipContent, setTooltipContent] = React.useState<string>("");
React.useEffect(() => {
const handleMouseLeave = () => setTooltipContent("");
return () => {
handleMouseLeave();
};
}, []);
const colorScale = React.useMemo(() => {
if (countries) {
const heighestNumberOfNodes = Math.max(
...Object.values(countries).map((country) => country.nodes)
...Object.values(countries).map((country) => country.nodes),
);
return scaleLinear<string, string>()
.domain([
@@ -74,34 +78,25 @@ export const WorldMap = ({}): JSX.Element => {
"#147A3D", // Medium green
"#1A994C", // Light green
theme.palette.accent.main,
]
],
)
.unknown(isDarkMode ? theme.palette.pine[950] : theme.palette.pine[25]);
}
return () =>
isDarkMode ? theme.palette.pine[950] : theme.palette.pine[25];
}, [
countries,
theme.palette.mode,
theme.palette.pine,
theme.palette.accent,
isDarkMode,
]);
}, [countries, theme.palette.pine, theme.palette.accent, isDarkMode]);
if (isLoadingCountries) {
return (
<ExplorerCard label="Nym Nodes in the world">
<Stack gap={1}>
<Skeleton variant="text" />
<Skeleton variant="text" height={238} />
</Stack>
</ExplorerCard>
<Stack gap={1} width="100%">
<Skeleton variant="text" height={238} />
</Stack>
);
}
if (isCountriesError) {
return (
<ExplorerCard label="Nym Nodes in the world">
<Stack gap={1}>
<Typography
variant="h5"
sx={{
@@ -112,12 +107,11 @@ export const WorldMap = ({}): JSX.Element => {
Failed to load data
</Typography>
<Skeleton variant="text" height={238} />
</ExplorerCard>
</Stack>
);
}
return (
// <ExplorerCard label="Nym Nodes in the world">
<>
<div
style={{
@@ -127,9 +121,7 @@ export const WorldMap = ({}): JSX.Element => {
margin: "0 auto",
}}
>
{/* <div style={{ width: "90%", margin: "0 auto" }}> */}
<ComposableMap
{...({} as any)}
data-tip=""
style={{
backgroundColor: isDarkMode ? "#000000" : theme.palette.pine[25],
@@ -160,6 +152,10 @@ export const WorldMap = ({}): JSX.Element => {
}) => {
setPosition({ coordinates, zoom });
}}
onClick={(e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
}}
>
<Geographies geography={MAP_TOPOJSON}>
{({ geographies }: { geographies: GeoJSON.Feature[] }) =>
@@ -171,7 +167,9 @@ export const WorldMap = ({}): JSX.Element => {
] || { nodes: 0 };
return (
<Geography
key={`${geo.properties?.ISO_A3 || ""}-${geo.id}-${geo.properties?.NAME_LONG || ""}`}
key={`${geo.properties?.ISO_A3 || ""}-${geo.id}-${
geo.properties?.NAME_LONG || ""
}`}
geography={geo}
fill={colorScale(d?.nodes || 0)}
stroke={
@@ -185,7 +183,6 @@ export const WorldMap = ({}): JSX.Element => {
const { NAME_LONG } = geo.properties as {
NAME_LONG: string;
};
setTooltipContent(`${NAME_LONG} | ${d?.nodes || 0}`);
}}
onMouseLeave={() => {
@@ -196,8 +193,15 @@ export const WorldMap = ({}): JSX.Element => {
? {
fill: theme.palette.accent.main,
outline: "white",
cursor: "pointer",
}
: undefined,
default: {
outline: "none",
},
pressed: {
outline: "none",
},
}}
/>
);
@@ -206,7 +210,6 @@ export const WorldMap = ({}): JSX.Element => {
</Geographies>
</ZoomableGroup>
</ComposableMap>
{/* </div> */}
<div
style={{
@@ -286,7 +289,8 @@ export const WorldMap = ({}): JSX.Element => {
</div>
<Tooltip
id="map-tooltip"
content={tooltipContent || ""}
content={tooltipContent}
float={true}
style={{
fontSize: "12px",
padding: "4px 8px",
@@ -299,10 +303,9 @@ export const WorldMap = ({}): JSX.Element => {
? theme.palette.base.white
: theme.palette.pine[950],
borderRadius: "4px",
zIndex: 1000,
zIndex: 9999,
}}
/>
{/* // </ExplorerCard> */}
</>
);
};
+4 -2
View File
@@ -1,6 +1,6 @@
declare module "react-simple-maps" {
import { FunctionComponent, ReactNode } from "react";
import { Feature, Geometry, GeoJsonProperties } from "geojson";
import type { FunctionComponent, ReactNode } from "react";
import type { Feature, Geometry, GeoJsonProperties } from "geojson";
export interface ComposableMapProps {
children?: ReactNode;
@@ -13,6 +13,7 @@ declare module "react-simple-maps" {
}
export interface GeographiesProps {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
geography: any;
children?: (props: {
geographies: Feature<Geometry, GeoJsonProperties>[];
@@ -21,6 +22,7 @@ declare module "react-simple-maps" {
export interface GeographyProps {
geography: Feature<Geometry, GeoJsonProperties>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}
-1
View File
@@ -1 +0,0 @@