Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4b065e5
Extract CrossChainIndexingStatus business-layer from generic types.ts…
tk-o Feb 11, 2026
752211c
Update import paths
tk-o Feb 11, 2026
8a091e9
Extract CrossChainIndexingStatus business-layer from generic helpers.…
tk-o Feb 11, 2026
3c30a97
Remove empty helpers.ts file
tk-o Feb 11, 2026
4babb45
Extract CrossChainIndexingStatus serialize-layer from generic seriali…
tk-o Feb 11, 2026
8e5500d
Update import paths
tk-o Feb 11, 2026
17d56b4
Extract CrossChainIndexingStatus serialize-layer from generic seriali…
tk-o Feb 11, 2026
ffd7b9d
Extract CrossChainIndexingStatus zod-schema-layer from generic zod-sc…
tk-o Feb 11, 2026
f3621c3
Extract CrossChainIndexingStatus deserialize-layer from generic deser…
tk-o Feb 11, 2026
a18df44
Update import paths
tk-o Feb 11, 2026
ac95ad7
Extract CrossChainIndexingStatus zod-schema-layer from generic valida…
tk-o Feb 11, 2026
79442e2
Extract RealtimeIndexingStatusProjection business-layer from generic …
tk-o Feb 11, 2026
4a25502
Extract RealtimeIndexingStatusProjection business-layer from generic …
tk-o Feb 11, 2026
b555191
Extract RealtimeIndexingStatusProjection serialize-layer from generic…
tk-o Feb 11, 2026
e05ac9c
Extract RealtimeIndexingStatusProjection serialize-layer from generic…
tk-o Feb 11, 2026
8cc84fd
Extract RealtimeIndexingStatusProjection zod-schema-layer from generi…
tk-o Feb 11, 2026
62010f7
Extract RealtimeIndexingStatusProjection zod-schema-layer from generi…
tk-o Feb 11, 2026
8466552
Extract RealtimeIndexingStatusProjection deserialize-layer from gener…
tk-o Feb 11, 2026
8c40bfa
Apply AI agent feedback
tk-o Feb 11, 2026
bf5bf94
Apply AI agent feedback
tk-o Feb 11, 2026
66ae12d
Apply AI agent feedback
tk-o Feb 11, 2026
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
@@ -1,6 +1,6 @@
import { z } from "zod/v4";

import { makeRealtimeIndexingStatusProjectionSchema } from "../../ensindexer/indexing-status/zod-schemas";
import { makeRealtimeIndexingStatusProjectionSchema } from "../../ensindexer/indexing-status/zod-schema/realtime-indexing-status-projection";
import {
type IndexingStatusResponse,
IndexingStatusResponseCodes,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import type { Duration, UnixTimestamp } from "../../shared/types";
import type {
ChainIndexingConfigTypeIds,
ChainIndexingStatusIds,
} from "./chain-indexing-status-snapshot";
import type { BlockRef, ChainId, UnixTimestamp } from "../../shared/types";
import { ChainIndexingStatusIds } from "./chain-indexing-status-snapshot";
import type { OmnichainIndexingStatusSnapshot } from "./omnichain-indexing-status-snapshot";

/**
Expand Down Expand Up @@ -95,32 +92,26 @@ export interface CrossChainIndexingStatusSnapshotOmnichain {
export type CrossChainIndexingStatusSnapshot = CrossChainIndexingStatusSnapshotOmnichain;

/**
* A "realtime" indexing status projection based on worst-case assumptions
* from the `snapshot`.
* Gets the latest indexed {@link BlockRef} for the given {@link ChainId}.
*
* Invariants:
* - `projectedAt` is always >= `snapshot.snapshotTime`.
* - `worstCaseDistance` is always equal to
* `projectedAt - snapshot.slowestChainIndexingCursor`.
* @returns the latest indexed {@link BlockRef} for the given {@link ChainId}, or null if the chain
* isn't being indexed at all or is queued and therefore hasn't started indexing yet.
*/
export type RealtimeIndexingStatusProjection = {
/**
* The timestamp representing "now" as of the time this projection was generated.
*/
projectedAt: UnixTimestamp;
export function getLatestIndexedBlockRef(
indexingStatus: CrossChainIndexingStatusSnapshot,
chainId: ChainId,
): BlockRef | null {
const chainIndexingStatus = indexingStatus.omnichainSnapshot.chains.get(chainId);

/**
* The distance between `projectedAt` and `snapshot.slowestChainIndexingCursor`.
*
* This is "worst-case" because it assumes all of the following:
* - the `snapshot` (which may have `snapshot.snapshotTime < projectedAt`) is still the
* latest snapshot and no indexing progress has been made since `snapshotTime`.
* - each indexed chain has added a new block as of `projectedAt`.
*/
worstCaseDistance: Duration;
if (chainIndexingStatus === undefined) {
// chain isn't being indexed at all
return null;
}

/**
* The {@link CrossChainIndexingStatusSnapshot} that this projection is based on.
*/
snapshot: CrossChainIndexingStatusSnapshot;
};
if (chainIndexingStatus.chainStatus === ChainIndexingStatusIds.Queued) {
// chain is queued, so no data for the chain has been indexed yet
return null;
}

return chainIndexingStatus.latestIndexedBlock;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { prettifyError } from "zod/v4";

import type { CrossChainIndexingStatusSnapshot } from "../cross-chain-indexing-status-snapshot";
import type { SerializedCrossChainIndexingStatusSnapshot } from "../serialize/cross-chain-indexing-status-snapshot";
import { makeCrossChainIndexingStatusSnapshotSchema } from "../zod-schema/cross-chain-indexing-status-snapshot";

/**
* Deserialize an {@link CrossChainIndexingStatusSnapshot} object.
*/
export function deserializeCrossChainIndexingStatusSnapshot(
maybeSnapshot: SerializedCrossChainIndexingStatusSnapshot,
valueLabel?: string,
): CrossChainIndexingStatusSnapshot {
const schema = makeCrossChainIndexingStatusSnapshotSchema(valueLabel);
const parsed = schema.safeParse(maybeSnapshot);

if (parsed.error) {
throw new Error(
`Cannot deserialize into CrossChainIndexingStatusSnapshot:\n${prettifyError(parsed.error)}\n`,
);
}

return parsed.data;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { prettifyError } from "zod/v4";

import type { RealtimeIndexingStatusProjection } from "../realtime-indexing-status-projection";
import type { SerializedRealtimeIndexingStatusProjection } from "../serialize/realtime-indexing-status-projection";
import { makeRealtimeIndexingStatusProjectionSchema } from "../zod-schema/realtime-indexing-status-projection";

/**
* Deserialize into a {@link RealtimeIndexingStatusProjection} object.
*/
export function deserializeRealtimeIndexingStatusProjection(
maybeProjection: SerializedRealtimeIndexingStatusProjection,
valueLabel?: string,
): RealtimeIndexingStatusProjection {
const schema = makeRealtimeIndexingStatusProjectionSchema(valueLabel);
const parsed = schema.safeParse(maybeProjection);

if (parsed.error) {
throw new Error(
`Cannot deserialize into RealtimeIndexingStatusProjection:\n${prettifyError(parsed.error)}\n`,
);
}

return parsed.data;
}
28 changes: 0 additions & 28 deletions packages/ensnode-sdk/src/ensindexer/indexing-status/helpers.ts

This file was deleted.

11 changes: 5 additions & 6 deletions packages/ensnode-sdk/src/ensindexer/indexing-status/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
export * from "./chain-indexing-status-snapshot";
export * from "./deserialize";
export * from "./cross-chain-indexing-status-snapshot";
export * from "./deserialize/chain-indexing-status-snapshot";
export * from "./deserialize/cross-chain-indexing-status-snapshot";
export * from "./deserialize/omnichain-indexing-status-snapshot";
export * from "./helpers";
export * from "./deserialize/realtime-indexing-status-projection";
export * from "./omnichain-indexing-status-snapshot";
export * from "./projection";
export * from "./serialize";
export * from "./realtime-indexing-status-projection";
export * from "./serialize/chain-indexing-status-snapshot";
export * from "./serialize/omnichain-indexing-status-snapshot";
export * from "./serialized-types";
export * from "./types";
export * from "./serialize/realtime-indexing-status-projection";
export * from "./validate/chain-indexing-status-snapshot";

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import {
ChainIndexingConfigTypeIds,
ChainIndexingStatusIds,
} from "./chain-indexing-status-snapshot";
import { deserializeCrossChainIndexingStatusSnapshot } from "./deserialize";
import { CrossChainIndexingStrategyIds } from "./cross-chain-indexing-status-snapshot";
import { deserializeCrossChainIndexingStatusSnapshot } from "./deserialize/cross-chain-indexing-status-snapshot";
import { OmnichainIndexingStatusIds } from "./omnichain-indexing-status-snapshot";
import { createRealtimeIndexingStatusProjection } from "./projection";
import { CrossChainIndexingStrategyIds, type RealtimeIndexingStatusProjection } from "./types";
import {
createRealtimeIndexingStatusProjection,
type RealtimeIndexingStatusProjection,
} from "./realtime-indexing-status-projection";

describe("Realtime Indexing Status Projection", () => {
it("can be created from existing omnichain snapshot", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type { Duration, UnixTimestamp } from "../../shared/types";
import type { CrossChainIndexingStatusSnapshot } from "./cross-chain-indexing-status-snapshot";

/**
* A "realtime" indexing status projection based on worst-case assumptions
* from the `snapshot`.
*
* Invariants:
* - `projectedAt` is always >= `snapshot.snapshotTime`.
* - `worstCaseDistance` is always equal to
* `projectedAt - snapshot.slowestChainIndexingCursor`.
*/
export type RealtimeIndexingStatusProjection = {
/**
* The timestamp representing "now" as of the time this projection was generated.
*/
projectedAt: UnixTimestamp;

/**
* The distance between `projectedAt` and `snapshot.slowestChainIndexingCursor`.
*
* This is "worst-case" because it assumes all of the following:
* - the `snapshot` (which may have `snapshot.snapshotTime < projectedAt`) is still the
* latest snapshot and no indexing progress has been made since `snapshotTime`.
* - each indexed chain has added a new block as of `projectedAt`.
*/
worstCaseDistance: Duration;

/**
* The {@link CrossChainIndexingStatusSnapshot} that this projection is based on.
*/
snapshot: CrossChainIndexingStatusSnapshot;
};

/**
* Create realtime indexing status projection from
* a {@link CrossChainIndexingStatusSnapshot}.
*/
export function createRealtimeIndexingStatusProjection(
snapshot: CrossChainIndexingStatusSnapshot,
now: UnixTimestamp,
): RealtimeIndexingStatusProjection {
/**
* The timestamp when the realtime indexing status was projected.
*
* Due to possible clock skew between different systems,
* if the "now" timestamp on the system generating this indexing status
* projection is less than the snapshot time, then this value must be set to
* equal to the whichever is higher between the `now` and
* the snapshot time to ensure all invariants are followed.
*/
const projectedAt = Math.max(now, snapshot.snapshotTime);

return {
projectedAt,
worstCaseDistance: projectedAt - snapshot.slowestChainIndexingCursor,
snapshot,
};
}

This file was deleted.

Loading
Loading