Skip to content

Commit

Permalink
feat: add next leader to the table
Browse files Browse the repository at this point in the history
  • Loading branch information
vindi-r committed Oct 25, 2024
1 parent 5ce90e8 commit f48d0b6
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 97 deletions.
8 changes: 8 additions & 0 deletions solfees-fe/src/common/isReal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { CustomRow, CustomRowBasic } from "./prepareValidatorRow.ts";

// TODO probably we should change CommitmentStatus to Enum and compare as if(elt.commitment in CommitmentStatus) to find extended statuses
export function isReal(
slot: CustomRow["slots"][number] | CustomRowBasic["slots"][number]
): slot is CustomRowBasic["slots"][number] {
return slot.commitment !== "next-leader" && slot.commitment !== "scheduled";
}
29 changes: 22 additions & 7 deletions solfees-fe/src/common/prepareValidatorRow.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { CommitmentStatus, SlotContent } from "../store/websocketStore.ts";

export type CustomRow = {
export type ExtendedCommitmentStatus = CommitmentStatus | "next-leader" | "scheduled";
type ExtendedSlotContent = Omit<SlotContent, "commitment"> & {
commitment: ExtendedCommitmentStatus;
};

export type CustomRowBasic = {
id: string;
leader: string;
slots: {
commitment: CommitmentStatus;
commitment: ExtendedCommitmentStatus;
slot: number;
}[];
transactions: {
Expand All @@ -22,15 +27,18 @@ export type CustomRow = {
fee1: number[];
fee2: number[];
};
export type CustomRow = Omit<CustomRowBasic, "slots"> & {
slots: { slot: number; commitment: ExtendedCommitmentStatus }[];
};
type FxType = (arg: [id: string, slots: SlotContent[]]) => CustomRow;

const getFakeSlot = (leader: string, newSlotId: number): SlotContent => ({
export const getFakeSlot = (leader: string, newSlotId: number): ExtendedSlotContent => ({
leader,
slot: newSlotId,
totalTransactionsFiltered: 0,
feeLevels: [0, 0, 0],
feeAverage: 0,
commitment: "fake" as "confirmed",
commitment: "scheduled",
totalUnitsConsumed: 0,
totalFee: 0,
hash: "",
Expand All @@ -40,7 +48,7 @@ const getFakeSlot = (leader: string, newSlotId: number): SlotContent => ({
time: 0,
});

function fillGaps(list: SlotContent[]): SlotContent[] {
function fillGaps(list: SlotContent[]): ExtendedSlotContent[] {
if (!list.length) return list;
if (list.length === 4) return list;
const groupIdx = ((list?.[0]?.slot || 0) / 4) | 0;
Expand All @@ -51,7 +59,7 @@ function fillGaps(list: SlotContent[]): SlotContent[] {
const isFourth = list.find((elt) => (elt.slot / 4) % 1 === 0.75);

const newLeader = list?.[0]?.leader || "UNKNOWN";
const newList: typeof list = [];
const newList: ExtendedSlotContent[] = [];
isFirst ? newList.push({ ...isFirst }) : newList.push(getFakeSlot(newLeader, groupIdx * 4));
isSecond ? newList.push({ ...isSecond }) : newList.push(getFakeSlot(newLeader, groupIdx * 4 + 1));
isThird ? newList.push({ ...isThird }) : newList.push(getFakeSlot(newLeader, groupIdx * 4 + 2));
Expand All @@ -66,6 +74,13 @@ function fillGaps(list: SlotContent[]): SlotContent[] {
export const prepareValidatorRow: FxType = ([id, rawSlots]) => {
const slots = fillGaps(rawSlots);
const leader = slots[0]?.leader || "UNKNOWN";
return prepareSingeRow(id, leader, slots);
};
export function prepareSingeRow(
id: string,
leader: string,
slots: ExtendedSlotContent[]
): CustomRow {
return {
id,
leader,
Expand Down Expand Up @@ -97,4 +112,4 @@ export const prepareValidatorRow: FxType = ([id, rawSlots]) => {
fee1: slots.map((elt) => elt.feeLevels[1] || 0),
fee2: slots.map((elt) => elt.feeLevels[2] || 0),
};
};
}
27 changes: 0 additions & 27 deletions solfees-fe/src/components/layout/NextSlotInformer.tsx

This file was deleted.

48 changes: 32 additions & 16 deletions solfees-fe/src/components/ui/ComputeUnits.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Text } from "@consta/uikit/Text";
import { CustomRow } from "../../common/prepareValidatorRow.ts";
import { withTooltip } from "@consta/uikit/withTooltip";
import { isReal } from "../../common/isReal.ts";

interface Props {
items: CustomRow["computeUnits"];
slots: CustomRow["slots"];
}

const TextWithTooltip = withTooltip({ content: "Top tooltip" })(Text);
Expand All @@ -26,25 +28,39 @@ const amountFormatter = (amount: number): string => {
return result;
};

export const ComputeUnits = ({ items }: Props) => {
export const ComputeUnits = ({ items, slots }: Props) => {
return (
<div className="px-3 min-w-0">
{items.map((elt, idx) => (
<div key={elt.amount === 0 ? idx : elt.amount} className="flex justify-end">
<TextWithTooltip
className="flex justify-end text-right gap-1 shrink-0"
tooltipProps={{
content: tooltipFormatter.format(elt.amount),
direction: "leftCenter",
appearTimeout: 0,
exitTimeout: 0,
}}
{items.map((elt, idx) => {
const currentSlot = slots[idx];
const isFilled = currentSlot ? isReal(currentSlot) : false;

return (
<div
key={elt.amount === 0 ? idx : elt.amount}
className="flex justify-end whitespace-pre"
>
<Text font="mono">{amountFormatter(elt.amount)}</Text>
<Text font="mono">({percentFormatter.format(elt.percent).replace(/,/g, " ")})</Text>
</TextWithTooltip>
</div>
))}
{isFilled ? (
<TextWithTooltip
className="flex justify-end text-right gap-1 shrink-0"
tooltipProps={{
content: tooltipFormatter.format(elt.amount),
direction: "leftCenter",
appearTimeout: 0,
exitTimeout: 0,
}}
>
<Text font="mono">{amountFormatter(elt.amount)}</Text>
<Text font="mono">({percentFormatter.format(elt.percent).replace(/,/g, " ")})</Text>
</TextWithTooltip>
) : (
<Text font="mono" className="flex-shrink-0">
{" "}
</Text>
)}
</div>
);
})}
</div>
);
};
21 changes: 14 additions & 7 deletions solfees-fe/src/components/ui/EarnedSol.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Text } from "@consta/uikit/Text";
import { CustomRow } from "../../common/prepareValidatorRow.ts";
import { isReal } from "../../common/isReal.ts";

interface Props {
list: CustomRow["earnedSol"];
items: CustomRow["earnedSol"];
slots: CustomRow["slots"];
}

function formatValue(value: number): string {
Expand All @@ -15,14 +17,19 @@ function formatValue(value: number): string {
.replace(/\s/g, "")
: value.toFixed(9);
}
export const EarnedSol = ({ list }: Props) => {
export const EarnedSol = ({ items, slots }: Props) => {
return (
<div className="px-3 text-right">
{list.map((elt, idx) => (
<Text key={idx} font="mono">
{formatValue(elt)}
</Text>
))}
{items.map((elt, idx) => {
const currentSlot = slots[idx];
const isFilled = currentSlot ? isReal(currentSlot) : false;

return (
<Text key={idx} font="mono" className="whitespace-pre">
{isFilled ? formatValue(elt) : " "}
</Text>
);
})}
</div>
);
};
22 changes: 15 additions & 7 deletions solfees-fe/src/components/ui/SimpleCell.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import { Text } from "@consta/uikit/Text";
import { CustomRow } from "../../common/prepareValidatorRow.ts";
import { isReal } from "../../common/isReal.ts";

interface Props {
list: number[];
items: number[];
slots: CustomRow["slots"];
}
export const SimpleCell = ({ list }: Props) => {
export const SimpleCell = ({ items, slots }: Props) => {
return (
<div className="px-3 text-right">
{list.map((elt, idx) => (
<Text key={idx} font="mono">
{elt.toLocaleString("en-US", { maximumFractionDigits: 2 })}
</Text>
))}
{items.map((elt, idx) => {
const currentSlot = slots[idx];
const isFilled = currentSlot ? isReal(currentSlot) : false;

return (
<Text key={idx} font="mono" className="whitespace-pre">
{isFilled ? elt.toLocaleString("en-US", { maximumFractionDigits: 2 }) : " "}
</Text>
);
})}
</div>
);
};
21 changes: 13 additions & 8 deletions solfees-fe/src/components/ui/Slots.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,26 @@ import { IconCopy } from "@consta/icons/IconCopy";
import { IconWarning } from "@consta/icons/IconWarning";
import { IconProcessing } from "@consta/icons/IconProcessing";
import { IconWatchStroked } from "@consta/icons/IconWatchStroked";
import { CustomRow, ExtendedCommitmentStatus } from "../../common/prepareValidatorRow.ts";
import { IconLoading } from "@consta/icons/IconLoading";

interface Props {
items: {
commitment: CommitmentStatus;
slot: number;
}[];
items: CustomRow["slots"];
}

type ComProps = {
value: CommitmentStatus;
value: CustomRow["slots"][number]["commitment"];
};

const statuses: (CommitmentStatus | "fake")[] = ["processed", "confirmed", "finalized", "fake"];
const colors: IconPropView[] = ["link", "primary", "success", "ghost"];
const icons = [IconProcessing, IconCheck, IconAllDone, IconWatchStroked];
const statuses: ExtendedCommitmentStatus[] = [
"processed",
"confirmed",
"finalized",
"scheduled",
"next-leader",
];
const colors: IconPropView[] = ["link", "primary", "success", "ghost", "disabled"];
const icons = [IconProcessing, IconCheck, IconAllDone, IconLoading, IconWatchStroked];
export const AnimateIconBaseIcons = ({ value }: ComProps) => {
const idx = statuses.findIndex((elt) => elt === value);
return (
Expand Down
18 changes: 12 additions & 6 deletions solfees-fe/src/components/ui/Transactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { Text } from "@consta/uikit/Text";
import { useWebSocketStore } from "../../store/websocketStore.ts";
import { useShallow } from "zustand/react/shallow";
import { CustomRow } from "../../common/prepareValidatorRow.ts";
import { isReal } from "../../common/isReal.ts";

interface Props {
items: CustomRow["transactions"];
slots: CustomRow["slots"];
}

function buildTransactions(slots: CustomRow["transactions"], withFiltered = false) {
Expand Down Expand Up @@ -32,17 +34,21 @@ function buildTransactions(slots: CustomRow["transactions"], withFiltered = fals
return alignedWithKeys;
}

export const Transactions = ({ items }: Props) => {
export const Transactions = ({ items, slots }: Props) => {
const hasRW = useWebSocketStore(useShallow((state) => !!state.readwriteKeys.length));
const hasRO = useWebSocketStore(useShallow((state) => !!state.readonlyKeys.length));

return (
<div className="px-3 text-right">
{buildTransactions(items, hasRO || hasRW).map((elt) => (
<Text key={elt.key} font="mono" className="whitespace-pre">
{elt.value}
</Text>
))}
{buildTransactions(items, hasRO || hasRW).map((elt, idx) => {
const currentSlot = slots[idx];
const isFilled = currentSlot ? isReal(currentSlot) : false;
return (
<Text key={elt.key} font="mono" className="whitespace-pre">
{isFilled ? elt.value : " "}
</Text>
);
})}
</div>
);
};
8 changes: 6 additions & 2 deletions solfees-fe/src/components/ui/Validator.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { CustomRow } from "../../common/prepareValidatorRow.ts";

interface Props {
leader: string;
slots: CustomRow["slots"];
}
export const Validator = ({ leader }: Props) => {
export const Validator = ({ leader, slots }: Props) => {
const isNext = slots.some((elt) => elt.commitment === "next-leader");
return (
<div className="px-3 w-full h-full flex flex-col flex-nowrap justify-center">
<h1 className="font-bold">Validator Name:</h1>
<h1 className="font-bold">{isNext ? "Next" : ""} Validator Name:</h1>
<a
className="hover:underline"
href={`https://www.validators.app/validators/${leader}?locale=en&network=mainnet`}
Expand Down
Loading

0 comments on commit f48d0b6

Please sign in to comment.