From f668681871c2eb57d70a74321984df36f55b8780 Mon Sep 17 00:00:00 2001 From: Poafs1 Date: Tue, 12 Mar 2024 14:52:36 +0700 Subject: [PATCH 01/11] feat(pages): validator details overview section --- .../ValidatorDescription.tsx | 13 +-- .../components/validator-overview/index.tsx | 62 +++++++------ .../validator-top/ValidatorStats.tsx | 86 ++++++++++++++----- .../validator-top/ValidatorTitle.tsx | 22 +++-- .../components/validator-top/index.tsx | 27 +++--- src/lib/pages/validator-details/index.tsx | 15 ++-- src/lib/services/validator.ts | 8 +- src/lib/types/validator.ts | 1 + 8 files changed, 149 insertions(+), 85 deletions(-) diff --git a/src/lib/pages/validator-details/components/validator-overview/ValidatorDescription.tsx b/src/lib/pages/validator-details/components/validator-overview/ValidatorDescription.tsx index 2f81b312a..26b8261cf 100644 --- a/src/lib/pages/validator-details/components/validator-overview/ValidatorDescription.tsx +++ b/src/lib/pages/validator-details/components/validator-overview/ValidatorDescription.tsx @@ -1,15 +1,18 @@ import { Flex, Heading, Text } from "@chakra-ui/react"; -export const ValidatorDescription = () => ( +import type { ValidatorData } from "lib/types"; + +interface ValidatorDescriptionProps { + info: ValidatorData; +} + +export const ValidatorDescription = ({ info }: ValidatorDescriptionProps) => ( Validator Description - Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam ad vel - assumenda, temporibus maiores quidem quibusdam sapiente expedita officiis - minus! Officiis itaque nisi reprehenderit tempora eaque eos quam, in - excepturi. + {info.details} ); diff --git a/src/lib/pages/validator-details/components/validator-overview/index.tsx b/src/lib/pages/validator-details/components/validator-overview/index.tsx index 11fe4fcde..8bae19056 100644 --- a/src/lib/pages/validator-details/components/validator-overview/index.tsx +++ b/src/lib/pages/validator-details/components/validator-overview/index.tsx @@ -9,6 +9,7 @@ import { VotedProposalsTable } from "../tables/VotedProposalsTable"; import { useMobile, useMoveConfig } from "lib/app-provider"; import { CustomIcon } from "lib/components/icon"; import { EmptyState } from "lib/components/state"; +import type { ValidatorData } from "lib/types"; import { ValidatorDescription } from "./ValidatorDescription"; import { VotingPowerOverview } from "./VotingPowerOverview"; @@ -17,49 +18,44 @@ interface ValidatorOverviewProps { onSelectVotes: () => void; onSelectPerformance: () => void; onSelectBondedTokenChanges: () => void; + info: ValidatorData; } export const ValidatorOverview = ({ onSelectVotes, onSelectPerformance, onSelectBondedTokenChanges, + info, }: ValidatorOverviewProps) => { const isMobile = useMobile(); const move = useMoveConfig({ shouldRedirect: false }); - return ( - <> - - - - - - - {!isMobile && ( - <> - - - - {!move.enabled && } - - )} - {isMobile && !move.enabled && ( - - )} - - - - {/* TODO: change to conditions and remove line 72-74 */} - {/* Inactive */} - - INACTIVE + return !info.isActive ? ( + + + + + + {!isMobile && ( + <> + + + + {!move.enabled && } + + )} + {isMobile && !move.enabled && ( + + )} + + + + ) : ( + <> @@ -67,7 +63,7 @@ export const ValidatorOverview = ({ reflects the latest available data. - + ( +const StatWithLabel = ({ + label, + value, +}: { + label: string; + value: string | ReactNode; +}) => ( {label} @@ -13,23 +25,53 @@ const StatWithLabel = ({ label, value }: { label: string; value: string }) => ( ); -export const ValidatorStats = () => ( - - - - {" "} - - - -); +interface ValidatorStatsProps { + info: ValidatorData; + totalVotingPower: Big; +} + +export const ValidatorStats = ({ + info, + totalVotingPower, +}: ValidatorStatsProps) => { + const { data: stakingProvisions } = useValidatorStakingProvisions(); + const { data: delegations, isLoading: isDelegationsLoading } = + useValidatorDelegators(info.validatorAddress); + + if (!stakingProvisions) return ; + + const estimatedApr = stakingProvisions.stakingProvisions.div( + totalVotingPower.mul(1 - info.commissionRate) + ); + + const delegationsValue = + !isDelegationsLoading && delegations ? ( + String(delegations.total) + ) : ( + + ); + + return ( + + + + + + + + ); +}; diff --git a/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx b/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx index e56d34d80..d61704d13 100644 --- a/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx +++ b/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx @@ -1,10 +1,17 @@ import { Flex, Heading } from "@chakra-ui/react"; +import Link from "next/link"; + +import type { ValidatorData } from "lib/types"; import { ValidatorImage } from "./ValidatorImage"; import { ValidatorStatusTag } from "./ValidatorStatusTag"; import { WebsiteButton } from "./WebsiteButton"; -export const ValidatorTitle = () => ( +interface ValidatorTitleProps { + info: ValidatorData; +} + +export const ValidatorTitle = ({ info }: ValidatorTitleProps) => ( ( variant={{ base: "h6", md: "h5" }} color="accent.main" > - #111 + #{info.rank} ( color="text.main" display={{ base: "none", md: "flex" }} > - Validator name + {info.moniker} - + {/* // TODO: Check isActive and isJailed */} + ( color="text.main" display={{ base: "flex", md: "none" }} > - Validator name + {info.moniker} - + + + ); diff --git a/src/lib/pages/validator-details/components/validator-top/index.tsx b/src/lib/pages/validator-details/components/validator-top/index.tsx index a0f4454ea..fe6ab3c96 100644 --- a/src/lib/pages/validator-details/components/validator-top/index.tsx +++ b/src/lib/pages/validator-details/components/validator-top/index.tsx @@ -1,15 +1,23 @@ import { Flex, Text } from "@chakra-ui/react"; +import type Big from "big.js"; +import Link from "next/link"; import { Breadcrumb } from "lib/components/Breadcrumb"; import { CopyLink } from "lib/components/CopyLink"; import { ExplorerLink } from "lib/components/ExplorerLink"; +import type { ValidatorData } from "lib/types"; import { ValidatorImage } from "./ValidatorImage"; import { ValidatorStats } from "./ValidatorStats"; import { ValidatorTitle } from "./ValidatorTitle"; import { WebsiteButton } from "./WebsiteButton"; -export const ValidatorTop = () => ( +interface ValidatorTopProps { + info: ValidatorData; + totalVotingPower: Big; +} + +export const ValidatorTop = ({ info, totalVotingPower }: ValidatorTopProps) => ( ( text: "Validators", href: "/validators", }, - { text: `validator name` }, + { text: info.moniker }, ]} /> - - + + ( > Validator Address: - + ( - + + + diff --git a/src/lib/pages/validator-details/index.tsx b/src/lib/pages/validator-details/index.tsx index 9626f6307..3adeb7f75 100644 --- a/src/lib/pages/validator-details/index.tsx +++ b/src/lib/pages/validator-details/index.tsx @@ -5,8 +5,10 @@ import { useCallback, useEffect } from "react"; import { AmpEvent, track, trackUseTab } from "lib/amplitude"; import { useInternalNavigate, useMoveConfig } from "lib/app-provider"; import { CustomTab } from "lib/components/CustomTab"; +import { Loading } from "lib/components/Loading"; import PageContainer from "lib/components/PageContainer"; -import { InvalidState } from "lib/components/state"; +import { ErrorFetching, InvalidState } from "lib/components/state"; +import { useValidatorData } from "lib/services/validatorService"; import { BondedTokenChanges, @@ -28,6 +30,7 @@ const ValidatorDetailsBody = ({ }: ValidatorDetailsQueryParams) => { const navigate = useInternalNavigate(); const move = useMoveConfig({ shouldRedirect: false }); + const { data, isLoading } = useValidatorData(validatorAddress); const handleTabChange = useCallback( (nextTab: TabIndex) => () => { @@ -47,14 +50,13 @@ const ValidatorDetailsBody = ({ [navigate, tab, validatorAddress] ); - // TODO - // if (isLoading) return ; - // if (!data) return ; - // if (!data.info) return ; + if (isLoading) return ; + if (!data) return ; + if (!data.info) return ; return ( <> - + diff --git a/src/lib/services/validator.ts b/src/lib/services/validator.ts index 6ee04b7a2..7678e76c8 100644 --- a/src/lib/services/validator.ts +++ b/src/lib/services/validator.ts @@ -142,9 +142,11 @@ export const getValidators = async ( }) .then(({ data }) => parseWithError(zValidatorsResponse, data)); -const zStakingProvisionsResponse = z.object({ - staking_provisions: zBig, -}); +const zStakingProvisionsResponse = z + .object({ + staking_provisions: zBig, + }) + .transform(snakeToCamel); export type StakingProvisionsResponse = z.infer< typeof zStakingProvisionsResponse >; diff --git a/src/lib/types/validator.ts b/src/lib/types/validator.ts index f7a93b7da..38b687903 100644 --- a/src/lib/types/validator.ts +++ b/src/lib/types/validator.ts @@ -33,6 +33,7 @@ export const zValidatorData = z is_active: z.boolean(), voting_power: zBig, uptime: z.number().optional(), + website: z.string(), }) .transform(snakeToCamel); From cbce7f1c105ffcbc328168adcb8fc2c35da2fbfb Mon Sep 17 00:00:00 2001 From: Poafs1 Date: Tue, 12 Mar 2024 14:55:21 +0700 Subject: [PATCH 02/11] feat: update changelog --- CHANGELOG.md | 1 + .../validator-details/components/validator-overview/index.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a33ffbcef..3d88b6100 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features +- [#819](https://github.com/alleslabs/celatone-frontend/pull/819) Add validator detail overview section with data from APIs - [#801](https://github.com/alleslabs/celatone-frontend/pull/801) Add validator detail ui structure - [#817](https://github.com/alleslabs/celatone-frontend/pull/817) api v1 - validator voted proposals - [#816](https://github.com/alleslabs/celatone-frontend/pull/816) api v1 - validator staking provisions diff --git a/src/lib/pages/validator-details/components/validator-overview/index.tsx b/src/lib/pages/validator-details/components/validator-overview/index.tsx index 8bae19056..62ca7a82b 100644 --- a/src/lib/pages/validator-details/components/validator-overview/index.tsx +++ b/src/lib/pages/validator-details/components/validator-overview/index.tsx @@ -30,7 +30,7 @@ export const ValidatorOverview = ({ const isMobile = useMobile(); const move = useMoveConfig({ shouldRedirect: false }); - return !info.isActive ? ( + return info.isActive ? ( From 5a19d2d3e3b5a26401a16101ca8cdd1c3b27c587 Mon Sep 17 00:00:00 2001 From: Poafs1 Date: Tue, 12 Mar 2024 16:35:50 +0700 Subject: [PATCH 03/11] feat(components): update validator overview components --- src/lib/components/ValidatorBadge.tsx | 44 +++--------- src/lib/components/ValidatorImage.tsx | 43 ++++++++++++ .../components/validator-overview/index.tsx | 4 +- .../validator-top/ValidatorImage.tsx | 12 ---- .../validator-top/ValidatorStatusTag.tsx | 68 ++++++++++++++----- .../validator-top/ValidatorTitle.tsx | 9 +-- .../components/validator-top/index.tsx | 6 +- 7 files changed, 115 insertions(+), 71 deletions(-) create mode 100644 src/lib/components/ValidatorImage.tsx delete mode 100644 src/lib/pages/validator-details/components/validator-top/ValidatorImage.tsx diff --git a/src/lib/components/ValidatorBadge.tsx b/src/lib/components/ValidatorBadge.tsx index 6a8f81f44..677e4e700 100644 --- a/src/lib/components/ValidatorBadge.tsx +++ b/src/lib/components/ValidatorBadge.tsx @@ -1,12 +1,12 @@ import type { ImageProps } from "@chakra-ui/react"; -import { Flex, Image, Spinner, Text } from "@chakra-ui/react"; +import { Flex, Text } from "@chakra-ui/react"; import { useMobile } from "lib/app-provider"; import { ExplorerLink } from "lib/components/ExplorerLink"; -import { useValidatorImage } from "lib/services/validatorService"; import type { Nullable, Validator } from "lib/types"; import { MobileLabel } from "./table/MobileLabel"; +import { ValidatorImage } from "./ValidatorImage"; interface ValidatorBadgeProps { validator: Nullable; @@ -17,24 +17,6 @@ interface ValidatorBadgeProps { moreInfo?: JSX.Element; } -const FallbackRender = ({ - badgeSize, -}: { - badgeSize: ValidatorBadgeProps["badgeSize"]; -}) => ( - <> - N/A - - N/A - - -); - export const ValidatorBadge = ({ validator, badgeSize = 10, @@ -43,24 +25,13 @@ export const ValidatorBadge = ({ hasLabel = true, moreInfo, }: ValidatorBadgeProps) => { - const { data: valImgSrc, isLoading } = useValidatorImage(validator); const isMobile = useMobile(); + return ( {validator ? ( <> - {isLoading ? ( - - ) : ( - {validator.moniker} - )} + {isMobile && hasLabel && } ) : ( - + <> + + + N/A + + )} ); diff --git a/src/lib/components/ValidatorImage.tsx b/src/lib/components/ValidatorImage.tsx new file mode 100644 index 000000000..adae3e474 --- /dev/null +++ b/src/lib/components/ValidatorImage.tsx @@ -0,0 +1,43 @@ +import type { ImageProps } from "@chakra-ui/react"; +import { Image, Spinner } from "@chakra-ui/react"; + +import { useValidatorImage } from "lib/services/validatorService"; +import type { Nullable, Validator } from "lib/types"; + +interface ValidatorImageProps { + validator: Nullable; + boxSize?: ImageProps["boxSize"]; +} + +export const ValidatorImage = ({ + validator, + boxSize = 10, +}: ValidatorImageProps) => { + const { data, isLoading } = useValidatorImage(validator); + + if (!validator) { + return ( + N/A + ); + } + + return isLoading || !data || !validator.moniker ? ( + + ) : ( + {validator.moniker} + ); +}; diff --git a/src/lib/pages/validator-details/components/validator-overview/index.tsx b/src/lib/pages/validator-details/components/validator-overview/index.tsx index 62ca7a82b..b8cf5787b 100644 --- a/src/lib/pages/validator-details/components/validator-overview/index.tsx +++ b/src/lib/pages/validator-details/components/validator-overview/index.tsx @@ -59,8 +59,8 @@ export const ValidatorOverview = ({ - This validator is currently inactive. The information displayed - reflects the latest available data. + This validator is currently {info.isJailed ? "jailed" : "inactive"}. + The information displayed reflects the latest available data. diff --git a/src/lib/pages/validator-details/components/validator-top/ValidatorImage.tsx b/src/lib/pages/validator-details/components/validator-top/ValidatorImage.tsx deleted file mode 100644 index d35718528..000000000 --- a/src/lib/pages/validator-details/components/validator-top/ValidatorImage.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import type { ImageProps } from "@chakra-ui/react"; -import { Image } from "@chakra-ui/react"; - -// TODO: combine to ValidatorBadge -export const ValidatorImage = (props: ImageProps) => ( - -); diff --git a/src/lib/pages/validator-details/components/validator-top/ValidatorStatusTag.tsx b/src/lib/pages/validator-details/components/validator-top/ValidatorStatusTag.tsx index 39a7d443b..e1bf7fd0b 100644 --- a/src/lib/pages/validator-details/components/validator-top/ValidatorStatusTag.tsx +++ b/src/lib/pages/validator-details/components/validator-top/ValidatorStatusTag.tsx @@ -1,22 +1,56 @@ import { Flex, Text } from "@chakra-ui/react"; +import { CustomIcon } from "lib/components/icon"; +import type { ValidatorData } from "lib/types"; + interface ValidatorStatusProps { - status: string; + info: ValidatorData; } -export const ValidatorStatusTag = ({ - status = "Active", -}: ValidatorStatusProps) => { - const getColor = () => { - switch (status) { - case "Active": - return "success.main"; - case "Jailed": - return "error.main"; - case "Inactive": - default: - return "gray.600"; - } - }; +export const ValidatorStatusTag = ({ info }: ValidatorStatusProps) => { + if (info.isActive) { + return ( + + + + Active + + + ); + } + + if (info.isJailed) { + return ( + + + + + + Jailed + + + ); + } return ( - + - {status} + Inactive ); diff --git a/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx b/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx index d61704d13..96e939f16 100644 --- a/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx +++ b/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx @@ -1,9 +1,9 @@ import { Flex, Heading } from "@chakra-ui/react"; import Link from "next/link"; +import { ValidatorImage } from "lib/components/ValidatorImage"; import type { ValidatorData } from "lib/types"; -import { ValidatorImage } from "./ValidatorImage"; import { ValidatorStatusTag } from "./ValidatorStatusTag"; import { WebsiteButton } from "./WebsiteButton"; @@ -13,7 +13,9 @@ interface ValidatorTitleProps { export const ValidatorTitle = ({ info }: ValidatorTitleProps) => ( - + + + ( > {info.moniker} - {/* // TODO: Check isActive and isJailed */} - + ( ]} /> - + + + From d1f93b3423645303315698daaad957631e6bf6b1 Mon Sep 17 00:00:00 2001 From: Poafs1 Date: Tue, 12 Mar 2024 17:11:21 +0700 Subject: [PATCH 04/11] feat(components): fix stat top overview section for mobile layout --- .../validator-top/ValidatorStats.tsx | 45 ++++++++++++------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx b/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx index 55a78a926..889d79fd6 100644 --- a/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx +++ b/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx @@ -1,6 +1,7 @@ -import { Flex, Spinner, Text } from "@chakra-ui/react"; +import { Box, Flex, Spinner, Text } from "@chakra-ui/react"; import type { ReactNode } from "react"; +import { useCelatoneApp } from "lib/app-provider"; import { DotSeparator } from "lib/components/DotSeparator"; import { useValidatorDelegators, @@ -37,12 +38,19 @@ export const ValidatorStats = ({ const { data: stakingProvisions } = useValidatorStakingProvisions(); const { data: delegations, isLoading: isDelegationsLoading } = useValidatorDelegators(info.validatorAddress); + const { + chainConfig: { + extra: { singleStakingDenom }, + }, + } = useCelatoneApp(); if (!stakingProvisions) return ; - const estimatedApr = stakingProvisions.stakingProvisions.div( - totalVotingPower.mul(1 - info.commissionRate) - ); + const estimatedApr = singleStakingDenom + ? stakingProvisions.stakingProvisions.div( + totalVotingPower.mul(1 - info.commissionRate) + ) + : undefined; const delegationsValue = !isDelegationsLoading && delegations ? ( @@ -52,26 +60,31 @@ export const ValidatorStats = ({ ); return ( - - - + {estimatedApr && ( + <> + + + + )} - + ); }; From 70de54216a9340a1454a2bd4e4af80002a11335f Mon Sep 17 00:00:00 2001 From: Poafs1 Date: Tue, 12 Mar 2024 17:19:32 +0700 Subject: [PATCH 05/11] feat(components): update validator image loading from spinner to skeleton --- src/lib/components/ValidatorImage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/ValidatorImage.tsx b/src/lib/components/ValidatorImage.tsx index adae3e474..7ef510986 100644 --- a/src/lib/components/ValidatorImage.tsx +++ b/src/lib/components/ValidatorImage.tsx @@ -1,5 +1,5 @@ import type { ImageProps } from "@chakra-ui/react"; -import { Image, Spinner } from "@chakra-ui/react"; +import { Image, SkeletonCircle } from "@chakra-ui/react"; import { useValidatorImage } from "lib/services/validatorService"; import type { Nullable, Validator } from "lib/types"; @@ -28,7 +28,7 @@ export const ValidatorImage = ({ } return isLoading || !data || !validator.moniker ? ( - + ) : ( Date: Wed, 13 Mar 2024 11:32:08 +0700 Subject: [PATCH 06/11] feat(pages): validator details page ui fix --- .../ValidatorDescription.tsx | 27 ++++++++++++------- .../components/validator-overview/index.tsx | 19 +++++++------ .../validator-top/ValidatorStats.tsx | 20 +++++++++----- .../validator-top/WebsiteButton.tsx | 1 + .../components/validator-top/index.tsx | 6 ++++- src/lib/pages/validator-details/index.tsx | 4 ++- 6 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/lib/pages/validator-details/components/validator-overview/ValidatorDescription.tsx b/src/lib/pages/validator-details/components/validator-overview/ValidatorDescription.tsx index 26b8261cf..b710a09a2 100644 --- a/src/lib/pages/validator-details/components/validator-overview/ValidatorDescription.tsx +++ b/src/lib/pages/validator-details/components/validator-overview/ValidatorDescription.tsx @@ -1,18 +1,25 @@ -import { Flex, Heading, Text } from "@chakra-ui/react"; - -import type { ValidatorData } from "lib/types"; +import { Flex, Text } from "@chakra-ui/react"; interface ValidatorDescriptionProps { - info: ValidatorData; + details: string; } -export const ValidatorDescription = ({ info }: ValidatorDescriptionProps) => ( - - +export const ValidatorDescription = ({ + details, +}: ValidatorDescriptionProps) => ( + + Validator Description - - - {info.details} + + + {details} ); diff --git a/src/lib/pages/validator-details/components/validator-overview/index.tsx b/src/lib/pages/validator-details/components/validator-overview/index.tsx index b8cf5787b..d13436896 100644 --- a/src/lib/pages/validator-details/components/validator-overview/index.tsx +++ b/src/lib/pages/validator-details/components/validator-overview/index.tsx @@ -9,7 +9,6 @@ import { VotedProposalsTable } from "../tables/VotedProposalsTable"; import { useMobile, useMoveConfig } from "lib/app-provider"; import { CustomIcon } from "lib/components/icon"; import { EmptyState } from "lib/components/state"; -import type { ValidatorData } from "lib/types"; import { ValidatorDescription } from "./ValidatorDescription"; import { VotingPowerOverview } from "./VotingPowerOverview"; @@ -18,21 +17,25 @@ interface ValidatorOverviewProps { onSelectVotes: () => void; onSelectPerformance: () => void; onSelectBondedTokenChanges: () => void; - info: ValidatorData; + isActive: boolean; + isJailed: boolean; + details: string; } export const ValidatorOverview = ({ onSelectVotes, onSelectPerformance, onSelectBondedTokenChanges, - info, + isActive, + isJailed, + details, }: ValidatorOverviewProps) => { const isMobile = useMobile(); const move = useMoveConfig({ shouldRedirect: false }); - return info.isActive ? ( + return isActive && !isJailed ? ( - + @@ -59,11 +62,11 @@ export const ValidatorOverview = ({ - This validator is currently {info.isJailed ? "jailed" : "inactive"}. - The information displayed reflects the latest available data. + This validator is currently {isJailed ? "jailed" : "inactive"}. The + information displayed reflects the latest available data. - + { const { data: stakingProvisions } = useValidatorStakingProvisions(); const { data: delegations, isLoading: isDelegationsLoading } = - useValidatorDelegators(info.validatorAddress); + useValidatorDelegators(validatorAddress); const { chainConfig: { extra: { singleStakingDenom }, @@ -48,7 +51,7 @@ export const ValidatorStats = ({ const estimatedApr = singleStakingDenom ? stakingProvisions.stakingProvisions.div( - totalVotingPower.mul(1 - info.commissionRate) + totalVotingPower.mul(1 - commissionRate) ) : undefined; @@ -73,13 +76,16 @@ export const ValidatorStats = ({ px={{ base: 3, md: 0 }} py={{ base: 1, md: 0 }} > - + {estimatedApr && ( <> )} diff --git a/src/lib/pages/validator-details/components/validator-top/WebsiteButton.tsx b/src/lib/pages/validator-details/components/validator-top/WebsiteButton.tsx index a28e15369..f3f64d578 100644 --- a/src/lib/pages/validator-details/components/validator-top/WebsiteButton.tsx +++ b/src/lib/pages/validator-details/components/validator-top/WebsiteButton.tsx @@ -9,6 +9,7 @@ export const WebsiteButton = (props: ButtonProps) => ( rightIcon={} size="sm" variant="outline-primary" + width={{ base: "full", md: "auto" }} {...props} > Website diff --git a/src/lib/pages/validator-details/components/validator-top/index.tsx b/src/lib/pages/validator-details/components/validator-top/index.tsx index 72b6ed229..4df9228b0 100644 --- a/src/lib/pages/validator-details/components/validator-top/index.tsx +++ b/src/lib/pages/validator-details/components/validator-top/index.tsx @@ -40,7 +40,11 @@ export const ValidatorTop = ({ info, totalVotingPower }: ValidatorTopProps) => ( - + From 706fbb1f2fc5080b1c23d2143b00e581b06c9dab Mon Sep 17 00:00:00 2001 From: Poafs1 Date: Wed, 13 Mar 2024 14:26:48 +0700 Subject: [PATCH 07/11] feat(pages): move variable from config to pages level --- .../bonded-token-changes/VotingPowerChart.tsx | 19 ++++-------- .../components/bonded-token-changes/index.tsx | 12 ++++++-- .../components/validator-overview/index.tsx | 12 ++++++-- .../validator-top/ValidatorStats.tsx | 8 ++--- .../components/validator-top/index.tsx | 8 ++++- src/lib/pages/validator-details/index.tsx | 30 ++++++++++++++++--- 6 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/lib/pages/validator-details/components/bonded-token-changes/VotingPowerChart.tsx b/src/lib/pages/validator-details/components/bonded-token-changes/VotingPowerChart.tsx index 1a218f7bf..5284a4796 100644 --- a/src/lib/pages/validator-details/components/bonded-token-changes/VotingPowerChart.tsx +++ b/src/lib/pages/validator-details/components/bonded-token-changes/VotingPowerChart.tsx @@ -2,13 +2,11 @@ import { Box, Flex, Heading, Text } from "@chakra-ui/react"; import type { BigSource } from "big.js"; import type { ScriptableContext, TooltipModel } from "chart.js"; -import { useCelatoneApp } from "lib/app-provider"; import { LineChart } from "lib/components/chart/LineChart"; import { Loading } from "lib/components/Loading"; import { ErrorFetching } from "lib/components/state"; -import { useAssetInfos } from "lib/services/assetService"; import { useValidatorHistoricalPowers } from "lib/services/validatorService"; -import type { Token, U, ValidatorAddr } from "lib/types"; +import type { AssetInfos, Token, U, ValidatorAddr } from "lib/types"; import { formatHHmm, formatUTokenWithPrecision, @@ -17,24 +15,19 @@ import { interface VotingPowerChartProps { validatorAddress: ValidatorAddr; + singleStakingDenom?: string; + assetInfos?: AssetInfos; } export const VotingPowerChart = ({ validatorAddress, + singleStakingDenom, + assetInfos, }: VotingPowerChartProps) => { - const { - chainConfig: { - extra: { singleStakingDenom }, - }, - } = useCelatoneApp(); - const { data: assetInfos, isLoading: isAssetInfosLoading } = useAssetInfos({ - withPrices: false, - }); - const { data: historicalPowers, isLoading } = useValidatorHistoricalPowers(validatorAddress); - if (isLoading || isAssetInfosLoading) return ; + if (isLoading) return ; if (!historicalPowers) return ; const labels = historicalPowers?.items.map((item) => diff --git a/src/lib/pages/validator-details/components/bonded-token-changes/index.tsx b/src/lib/pages/validator-details/components/bonded-token-changes/index.tsx index 83717841a..bb7ad4282 100644 --- a/src/lib/pages/validator-details/components/bonded-token-changes/index.tsx +++ b/src/lib/pages/validator-details/components/bonded-token-changes/index.tsx @@ -1,20 +1,28 @@ import { Flex } from "@chakra-ui/react"; import { RelatedTransactionTable } from "../tables/RelatedTransactionsTable"; -import type { ValidatorAddr } from "lib/types"; +import type { AssetInfos, ValidatorAddr } from "lib/types"; import { VotingPowerChart } from "./VotingPowerChart"; interface BondedTokenChangesProps { validatorAddress: ValidatorAddr; + singleStakingDenom?: string; + assetInfos?: AssetInfos; } export const BondedTokenChanges = ({ validatorAddress, + singleStakingDenom, + assetInfos, }: BondedTokenChangesProps) => { return ( - + ); diff --git a/src/lib/pages/validator-details/components/validator-overview/index.tsx b/src/lib/pages/validator-details/components/validator-overview/index.tsx index 69f05c565..5f2948c6d 100644 --- a/src/lib/pages/validator-details/components/validator-overview/index.tsx +++ b/src/lib/pages/validator-details/components/validator-overview/index.tsx @@ -9,7 +9,7 @@ import { VotedProposalsTable } from "../tables/VotedProposalsTable"; import { useMobile, useMoveConfig } from "lib/app-provider"; import { CustomIcon } from "lib/components/icon"; import { EmptyState } from "lib/components/state"; -import type { ValidatorAddr } from "lib/types"; +import type { AssetInfos, ValidatorAddr } from "lib/types"; import { ValidatorDescription } from "./ValidatorDescription"; import { VotingPowerOverview } from "./VotingPowerOverview"; @@ -22,6 +22,8 @@ interface ValidatorOverviewProps { isJailed: boolean; details: string; validatorAddress: ValidatorAddr; + singleStakingDenom?: string; + assetInfos?: AssetInfos; } export const ValidatorOverview = ({ @@ -32,6 +34,8 @@ export const ValidatorOverview = ({ isJailed, details, validatorAddress, + singleStakingDenom, + assetInfos, }: ValidatorOverviewProps) => { const isMobile = useMobile(); const move = useMoveConfig({ shouldRedirect: false }); @@ -49,7 +53,11 @@ export const ValidatorOverview = ({ {!move.enabled && ( - + )} )} diff --git a/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx b/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx index abd344d48..8d5eb0cfb 100644 --- a/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx +++ b/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx @@ -1,7 +1,6 @@ import { Box, Flex, Spinner, Text } from "@chakra-ui/react"; import type { ReactNode } from "react"; -import { useCelatoneApp } from "lib/app-provider"; import { DotSeparator } from "lib/components/DotSeparator"; import { useValidatorDelegators, @@ -31,21 +30,18 @@ interface ValidatorStatsProps { validatorAddress: ValidatorAddr; commissionRate: number; totalVotingPower: Big; + singleStakingDenom?: string; } export const ValidatorStats = ({ validatorAddress, commissionRate, totalVotingPower, + singleStakingDenom, }: ValidatorStatsProps) => { const { data: stakingProvisions } = useValidatorStakingProvisions(); const { data: delegations, isLoading: isDelegationsLoading } = useValidatorDelegators(validatorAddress); - const { - chainConfig: { - extra: { singleStakingDenom }, - }, - } = useCelatoneApp(); if (!stakingProvisions) return ; diff --git a/src/lib/pages/validator-details/components/validator-top/index.tsx b/src/lib/pages/validator-details/components/validator-top/index.tsx index 4df9228b0..f09165bd0 100644 --- a/src/lib/pages/validator-details/components/validator-top/index.tsx +++ b/src/lib/pages/validator-details/components/validator-top/index.tsx @@ -15,9 +15,14 @@ import { WebsiteButton } from "./WebsiteButton"; interface ValidatorTopProps { info: ValidatorData; totalVotingPower: Big; + singleStakingDenom?: string; } -export const ValidatorTop = ({ info, totalVotingPower }: ValidatorTopProps) => ( +export const ValidatorTop = ({ + info, + totalVotingPower, + singleStakingDenom, +}: ValidatorTopProps) => ( ( validatorAddress={info.validatorAddress} commissionRate={info.commissionRate} totalVotingPower={totalVotingPower} + singleStakingDenom={singleStakingDenom} /> () => { if (nextTab === tab) return; @@ -50,13 +64,17 @@ const ValidatorDetailsBody = ({ [navigate, tab, validatorAddress] ); - if (isLoading) return ; + if (isLoading || isAssetInfosLoading) return ; if (!data) return ; if (!data.info) return ; return ( <> - + {!move.enabled && ( - + )} From 2dfcf0cda7e0d1b9ffecb51ecf533f8737f221f4 Mon Sep 17 00:00:00 2001 From: Poafs1 Date: Wed, 13 Mar 2024 14:42:08 +0700 Subject: [PATCH 08/11] feat(utils): fix external link redirect --- .../components/validator-top/ValidatorTitle.tsx | 5 ++--- .../validator-details/components/validator-top/index.tsx | 5 ++--- src/lib/types/validator.ts | 6 +++++- src/lib/utils/formatter/index.ts | 1 + src/lib/utils/formatter/url.ts | 7 +++++++ 5 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 src/lib/utils/formatter/url.ts diff --git a/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx b/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx index 96e939f16..8c3016e25 100644 --- a/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx +++ b/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx @@ -1,5 +1,4 @@ -import { Flex, Heading } from "@chakra-ui/react"; -import Link from "next/link"; +import { Flex, Heading, Link } from "@chakra-ui/react"; import { ValidatorImage } from "lib/components/ValidatorImage"; import type { ValidatorData } from "lib/types"; @@ -53,7 +52,7 @@ export const ValidatorTitle = ({ info }: ValidatorTitleProps) => ( > {info.moniker} - + diff --git a/src/lib/pages/validator-details/components/validator-top/index.tsx b/src/lib/pages/validator-details/components/validator-top/index.tsx index f09165bd0..68bff3a8d 100644 --- a/src/lib/pages/validator-details/components/validator-top/index.tsx +++ b/src/lib/pages/validator-details/components/validator-top/index.tsx @@ -1,6 +1,5 @@ -import { Flex, Text } from "@chakra-ui/react"; +import { Flex, Link, Text } from "@chakra-ui/react"; import type Big from "big.js"; -import Link from "next/link"; import { Breadcrumb } from "lib/components/Breadcrumb"; import { CopyLink } from "lib/components/CopyLink"; @@ -91,7 +90,7 @@ export const ValidatorTop = ({ fixedHeight={false} /> - + diff --git a/src/lib/types/validator.ts b/src/lib/types/validator.ts index 38b687903..4369274d2 100644 --- a/src/lib/types/validator.ts +++ b/src/lib/types/validator.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { snakeToCamel } from "lib/utils/formatter/snakeToCamel"; +import { formatUrl } from "lib/utils/formatter/url"; import { zBechAddr20, zValidatorAddr } from "./addrs"; import { zBig } from "./big"; @@ -35,7 +36,10 @@ export const zValidatorData = z uptime: z.number().optional(), website: z.string(), }) - .transform(snakeToCamel); + .transform((val) => ({ + ...snakeToCamel(val), + website: formatUrl(val.website), + })); export type ValidatorData = z.infer; diff --git a/src/lib/utils/formatter/index.ts b/src/lib/utils/formatter/index.ts index 6df8866f8..ed4289a73 100644 --- a/src/lib/utils/formatter/index.ts +++ b/src/lib/utils/formatter/index.ts @@ -7,3 +7,4 @@ export * from "./percentage"; export * from "./tokenType"; export * from "./token"; export * from "./text"; +export * from "./url"; diff --git a/src/lib/utils/formatter/url.ts b/src/lib/utils/formatter/url.ts new file mode 100644 index 000000000..4a6697235 --- /dev/null +++ b/src/lib/utils/formatter/url.ts @@ -0,0 +1,7 @@ +export const formatUrl = (url: string): string => { + if (url.startsWith("http://") || url.startsWith("https://")) { + return url; + } + + return `http://${url}`; +}; From 99819994b81a7d00096f0d273ff13f48812edf45 Mon Sep 17 00:00:00 2001 From: Poafs1 Date: Wed, 13 Mar 2024 16:57:01 +0700 Subject: [PATCH 09/11] fix(types): validator data rank cummulative voiting power can be undefined --- src/lib/types/validator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/types/validator.ts b/src/lib/types/validator.ts index 4369274d2..2a953c32e 100644 --- a/src/lib/types/validator.ts +++ b/src/lib/types/validator.ts @@ -23,7 +23,7 @@ export type Validator = z.infer; export const zValidatorData = z .object({ rank: z.number().nullable(), - rank_cummulative_voting_power: zBig, + rank_cummulative_voting_power: zBig.optional(), validator_address: zValidatorAddr, account_address: zBechAddr20, identity: z.string(), From c4bb276ddeb8159fe63018f7681956d0ca528ef1 Mon Sep 17 00:00:00 2001 From: Poafs1 Date: Thu, 14 Mar 2024 14:02:26 +0700 Subject: [PATCH 10/11] feat(components): fix pr comments --- src/lib/components/ValidatorBadge.tsx | 32 +++++------ .../bonded-token-changes/VotingPowerChart.tsx | 6 +- .../components/bonded-token-changes/index.tsx | 28 +++++---- .../components/validator-overview/index.tsx | 34 +++++------ .../validator-top/ValidatorStats.tsx | 57 ++++++++++++------- .../validator-top/ValidatorTitle.tsx | 20 ++++--- .../components/validator-top/index.tsx | 4 +- src/lib/pages/validator-details/index.tsx | 2 + src/lib/types/validator.ts | 1 - src/lib/utils/formatter/url.ts | 2 +- 10 files changed, 97 insertions(+), 89 deletions(-) diff --git a/src/lib/components/ValidatorBadge.tsx b/src/lib/components/ValidatorBadge.tsx index 677e4e700..d3c4aa026 100644 --- a/src/lib/components/ValidatorBadge.tsx +++ b/src/lib/components/ValidatorBadge.tsx @@ -29,24 +29,22 @@ export const ValidatorBadge = ({ return ( + {validator ? ( - <> - - - {isMobile && hasLabel && } - - {moreInfo} - - + + {isMobile && hasLabel && } + + {moreInfo} + ) : ( <> diff --git a/src/lib/pages/validator-details/components/bonded-token-changes/VotingPowerChart.tsx b/src/lib/pages/validator-details/components/bonded-token-changes/VotingPowerChart.tsx index 5284a4796..69f785ca9 100644 --- a/src/lib/pages/validator-details/components/bonded-token-changes/VotingPowerChart.tsx +++ b/src/lib/pages/validator-details/components/bonded-token-changes/VotingPowerChart.tsx @@ -6,7 +6,7 @@ import { LineChart } from "lib/components/chart/LineChart"; import { Loading } from "lib/components/Loading"; import { ErrorFetching } from "lib/components/state"; import { useValidatorHistoricalPowers } from "lib/services/validatorService"; -import type { AssetInfos, Token, U, ValidatorAddr } from "lib/types"; +import type { AssetInfos, Option, Token, U, ValidatorAddr } from "lib/types"; import { formatHHmm, formatUTokenWithPrecision, @@ -15,8 +15,8 @@ import { interface VotingPowerChartProps { validatorAddress: ValidatorAddr; - singleStakingDenom?: string; - assetInfos?: AssetInfos; + singleStakingDenom: Option; + assetInfos: Option; } export const VotingPowerChart = ({ diff --git a/src/lib/pages/validator-details/components/bonded-token-changes/index.tsx b/src/lib/pages/validator-details/components/bonded-token-changes/index.tsx index bb7ad4282..5cf7f8200 100644 --- a/src/lib/pages/validator-details/components/bonded-token-changes/index.tsx +++ b/src/lib/pages/validator-details/components/bonded-token-changes/index.tsx @@ -1,29 +1,27 @@ import { Flex } from "@chakra-ui/react"; import { RelatedTransactionTable } from "../tables/RelatedTransactionsTable"; -import type { AssetInfos, ValidatorAddr } from "lib/types"; +import type { AssetInfos, Option, ValidatorAddr } from "lib/types"; import { VotingPowerChart } from "./VotingPowerChart"; interface BondedTokenChangesProps { validatorAddress: ValidatorAddr; - singleStakingDenom?: string; - assetInfos?: AssetInfos; + singleStakingDenom: Option; + assetInfos: Option; } export const BondedTokenChanges = ({ validatorAddress, singleStakingDenom, assetInfos, -}: BondedTokenChangesProps) => { - return ( - - - - - ); -}; +}: BondedTokenChangesProps) => ( + + + + +); diff --git a/src/lib/pages/validator-details/components/validator-overview/index.tsx b/src/lib/pages/validator-details/components/validator-overview/index.tsx index 5f2948c6d..fe26a2e57 100644 --- a/src/lib/pages/validator-details/components/validator-overview/index.tsx +++ b/src/lib/pages/validator-details/components/validator-overview/index.tsx @@ -6,10 +6,10 @@ import { RecentBlocksSection } from "../performance/RecentBlocksSection"; import { UptimeSection } from "../performance/UptimeSection"; import { ProposedBlocksTable } from "../tables/ProposedBlocksTable"; import { VotedProposalsTable } from "../tables/VotedProposalsTable"; -import { useMobile, useMoveConfig } from "lib/app-provider"; +import { useMobile } from "lib/app-provider"; import { CustomIcon } from "lib/components/icon"; import { EmptyState } from "lib/components/state"; -import type { AssetInfos, ValidatorAddr } from "lib/types"; +import type { AssetInfos, Option, ValidatorAddr } from "lib/types"; import { ValidatorDescription } from "./ValidatorDescription"; import { VotingPowerOverview } from "./VotingPowerOverview"; @@ -22,8 +22,8 @@ interface ValidatorOverviewProps { isJailed: boolean; details: string; validatorAddress: ValidatorAddr; - singleStakingDenom?: string; - assetInfos?: AssetInfos; + singleStakingDenom: Option; + assetInfos: Option; } export const ValidatorOverview = ({ @@ -38,7 +38,6 @@ export const ValidatorOverview = ({ assetInfos, }: ValidatorOverviewProps) => { const isMobile = useMobile(); - const move = useMoveConfig({ shouldRedirect: false }); return isActive && !isJailed ? ( @@ -47,26 +46,23 @@ export const ValidatorOverview = ({ - {!isMobile && ( + {isMobile ? ( + + ) : ( <> - {!move.enabled && ( - - )} + )} - {isMobile && !move.enabled && ( - - )} diff --git a/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx b/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx index 8d5eb0cfb..62b060e27 100644 --- a/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx +++ b/src/lib/pages/validator-details/components/validator-top/ValidatorStats.tsx @@ -1,28 +1,37 @@ import { Box, Flex, Spinner, Text } from "@chakra-ui/react"; -import type { ReactNode } from "react"; import { DotSeparator } from "lib/components/DotSeparator"; import { useValidatorDelegators, useValidatorStakingProvisions, } from "lib/services/validatorService"; -import type { ValidatorAddr } from "lib/types"; +import type { Option, ValidatorAddr } from "lib/types"; import { formatPrettyPercent } from "lib/utils"; const StatWithLabel = ({ label, value, + isLoading, }: { label: string; - value: string | ReactNode; + value: Option; + isLoading: boolean; }) => ( {label} - - {value} - + {isLoading ? ( + + ) : ( + + {value ?? "N/A"} + + )} ); @@ -30,7 +39,7 @@ interface ValidatorStatsProps { validatorAddress: ValidatorAddr; commissionRate: number; totalVotingPower: Big; - singleStakingDenom?: string; + singleStakingDenom: Option; } export const ValidatorStats = ({ @@ -39,24 +48,22 @@ export const ValidatorStats = ({ totalVotingPower, singleStakingDenom, }: ValidatorStatsProps) => { - const { data: stakingProvisions } = useValidatorStakingProvisions(); + const { data: stakingProvisions, isLoading: isStakingProvisionsLoading } = + useValidatorStakingProvisions(); const { data: delegations, isLoading: isDelegationsLoading } = useValidatorDelegators(validatorAddress); - if (!stakingProvisions) return ; - - const estimatedApr = singleStakingDenom - ? stakingProvisions.stakingProvisions.div( - totalVotingPower.mul(1 - commissionRate) + const estimatedApr = stakingProvisions + ? formatPrettyPercent( + stakingProvisions.stakingProvisions + .div(totalVotingPower.mul(1 - commissionRate)) + .toNumber(), + 2, + true ) : undefined; - const delegationsValue = - !isDelegationsLoading && delegations ? ( - String(delegations.total) - ) : ( - - ); + const delegatorsCount = delegations ? String(delegations.total) : undefined; return ( - {estimatedApr && ( + {singleStakingDenom && ( <> )} - + ); }; diff --git a/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx b/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx index 8c3016e25..ac520f5d7 100644 --- a/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx +++ b/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx @@ -22,15 +22,17 @@ export const ValidatorTitle = ({ info }: ValidatorTitleProps) => ( alignItems={{ base: "start", md: "center" }} > - - #{info.rank} - + {info?.rank && ( + + #{info.rank} + + )} ; } export const ValidatorTop = ({ diff --git a/src/lib/pages/validator-details/index.tsx b/src/lib/pages/validator-details/index.tsx index 44d713e5e..d1643eacd 100644 --- a/src/lib/pages/validator-details/index.tsx +++ b/src/lib/pages/validator-details/index.tsx @@ -113,6 +113,8 @@ const ValidatorDetailsBody = ({ isJailed={data.info.isJailed} details={data.info.details} validatorAddress={validatorAddress} + singleStakingDenom={singleStakingDenom} + assetInfos={assetInfos} /> diff --git a/src/lib/types/validator.ts b/src/lib/types/validator.ts index 2a953c32e..f91ba7b5e 100644 --- a/src/lib/types/validator.ts +++ b/src/lib/types/validator.ts @@ -23,7 +23,6 @@ export type Validator = z.infer; export const zValidatorData = z .object({ rank: z.number().nullable(), - rank_cummulative_voting_power: zBig.optional(), validator_address: zValidatorAddr, account_address: zBechAddr20, identity: z.string(), diff --git a/src/lib/utils/formatter/url.ts b/src/lib/utils/formatter/url.ts index 4a6697235..ef1d7eacc 100644 --- a/src/lib/utils/formatter/url.ts +++ b/src/lib/utils/formatter/url.ts @@ -3,5 +3,5 @@ export const formatUrl = (url: string): string => { return url; } - return `http://${url}`; + return `https://${url}`; }; From ca268a759a9b9abd5190166589790ce5c39ca760 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Thu, 14 Mar 2024 17:40:42 +0700 Subject: [PATCH 11/11] fix: ordering --- .../validator-top/ValidatorTitle.tsx | 2 +- src/lib/pages/validator-details/index.tsx | 26 +++++++++---------- src/lib/types/validator.ts | 4 +-- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx b/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx index ac520f5d7..e759c5ca9 100644 --- a/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx +++ b/src/lib/pages/validator-details/components/validator-top/ValidatorTitle.tsx @@ -22,7 +22,7 @@ export const ValidatorTitle = ({ info }: ValidatorTitleProps) => ( alignItems={{ base: "start", md: "center" }} > - {info?.rank && ( + {info.rank && ( { const navigate = useInternalNavigate(); - const move = useMoveConfig({ shouldRedirect: false }); - const { data, isLoading } = useValidatorData(validatorAddress); - const { chainConfig: { extra: { singleStakingDenom }, }, } = useCelatoneApp(); + const move = useMoveConfig({ shouldRedirect: false }); + const { data: assetInfos, isLoading: isAssetInfosLoading } = useAssetInfos({ withPrices: true, }); + const { data, isLoading } = useValidatorData(validatorAddress); const handleTabChange = useCallback( (nextTab: TabIndex) => () => { @@ -123,15 +123,13 @@ const ValidatorDetailsBody = ({ - {!move.enabled && ( - - - - )} + + + @@ -150,13 +148,13 @@ const ValidatorDetails = () => { }, [router.isReady]); return ( -
+ <> {!validated.success ? ( ) : ( )} -
+ ); }; diff --git a/src/lib/types/validator.ts b/src/lib/types/validator.ts index f91ba7b5e..3e9ef76bf 100644 --- a/src/lib/types/validator.ts +++ b/src/lib/types/validator.ts @@ -35,9 +35,9 @@ export const zValidatorData = z uptime: z.number().optional(), website: z.string(), }) - .transform((val) => ({ + .transform(({ website, ...val }) => ({ ...snakeToCamel(val), - website: formatUrl(val.website), + website: formatUrl(website), })); export type ValidatorData = z.infer;