Skip to content

Commit 15fb8b0

Browse files
authored
Merge pull request #364 from ethpandaops/feat/el-client-colours
refactor: replace inline client color arrays with centralized getExecutionClientColor utility
2 parents 33added + 0271be9 commit 15fb8b0

File tree

3 files changed

+54
-31
lines changed

3 files changed

+54
-31
lines changed

src/pages/ethereum/execution/timings/components/GetBlobsTab/GetBlobsTab.tsx

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { MultiLineChart } from '@/components/Charts/MultiLine';
77
import { BarChart } from '@/components/Charts/Bar';
88
import { LoadingContainer } from '@/components/Layout/LoadingContainer';
99
import { useThemeColors } from '@/hooks/useThemeColors';
10-
import { formatSlot } from '@/utils';
10+
import { formatSlot, getExecutionClientColor } from '@/utils';
1111
import type { EngineTimingsData } from '../../hooks/useEngineTimingsData';
1212
import { PER_SLOT_CHART_RANGES, type TimeRange } from '../../IndexPage.types';
1313
import { ClientVersionBreakdown } from '../ClientVersionBreakdown';
@@ -249,16 +249,6 @@ export function GetBlobsTab({ data, timeRange, isLoading }: GetBlobsTabProps): J
249249
clientSlotData.get(client)!.set(slot, duration);
250250
});
251251

252-
// Create series for the by-client chart
253-
const clientColors = [
254-
themeColors.primary,
255-
themeColors.success,
256-
themeColors.warning,
257-
themeColors.danger,
258-
themeColors.accent,
259-
themeColors.secondary,
260-
];
261-
262252
// Downsample to ~400 points max per series to keep chart performant
263253
const MAX_POINTS_PER_SERIES = 400;
264254

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

@@ -350,7 +340,7 @@ export function GetBlobsTab({ data, timeRange, isLoading }: GetBlobsTabProps): J
350340
return {
351341
name: client,
352342
data: dataPoints,
353-
color: clientColors[index % clientColors.length],
343+
color: getExecutionClientColor(client, index),
354344
};
355345
});
356346

@@ -369,7 +359,7 @@ export function GetBlobsTab({ data, timeRange, isLoading }: GetBlobsTabProps): J
369359
return {
370360
name: client,
371361
data: dataPoints,
372-
color: clientColors[index % clientColors.length],
362+
color: getExecutionClientColor(client, index),
373363
};
374364
});
375365

@@ -423,7 +413,7 @@ export function GetBlobsTab({ data, timeRange, isLoading }: GetBlobsTabProps): J
423413
return {
424414
name: client,
425415
data: dataPoints,
426-
color: clientColors[index % clientColors.length],
416+
color: getExecutionClientColor(client, index),
427417
};
428418
});
429419

src/pages/ethereum/execution/timings/components/NewPayloadTab/NewPayloadTab.tsx

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { MultiLineChart } from '@/components/Charts/MultiLine';
77
import { BarChart } from '@/components/Charts/Bar';
88
import { ScatterAndLineChart } from '@/components/Charts/ScatterAndLine';
99
import { useThemeColors } from '@/hooks/useThemeColors';
10-
import { formatSlot } from '@/utils';
10+
import { formatSlot, getExecutionClientColor } from '@/utils';
1111
import type { EngineTimingsData } from '../../hooks/useEngineTimingsData';
1212
import { PER_SLOT_CHART_RANGES, type TimeRange } from '../../IndexPage.types';
1313
import { ClientVersionBreakdown } from '../ClientVersionBreakdown';
@@ -158,16 +158,6 @@ export function NewPayloadTab({ data, timeRange }: NewPayloadTabProps): JSX.Elem
158158

159159
const hasBlockComplexityData = clientGasData.size > 0;
160160

161-
// Shared color palette for client charts
162-
const clientColors = [
163-
themeColors.primary,
164-
themeColors.success,
165-
themeColors.warning,
166-
themeColors.danger,
167-
themeColors.accent,
168-
themeColors.secondary,
169-
];
170-
171161
// === EL Client Analysis ===
172162
// Build a map of EL client -> metrics (VALID status only)
173163
const elClientMetrics = new Map<
@@ -240,7 +230,7 @@ export function NewPayloadTab({ data, timeRange }: NewPayloadTabProps): JSX.Elem
240230
return {
241231
name: client,
242232
data: sampledSlots.map(([slot, duration]) => [slot, duration] as [number, number]),
243-
color: clientColors[index % clientColors.length],
233+
color: getExecutionClientColor(client, index),
244234
};
245235
});
246236

@@ -314,7 +304,7 @@ export function NewPayloadTab({ data, timeRange }: NewPayloadTabProps): JSX.Elem
314304
return {
315305
name: client,
316306
data: dataPoints,
317-
color: clientColors[index % clientColors.length],
307+
color: getExecutionClientColor(client, index),
318308
};
319309
});
320310

@@ -333,7 +323,7 @@ export function NewPayloadTab({ data, timeRange }: NewPayloadTabProps): JSX.Elem
333323
return {
334324
name: client,
335325
data: dataPoints,
336-
color: clientColors[index % clientColors.length],
326+
color: getExecutionClientColor(client, index),
337327
};
338328
});
339329

@@ -386,15 +376,15 @@ export function NewPayloadTab({ data, timeRange }: NewPayloadTabProps): JSX.Elem
386376
return {
387377
name: client,
388378
data: dataPoints,
389-
color: clientColors[index % clientColors.length],
379+
color: getExecutionClientColor(client, index),
390380
};
391381
});
392382

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

src/utils/ethereum.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,49 @@ export function truncateAddress(pubkey?: string, startChars = 6, endChars = 4):
102102
*/
103103
const EXECUTION_CLIENTS = ['geth', 'nethermind', 'besu', 'erigon', 'reth'] as const;
104104

105+
/**
106+
* Official brand colors for Ethereum execution clients
107+
*/
108+
export const EXECUTION_CLIENT_COLORS: Record<string, string> = {
109+
besu: '#1ba0a1',
110+
nethermind: '#02bbec',
111+
reth: '#f44f02',
112+
geth: '#707d91',
113+
'go-ethereum': '#707d91',
114+
erigon: '#f5ad73',
115+
};
116+
117+
/**
118+
* Default fallback colors for unknown clients
119+
*/
120+
const FALLBACK_COLORS = [
121+
'#6b7280', // gray-500
122+
'#8b5cf6', // violet-500
123+
'#ec4899', // pink-500
124+
'#14b8a6', // teal-500
125+
'#f97316', // orange-500
126+
'#84cc16', // lime-500
127+
];
128+
129+
/**
130+
* Get the brand color for an execution client
131+
*
132+
* @param clientName - Name of the execution client (case-insensitive)
133+
* @param fallbackIndex - Index for fallback color if client is unknown (cycles through fallback colors)
134+
* @returns Hex color string
135+
*
136+
* @example
137+
* ```tsx
138+
* getExecutionClientColor('nethermind') // Returns '#02bbec'
139+
* getExecutionClientColor('Reth') // Returns '#f44f02'
140+
* getExecutionClientColor('unknown', 0) // Returns '#6b7280'
141+
* ```
142+
*/
143+
export function getExecutionClientColor(clientName: string, fallbackIndex = 0): string {
144+
const normalized = clientName.toLowerCase().trim();
145+
return EXECUTION_CLIENT_COLORS[normalized] ?? FALLBACK_COLORS[fallbackIndex % FALLBACK_COLORS.length];
146+
}
147+
105148
/**
106149
* Parse execution client name from meta client name
107150
* Extracts client name and version from strings like "Nethermind/v1.25.4"

0 commit comments

Comments
 (0)