Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MultiLineChart } from '@/components/Charts/MultiLine';
import { BarChart } from '@/components/Charts/Bar';
import { LoadingContainer } from '@/components/Layout/LoadingContainer';
import { useThemeColors } from '@/hooks/useThemeColors';
import { formatSlot } from '@/utils';
import { formatSlot, getExecutionClientColor } from '@/utils';
import type { EngineTimingsData } from '../../hooks/useEngineTimingsData';
import { PER_SLOT_CHART_RANGES, type TimeRange } from '../../IndexPage.types';
import { ClientVersionBreakdown } from '../ClientVersionBreakdown';
Expand Down Expand Up @@ -249,16 +249,6 @@ export function GetBlobsTab({ data, timeRange, isLoading }: GetBlobsTabProps): J
clientSlotData.get(client)!.set(slot, duration);
});

// Create series for the by-client chart
const clientColors = [
themeColors.primary,
themeColors.success,
themeColors.warning,
themeColors.danger,
themeColors.accent,
themeColors.secondary,
];

// Downsample to ~400 points max per series to keep chart performant
const MAX_POINTS_PER_SERIES = 400;

Expand All @@ -276,7 +266,7 @@ export function GetBlobsTab({ data, timeRange, isLoading }: GetBlobsTabProps): J
return {
name: client,
data: sampledSlots.map(([slot, duration]) => [slot, duration]) as [number, number][],
color: clientColors[index % clientColors.length],
color: getExecutionClientColor(client, index),
};
});

Expand Down Expand Up @@ -350,7 +340,7 @@ export function GetBlobsTab({ data, timeRange, isLoading }: GetBlobsTabProps): J
return {
name: client,
data: dataPoints,
color: clientColors[index % clientColors.length],
color: getExecutionClientColor(client, index),
};
});

Expand All @@ -369,7 +359,7 @@ export function GetBlobsTab({ data, timeRange, isLoading }: GetBlobsTabProps): J
return {
name: client,
data: dataPoints,
color: clientColors[index % clientColors.length],
color: getExecutionClientColor(client, index),
};
});

Expand Down Expand Up @@ -423,7 +413,7 @@ export function GetBlobsTab({ data, timeRange, isLoading }: GetBlobsTabProps): J
return {
name: client,
data: dataPoints,
color: clientColors[index % clientColors.length],
color: getExecutionClientColor(client, index),
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MultiLineChart } from '@/components/Charts/MultiLine';
import { BarChart } from '@/components/Charts/Bar';
import { ScatterAndLineChart } from '@/components/Charts/ScatterAndLine';
import { useThemeColors } from '@/hooks/useThemeColors';
import { formatSlot } from '@/utils';
import { formatSlot, getExecutionClientColor } from '@/utils';
import type { EngineTimingsData } from '../../hooks/useEngineTimingsData';
import { PER_SLOT_CHART_RANGES, type TimeRange } from '../../IndexPage.types';
import { ClientVersionBreakdown } from '../ClientVersionBreakdown';
Expand Down Expand Up @@ -158,16 +158,6 @@ export function NewPayloadTab({ data, timeRange }: NewPayloadTabProps): JSX.Elem

const hasBlockComplexityData = clientGasData.size > 0;

// Shared color palette for client charts
const clientColors = [
themeColors.primary,
themeColors.success,
themeColors.warning,
themeColors.danger,
themeColors.accent,
themeColors.secondary,
];

// === EL Client Analysis ===
// Build a map of EL client -> metrics (VALID status only)
const elClientMetrics = new Map<
Expand Down Expand Up @@ -240,7 +230,7 @@ export function NewPayloadTab({ data, timeRange }: NewPayloadTabProps): JSX.Elem
return {
name: client,
data: sampledSlots.map(([slot, duration]) => [slot, duration] as [number, number]),
color: clientColors[index % clientColors.length],
color: getExecutionClientColor(client, index),
};
});

Expand Down Expand Up @@ -314,7 +304,7 @@ export function NewPayloadTab({ data, timeRange }: NewPayloadTabProps): JSX.Elem
return {
name: client,
data: dataPoints,
color: clientColors[index % clientColors.length],
color: getExecutionClientColor(client, index),
};
});

Expand All @@ -333,7 +323,7 @@ export function NewPayloadTab({ data, timeRange }: NewPayloadTabProps): JSX.Elem
return {
name: client,
data: dataPoints,
color: clientColors[index % clientColors.length],
color: getExecutionClientColor(client, index),
};
});

Expand Down Expand Up @@ -386,15 +376,15 @@ export function NewPayloadTab({ data, timeRange }: NewPayloadTabProps): JSX.Elem
return {
name: client,
data: dataPoints,
color: clientColors[index % clientColors.length],
color: getExecutionClientColor(client, index),
};
});

// Create scatter series for block complexity - using same client order for consistent colors
const blockComplexitySeries = elClientList.map((client, index) => ({
name: client,
data: clientGasData.get(client) ?? [],
color: clientColors[index % clientColors.length],
color: getExecutionClientColor(client, index),
symbolSize: 6,
}));

Expand Down
43 changes: 43 additions & 0 deletions src/utils/ethereum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,49 @@ export function truncateAddress(pubkey?: string, startChars = 6, endChars = 4):
*/
const EXECUTION_CLIENTS = ['geth', 'nethermind', 'besu', 'erigon', 'reth'] as const;

/**
* Official brand colors for Ethereum execution clients
*/
export const EXECUTION_CLIENT_COLORS: Record<string, string> = {
besu: '#1ba0a1',
nethermind: '#02bbec',
reth: '#f44f02',
geth: '#707d91',
'go-ethereum': '#707d91',
erigon: '#f5ad73',
};

/**
* Default fallback colors for unknown clients
*/
const FALLBACK_COLORS = [
'#6b7280', // gray-500
'#8b5cf6', // violet-500
'#ec4899', // pink-500
'#14b8a6', // teal-500
'#f97316', // orange-500
'#84cc16', // lime-500
];

/**
* Get the brand color for an execution client
*
* @param clientName - Name of the execution client (case-insensitive)
* @param fallbackIndex - Index for fallback color if client is unknown (cycles through fallback colors)
* @returns Hex color string
*
* @example
* ```tsx
* getExecutionClientColor('nethermind') // Returns '#02bbec'
* getExecutionClientColor('Reth') // Returns '#f44f02'
* getExecutionClientColor('unknown', 0) // Returns '#6b7280'
* ```
*/
export function getExecutionClientColor(clientName: string, fallbackIndex = 0): string {
const normalized = clientName.toLowerCase().trim();
return EXECUTION_CLIENT_COLORS[normalized] ?? FALLBACK_COLORS[fallbackIndex % FALLBACK_COLORS.length];
}

/**
* Parse execution client name from meta client name
* Extracts client name and version from strings like "Nethermind/v1.25.4"
Expand Down
Loading