From 802f7a8b0bc0f9f1b811c4db6d21b183ce19c253 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 2 Jul 2025 11:25:32 +0200 Subject: [PATCH 1/4] refactor: update terminology Replace `network` with `chain`, and `networks` with `chains`. This change aligns well with updates introduced in Ponder 0.11 version. --- apps/ensadmin/src/components/ensnode/hooks.ts | 18 +-- apps/ensadmin/src/components/ensnode/types.ts | 4 +- .../components/indexing-status/components.tsx | 140 +++++++++--------- .../src/components/indexing-status/utils.ts | 22 +-- .../indexing-status/view-models.test.ts | 26 ++-- .../components/indexing-status/view-models.ts | 74 +++++---- .../recent-registrations/components.tsx | 2 +- .../content/docs/docs/deploying/terraform.mdx | 2 +- packages/ponder-metadata/src/index.ts | 2 +- packages/ponder-metadata/src/middleware.ts | 30 ++-- packages/ponder-metadata/src/types/common.ts | 4 +- 11 files changed, 167 insertions(+), 157 deletions(-) diff --git a/apps/ensadmin/src/components/ensnode/hooks.ts b/apps/ensadmin/src/components/ensnode/hooks.ts index 39da6d357..09fccb1b4 100644 --- a/apps/ensadmin/src/components/ensnode/hooks.ts +++ b/apps/ensadmin/src/components/ensnode/hooks.ts @@ -57,23 +57,23 @@ export function useIndexingStatusQuery( * @throws Error if the response is invalid */ function validateResponse(response: EnsNode.Metadata) { - const { networkIndexingStatusByChainId } = response.runtime; + const { chainIndexingStatuses } = response.runtime; - if (typeof networkIndexingStatusByChainId === "undefined") { - throw new Error(`Network indexing status not found in the response.`); + if (typeof chainIndexingStatuses === "undefined") { + throw new Error(`Chain indexing status not found in the response.`); } - if (Object.keys(networkIndexingStatusByChainId).length === 0) { - throw new Error(`No network indexing status found response.`); + if (Object.keys(chainIndexingStatuses).length === 0) { + throw new Error(`No chain indexing status found response.`); } - const networksWithoutFirstBlockToIndex = Object.entries(networkIndexingStatusByChainId).filter( - ([, network]) => network.firstBlockToIndex === null, + const chainsWithoutFirstBlockToIndex = Object.entries(chainIndexingStatuses).filter( + ([, chain]) => chain.firstBlockToIndex === null, ); - if (networksWithoutFirstBlockToIndex.length > 0) { + if (chainsWithoutFirstBlockToIndex.length > 0) { throw new Error( - `Missing first block to index for some networks with the following chain IDs: ${networksWithoutFirstBlockToIndex + `Missing first block to index for some chains with the following chain IDs: ${chainsWithoutFirstBlockToIndex .map(([chainId]) => chainId) .join(", ")}`, ); diff --git a/apps/ensadmin/src/components/ensnode/types.ts b/apps/ensadmin/src/components/ensnode/types.ts index 172bf7b88..1db45f8f1 100644 --- a/apps/ensadmin/src/components/ensnode/types.ts +++ b/apps/ensadmin/src/components/ensnode/types.ts @@ -28,7 +28,7 @@ export namespace EnsNode { export type BlockInfo = PonderMetadata.BlockInfo; /** - * Network indexing status for a chain. + * Chain indexing status for a chain. */ - export type NetworkIndexingStatus = PonderMetadata.NetworkIndexingStatus; + export type ChainIndexingStatus = PonderMetadata.ChainIndexingStatus; } diff --git a/apps/ensadmin/src/components/indexing-status/components.tsx b/apps/ensadmin/src/components/indexing-status/components.tsx index af8b8e986..400ace4f4 100644 --- a/apps/ensadmin/src/components/indexing-status/components.tsx +++ b/apps/ensadmin/src/components/indexing-status/components.tsx @@ -14,9 +14,9 @@ import { Clock } from "lucide-react"; import { useSearchParams } from "next/navigation"; import { currentPhase, generateYearMarkers, getTimelinePosition } from "./utils"; import { + ChainIndexingPhaseViewModel, + ChainStatusViewModel, GlobalIndexingStatusViewModel, - NetworkIndexingPhaseViewModel, - NetworkStatusViewModel, ensNodeDepsViewModel, ensNodeEnvViewModel, ensRainbowViewModel, @@ -29,35 +29,35 @@ export function IndexingStatus() { return (
- + - +
); } -interface NetworkIndexingStatsProps { +interface ChainIndexingStatsProps { indexingStatus: ReturnType; } /** - * Component to display network indexing stats for each indexed blockchain network. + * Component to display chain indexing stats for each indexed blockchain chain. * @param props * @returns */ -function NetworkIndexingStats(props: NetworkIndexingStatsProps) { +function ChainIndexingStats(props: ChainIndexingStatsProps) { const { data, isLoading } = props.indexingStatus; if (isLoading) { - return ; + return ; } if (!data) { // propagate error to error boundary - throw new Error("No data available for network indexing stats"); + throw new Error("No data available for chain indexing stats"); } - const { networkIndexingStatusByChainId } = data.runtime; + const { chainIndexingStatuses } = data.runtime; const namespace = data.env.NAMESPACE; return ( @@ -70,44 +70,43 @@ function NetworkIndexingStats(props: NetworkIndexingStatsProps) { - {globalIndexingStatusViewModel( - networkIndexingStatusByChainId, - namespace, - ).networkStatuses.map((networkStatus) => ( - - ))} + {globalIndexingStatusViewModel(chainIndexingStatuses, namespace).chainStatuses.map( + (chainStatus) => ( + + ), + )} ); } -interface NetworkIndexingStatsCardProps { - network: NetworkStatusViewModel; +interface ChainIndexingStatsCardProps { + chainStatus: ChainStatusViewModel; } /** - * Component to display network indexing stats for a single network. + * Component to display chain indexing stats for a single chain. * @param props * @returns */ -function NetworkIndexingStatsCard(props: NetworkIndexingStatsCardProps) { - const { network } = props; +function ChainIndexingStatsCard(props: ChainIndexingStatsCardProps) { + const { chainStatus } = props; return ( - +
- {network.name} + {chainStatus.name}
- - + +
@@ -149,9 +148,9 @@ interface FallbackViewProps { } /** - * Component to display loading state for network indexing stats. + * Component to display loading state for chain indexing stats. */ -function NetworkIndexingStatsFallback(props: FallbackViewProps) { +function ChainIndexingStatsFallback(props: FallbackViewProps) { const { placeholderCount = 3 } = props; return ( @@ -160,7 +159,7 @@ function NetworkIndexingStatsFallback(props: FallbackViewProps) {
{Array.from(Array(placeholderCount).keys()).map((i) => ( - + ))}
@@ -169,9 +168,9 @@ function NetworkIndexingStatsFallback(props: FallbackViewProps) { } /** - * Component to display a placeholder for the network indexing stats. + * Component to display a placeholder for the chain indexing stats. */ -function NetworkIndexingStatsPlaceholder() { +function ChainIndexingStatsPlaceholder() { return ( @@ -187,21 +186,21 @@ function NetworkIndexingStatsPlaceholder() { ); } -interface NetworkIndexingTimelineProps { +interface ChainIndexingTimelineProps { /** ENSNode status query result */ indexingStatus: ReturnType; } /** - * Component to display network indexing timeline for each indexed blockchain network. + * Component to display chain indexing timeline for each indexed blockchain chain. */ -function NetworkIndexingTimeline(props: NetworkIndexingTimelineProps) { +function ChainIndexingTimeline(props: ChainIndexingTimelineProps) { const { indexingStatus } = props; const searchParams = useSearchParams(); const currentEnsNodeUrl = selectedEnsNodeUrl(searchParams); if (indexingStatus.isLoading) { - return ; + return ; } if (indexingStatus.error) { @@ -211,7 +210,7 @@ function NetworkIndexingTimeline(props: NetworkIndexingTimelineProps) { if (!indexingStatus.data) { // propagate error to error boundary - throw new Error("No data available for network indexing timeline"); + throw new Error("No data available for chain indexing timeline"); } const { data } = indexingStatus; @@ -281,10 +280,7 @@ function NetworkIndexingTimeline(props: NetworkIndexingTimelineProps) {
@@ -320,9 +316,9 @@ function InlineSummaryItem(props: InlineSummaryItemProps) { } /** - * Component to display loading state for the network indexing timeline. + * Component to display loading state for the chain indexing timeline. */ -function NetworkIndexingTimelineFallback(props: FallbackViewProps) { +function ChainIndexingTimelineFallback(props: FallbackViewProps) { const { placeholderCount = 3 } = props; return ( @@ -331,7 +327,7 @@ function NetworkIndexingTimelineFallback(props: FallbackViewProps) {
{Array.from(Array(placeholderCount).keys()).map((i) => ( - + ))}
@@ -340,9 +336,9 @@ function NetworkIndexingTimelineFallback(props: FallbackViewProps) { } /** - * Component to display a placeholder for the network indexing timeline. + * Component to display a placeholder for the chain indexing timeline. */ -function NetworkIndexingTimelinePlaceholder() { +function ChainIndexingTimelinePlaceholder() { return ( @@ -361,7 +357,7 @@ function NetworkIndexingTimelinePlaceholder() { interface TimelineProps extends GlobalIndexingStatusViewModel {} export function IndexingTimeline({ - networkStatuses, + chainStatuses, currentIndexingDate, indexingStartsAt, }: TimelineProps) { @@ -422,7 +418,7 @@ export function IndexingTimeline({ left: `${timelinePosition}%`, top: "0", bottom: "0", - height: `${networkStatuses.length * 60}px`, + height: `${chainStatuses.length * 60}px`, }} >
@@ -434,13 +430,13 @@ export function IndexingTimeline({
- {/* Network bars */} + {/* Chain indexing status: progress bars */}
- {networkStatuses.map((networkStatus) => ( - ( + @@ -467,33 +463,33 @@ export function IndexingTimeline({ ); } -interface NetworkIndexingStatusProps { +interface ChainIndexingStatusProps { currentIndexingDate: Date | null; timelineStart: Date; timelineEnd: Date; - networkStatus: NetworkStatusViewModel; + chainStatus: ChainStatusViewModel; } /** - * Component to display network indexing status for a single network. + * Component to display chain indexing status for a single chain. * Includes a timeline bar for each indexing phase. */ -function NetworkIndexingStatus(props: NetworkIndexingStatusProps) { - const { currentIndexingDate, networkStatus, timelineStart, timelineEnd } = props; - const currentIndexingPhase = currentPhase(currentIndexingDate, networkStatus); +function ChainIndexingStatus(props: ChainIndexingStatusProps) { + const { currentIndexingDate, chainStatus, timelineStart, timelineEnd } = props; + const currentIndexingPhase = currentPhase(currentIndexingDate, chainStatus); return ( -
- {/* Network label */} +
+ {/* Chain label */}
- {networkStatus.name} + {chainStatus.name}
- {/* Network timeline bar */} + {/* Chain timeline bar */}
- {networkStatus.phases.map((phase) => ( - ( + ))} - {/* Network start indicator */} + {/* Chain start indicator */}
- {intlFormat(networkStatus.firstBlockToIndex.date)} + {intlFormat(chainStatus.firstBlockToIndex.date)}
@@ -523,22 +519,22 @@ function NetworkIndexingStatus(props: NetworkIndexingStatusProps) { ); } -interface NetworkIndexingPhaseProps { - phase: NetworkIndexingPhaseViewModel; +interface ChainIndexingPhaseProps { + phase: ChainIndexingPhaseViewModel; isActive: boolean; timelineStart: Date; timelineEnd: Date; } /** - * Component to display a single indexing phase on the network indexing timeline. + * Component to display a single indexing phase on the chain indexing timeline. */ -function NetworkIndexingPhase({ +function ChainIndexingPhase({ phase, isActive, timelineStart, timelineEnd, -}: NetworkIndexingPhaseProps) { +}: ChainIndexingPhaseProps) { const isQueued = phase.state === "queued"; const isIndexing = phase.state === "indexing"; diff --git a/apps/ensadmin/src/components/indexing-status/utils.ts b/apps/ensadmin/src/components/indexing-status/utils.ts index 6901d0553..633739986 100644 --- a/apps/ensadmin/src/components/indexing-status/utils.ts +++ b/apps/ensadmin/src/components/indexing-status/utils.ts @@ -1,4 +1,4 @@ -import { NetworkIndexingPhaseViewModel, NetworkStatusViewModel } from "./view-models"; +import { ChainIndexingPhaseViewModel, ChainStatusViewModel } from "./view-models"; /** * Calculate the position of a date in a timeline. @@ -51,24 +51,24 @@ export function generateYearMarkers(timelineStart: Date, timelineEnd: Date): Arr } /** - * Get the current phase of the network indexing. + * Get the current phase of the chain indexing. * @param date current indexing date - * @param networkStatus view model + * @param chainStatus view model */ export function currentPhase( date: Date | null, - networkStatus: NetworkStatusViewModel, -): NetworkIndexingPhaseViewModel { - // if the network is not indexed yet, return the first phase + chainStatus: ChainStatusViewModel, +): ChainIndexingPhaseViewModel { + // if the chain is not indexed yet, return the first phase if (!date) { - return networkStatus.phases[0]; + return chainStatus.phases[0]; } - for (let i = networkStatus.phases.length - 1; i >= 0; i--) { - if (date >= networkStatus.phases[i].startDate) { - return networkStatus.phases[i]; + for (let i = chainStatus.phases.length - 1; i >= 0; i--) { + if (date >= chainStatus.phases[i].startDate) { + return chainStatus.phases[i]; } } - return networkStatus.phases[0]; + return chainStatus.phases[0]; } diff --git a/apps/ensadmin/src/components/indexing-status/view-models.test.ts b/apps/ensadmin/src/components/indexing-status/view-models.test.ts index 045b73f3f..480468a83 100644 --- a/apps/ensadmin/src/components/indexing-status/view-models.test.ts +++ b/apps/ensadmin/src/components/indexing-status/view-models.test.ts @@ -3,13 +3,13 @@ import { fromUnixTime } from "date-fns"; import { base, mainnet } from "viem/chains"; import { describe, expect, it } from "vitest"; import { + type ChainStatusViewModel, type GlobalIndexingStatusViewModel, - type NetworkStatusViewModel, blockViewModel, + chainIndexingStatusViewModel, ensNodeDepsViewModel, ensNodeEnvViewModel, globalIndexingStatusViewModel, - networkIndexingStatusViewModel, } from "./view-models"; describe("View Models", () => { @@ -45,14 +45,15 @@ describe("View Models", () => { describe("globalIndexingStatusViewModel", () => { it("should return the correct view model", () => { - const ensNodeNetworkStatus = testEnsNodeNetworkStatus(); + const ensNodeChainStatus = testEnsNodeChainStatus(); - const mainnetStatus = ensNodeNetworkStatus[mainnet.id]; - const baseStatus = ensNodeNetworkStatus[base.id]; + const mainnetStatus = ensNodeChainStatus[mainnet.id]; + const baseStatus = ensNodeChainStatus[base.id]; - expect(globalIndexingStatusViewModel(ensNodeNetworkStatus, "mainnet")).toEqual({ - networkStatuses: [ + expect(globalIndexingStatusViewModel(ensNodeChainStatus, "mainnet")).toEqual({ + chainStatuses: [ { + id: 1, name: "Ethereum", latestSafeBlock: blockViewModel(mainnetStatus.latestSafeBlock), firstBlockToIndex: blockViewModel(mainnetStatus.firstBlockToIndex), @@ -67,6 +68,7 @@ describe("View Models", () => { ], }, { + id: 8453, name: "Base", latestSafeBlock: blockViewModel(baseStatus.latestSafeBlock), firstBlockToIndex: blockViewModel(baseStatus.firstBlockToIndex), @@ -92,10 +94,11 @@ describe("View Models", () => { }); }); - describe("networkIndexingStatusViewModel", () => { + describe("chainIndexingStatusViewModel", () => { it("should return the correct view model", () => { expect( - networkIndexingStatusViewModel( + chainIndexingStatusViewModel( + base.id, `${base.name}`, { latestSafeBlock: { @@ -115,6 +118,7 @@ describe("View Models", () => { 1000, ), ).toEqual({ + id: 8453, name: "Base", latestSafeBlock: { number: 333, @@ -150,12 +154,12 @@ describe("View Models", () => { endDate: fromUnixTime(1501), }, ], - } satisfies NetworkStatusViewModel); + } satisfies ChainStatusViewModel); }); }); }); -function testEnsNodeNetworkStatus() { +function testEnsNodeChainStatus() { return { [mainnet.id]: { firstBlockToIndex: { diff --git a/apps/ensadmin/src/components/indexing-status/view-models.ts b/apps/ensadmin/src/components/indexing-status/view-models.ts index 9399bc313..7e0441112 100644 --- a/apps/ensadmin/src/components/indexing-status/view-models.ts +++ b/apps/ensadmin/src/components/indexing-status/view-models.ts @@ -9,69 +9,75 @@ export interface BlockInfoViewModel extends EnsNode.BlockInfo { get date(): Date; } -export interface NetworkIndexingPhaseViewModel { +export interface ChainIndexingPhaseViewModel { state: "queued" | "indexing"; startDate: Date; endDate: Date; } /** - * Network status view model, includes indexing phases. + * Chain status view model, includes indexing phases. */ -export interface NetworkStatusViewModel { +export interface ChainStatusViewModel { + id: number; name: string; firstBlockToIndex: BlockInfoViewModel; lastIndexedBlock: BlockInfoViewModel | null; lastSyncedBlock: BlockInfoViewModel | null; latestSafeBlock: BlockInfoViewModel; - phases: Array; + phases: Array; } /** - * Global indexing status view model, includes network status view models. + * Global indexing status view model, includes chain status view models. */ export interface GlobalIndexingStatusViewModel { - /** list of network status view models */ - networkStatuses: Array; + /** list of chain status view models */ + chainStatuses: Array; /** indexing starts at */ indexingStartsAt: Date; - /** latest indexed block date across all networks */ + /** latest indexed block date across all chains */ currentIndexingDate: Date | null; } /** - * View model for the global indexing status. Includes network status view models. + * View model for the global indexing status. Includes chain status view models. * - * @param networkIndexingStatus + * @param chainIndexingStatuses * @returns */ export function globalIndexingStatusViewModel( - networkIndexingStatus: Record, + chainIndexingStatuses: Record, namespace: ENSNamespaceId, ): GlobalIndexingStatusViewModel { - const indexingStartDatesAcrossNetworks = Object.values(networkIndexingStatus).map( + const indexingStartDatesAcrossChains = Object.values(chainIndexingStatuses).map( (status) => status.firstBlockToIndex.timestamp, ); - const firstBlockToIndexGloballyTimestamp = Math.min(...indexingStartDatesAcrossNetworks); + const firstBlockToIndexGloballyTimestamp = Math.min(...indexingStartDatesAcrossChains); const getChainName = (chainId: number) => getChainById(namespace, chainId).name; - const networkStatusesViewModel = Object.entries(networkIndexingStatus).map( - ([chainId, networkIndexingStatus]) => - networkIndexingStatusViewModel( - getChainName(parseInt(chainId, 10)), - networkIndexingStatus, + const chainStatusesViewModel = Object.entries(chainIndexingStatuses).map( + ([chainIdKey, chainIndexingStatus]) => { + // map string representation of chainId into a number + const chainId = parseInt(chainIdKey, 10); + + return chainIndexingStatusViewModel( + chainId, + getChainName(chainId), + chainIndexingStatus, firstBlockToIndexGloballyTimestamp, - ), - ) satisfies Array; + ); + }, + ) satisfies Array; - // Sort the network statuses by the first block to index timestamp - networkStatusesViewModel.sort( + // Sort the chain statuses by the first block to index timestamp + chainStatusesViewModel.sort( (a, b) => a.firstBlockToIndex.timestamp - b.firstBlockToIndex.timestamp, ); - const lastIndexedBlockDates = networkStatusesViewModel + const lastIndexedBlockDates = chainStatusesViewModel .filter((n) => Boolean(n.lastIndexedBlock)) .map((n) => n.lastIndexedBlock!.timestamp); @@ -79,27 +85,30 @@ export function globalIndexingStatusViewModel( lastIndexedBlockDates.length > 0 ? fromUnixTime(Math.max(...lastIndexedBlockDates)) : null; return { - networkStatuses: networkStatusesViewModel, + chainStatuses: chainStatusesViewModel, indexingStartsAt: fromUnixTime(firstBlockToIndexGloballyTimestamp), currentIndexingDate, }; } /** - * View model for the network indexing status. + * View model for the chain indexing status. + * + * @param chainId * @param chainName - * @param networkStatus + * @param chainStatus * @param firstBlockToIndexGloballyTimestamp * @returns */ -export function networkIndexingStatusViewModel( +export function chainIndexingStatusViewModel( + chainId: number, chainName: string, - networkStatus: EnsNode.NetworkIndexingStatus, + chainStatus: EnsNode.ChainIndexingStatus, firstBlockToIndexGloballyTimestamp: number, -): NetworkStatusViewModel { - const phases: NetworkStatusViewModel["phases"] = []; +): ChainStatusViewModel { + const phases: ChainStatusViewModel["phases"] = []; - const { lastIndexedBlock, lastSyncedBlock, latestSafeBlock, firstBlockToIndex } = networkStatus; + const { lastIndexedBlock, lastSyncedBlock, latestSafeBlock, firstBlockToIndex } = chainStatus; if (firstBlockToIndex.timestamp > firstBlockToIndexGloballyTimestamp) { phases.push({ @@ -116,13 +125,14 @@ export function networkIndexingStatusViewModel( }); return { + id: chainId, name: chainName, latestSafeBlock: blockViewModel(latestSafeBlock), firstBlockToIndex: blockViewModel(firstBlockToIndex), lastIndexedBlock: lastIndexedBlock ? blockViewModel(lastIndexedBlock) : null, lastSyncedBlock: lastSyncedBlock ? blockViewModel(lastSyncedBlock) : null, phases, - } satisfies NetworkStatusViewModel; + } satisfies ChainStatusViewModel; } /** diff --git a/apps/ensadmin/src/components/recent-registrations/components.tsx b/apps/ensadmin/src/components/recent-registrations/components.tsx index b84299bf4..c065a5f9c 100644 --- a/apps/ensadmin/src/components/recent-registrations/components.tsx +++ b/apps/ensadmin/src/components/recent-registrations/components.tsx @@ -49,7 +49,7 @@ export function RecentRegistrations() { // Get the current indexing date from the indexing status const currentIndexingDate = indexingStatus.data ? globalIndexingStatusViewModel( - indexingStatus.data.runtime.networkIndexingStatusByChainId, + indexingStatus.data.runtime.chainIndexingStatuses, indexingStatus.data.env.NAMESPACE, ).currentIndexingDate : null; diff --git a/docs/ensnode.io/src/content/docs/docs/deploying/terraform.mdx b/docs/ensnode.io/src/content/docs/docs/deploying/terraform.mdx index 0eca83f7f..6edde97db 100644 --- a/docs/ensnode.io/src/content/docs/docs/deploying/terraform.mdx +++ b/docs/ensnode.io/src/content/docs/docs/deploying/terraform.mdx @@ -24,7 +24,7 @@ These Terraform scripts are currently specific to ENSNode instances hosted by Na - [Terraform](https://www.terraform.io/downloads.html) installed - [Railway](https://railway.app/) account - Railway API token (generate from https://railway.com/account/tokens) -- RPC URLs for the networks you want to support (Mainnet, Sepolia, Holesky, Base, Linea) +- RPC URLs for the chains you want to support (Mainnet, Sepolia, Holesky, Base, Linea) - AWS account (for DNS management) - AWS S3 bucket defined inside AWS account - `ensnode-terraform` (for Terraform state) diff --git a/packages/ponder-metadata/src/index.ts b/packages/ponder-metadata/src/index.ts index 21deee37f..0c90a7c46 100644 --- a/packages/ponder-metadata/src/index.ts +++ b/packages/ponder-metadata/src/index.ts @@ -1,5 +1,5 @@ export { ponderMetadata, type MetadataMiddlewareResponse } from "./middleware"; export { queryPonderMeta, queryPonderStatus } from "./db-helpers"; export type { PonderMetadataMiddlewareResponse } from "./types/api"; -export type { BlockInfo, NetworkIndexingStatus } from "./types/common"; +export type { BlockInfo, ChainIndexingStatus } from "./types/common"; export { PrometheusMetrics } from "./prometheus-metrics"; diff --git a/packages/ponder-metadata/src/middleware.ts b/packages/ponder-metadata/src/middleware.ts index ea7fac0db..cd0c787ac 100644 --- a/packages/ponder-metadata/src/middleware.ts +++ b/packages/ponder-metadata/src/middleware.ts @@ -9,7 +9,7 @@ import type { PonderMetadataMiddlewareOptions, PonderMetadataMiddlewareResponse, } from "./types/api"; -import type { BlockInfo, NetworkIndexingStatus, PonderBlockStatus } from "./types/common"; +import type { BlockInfo, ChainIndexingStatus, PonderBlockStatus } from "./types/common"; /** * Ponder Metadata types definition. @@ -37,8 +37,8 @@ interface PonderMetadataModule { **/ codebaseBuildId: string; - /** Network indexing status by chain ID */ - networkIndexingStatusByChainId: Record; + /** Chain indexing statuses by chain ID */ + chainIndexingStatuses: { [chainId: number]: ChainIndexingStatus }; /** ENSRainbow version info */ ensRainbow?: EnsRainbow.VersionInfo; @@ -67,7 +67,7 @@ export function ponderMetadata< const ponderStatus = await queryPonderStatus(env.DATABASE_SCHEMA, db); const metrics = PrometheusMetrics.parse(await query.prometheusMetrics()); - const networkIndexingStatusByChainId: Record = {}; + const chainIndexingStatuses: Record = {}; for (const indexedChainId of indexedChainIds) { const publicClient = publicClients[indexedChainId]; @@ -132,22 +132,22 @@ export function ponderMetadata< } // mapping ponder status for current network - const ponderStatusForNetwork = ponderStatus.find( + const ponderStatusForChain = ponderStatus.find( (ponderStatusEntry) => ponderStatusEntry.network_name === network, ); // mapping last indexed block if available let lastIndexedBlock: BlockInfo | null = null; - if (ponderStatusForNetwork) { - lastIndexedBlock = ponderBlockInfoToBlockMetadata(ponderStatusForNetwork); + if (ponderStatusForChain) { + lastIndexedBlock = ponderBlockInfoToBlockMetadata(ponderStatusForChain); } - networkIndexingStatusByChainId[indexedChainId] = { + chainIndexingStatuses[indexedChainId] = { lastSyncedBlock, lastIndexedBlock, latestSafeBlock, firstBlockToIndex: await query.firstBlockToIndexByChainId(indexedChainId, publicClient), - } satisfies NetworkIndexingStatus; + } satisfies ChainIndexingStatus; } // mapping ponder app build id if available @@ -177,7 +177,7 @@ export function ponderMetadata< env, runtime: { codebaseBuildId: formatTextMetricValue(ponderAppBuildId), - networkIndexingStatusByChainId, + chainIndexingStatuses, ensRainbow: ensRainbowVersionInfo, }, } satisfies MetadataMiddlewareResponse; @@ -196,17 +196,17 @@ export function ponderMetadata< * @throws {HTTPException} if the response is in an invalid state */ function validateResponse(response: MetadataMiddlewareResponse): void { - const { networkIndexingStatusByChainId } = response.runtime; + const { chainIndexingStatuses } = response.runtime; - if (Object.keys(networkIndexingStatusByChainId).length === 0) { + if (Object.keys(chainIndexingStatuses).length === 0) { throw new HTTPException(500, { - message: "No network indexing status found", + message: "No chain indexing status found", }); } - if (Object.values(networkIndexingStatusByChainId).some((n) => n.firstBlockToIndex === null)) { + if (Object.values(chainIndexingStatuses).some((n) => n.firstBlockToIndex === null)) { throw new HTTPException(500, { - message: "Failed to fetch first block to index for some networks", + message: "Failed to fetch first block to index for some chains", }); } } diff --git a/packages/ponder-metadata/src/types/common.ts b/packages/ponder-metadata/src/types/common.ts index f38391237..fae400faa 100644 --- a/packages/ponder-metadata/src/types/common.ts +++ b/packages/ponder-metadata/src/types/common.ts @@ -21,9 +21,9 @@ export interface BlockInfo { } /** - * Network indexing status for a chain. + * Chain indexing status for a chain. */ -export interface NetworkIndexingStatus { +export interface ChainIndexingStatus { /** * First block required to be indexed during the historical sync. */ From e6206464405843d8e3ee0ce60322bcb321078064 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 2 Jul 2025 11:41:45 +0200 Subject: [PATCH 2/4] refactor(ponder-metadata): add `chainId` to `ChainIndexingStatus` type --- .../components/indexing-status/components.tsx | 14 ++++----- .../indexing-status/view-models.test.ts | 16 +++++----- .../components/indexing-status/view-models.ts | 31 +++++++------------ packages/ponder-metadata/src/middleware.ts | 1 + packages/ponder-metadata/src/types/common.ts | 3 ++ 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/apps/ensadmin/src/components/indexing-status/components.tsx b/apps/ensadmin/src/components/indexing-status/components.tsx index 400ace4f4..9ef6aefaa 100644 --- a/apps/ensadmin/src/components/indexing-status/components.tsx +++ b/apps/ensadmin/src/components/indexing-status/components.tsx @@ -72,7 +72,7 @@ function ChainIndexingStats(props: ChainIndexingStatsProps) { {globalIndexingStatusViewModel(chainIndexingStatuses, namespace).chainStatuses.map( (chainStatus) => ( - + ), )} @@ -94,11 +94,11 @@ function ChainIndexingStatsCard(props: ChainIndexingStatsCardProps) { const { chainStatus } = props; return ( - +
- {chainStatus.name} + {chainStatus.chainName}
@@ -434,7 +434,7 @@ export function IndexingTimeline({
{chainStatuses.map((chainStatus) => ( +
{/* Chain label */}
- {chainStatus.name} + {chainStatus.chainName}
{/* Chain timeline bar */}
{chainStatus.phases.map((phase) => ( { expect(globalIndexingStatusViewModel(ensNodeChainStatus, "mainnet")).toEqual({ chainStatuses: [ { - id: 1, - name: "Ethereum", + chainId: 1, + chainName: "Ethereum", latestSafeBlock: blockViewModel(mainnetStatus.latestSafeBlock), firstBlockToIndex: blockViewModel(mainnetStatus.firstBlockToIndex), lastIndexedBlock: blockViewModel(mainnetStatus.lastIndexedBlock), @@ -68,8 +68,8 @@ describe("View Models", () => { ], }, { - id: 8453, - name: "Base", + chainId: 8453, + chainName: "Base", latestSafeBlock: blockViewModel(baseStatus.latestSafeBlock), firstBlockToIndex: blockViewModel(baseStatus.firstBlockToIndex), lastIndexedBlock: null, @@ -98,9 +98,9 @@ describe("View Models", () => { it("should return the correct view model", () => { expect( chainIndexingStatusViewModel( - base.id, `${base.name}`, { + chainId: base.id, latestSafeBlock: { number: 333, timestamp: 1501, @@ -118,8 +118,8 @@ describe("View Models", () => { 1000, ), ).toEqual({ - id: 8453, - name: "Base", + chainId: 8453, + chainName: "Base", latestSafeBlock: { number: 333, timestamp: 1501, @@ -162,6 +162,7 @@ describe("View Models", () => { function testEnsNodeChainStatus() { return { [mainnet.id]: { + chainId: mainnet.id, firstBlockToIndex: { number: 17, timestamp: 1000, @@ -181,6 +182,7 @@ function testEnsNodeChainStatus() { }, [base.id]: { + chainId: base.id, firstBlockToIndex: { number: 222, timestamp: 1111, diff --git a/apps/ensadmin/src/components/indexing-status/view-models.ts b/apps/ensadmin/src/components/indexing-status/view-models.ts index 7e0441112..4d646df53 100644 --- a/apps/ensadmin/src/components/indexing-status/view-models.ts +++ b/apps/ensadmin/src/components/indexing-status/view-models.ts @@ -19,8 +19,8 @@ export interface ChainIndexingPhaseViewModel { * Chain status view model, includes indexing phases. */ export interface ChainStatusViewModel { - id: number; - name: string; + chainId: number; + chainName: string; firstBlockToIndex: BlockInfoViewModel; lastIndexedBlock: BlockInfoViewModel | null; lastSyncedBlock: BlockInfoViewModel | null; @@ -58,18 +58,12 @@ export function globalIndexingStatusViewModel( const firstBlockToIndexGloballyTimestamp = Math.min(...indexingStartDatesAcrossChains); const getChainName = (chainId: number) => getChainById(namespace, chainId).name; - const chainStatusesViewModel = Object.entries(chainIndexingStatuses).map( - ([chainIdKey, chainIndexingStatus]) => { - // map string representation of chainId into a number - const chainId = parseInt(chainIdKey, 10); - - return chainIndexingStatusViewModel( - chainId, - getChainName(chainId), - chainIndexingStatus, - firstBlockToIndexGloballyTimestamp, - ); - }, + const chainStatusesViewModel = Object.values(chainIndexingStatuses).map((chainIndexingStatus) => + chainIndexingStatusViewModel( + getChainName(chainIndexingStatus.chainId), + chainIndexingStatus, + firstBlockToIndexGloballyTimestamp, + ), ) satisfies Array; // Sort the chain statuses by the first block to index timestamp @@ -94,21 +88,20 @@ export function globalIndexingStatusViewModel( /** * View model for the chain indexing status. * - * @param chainId * @param chainName * @param chainStatus * @param firstBlockToIndexGloballyTimestamp * @returns */ export function chainIndexingStatusViewModel( - chainId: number, chainName: string, chainStatus: EnsNode.ChainIndexingStatus, firstBlockToIndexGloballyTimestamp: number, ): ChainStatusViewModel { const phases: ChainStatusViewModel["phases"] = []; - const { lastIndexedBlock, lastSyncedBlock, latestSafeBlock, firstBlockToIndex } = chainStatus; + const { lastIndexedBlock, lastSyncedBlock, latestSafeBlock, firstBlockToIndex, chainId } = + chainStatus; if (firstBlockToIndex.timestamp > firstBlockToIndexGloballyTimestamp) { phases.push({ @@ -125,8 +118,8 @@ export function chainIndexingStatusViewModel( }); return { - id: chainId, - name: chainName, + chainId, + chainName, latestSafeBlock: blockViewModel(latestSafeBlock), firstBlockToIndex: blockViewModel(firstBlockToIndex), lastIndexedBlock: lastIndexedBlock ? blockViewModel(lastIndexedBlock) : null, diff --git a/packages/ponder-metadata/src/middleware.ts b/packages/ponder-metadata/src/middleware.ts index cd0c787ac..d05fb2691 100644 --- a/packages/ponder-metadata/src/middleware.ts +++ b/packages/ponder-metadata/src/middleware.ts @@ -143,6 +143,7 @@ export function ponderMetadata< } chainIndexingStatuses[indexedChainId] = { + chainId: indexedChainId, lastSyncedBlock, lastIndexedBlock, latestSafeBlock, diff --git a/packages/ponder-metadata/src/types/common.ts b/packages/ponder-metadata/src/types/common.ts index fae400faa..ae200811a 100644 --- a/packages/ponder-metadata/src/types/common.ts +++ b/packages/ponder-metadata/src/types/common.ts @@ -24,6 +24,9 @@ export interface BlockInfo { * Chain indexing status for a chain. */ export interface ChainIndexingStatus { + /** Chain ID of the indexed chain */ + chainId: number; + /** * First block required to be indexed during the historical sync. */ From 687ca2e0160b163ae1f1ee52d18deb60365a5532 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 2 Jul 2025 11:47:54 +0200 Subject: [PATCH 3/4] docs(changeset): Updated terminology to replace `network` with `chain`. --- .changeset/tricky-keys-design.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tricky-keys-design.md diff --git a/.changeset/tricky-keys-design.md b/.changeset/tricky-keys-design.md new file mode 100644 index 000000000..d121f213c --- /dev/null +++ b/.changeset/tricky-keys-design.md @@ -0,0 +1,5 @@ +--- +"@ensnode/ponder-metadata": minor +--- + +Updated terminology to replace `network` with `chain`. From 8e69a678f990a97beda18ed9404ebdd4da670a5a Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 2 Jul 2025 13:07:20 +0200 Subject: [PATCH 4/4] apply pr feedback --- apps/ensadmin/src/components/ensnode/types.ts | 2 +- packages/ponder-metadata/src/types/common.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ensadmin/src/components/ensnode/types.ts b/apps/ensadmin/src/components/ensnode/types.ts index 1db45f8f1..9b470801d 100644 --- a/apps/ensadmin/src/components/ensnode/types.ts +++ b/apps/ensadmin/src/components/ensnode/types.ts @@ -28,7 +28,7 @@ export namespace EnsNode { export type BlockInfo = PonderMetadata.BlockInfo; /** - * Chain indexing status for a chain. + * Indexing status for a chain. */ export type ChainIndexingStatus = PonderMetadata.ChainIndexingStatus; } diff --git a/packages/ponder-metadata/src/types/common.ts b/packages/ponder-metadata/src/types/common.ts index ae200811a..95e0363e7 100644 --- a/packages/ponder-metadata/src/types/common.ts +++ b/packages/ponder-metadata/src/types/common.ts @@ -21,7 +21,7 @@ export interface BlockInfo { } /** - * Chain indexing status for a chain. + * Indexing status for a chain. */ export interface ChainIndexingStatus { /** Chain ID of the indexed chain */