Feature/explorer v2 connect wallet (#5301)

* set up libs for connecting wallet

* wallet - get address and balance

* format wallet balance

* start staking modal work

* Yana/node page (#5276)

* Add nym-node page api WIP

* nym-node page api WIP

* Add rewards card

* Add account balances

* fix build

* Add USD price to tokenomics card

* fix build

* fix build

* fix build

* Refactor ProgressBar

* Add profile card

* fix build

* replace hardcoded id

* Add build version and node roles

* fix build

* rename id param to address

* add node table to explorer page

* get node details from unstable endpoint + layout updates

* allow node select from table

* stop propogation on favorite/unfavorite

* update self bond data

* card refactors

* revert node engine requirement

* use node v20

---------

Co-authored-by: Yana <yanok87@users.noreply.github.com>
Co-authored-by: fmtabbara <fmtabbara@hotmail.co.uk>

* set up libs for connecting wallet

* wallet - get address and balance

* update typings + refactor favorite component

* fix event propogation

* fix multiple url declarations

* move pages to pages directory

* build staking page and base components

* refactor wallet components and add useNymClient hook

* enhance DesktopHeader to highlight active menu item with icon

* remove StakeModal and getNymNodes components

* refactor NodeTable and NodeTableWithAction components for improved staking functionality

* refactor API configuration and theme styles for improved maintainability

* refactor Loading component to implement LoadingModal with enhanced styling and functionality

* add InfoModal component for displaying informational messages with customizable actions

* fix type

* fix linting

* update CI workflow to use Node.js 20

* add explorer package to dependencies in package.json

* fix mui grid2 build errors

* fix full page reload

* fix unstaking

* fix delegation operation

* fix up workspace packages

* refactor staking and wallet components for improved functionality and readability

* fix undelegation (again)

* update ci to include new explorer

* update wallet ci node version

* remove logs

---------

Co-authored-by: Yana Matrosova <42305364+yanok87@users.noreply.github.com>
Co-authored-by: Yana <yanok87@users.noreply.github.com>
This commit is contained in:
Fouad
2024-12-30 22:19:13 +00:00
committed by GitHub
parent fb3a7aed6b
commit c45492cdc8
74 changed files with 4355 additions and 3228 deletions
@@ -1,16 +1,23 @@
"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 } from "react";
import { useCallback, useMemo, useState } from "react";
import CountryFlag from "../countryFlag/CountryFlag";
import { Favorite, UnFavorite } from "../favorite/Favorite";
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 = ({
@@ -27,24 +34,90 @@ const ColumnHeading = ({
const NodeTable = ({ nodes }: { nodes: MappedNymNodes }) => {
const router = useRouter();
const { nymClient } = useNymClient();
const [favorites, saveFavorites] = useLocalStorage<string[]>(
"nym-node-favorites",
[],
);
const [infoModalProps, setInfoModalProps] = useState<InfoModalProps>({
open: false,
});
const [isLoading, setIsLoading] = useState(false);
const [selectedNodeForStaking, setSelectedNodeForStaking] = useState<{
nodeId: number;
identityKey: string;
}>();
const handleFavorite = useCallback(
(address: string) => {
saveFavorites([...favorites, address]);
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: (
<ConnectWallet
fullWidth
onClick={() =>
setInfoModalProps({
open: false,
})
}
/>
),
onClose: () => setInfoModalProps({ open: false }),
});
return;
}
setSelectedNodeForStaking({
nodeId: node.nodeId,
identityKey: node.bondInformation.node.identity_key,
});
},
[favorites, saveFavorites],
);
const handleUnfavorite = useCallback(
(address: string) => {
saveFavorites(favorites.filter((favorite) => favorite !== address));
},
[favorites, saveFavorites],
[isWalletConnected],
);
const columns: MRT_ColumnDef<MappedNymNode>[] = useMemo(
@@ -117,8 +190,16 @@ const NodeTable = ({ nodes }: { nodes: MappedNymNodes }) => {
header: "Action",
accessorKey: "Action",
Header: <ColumnHeading>Action</ColumnHeading>,
Cell: () => (
<Button size="small" variant="outlined">
hidden: !isWalletConnected,
Cell: ({ row }) => (
<Button
size="small"
variant="outlined"
onClick={(e) => {
e.stopPropagation();
handleOnSelectStake(row.original);
}}
>
Stake
</Button>
),
@@ -130,23 +211,12 @@ const NodeTable = ({ nodes }: { nodes: MappedNymNodes }) => {
accessorKey: "Favorite",
Header: <ColumnHeading>Favorite</ColumnHeading>,
sortingFn: "Favorite",
Cell: ({ row }) =>
favorites.includes(row.original.bondInformation.node.identity_key) ? (
<UnFavorite
onUnfavorite={() =>
handleUnfavorite(row.original.bondInformation.node.identity_key)
}
/>
) : (
<Favorite
onFavorite={() =>
handleFavorite(row.original.bondInformation.node.identity_key)
}
/>
),
Cell: ({ row }) => (
<Favorite address={row.original.bondInformation.owner} />
),
},
],
[favorites, handleFavorite, handleUnfavorite],
[isWalletConnected, handleOnSelectStake],
);
const table = useMaterialReactTable({
columns,
@@ -214,7 +284,19 @@ const NodeTable = ({ nodes }: { nodes: MappedNymNodes }) => {
},
}),
});
return <MaterialReactTable table={table} />;
return (
<>
{isLoading && <Loading />}
<StakeModal
nodeId={selectedNodeForStaking?.nodeId}
identityKey={selectedNodeForStaking?.identityKey}
onStake={handleStakeOnNode}
onClose={() => setSelectedNodeForStaking(undefined)}
/>
<InfoModal {...infoModalProps} />
<MaterialReactTable table={table} />
</>
);
};
export default NodeTable;