Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@
as="image"
href="./src/assets/frankendancer_logo.svg"
/>
<link
rel="preload"
type="image/svg+xml"
as="image"
href="./src/assets/boot_progress_background.svg"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Firedancer</title>
</head>
Expand Down
7 changes: 7 additions & 0 deletions src/api/atoms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import type {
BlockEngineUpdate,
VoteBalance,
ScheduleStrategy,
BootProgress,
GossipNetworkStats,
} from "./types";
import { rafAtom } from "../atomUtils";

Expand Down Expand Up @@ -74,8 +76,13 @@ export const liveTilePrimaryMetricAtom = atom<

export const tileTimerAtom = atom<number[] | undefined>(undefined);

export const bootProgressAtom = atom<BootProgress | undefined>(undefined);
export const startupProgressAtom = atom<StartupProgress | undefined>(undefined);

export const gossipNetworkStatsAtom = atom<GossipNetworkStats | undefined>(
undefined,
);

export const tpsHistoryAtom = atom<TpsHistory | undefined>(undefined);

export const voteStateAtom = atom<VoteState | undefined>(undefined);
Expand Down
222 changes: 218 additions & 4 deletions src/api/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ const epochTopicSchema = z.object({
topic: z.literal("epoch"),
});

const gossipTopicSchema = z.object({
topic: z.literal("gossip"),
});

const peersTopicSchema = z.object({
topic: z.literal("peers"),
});
Expand All @@ -26,6 +30,7 @@ const blockEngineTopicSchema = z.object({
export const topicSchema = z.discriminatedUnion("topic", [
summaryTopicSchema,
epochTopicSchema,
gossipTopicSchema,
peersTopicSchema,
slotTopicSchema,
blockEngineTopicSchema,
Expand Down Expand Up @@ -71,6 +76,9 @@ export const tileTypeSchema = z.enum([
"plugin",
"gui",
"cswtch",
"snaprd",
"snapdc",
"snapin",
]);

export const tileSchema = z.object({
Expand Down Expand Up @@ -198,17 +206,17 @@ export const startupProgressSchema = z.object({
downloading_full_snapshot_elapsed_secs: z.number().nullable(),
downloading_full_snapshot_remaining_secs: z.number().nullable(),
downloading_full_snapshot_throughput: z.number().nullable(),
downloading_full_snapshot_total_bytes: z.number().nullable(),
downloading_full_snapshot_current_bytes: z.number().nullable(),
downloading_full_snapshot_total_bytes: z.coerce.number().nullable(),
downloading_full_snapshot_current_bytes: z.coerce.number().nullable(),

// downloading incremental snapshot
downloading_incremental_snapshot_slot: z.number().nullable(),
downloading_incremental_snapshot_peer: z.string().nullable(),
downloading_incremental_snapshot_elapsed_secs: z.number().nullable(),
downloading_incremental_snapshot_remaining_secs: z.number().nullable(),
downloading_incremental_snapshot_throughput: z.number().nullable(),
downloading_incremental_snapshot_total_bytes: z.number().nullable(),
downloading_incremental_snapshot_current_bytes: z.number().nullable(),
downloading_incremental_snapshot_total_bytes: z.coerce.number().nullable(),
downloading_incremental_snapshot_current_bytes: z.coerce.number().nullable(),

// processing ledger
ledger_slot: z.number().nullable(),
Expand All @@ -219,6 +227,148 @@ export const startupProgressSchema = z.object({
waiting_for_supermajority_stake_percent: z.number().nullable(),
});

export const bootPhaseSchema = z.enum([
"joining_gossip",
"loading_full_snapshot",
"loading_incr_snapshot",
"catching_up",
"running",
]);

export const BootPhaseEnum = bootPhaseSchema.enum;

export const bootProgressSchema = z.object({
phase: bootPhaseSchema,
total_elapsed: z.number(),

// joining_gossip
joining_gossip_elapsed: z.number().nullable(),

// loading_full_snapshot
loading_full_snapshot_reset_cnt: z.number().nullable().optional(),
loading_full_snapshot_slot: z.number().nullable().optional(),
loading_full_snapshot_peer: z.string().nullable().optional(),
loading_full_snapshot_peer_identity: z.string().nullable().optional(),
loading_full_snapshot_total_bytes: z.coerce.number().nullable().optional(),
loading_full_snapshot_elapsed: z.number().nullable().optional(),
loading_full_snapshot_read_bytes: z.coerce.number().nullable().optional(),
loading_full_snapshot_read_throughput: z.number().nullable().optional(),
loading_full_snapshot_current_bytes: z.coerce.number().nullable().optional(),
loading_full_snapshot_read_remaining: z.number().nullable().optional(),
loading_full_snapshot_read_elapsed: z.number().nullable().optional(),
loading_full_snapshot_read_path: z.string().nullable().optional(),
loading_full_snapshot_decompress_bytes: z.number().nullable().optional(),
loading_full_snapshot_decompress_elapsed: z.number().nullable().optional(),
loading_full_snapshot_decompress_throughput: z.number().nullable().optional(),
loading_full_snapshot_decompress_compressed_bytes: z.coerce
.number()
.nullable()
.optional(),
loading_full_snapshot_decompress_decompressed_bytes: z.coerce
.number()
.nullable()
.optional(),
loading_full_snapshot_decompress_remaining: z.number().nullable().optional(),
loading_full_snapshot_insert_bytes: z.coerce.number().nullable().optional(),
loading_full_snapshot_insert_throughput: z.number().nullable().optional(),
loading_full_snapshot_insert_remaining: z.number().nullable().optional(),
loading_full_snapshot_insert_path: z.string().nullable().optional(),
loading_full_snapshot_insert_elapsed: z.number().nullable().optional(),
loading_full_snapshot_insert_accounts_throughput: z
.number()
.nullable()
.optional(),
loading_full_snapshot_insert_accounts_current: z
.number()
.nullable()
.optional(),

// loading_incremental_snapshot
loading_incremental_snapshot_reset_cnt: z.number().nullable().optional(),
loading_incremental_snapshot_peer_identity: z.string().nullable().optional(),
loading_incremental_snapshot_slot: z.number().nullable().optional(),
loading_incremental_snapshot_peer: z.string().nullable().optional(),
loading_incremental_snapshot_total_bytes: z.coerce
.number()
.nullable()
.optional(),
loading_incremental_snapshot_elapsed: z.number().nullable().optional(),
loading_incremental_snapshot_read_bytes: z.coerce
.number()
.nullable()
.optional(),
loading_incremental_snapshot_read_elapsed: z.number().nullable().optional(),
loading_incremental_snapshot_read_throughput: z
.number()
.nullable()
.optional(),
loading_incremental_snapshot_read_remaining: z.number().nullable().optional(),
loading_incremental_snapshot_read_path: z.string().nullable().optional(),
loading_incremental_snapshot_current_bytes: z.coerce
.number()
.nullable()
.optional(),
loading_incremental_snapshot_decompress_bytes: z.coerce
.number()
.nullable()
.optional(),

loading_incremental_snapshot_decompress_elapsed: z
.number()
.nullable()
.optional(),
loading_incremental_snapshot_decompress_throughput: z
.number()
.nullable()
.optional(),
loading_incremental_snapshot_decompress_compressed_bytes: z.coerce
.number()
.nullable()
.optional(),
loading_incremental_snapshot_decompress_decompressed_bytes: z.coerce
.number()
.nullable()
.optional(),
loading_incremental_snapshot_decompress_remaining: z
.number()
.nullable()
.optional(),
loading_incremental_snapshot_insert_bytes: z.coerce
.number()
.nullable()
.optional(),
loading_incremental_snapshot_insert_elapsed: z.number().nullable().optional(),
loading_incremental_snapshot_insert_throughput: z
.number()
.nullable()
.optional(),
loading_incremental_snapshot_insert_remaining: z
.number()
.nullable()
.optional(),
loading_incremental_snapshot_insert_path: z.string().nullable().optional(),
loading_incremental_snapshot_insert_accounts_throughput: z
.number()
.nullable()
.optional(),
loading_incremental_snapshot_insert_accounts_current: z
.number()
.nullable()
.optional(),

// catching_up
catching_up_elapsed: z.number().nullable().optional(),
catching_up_min_turbine_slot: z.number().nullable().optional(),
catching_up_max_turbine_slot: z.number().nullable().optional(),
catching_up_min_repair_slot: z.number().nullable().optional(),
catching_up_max_repair_slot: z.number().nullable().optional(),
catching_up_max_replay_slot: z.number().nullable().optional(),
catching_up_first_turbine_slot: z.number().nullable().optional(),
catching_up_latest_turbine_slot: z.number().nullable().optional(),
catching_up_latest_repair_slot: z.number().nullable().optional(),
catching_up_latest_replay_slot: z.number().nullable().optional(),
});

export const slotTransactionsSchema = z.object({
start_timestamp_nanos: z.coerce.bigint(),
target_end_timestamp_nanos: z.coerce.bigint(),
Expand Down Expand Up @@ -371,6 +521,10 @@ export const summarySchema = z.discriminatedUnion("key", [
key: z.literal("startup_progress"),
value: startupProgressSchema,
}),
summaryTopicSchema.extend({
key: z.literal("boot_progress"),
value: bootProgressSchema,
}),
summaryTopicSchema.extend({
key: z.literal("tps_history"),
value: tpsHistorySchema,
Expand Down Expand Up @@ -408,6 +562,66 @@ export const epochSchema = z.discriminatedUnion("key", [
}),
]);

const gossipNetworkHealthSchema = z.object({
push_rx_pct: z.number().nullable().optional(),
pull_response_rx_pct: z.number().nullable().optional(),
push_rx_dup_pct: z.number().nullable().optional(),
pull_response_rx_dup_pct: z.number().nullable().optional(),
push_rx_msg_bad_pct: z.number().nullable().optional(),
push_rx_entry_bad_pct: z.number().nullable().optional(),
pull_response_rx_msg_bad_pct: z.number().nullable().optional(),
pull_response_rx_entry_bad_pct: z.number().nullable().optional(),
pull_already_known_pct: z.number().nullable().optional(),
total_stake: z.coerce.bigint().nullable().optional(),
total_staked_peers: z.number().nullable().optional(),
total_unstaked_peers: z.number().nullable().optional(),
connected_stake: z.coerce.bigint().nullable().optional(),
connected_staked_peers: z.number().nullable().optional(),
connected_unstaked_peers: z.number().nullable().optional(),
});

const gossipNetworkTrafficSchema = z.object({
total_throughput: z.number().nullable().optional(),
peer_names: z.string().array().nullable().optional(),
peer_identities: z.string().array().nullable().optional(),
peer_throughput: z.number().array().nullable().optional(),
});

const gossipStorageStatsSchema = z.object({
capacity: z.number().nullable().optional(),
expired_total: z.number().nullable().optional(),
evicted_total: z.number().nullable().optional(),
count: z.number().array().nullable().optional(),
bps_tx: z.number().array().nullable().optional(),
eps_tx: z.number().array().nullable().optional(),
});

const gossipMessageStatsSchema = z.object({
bytes_rx_total: z.number().array().nullable().optional(),
count_rx_total: z.number().array().nullable().optional(),
bytes_tx_total: z.number().array().nullable().optional(),
count_tx_total: z.number().array().nullable().optional(),
bps_rx: z.number().array().nullable().optional(),
mps_rx: z.number().array().nullable().optional(),
bps_tx: z.number().array().nullable().optional(),
mps_tx: z.number().array().nullable().optional(),
});

export const gossipNetworkStatsSchema = z.object({
health: gossipNetworkHealthSchema,
ingress: gossipNetworkTrafficSchema,
egress: gossipNetworkTrafficSchema,
storage: gossipStorageStatsSchema,
messages: gossipMessageStatsSchema,
});

export const gossipSchema = z.discriminatedUnion("key", [
gossipTopicSchema.extend({
key: z.literal("network_stats"),
value: gossipNetworkStatsSchema,
}),
]);

const peerUpdateGossipSchema = z.object({
wallclock: z.number(),
shred_version: z.number(),
Expand Down
9 changes: 9 additions & 0 deletions src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ import type {
slotTransactionsSchema,
voteBalanceSchema,
scheduleStrategySchema,
bootPhaseSchema,
bootProgressSchema,
gossipNetworkStatsSchema,
} from "./entities";

export type Client = z.infer<typeof clientSchema>;
Expand Down Expand Up @@ -98,10 +101,14 @@ export type TileType = z.infer<typeof tileTypeSchema>;

export type TileTimer = z.infer<typeof tileTimerSchema>;

export type BootProgress = z.infer<typeof bootProgressSchema>;

export type StartupProgress = z.infer<typeof startupProgressSchema>;

export type StartupPhase = z.infer<typeof startupPhaseSchema>;

export type BootPhase = z.infer<typeof bootPhaseSchema>;

export type TpsHistory = z.infer<typeof tpsHistorySchema>;

export type VoteState = z.infer<typeof voteStateSchema>;
Expand All @@ -114,6 +121,8 @@ export type Epoch = z.infer<typeof epochNewSchema>;

export type SlotLevel = z.infer<typeof slotLevelSchema>;

export type GossipNetworkStats = z.infer<typeof gossipNetworkStatsSchema>;

export interface Peer extends z.infer<typeof peerUpdateSchema> {
removed?: boolean;
}
Expand Down
Loading