Skip to content

Commit

Permalink
528 UI show delegation with slashed design (#539)
Browse files Browse the repository at this point in the history
* show delegation with slashed design

* resolve comments
  • Loading branch information
jeremy-babylonlabs authored Dec 26, 2024
1 parent 49ac8d7 commit f72682d
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 89 deletions.
5 changes: 3 additions & 2 deletions src/app/components/Delegations/Delegation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const Delegation: React.FC<DelegationProps> = ({
const [currentTime, setCurrentTime] = useState(Date.now());
const { isApiNormal, isGeoBlocked } = useHealthCheck();
const { transitionPhase1Delegation } = useTransactionService();
const { getFinalityProviderMoniker } = useFinalityProviderState();
const { getFinalityProvider } = useFinalityProviderState();
const { coinName, mempoolApiUrl } = getNetworkConfigBTC();

useEffect(() => {
Expand Down Expand Up @@ -102,7 +102,8 @@ export const Delegation: React.FC<DelegationProps> = ({
</DelegationCell>

<DelegationCell order="order-4 lg:order-2 text-right lg:text-left">
{getFinalityProviderMoniker(finalityProviderPkHex)}
{getFinalityProvider(finalityProviderPkHex)?.description?.moniker ??
"-"}
</DelegationCell>

<DelegationCell
Expand Down
5 changes: 5 additions & 0 deletions src/app/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ export const DELEGATION_ACTIONS = {
WITHDRAW_ON_TIMELOCK_SLASHING: "WITHDRAW_ON_TIMELOCK_SLASHING",
WITHDRAW_ON_EARLY_UNBONDING_SLASHING: "WITHDRAW_ON_EARLY_UNBONDING_SLASHING",
} as const;

export const DOCUMENTATION_LINKS = {
TECHNICAL_PRELIMINARIES:
"https://babylonlabs.io/blog/technical-preliminaries-of-bitcoin-staking",
} as const;
21 changes: 8 additions & 13 deletions src/app/state/FinalityProviderState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ interface FinalityProviderState {
handleFilter: (value: string | number) => void;
handleRowSelect: (row: FinalityProvider | null) => void;
isRowSelectable: (row: FinalityProvider) => boolean;
getFinalityProviderMoniker: (btcPkHex: string) => string;
getFinalityProvider: (btcPkHex: string) => FinalityProvider | null;
fetchNextPage: () => void;
}

Expand All @@ -65,7 +65,7 @@ const defaultState: FinalityProviderState = {
handleSort: () => {},
handleFilter: () => {},
handleRowSelect: () => {},
getFinalityProviderMoniker: () => "-",
getFinalityProvider: () => null,
fetchNextPage: () => {},
};

Expand Down Expand Up @@ -158,18 +158,13 @@ function FinalityProviderStateInner({ children }: PropsWithChildren) {
});
}, [data?.finalityProviders, filterValue, searchValue]);

const getFinalityProviderMoniker = useCallback(
const getFinalityProvider = useCallback(
(btcPkHex: string) => {
const moniker = filteredFinalityProviders.find(
(fp) => fp.btcPk === btcPkHex,
)?.description?.moniker;

if (!moniker) {
return "-";
}
return moniker;
return (
data?.finalityProviders.find((fp) => fp.btcPk === btcPkHex) || null
);
},
[filteredFinalityProviders],
[data?.finalityProviders],
);

useEffect(() => {
Expand Down Expand Up @@ -204,7 +199,7 @@ function FinalityProviderStateInner({ children }: PropsWithChildren) {
handleFilter,
handleRowSelect,
isRowSelectable,
getFinalityProviderMoniker,
getFinalityProvider,
fetchNextPage,
};

Expand Down
40 changes: 33 additions & 7 deletions src/components/common/Hint/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,52 @@
import { type PropsWithChildren, useId } from "react";
import { useId, type PropsWithChildren, type ReactNode } from "react";
import { AiOutlineInfoCircle } from "react-icons/ai";
import { Tooltip } from "react-tooltip";
import { twJoin } from "tailwind-merge";

type HintStatus = "default" | "warning" | "error";

interface HintProps {
tooltip: string;
tooltip: ReactNode;
status?: HintStatus;
}

export function Hint({ children, tooltip }: PropsWithChildren<HintProps>) {
const STATUS_COLORS = {
default: "text-primary-main",
warning: "text-warning-main",
error: "text-error-main",
} as const;

export function Hint({
children,
tooltip,
status = "default",
}: PropsWithChildren<HintProps>) {
const id = useId();

return (
<div className="inline-flex items-center gap-1">
<div
className={twJoin(
"inline-flex items-center gap-1",
STATUS_COLORS[status],
)}
>
{children && <p>{children}</p>}
<span
className="cursor-pointer text-xs"
className={twJoin("cursor-pointer text-xs", STATUS_COLORS[status])}
data-tooltip-id={id}
data-tooltip-content={tooltip}
data-tooltip-content={typeof tooltip === "string" ? tooltip : undefined}
data-tooltip-place="top"
>
<AiOutlineInfoCircle />
</span>
<Tooltip id={id} className="tooltip-wrap" />
<Tooltip
id={id}
className="tooltip-wrap"
openOnClick={false}
clickable={true}
>
{typeof tooltip !== "string" && tooltip}
</Tooltip>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,69 @@
import Link from "next/link";

import { DOCUMENTATION_LINKS } from "@/app/constants";
import { useFinalityProviderState } from "@/app/state/FinalityProviderState";
import { FinalityProviderState } from "@/app/types/finalityProviders";
import { Hint } from "@/components/common/Hint";

interface FinalityProviderMoniker {
interface FinalityProviderMonikerProps {
value: string;
}

export function FinalityProviderMoniker({ value }: FinalityProviderMoniker) {
const { getFinalityProviderMoniker } = useFinalityProviderState();
const STATUSES: Record<
FinalityProviderState,
{
tooltip?: React.ReactNode;
status?: "warning" | "error";
}
> = {
[FinalityProviderState.ACTIVE]: {},
[FinalityProviderState.INACTIVE]: {},
[FinalityProviderState.JAILED]: {
tooltip: (
<span>
This finality provider has been jailed.
<Link
className="text-secondary-main"
target="_blank"
href={DOCUMENTATION_LINKS.TECHNICAL_PRELIMINARIES}
>
Learn more
</Link>
</span>
),
status: "error",
},
[FinalityProviderState.SLASHED]: {
tooltip: (
<span>
This finality provider has been slashed.
<Link
className="text-secondary-main"
target="_blank"
href={DOCUMENTATION_LINKS.TECHNICAL_PRELIMINARIES}
>
Learn more
</Link>
</span>
),
status: "error",
},
};

export function FinalityProviderMoniker({
value,
}: FinalityProviderMonikerProps) {
const { getFinalityProvider } = useFinalityProviderState();

const moniker = getFinalityProviderMoniker(value);
const finalProvider = getFinalityProvider(value);
const moniker = finalProvider?.description?.moniker ?? "-";
const state = finalProvider?.state ?? FinalityProviderState.ACTIVE;
const { tooltip = "unknown", status } =
STATUSES[state as FinalityProviderState] ?? {};

return (
<div className="order-4 lg:order-2 text-right lg:text-left">{moniker}</div>
<Hint tooltip={tooltip} status={status}>
{moniker}
</Hint>
);
}
Loading

0 comments on commit f72682d

Please sign in to comment.