"use client"; import { COSMOS_KIT_USE_CHAIN } from "@/config"; import { useNymClient } from "@/hooks/useNymClient"; import { useChain } from "@cosmos-kit/react"; import { Box, Button, Stack, Tooltip, Typography } from "@mui/material"; import { useLocalStorage } from "@uidotdev/usehooks"; import { type MRT_ColumnDef, MaterialReactTable, useMaterialReactTable, } from "material-react-table"; import { useRouter } from "next/navigation"; import { useCallback, useMemo, useState } from "react"; import CountryFlag from "../countryFlag/CountryFlag"; import { Favorite } from "../favorite/Favorite"; import Loading from "../loading"; import InfoModal, { type InfoModalProps } from "../modal/InfoModal"; import StakeModal from "../staking/StakeModal"; import { fee } from "../staking/schemas"; import ConnectWallet from "../wallet/ConnectWallet"; import type { MappedNymNode, MappedNymNodes } from "./NodeTableWithAction"; const ColumnHeading = ({ children, }: { children: string | React.ReactNode; }) => { return ( {children} ); }; const NodeTable = ({ nodes }: { nodes: MappedNymNodes }) => { const router = useRouter(); const { nymClient } = useNymClient(); const [infoModalProps, setInfoModalProps] = useState({ open: false, }); const [isLoading, setIsLoading] = useState(false); const [selectedNodeForStaking, setSelectedNodeForStaking] = useState<{ nodeId: number; identityKey: string; }>(); const [favorites] = useLocalStorage("nym-node-favorites", []); const { isWalletConnected } = useChain(COSMOS_KIT_USE_CHAIN); const handleStakeOnNode = async ({ nodeId, amount, }: { nodeId: number; amount: string; }) => { const amountToDelegate = (Number(amount) * 1_000_000).toString(); const uNymFunds = [{ amount: amountToDelegate, denom: "unym" }]; setIsLoading(true); setSelectedNodeForStaking(undefined); try { const tx = await nymClient?.delegate( { nodeId }, fee, "Delegation from Nym Explorer V2", uNymFunds, ); console.log({ tx }); setSelectedNodeForStaking(undefined); setInfoModalProps({ open: true, title: "Success", message: "This operation can take up to one hour to process", tx: tx?.transactionHash, onClose: () => setInfoModalProps({ open: false }), }); } catch (e) { const errorMessage = e instanceof Error ? e.message : "An error occurred while staking"; setInfoModalProps({ open: true, title: "Error", message: errorMessage, onClose: () => { setInfoModalProps({ open: false }); }, }); } setIsLoading(false); }; const handleOnSelectStake = useCallback( (node: MappedNymNode) => { if (!isWalletConnected) { setInfoModalProps({ open: true, title: "Connect Wallet", message: "Connect your wallet to stake", Action: ( setInfoModalProps({ open: false, }) } /> ), onClose: () => setInfoModalProps({ open: false }), }); return; } setSelectedNodeForStaking({ nodeId: node.nodeId, identityKey: node.identity_key, }); }, [isWalletConnected], ); const columns: MRT_ColumnDef[] = useMemo( () => [ { id: "node", header: "", Header: Node, accessorKey: "bondInformation.node.identity_key", Cell: ({ row }) => ( {row.original.nodeId} {row.original.identity_key} ), }, { id: "qos", header: "Quality of Service", align: "center", accessorKey: "qos", Header: Quality of Service, Cell: () => Unavailable, }, { id: "location", header: "Location", accessorKey: "location.country_name", Header: Location, Cell: ({ row }) => row.original.countryCode && row.original.countryName ? ( ) : ( "-" ), }, { id: "stakeSaturation", header: "Stake saturation", accessorKey: "stakeSaturation", Header: Stake saturation, Cell: () => Unavailable, }, { id: "profitMarginPercentage", header: "Profit margin", accessorKey: "profitMarginPercentage", Header: Profit margin, Cell: ({ row }) => ( {row.original.profitMarginPercentage}% ), }, { id: "Action", header: "Action", accessorKey: "Action", Header: Action, hidden: !isWalletConnected, Cell: ({ row }) => ( ), enableSorting: false, }, { id: "Favorite", header: "Favorite", accessorKey: "Favorite", Header: Favorite, sortingFn: "Favorite", Cell: ({ row }) => , }, ], [isWalletConnected, handleOnSelectStake], ); const table = useMaterialReactTable({ columns, data: nodes, enableRowSelection: false, //enable some features enableColumnOrdering: false, //enable a feature for all columns enableColumnActions: false, enableFullScreenToggle: false, enableHiding: false, paginationDisplayMode: "pages", muiPaginationProps: { showRowsPerPage: false, SelectProps: { sx: { fontFamily: "labGrotesqueMono", fontSize: "14px", }, }, color: "primary", shape: "circular", }, sortingFns: { Favorite: (rowA, rowB) => { const isFavoriteA = favorites.includes( rowA.original.bondInformation.owner, ); const isFavoriteB = favorites.includes( rowB.original.bondInformation.owner, ); // Sort favorites first if (isFavoriteA && !isFavoriteB) return -1; if (!isFavoriteA && isFavoriteB) return 1; // If both are favorites or neither, keep the original order return 0; }, }, initialState: { columnPinning: { right: ["Action", "Favorite"] }, }, muiColumnActionsButtonProps: { sx: { color: "red", }, size: "small", }, muiTablePaperProps: { elevation: 0, }, muiTableHeadRowProps: { sx: { bgcolor: "background.paper", }, }, muiTableBodyCellProps: { sx: { border: "none", }, }, muiTableBodyRowProps: ({ row }) => ({ onClick: () => { router.push(`/nym-node/${row.original.nodeId}`); }, hover: true, sx: { ":nth-child(odd)": { bgcolor: "#F3F7FB !important", }, ":nth-child(even)": { bgcolor: "white !important", }, cursor: "pointer", }, }), }); return ( <> {isLoading && } setSelectedNodeForStaking(undefined)} /> ); }; export default NodeTable;