From c62872b7ed2f1a28cf57759500cc535a02075360 Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Mon, 2 Mar 2026 19:37:09 +0100
Subject: [PATCH 01/15] Make ENSRainbow SDK to re-use ENSNode SDK type for
`EnsRainbowPublicConfig`
Allows modifying ENSIndexer public config to include ENSRainbow public config.
---
packages/ensnode-sdk/src/ensrainbow/config.ts | 26 +++++++++++++++++++
packages/ensnode-sdk/src/ensrainbow/index.ts | 1 +
packages/ensrainbow-sdk/src/client.ts | 20 ++------------
3 files changed, 29 insertions(+), 18 deletions(-)
create mode 100644 packages/ensnode-sdk/src/ensrainbow/config.ts
diff --git a/packages/ensnode-sdk/src/ensrainbow/config.ts b/packages/ensnode-sdk/src/ensrainbow/config.ts
new file mode 100644
index 000000000..d5f141c59
--- /dev/null
+++ b/packages/ensnode-sdk/src/ensrainbow/config.ts
@@ -0,0 +1,26 @@
+import type { EnsRainbowServerLabelSet } from "./types";
+
+/**
+ * Complete public configuration object for ENSRainbow.
+ *
+ * Contains all public configuration information about the ENSRainbow service instance,
+ * including version, label set information, and record counts.
+ */
+export interface EnsRainbowPublicConfig {
+ /**
+ * ENSRainbow service version
+ *
+ * @see https://ghcr.io/namehash/ensnode/ensrainbow
+ */
+ version: string;
+
+ /**
+ * The label set reference managed by the ENSRainbow server.
+ */
+ labelSet: EnsRainbowServerLabelSet;
+
+ /**
+ * The total count of records managed by the ENSRainbow service.
+ */
+ recordsCount: number;
+}
diff --git a/packages/ensnode-sdk/src/ensrainbow/index.ts b/packages/ensnode-sdk/src/ensrainbow/index.ts
index eea524d65..b4fb84ab2 100644
--- a/packages/ensnode-sdk/src/ensrainbow/index.ts
+++ b/packages/ensnode-sdk/src/ensrainbow/index.ts
@@ -1 +1,2 @@
+export * from "./config";
export * from "./types";
diff --git a/packages/ensrainbow-sdk/src/client.ts b/packages/ensrainbow-sdk/src/client.ts
index 3a81a5dc5..5f8fe0d87 100644
--- a/packages/ensrainbow-sdk/src/client.ts
+++ b/packages/ensrainbow-sdk/src/client.ts
@@ -3,6 +3,7 @@ import {
type Cache,
type EncodedLabelHash,
type EnsRainbowClientLabelSet,
+ type EnsRainbowPublicConfig,
type EnsRainbowServerLabelSet,
type Label,
type LabelHash,
@@ -168,24 +169,7 @@ export namespace EnsRainbow {
* Contains all public configuration information about the ENSRainbow service instance,
* including version, label set information, and record counts.
*/
- export interface ENSRainbowPublicConfig {
- /**
- * ENSRainbow service version
- *
- * @see https://ghcr.io/namehash/ensnode/ensrainbow
- */
- version: string;
-
- /**
- * The label set reference managed by the ENSRainbow server.
- */
- labelSet: EnsRainbowServerLabelSet;
-
- /**
- * The total count of records managed by the ENSRainbow service.
- */
- recordsCount: number;
- }
+ export type ENSRainbowPublicConfig = EnsRainbowPublicConfig;
}
export interface EnsRainbowApiClientOptions {
From f16dfa12671d462119f5b6db401e9e89ac8cdeda Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Mon, 2 Mar 2026 19:41:39 +0100
Subject: [PATCH 02/15] Move ENSRainbow schemas to ENSRainbow module
---
.../src/ensindexer/config/zod-schemas.ts | 49 +++++-------------
.../src/ensrainbow/zod-schemas/config.ts | 50 +++++++++++++++++++
2 files changed, 63 insertions(+), 36 deletions(-)
create mode 100644 packages/ensnode-sdk/src/ensrainbow/zod-schemas/config.ts
diff --git a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
index 5f221d558..8e2e2772f 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
@@ -8,12 +8,15 @@
*/
import { z } from "zod/v4";
+import {
+ makeLabelSetIdSchema,
+ makeLabelSetVersionSchema,
+} from "../../ensrainbow/zod-schemas/config";
import { uniq } from "../../shared/collections";
import {
makeChainIdSchema,
makeENSNamespaceIdSchema,
makeNonNegativeIntegerSchema,
- makePositiveIntegerSchema,
} from "../../shared/zod-schemas";
import type { ZodCheckFnInput } from "../../shared/zod-types";
import { isSubgraphCompatible } from "./is-subgraph-compatible";
@@ -69,38 +72,6 @@ export const makeDatabaseSchemaNameSchema = (valueLabel: string = "Database sche
error: `${valueLabel} is required and must be a non-empty string.`,
});
-/**
- * Makes a schema for parsing a label set ID.
- *
- * The label set ID is guaranteed to be a string between 1-50 characters
- * containing only lowercase letters (a-z) and hyphens (-).
- *
- * @param valueLabel - The label to use in error messages (e.g., "Label set ID", "LABEL_SET_ID")
- */
-export const makeLabelSetIdSchema = (valueLabel: string) => {
- return z
- .string({ error: `${valueLabel} must be a string` })
- .min(1, { error: `${valueLabel} must be 1-50 characters long` })
- .max(50, { error: `${valueLabel} must be 1-50 characters long` })
- .regex(/^[a-z-]+$/, {
- error: `${valueLabel} can only contain lowercase letters (a-z) and hyphens (-)`,
- });
-};
-
-/**
- * Makes a schema for parsing a label set version.
- *
- * The label set version is guaranteed to be a non-negative integer.
- *
- * @param valueLabel - The label to use in error messages (e.g., "Label set version", "LABEL_SET_VERSION")
-
- */
-export const makeLabelSetVersionSchema = (valueLabel: string) => {
- return z.coerce
- .number({ error: `${valueLabel} must be an integer.` })
- .pipe(makeNonNegativeIntegerSchema(valueLabel));
-};
-
/**
* Makes a schema for parsing a label set where both label set ID and label set version are required.
*
@@ -127,15 +98,21 @@ const makeNonEmptyStringSchema = (valueLabel: string = "Value") =>
export const makeEnsIndexerVersionInfoSchema = (valueLabel: string = "Value") =>
z
- .strictObject(
+ .object(
{
nodejs: makeNonEmptyStringSchema(),
ponder: makeNonEmptyStringSchema(),
ensDb: makeNonEmptyStringSchema(),
ensIndexer: makeNonEmptyStringSchema(),
ensNormalize: makeNonEmptyStringSchema(),
- ensRainbow: makeNonEmptyStringSchema(),
- ensRainbowSchema: makePositiveIntegerSchema(),
+ ensRainbowPublicConfig: z.object({
+ version: makeNonEmptyStringSchema(),
+ labelSet: z.object({
+ labelSetId: makeLabelSetIdSchema(),
+ highestLabelSetVersion: makeLabelSetVersionSchema(),
+ }),
+ recordsCount: makeNonNegativeIntegerSchema(),
+ }),
},
{
error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`,
diff --git a/packages/ensnode-sdk/src/ensrainbow/zod-schemas/config.ts b/packages/ensnode-sdk/src/ensrainbow/zod-schemas/config.ts
new file mode 100644
index 000000000..a0744a10e
--- /dev/null
+++ b/packages/ensnode-sdk/src/ensrainbow/zod-schemas/config.ts
@@ -0,0 +1,50 @@
+import { z } from "zod/v4";
+
+import { makeNonNegativeIntegerSchema } from "../../shared/zod-schemas";
+
+/**
+ * Makes a schema for parsing a label set ID.
+ *
+ * The label set ID is guaranteed to be a string between 1-50 characters
+ * containing only lowercase letters (a-z) and hyphens (-).
+ *
+ * @param valueLabel - The label to use in error messages (e.g., "Label set ID", "LABEL_SET_ID")
+ */
+export const makeLabelSetIdSchema = (valueLabel?: string) => {
+ return z
+ .string({ error: `${valueLabel} must be a string` })
+ .min(1, { error: `${valueLabel} must be 1-50 characters long` })
+ .max(50, { error: `${valueLabel} must be 1-50 characters long` })
+ .regex(/^[a-z-]+$/, {
+ error: `${valueLabel} can only contain lowercase letters (a-z) and hyphens (-)`,
+ });
+};
+
+/**
+ * Makes a schema for parsing a label set version.
+ *
+ * The label set version is guaranteed to be a non-negative integer.
+ *
+ * @param valueLabel - The label to use in error messages (e.g., "Label set version", "LABEL_SET_VERSION")
+
+ */
+export const makeLabelSetVersionSchema = (valueLabel?: string) => {
+ return z.coerce
+ .number({ error: `${valueLabel} must be an integer.` })
+ .pipe(makeNonNegativeIntegerSchema(valueLabel));
+};
+
+/**
+ * Makes a schema for parsing the EnsRainbowPublicConfig object.
+ */
+export const makeEnsRainbowPublicConfigSchema = (valueLabel: string = "EnsRainbowPublicConfig") =>
+ z.object({
+ version: z.string().nonempty({ error: `${valueLabel}.version must be a non-empty string.` }),
+ labelSet: z.object({
+ labelSetId: makeLabelSetIdSchema(`${valueLabel}.labelSet.labelSetId`),
+ highestLabelSetVersion: makeLabelSetVersionSchema(
+ `${valueLabel}.labelSet.highestLabelSetVersion`,
+ ),
+ }),
+ recordsCount: makeNonNegativeIntegerSchema(`${valueLabel}.recordsCount`),
+ });
From ea1f7c3072d932529acefefbb22fbc001dd788fe Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Mon, 2 Mar 2026 19:42:41 +0100
Subject: [PATCH 03/15] Update ENSNode SDK to use updated
`EnsIndexerPublicConfig` data model
Includes `ensRainbowPublicConfig: EnsRainbowPublicConfig` field.
---
.../ensnode-sdk/src/ensapi/client.test.ts | 7 ++-
.../src/ensapi/config/conversions.test.ts | 14 ++++--
.../ensnode-sdk/src/ensindexer/client.mock.ts | 10 +++-
.../src/ensindexer/config/conversions.test.ts | 14 ++++--
.../src/ensindexer/config/labelset-utils.ts | 5 +-
.../src/ensindexer/config/types.ts | 15 ++----
.../src/ensindexer/config/zod-schemas.test.ts | 49 ++++++++++++++-----
7 files changed, 79 insertions(+), 35 deletions(-)
diff --git a/packages/ensnode-sdk/src/ensapi/client.test.ts b/packages/ensnode-sdk/src/ensapi/client.test.ts
index 1c3c6dedc..88baf4fbd 100644
--- a/packages/ensnode-sdk/src/ensapi/client.test.ts
+++ b/packages/ensnode-sdk/src/ensapi/client.test.ts
@@ -86,8 +86,11 @@ const EXAMPLE_CONFIG_RESPONSE = {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbow: "0.31.0",
- ensRainbowSchema: 2,
+ ensRainbowPublicConfig: {
+ version: "0.31.0",
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
},
},
} satisfies SerializedEnsApiPublicConfig;
diff --git a/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts b/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts
index fb424aa60..44884ccbb 100644
--- a/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts
+++ b/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts
@@ -23,8 +23,11 @@ const MOCK_ENSAPI_PUBLIC_CONFIG = {
versionInfo: {
ensDb: "0.36.0",
ensIndexer: "0.36.0",
- ensRainbow: "0.36.0",
- ensRainbowSchema: 1,
+ ensRainbowPublicConfig: {
+ version: "0.36.0",
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
ensNormalize: "1.1.1",
nodejs: "20.0.0",
ponder: "0.5.0",
@@ -55,8 +58,11 @@ describe("ENSApi Config Serialization/Deserialization", () => {
versionInfo: {
ensDb: "0.36.0",
ensIndexer: "0.36.0",
- ensRainbow: "0.36.0",
- ensRainbowSchema: 1,
+ ensRainbowPublicConfig: {
+ version: "0.36.0",
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
ensNormalize: "1.1.1",
nodejs: "20.0.0",
ponder: "0.5.0",
diff --git a/packages/ensnode-sdk/src/ensindexer/client.mock.ts b/packages/ensnode-sdk/src/ensindexer/client.mock.ts
index 5676b7723..f7fffb84a 100644
--- a/packages/ensnode-sdk/src/ensindexer/client.mock.ts
+++ b/packages/ensnode-sdk/src/ensindexer/client.mock.ts
@@ -30,8 +30,14 @@ export const configResponseMock = {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbow: "0.31.0",
- ensRainbowSchema: 2,
+ ensRainbowPublicConfig: {
+ version: "0.31.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
},
} satisfies SerializedEnsIndexerConfigResponse;
diff --git a/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts b/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts
index 298dbfbd0..ae23548ff 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts
@@ -25,8 +25,11 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbow: "0.32.0",
- ensRainbowSchema: 2,
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
},
} satisfies EnsIndexerPublicConfig;
@@ -65,8 +68,11 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbow: "0.32.0",
- ensRainbowSchema: 2,
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
},
} satisfies SerializedEnsIndexerPublicConfig;
diff --git a/packages/ensnode-sdk/src/ensindexer/config/labelset-utils.ts b/packages/ensnode-sdk/src/ensindexer/config/labelset-utils.ts
index 01ab16613..5661d211c 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/labelset-utils.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/labelset-utils.ts
@@ -4,7 +4,10 @@ import type {
LabelSetId,
LabelSetVersion,
} from "../../ensrainbow";
-import { makeLabelSetIdSchema, makeLabelSetVersionSchema } from "./zod-schemas";
+import {
+ makeLabelSetIdSchema,
+ makeLabelSetVersionSchema,
+} from "../../ensrainbow/zod-schemas/config";
/**
* Builds a valid LabelSetId from a string.
diff --git a/packages/ensnode-sdk/src/ensindexer/config/types.ts b/packages/ensnode-sdk/src/ensindexer/config/types.ts
index f3067937d..1b4d71e41 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/types.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/types.ts
@@ -1,6 +1,6 @@
import type { ENSNamespaceId } from "@ensnode/datasources";
-import type { EnsRainbowClientLabelSet } from "../../ensrainbow";
+import type { EnsRainbowClientLabelSet, EnsRainbowPublicConfig } from "../../ensrainbow";
import type { ChainId } from "../../shared/types";
/**
@@ -51,16 +51,9 @@ export interface EnsIndexerVersionInfo {
ensIndexer: string;
/**
- * ENSRainbow service version
- *
- * @see https://ghcr.io/namehash/ensnode/ensindexer
- **/
- ensRainbow: string;
-
- /**
- * ENSRainbow schema version
- **/
- ensRainbowSchema: number;
+ * ENSRainbow public config
+ */
+ ensRainbowPublicConfig: EnsRainbowPublicConfig;
/**
* ENS Normalize package version
diff --git a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
index 60bc78860..ad433e32a 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
@@ -110,8 +110,14 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbow: "0.32.0",
- ensRainbowSchema: 2,
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
} satisfies EnsIndexerVersionInfo),
).toStrictEqual({
nodejs: "v22.22.22",
@@ -119,8 +125,14 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbow: "0.32.0",
- ensRainbowSchema: 2,
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
} satisfies EnsIndexerVersionInfo);
expect(
@@ -131,8 +143,11 @@ describe("ENSIndexer: Config", () => {
ensDb: "",
ensIndexer: "",
ensNormalize: "",
- ensRainbow: "",
- ensRainbowSchema: -1,
+ ensRainbowPublicConfig: {
+ version: "",
+ labelSet: { labelSetId: "", highestLabelSetVersion: -1 },
+ recordsCount: -1,
+ },
} satisfies EnsIndexerVersionInfo),
),
).toStrictEqual(`✖ Value must be a non-empty string.
@@ -146,9 +161,15 @@ describe("ENSIndexer: Config", () => {
✖ Value must be a non-empty string.
→ at ensNormalize
✖ Value must be a non-empty string.
- → at ensRainbow
-✖ Value must be a positive integer (>0).
- → at ensRainbowSchema`);
+ → at ensRainbowPublicConfig.version
+✖ Value must be a non-negative integer (>=0).
+ → at ensRainbowPublicConfig.recordsCount
+✖ undefined must be 1-50 characters long
+ → at ensRainbowPublicConfig.labelSet.labelSetId
+✖ undefined can only contain lowercase letters (a-z) and hyphens (-)
+ → at ensRainbowPublicConfig.labelSet.labelSetId
+✖ Value must be a non-negative integer (>=0).
+ → at ensRainbowPublicConfig.labelSet.highestLabelSetVersion`);
});
it("can parse full ENSIndexerPublicConfig with label set", () => {
@@ -168,8 +189,14 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbow: "0.32.0",
- ensRainbowSchema: 2,
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
},
} satisfies SerializedEnsIndexerPublicConfig;
From bc516d103eb51d12592b2f3512cd2ac70baf5fa8 Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Mon, 2 Mar 2026 19:43:46 +0100
Subject: [PATCH 04/15] Make ENSIndexer to fetch ENSRainbow public config into
its own pulic config object
---
apps/ensindexer/src/lib/version-info.ts | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/apps/ensindexer/src/lib/version-info.ts b/apps/ensindexer/src/lib/version-info.ts
index aa1efb8d7..30c9624c6 100644
--- a/apps/ensindexer/src/lib/version-info.ts
+++ b/apps/ensindexer/src/lib/version-info.ts
@@ -110,10 +110,7 @@ function getPackageVersionFromPnpmStore(pnpmDir: string, packageName: string): s
*/
export async function getENSIndexerVersionInfo(): Promise {
const ensRainbowApiClient = getENSRainbowApiClient();
- const { versionInfo: ensRainbowVersionInfo } = await ensRainbowApiClient.version();
-
- // ENSRainbow version (fetched dynamically from the connected ENSRainbow service instance)
- const ensRainbowSchema = ensRainbowVersionInfo.dbSchemaVersion;
+ const ensRainbowPublicConfig = await ensRainbowApiClient.config();
// ENSIndexer version
const ensIndexerVersion = packageJson.version;
@@ -125,13 +122,12 @@ export async function getENSIndexerVersionInfo(): Promise
// parse unvalidated version info
const schema = makeENSIndexerVersionInfoSchema();
const parsed = schema.safeParse({
- ensRainbow: ensRainbowVersionInfo.version,
+ ensRainbowPublicConfig,
nodejs: process.versions.node,
ponder: getPackageVersion("ponder"),
ensDb: ensDbVersion,
ensIndexer: ensIndexerVersion,
ensNormalize: getPackageVersion("@adraffy/ens-normalize"),
- ensRainbowSchema,
} satisfies SerializedENSIndexerVersionInfo);
if (parsed.error) {
From ed0095c711d78558e99ad5309a722cfa143edb85 Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Mon, 2 Mar 2026 19:44:27 +0100
Subject: [PATCH 05/15] Update ENSApi to reference changed ENSIndexer config
data model
---
apps/ensapi/src/config/config.schema.test.ts | 7 +++++--
apps/ensapi/src/config/validations.ts | 8 ++++----
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/apps/ensapi/src/config/config.schema.test.ts b/apps/ensapi/src/config/config.schema.test.ts
index f0905c285..6c5d0348f 100644
--- a/apps/ensapi/src/config/config.schema.test.ts
+++ b/apps/ensapi/src/config/config.schema.test.ts
@@ -39,8 +39,11 @@ const ENSINDEXER_PUBLIC_CONFIG = {
versionInfo: {
ensDb: packageJson.version,
ensIndexer: packageJson.version,
- ensRainbow: packageJson.version,
- ensRainbowSchema: 1,
+ ensRainbowPublicConfig: {
+ version: packageJson.version,
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
ensNormalize: "1.1.1",
nodejs: "1.1.1",
ponder: "1.1.1",
diff --git a/apps/ensapi/src/config/validations.ts b/apps/ensapi/src/config/validations.ts
index 2b06e1e3e..62913bdb1 100644
--- a/apps/ensapi/src/config/validations.ts
+++ b/apps/ensapi/src/config/validations.ts
@@ -34,12 +34,12 @@ export function invariant_ensIndexerPublicConfigVersionInfo(
}
// Invariant: ENSApi & ENSRainbow must match version numbers
- if (ensIndexerPublicConfig.versionInfo.ensRainbow !== packageJson.version) {
+ if (ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version !== packageJson.version) {
ctx.issues.push({
code: "custom",
- path: ["ensIndexerPublicConfig.versionInfo.ensRainbow"],
- input: ensIndexerPublicConfig.versionInfo.ensRainbow,
- message: `Version Mismatch: ENSRainbow@${ensIndexerPublicConfig.versionInfo.ensRainbow} !== ENSApi@${packageJson.version}`,
+ path: ["ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version"],
+ input: ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version,
+ message: `Version Mismatch: ENSRainbow@${ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version} !== ENSApi@${packageJson.version}`,
});
}
}
From 4ff67430a739bd5edc4e0867bc02c494601dcd12 Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Mon, 2 Mar 2026 19:44:40 +0100
Subject: [PATCH 06/15] Update docs to reference changed ENSIndexer config data
model
---
docs/ensnode.io/src/content/docs/docs/usage/api.mdx | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/docs/ensnode.io/src/content/docs/docs/usage/api.mdx b/docs/ensnode.io/src/content/docs/docs/usage/api.mdx
index 52196100c..ddd1ac0b5 100644
--- a/docs/ensnode.io/src/content/docs/docs/usage/api.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/usage/api.mdx
@@ -118,12 +118,15 @@ The response includes several important configuration categories:
],
"versionInfo": {
"nodejs": "22.18.0",
- "ponder": "0.11.43",
- "ensDb": "0.35.0",
- "ensIndexer": "0.35.0",
+ "ponder": "0.16.1",
+ "ensDb": "1.5.1",
+ "ensIndexer": "1.5.1",
"ensNormalize": "1.11.1",
- "ensRainbow": "0.34.0",
- "ensRainbowSchema": 3
+ "ensRainbowPublicConfig": {
+ "version": "1.5.1",
+ "labelSet": { "labelSetId": "subgraph", "highestLabelSetVersion": 0 },
+ "recordsCount": 100
+ }
}
}
```
From 04336fb271501583b46df007cea30e65eda53f88 Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Mon, 2 Mar 2026 19:45:05 +0100
Subject: [PATCH 07/15] Update ENSAdmin to reference changed ENSIndexer config
data model
---
apps/ensadmin/src/app/mock/config-api.mock.ts | 10 +++-
.../src/app/mock/config-info/data.json | 50 +++++++++++++++----
.../connection/cards/ensnode-info.tsx | 30 +++++++++--
3 files changed, 74 insertions(+), 16 deletions(-)
diff --git a/apps/ensadmin/src/app/mock/config-api.mock.ts b/apps/ensadmin/src/app/mock/config-api.mock.ts
index 8edbde34c..9893115ed 100644
--- a/apps/ensadmin/src/app/mock/config-api.mock.ts
+++ b/apps/ensadmin/src/app/mock/config-api.mock.ts
@@ -23,8 +23,14 @@ export const ensIndexerPublicConfig = deserializeENSIndexerPublicConfig({
ponder: "0.11.43",
ensIndexer: "0.35.0",
ensDb: "0.35.0",
- ensRainbow: "0.34.0",
- ensRainbowSchema: 3,
+ ensRainbowPublicConfig: {
+ version: "0.34.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
ensNormalize: "1.11.1",
},
});
diff --git a/apps/ensadmin/src/app/mock/config-info/data.json b/apps/ensadmin/src/app/mock/config-info/data.json
index f8d9f90fb..1f97daa8f 100644
--- a/apps/ensadmin/src/app/mock/config-info/data.json
+++ b/apps/ensadmin/src/app/mock/config-info/data.json
@@ -29,8 +29,14 @@
"ensDb": "0.35.0",
"ensIndexer": "0.35.0",
"ensNormalize": "1.11.1",
- "ensRainbow": "0.34.0",
- "ensRainbowSchema": 3
+ "ensRainbowPublicConfig": {
+ "version": "0.34.0",
+ "labelSet": {
+ "labelSetId": "subgraph",
+ "highestLabelSetVersion": 0
+ },
+ "recordsCount": 100
+ }
}
}
},
@@ -51,8 +57,14 @@
"ensDb": "0.35.0",
"ensIndexer": "0.35.0",
"ensNormalize": "1.11.1",
- "ensRainbow": "0.34.0",
- "ensRainbowSchema": 3
+ "ensRainbowPublicConfig": {
+ "version": "0.34.0",
+ "labelSet": {
+ "labelSetId": "subgraph",
+ "highestLabelSetVersion": 0
+ },
+ "recordsCount": 100
+ }
},
"indexedChainIds": [11155111, 84532, 59141, 11155420, 421614, 534351],
"namespace": "sepolia",
@@ -85,8 +97,14 @@
"ensDb": "0.35.0",
"ensIndexer": "0.35.0",
"ensNormalize": "1.11.1",
- "ensRainbow": "0.34.0",
- "ensRainbowSchema": 3
+ "ensRainbowPublicConfig": {
+ "version": "0.34.0",
+ "labelSet": {
+ "labelSetId": "subgraph",
+ "highestLabelSetVersion": 0
+ },
+ "recordsCount": 100
+ }
},
"indexedChainIds": [1],
"namespace": "mainnet",
@@ -112,8 +130,14 @@
"ensDb": "0.35.0",
"ensIndexer": "0.35.0",
"ensNormalize": "1.11.1",
- "ensRainbow": "0.34.0",
- "ensRainbowSchema": 3
+ "ensRainbowPublicConfig": {
+ "version": "0.34.0",
+ "labelSet": {
+ "labelSetId": "subgraph",
+ "highestLabelSetVersion": 0
+ },
+ "recordsCount": 100
+ }
},
"indexedChainIds": [11155111],
"namespace": "sepolia",
@@ -139,8 +163,14 @@
"ensDb": "",
"ensIndexer": "",
"ensNormalize": "",
- "ensRainbow": "",
- "ensRainbowSchema": -1
+ "ensRainbowPublicConfig": {
+ "version": "",
+ "labelSet": {
+ "labelSetId": "",
+ "highestLabelSetVersion": -1
+ },
+ "recordsCount": -1
+ }
},
"indexedChainIds": [11155111],
"namespace": "sepolia",
diff --git a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx
index 29210bb11..fcdae1d44 100644
--- a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx
+++ b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx
@@ -507,7 +507,7 @@ function ENSNodeConfigCardContent({
{ensIndexerPublicConfig.plugins.map((plugin) => (
{plugin}
@@ -561,7 +561,7 @@ function ENSNodeConfigCardContent({
icon={}
version={
- v{ensIndexerPublicConfig.versionInfo.ensRainbow}
+ v{ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version}
}
docsLink={new URL("https://ensnode.io/ensrainbow/")}
@@ -571,8 +571,11 @@ function ENSNodeConfigCardContent({
label="Server LabelSet"
value={
- {ensIndexerPublicConfig.labelSet.labelSetId}:
- {ensIndexerPublicConfig.labelSet.labelSetVersion}
+ {ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.labelSet.labelSetId}:
+ {
+ ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.labelSet
+ .highestLabelSetVersion
+ }
}
additionalInfo={
@@ -586,6 +589,25 @@ function ENSNodeConfigCardContent({
}
/>
+
+
+ {ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.recordsCount}
+
+ }
+ additionalInfo={
+
+ The total number of Rainbow Records.{" "}
+
+ Learn more.
+
+
+ }
+ />
From 2078c6931a33e2d4e658db0cc55e34a32db89eb7 Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Mon, 2 Mar 2026 19:54:42 +0100
Subject: [PATCH 08/15] docs(changeset): Added `ensRainbowPublicConfig` field
to `EnsIndexerPublicConfig`.
---
.changeset/lovely-teeth-hunt.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/lovely-teeth-hunt.md
diff --git a/.changeset/lovely-teeth-hunt.md b/.changeset/lovely-teeth-hunt.md
new file mode 100644
index 000000000..588fd8e99
--- /dev/null
+++ b/.changeset/lovely-teeth-hunt.md
@@ -0,0 +1,5 @@
+---
+"@ensnode/ensnode-sdk": minor
+---
+
+Added `ensRainbowPublicConfig` field to `EnsIndexerPublicConfig`.
From 5dd25f09e24d34bbe34fde6803894ae9bcfbdc1d Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Mon, 2 Mar 2026 19:56:18 +0100
Subject: [PATCH 09/15] docs(changeset): Altered code references accordingly to
the updated `EnsIndexerPublicConfig` data model.
---
.changeset/fast-bats-train.md | 9 +++++++++
1 file changed, 9 insertions(+)
create mode 100644 .changeset/fast-bats-train.md
diff --git a/.changeset/fast-bats-train.md b/.changeset/fast-bats-train.md
new file mode 100644
index 000000000..89d39b3cb
--- /dev/null
+++ b/.changeset/fast-bats-train.md
@@ -0,0 +1,9 @@
+---
+"@ensnode/ensrainbow-sdk": minor
+"ensindexer": minor
+"@docs/ensnode": minor
+"ensadmin": minor
+"ensapi": minor
+---
+
+Altered code references accordingly to the updated `EnsIndexerPublicConfig` data model.
From ac2c5217a76e02adab5083af1d71e2dbdb94297c Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Mon, 2 Mar 2026 20:07:11 +0100
Subject: [PATCH 10/15] Apply AI PR feedback
---
.../src/content/docs/docs/usage/api.mdx | 4 ++--
.../src/ensindexer/config/zod-schemas.test.ts | 10 +++++-----
.../src/ensindexer/config/zod-schemas.ts | 16 +++-------------
.../src/ensrainbow/zod-schemas/config.ts | 5 ++---
4 files changed, 12 insertions(+), 23 deletions(-)
diff --git a/docs/ensnode.io/src/content/docs/docs/usage/api.mdx b/docs/ensnode.io/src/content/docs/docs/usage/api.mdx
index ddd1ac0b5..4eba56e49 100644
--- a/docs/ensnode.io/src/content/docs/docs/usage/api.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/usage/api.mdx
@@ -86,7 +86,7 @@ The response includes several important configuration categories:
functionality
- **Plugins**: Activated plugins
- **ENSIndexer Version Information**: Node.js version, Ponder framework version,
- ENSRainbow version and schema details, ENSDb version, ENSIndexer version, [ENS Normalize version](https://www.npmjs.com/package/@adraffy/ens-normalize)
+ ENSRainbow public config, ENSDb version, ENSIndexer version, [ENS Normalize version](https://www.npmjs.com/package/@adraffy/ens-normalize)
### Example response
@@ -125,7 +125,7 @@ The response includes several important configuration categories:
"ensRainbowPublicConfig": {
"version": "1.5.1",
"labelSet": { "labelSetId": "subgraph", "highestLabelSetVersion": 0 },
- "recordsCount": 100
+ "recordsCount": 133856894
}
}
}
diff --git a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
index ad433e32a..0bfaaf9e6 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
@@ -160,15 +160,15 @@ describe("ENSIndexer: Config", () => {
→ at ensIndexer
✖ Value must be a non-empty string.
→ at ensNormalize
-✖ Value must be a non-empty string.
+✖ EnsRainbowPublicConfig.version must be a non-empty string.
→ at ensRainbowPublicConfig.version
-✖ Value must be a non-negative integer (>=0).
+✖ EnsRainbowPublicConfig.recordsCount must be a non-negative integer (>=0).
→ at ensRainbowPublicConfig.recordsCount
-✖ undefined must be 1-50 characters long
+✖ EnsRainbowPublicConfig.labelSet.labelSetId must be 1-50 characters long
→ at ensRainbowPublicConfig.labelSet.labelSetId
-✖ undefined can only contain lowercase letters (a-z) and hyphens (-)
+✖ EnsRainbowPublicConfig.labelSet.labelSetId can only contain lowercase letters (a-z) and hyphens (-)
→ at ensRainbowPublicConfig.labelSet.labelSetId
-✖ Value must be a non-negative integer (>=0).
+✖ EnsRainbowPublicConfig.labelSet.highestLabelSetVersion must be a non-negative integer (>=0).
→ at ensRainbowPublicConfig.labelSet.highestLabelSetVersion`);
});
diff --git a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
index 8e2e2772f..121779d2c 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
@@ -9,15 +9,12 @@
import { z } from "zod/v4";
import {
+ makeEnsRainbowPublicConfigSchema,
makeLabelSetIdSchema,
makeLabelSetVersionSchema,
} from "../../ensrainbow/zod-schemas/config";
import { uniq } from "../../shared/collections";
-import {
- makeChainIdSchema,
- makeENSNamespaceIdSchema,
- makeNonNegativeIntegerSchema,
-} from "../../shared/zod-schemas";
+import { makeChainIdSchema, makeENSNamespaceIdSchema } from "../../shared/zod-schemas";
import type { ZodCheckFnInput } from "../../shared/zod-types";
import { isSubgraphCompatible } from "./is-subgraph-compatible";
import type { EnsIndexerPublicConfig } from "./types";
@@ -105,14 +102,7 @@ export const makeEnsIndexerVersionInfoSchema = (valueLabel: string = "Value") =>
ensDb: makeNonEmptyStringSchema(),
ensIndexer: makeNonEmptyStringSchema(),
ensNormalize: makeNonEmptyStringSchema(),
- ensRainbowPublicConfig: z.object({
- version: makeNonEmptyStringSchema(),
- labelSet: z.object({
- labelSetId: makeLabelSetIdSchema(),
- highestLabelSetVersion: makeLabelSetVersionSchema(),
- }),
- recordsCount: makeNonNegativeIntegerSchema(),
- }),
+ ensRainbowPublicConfig: makeEnsRainbowPublicConfigSchema(),
},
{
error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`,
diff --git a/packages/ensnode-sdk/src/ensrainbow/zod-schemas/config.ts b/packages/ensnode-sdk/src/ensrainbow/zod-schemas/config.ts
index a0744a10e..d0022f310 100644
--- a/packages/ensnode-sdk/src/ensrainbow/zod-schemas/config.ts
+++ b/packages/ensnode-sdk/src/ensrainbow/zod-schemas/config.ts
@@ -10,7 +10,7 @@ import { makeNonNegativeIntegerSchema } from "../../shared/zod-schemas";
*
* @param valueLabel - The label to use in error messages (e.g., "Label set ID", "LABEL_SET_ID")
*/
-export const makeLabelSetIdSchema = (valueLabel?: string) => {
+export const makeLabelSetIdSchema = (valueLabel: string = "Label set ID") => {
return z
.string({ error: `${valueLabel} must be a string` })
.min(1, { error: `${valueLabel} must be 1-50 characters long` })
@@ -26,9 +26,8 @@ export const makeLabelSetIdSchema = (valueLabel?: string) => {
* The label set version is guaranteed to be a non-negative integer.
*
* @param valueLabel - The label to use in error messages (e.g., "Label set version", "LABEL_SET_VERSION")
-
*/
-export const makeLabelSetVersionSchema = (valueLabel?: string) => {
+export const makeLabelSetVersionSchema = (valueLabel: string = "Label set version") => {
return z.coerce
.number({ error: `${valueLabel} must be an integer.` })
.pipe(makeNonNegativeIntegerSchema(valueLabel));
From 046af3cb695cb17effdbda8185da7a155f9b4093 Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Tue, 3 Mar 2026 18:03:30 +0100
Subject: [PATCH 11/15] Include invariant for ENSRainbow client/server labelset
match
---
.../src/ensindexer/config/zod-schemas.test.ts | 73 +++++++++++++++++++
.../src/ensindexer/config/zod-schemas.ts | 25 ++++++-
2 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
index 0bfaaf9e6..f8ddd1cfa 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
@@ -172,6 +172,79 @@ describe("ENSIndexer: Config", () => {
→ at ensRainbowPublicConfig.labelSet.highestLabelSetVersion`);
});
+ it("validates ensDb and ensIndexer versions match", () => {
+ expect(
+ formatParseError(
+ makeEnsIndexerVersionInfoSchema().safeParse({
+ nodejs: "v22.22.22",
+ ponder: "0.11.25",
+ ensDb: "0.32.0",
+ ensIndexer: "0.33.0", // Different from ensDb
+ ensNormalize: "1.11.1",
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
+ } satisfies EnsIndexerVersionInfo),
+ ),
+ ).toContain("`ensDb` version must be same as `ensIndexer` version");
+ });
+
+ it("validates ENSRainbow label set and version compatibility", () => {
+ const baseConfig = {
+ indexedChainIds: [1], // Use array for serialized config
+ isSubgraphCompatible: false, // Set to false to bypass isSubgraphCompatible invariant
+ namespace: "mainnet" as const,
+ plugins: [PluginName.Subgraph, PluginName.Registrars], // Multiple plugins allowed when not subgraph compatible
+ databaseSchemaName: "test_schema",
+ versionInfo: {
+ nodejs: "v22.22.22",
+ ponder: "0.11.25",
+ ensDb: "0.32.0",
+ ensIndexer: "0.32.0",
+ ensNormalize: "1.11.1",
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
+ },
+ };
+
+ // Test mismatched label set IDs
+ expect(
+ formatParseError(
+ makeEnsIndexerPublicConfigSchema().safeParse(
+ buildUnvalidatedEnsIndexerPublicConfig({
+ ...baseConfig,
+ labelSet: { labelSetId: "custom-labels", labelSetVersion: 0 },
+ }),
+ ),
+ ),
+ ).toContain(
+ 'Server label set ID "subgraph" does not match client\'s requested label set ID "custom-labels"',
+ );
+
+ // Test server version too low
+ expect(
+ formatParseError(
+ makeEnsIndexerPublicConfigSchema().safeParse(
+ buildUnvalidatedEnsIndexerPublicConfig({
+ ...baseConfig,
+ labelSet: { labelSetId: "subgraph", labelSetVersion: 5 },
+ }),
+ ),
+ ),
+ ).toContain("Server highest label set version 0 is less than client's requested version 5");
+ });
+
it("can parse full ENSIndexerPublicConfig with label set", () => {
const validConfig = {
labelSet: {
diff --git a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
index 121779d2c..541b4f93a 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
@@ -8,6 +8,7 @@
*/
import { z } from "zod/v4";
+import type { EnsRainbowClientLabelSet, EnsRainbowServerLabelSet } from "../../ensrainbow/types";
import {
makeEnsRainbowPublicConfigSchema,
makeLabelSetIdSchema,
@@ -17,6 +18,7 @@ import { uniq } from "../../shared/collections";
import { makeChainIdSchema, makeENSNamespaceIdSchema } from "../../shared/zod-schemas";
import type { ZodCheckFnInput } from "../../shared/zod-types";
import { isSubgraphCompatible } from "./is-subgraph-compatible";
+import { validateSupportedLabelSetAndVersion } from "./labelset-utils";
import type { EnsIndexerPublicConfig } from "./types";
import { PluginName } from "./types";
import { invariant_ensDbVersionIsSameAsEnsIndexerVersion } from "./validations";
@@ -132,6 +134,26 @@ export function invariant_isSubgraphCompatibleRequirements(
}
}
+export function invariant_ensRainbowSupportedLabelSetAndVersion(
+ ctx: ZodCheckFnInput>,
+) {
+ const clientLabelSet = ctx.value.labelSet satisfies EnsRainbowClientLabelSet;
+ const serverLabelSet = ctx.value.versionInfo.ensRainbowPublicConfig
+ .labelSet satisfies EnsRainbowServerLabelSet;
+
+ try {
+ validateSupportedLabelSetAndVersion(serverLabelSet, clientLabelSet);
+ } catch (error) {
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
+
+ ctx.issues.push({
+ code: "custom",
+ input: ctx.value,
+ message: `The ENSRainbow label set and version specified in the config are not supported by the ENSRainbow version specified in versionInfo.ensRainbowPublicConfig. Cause: ${errorMessage}`,
+ });
+ }
+}
+
/**
* ENSIndexer Public Config Schema
*
@@ -156,7 +178,8 @@ export const makeEnsIndexerPublicConfigSchema = (valueLabel: string = "ENSIndexe
*
* All required data validations must be performed below.
*/
- .check(invariant_isSubgraphCompatibleRequirements);
+ .check(invariant_isSubgraphCompatibleRequirements)
+ .check(invariant_ensRainbowSupportedLabelSetAndVersion);
/**
* ENSIndexer Public Config Schema
From 45f9f7b12f0032ee55c2795a486c847614e81c2c Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Tue, 3 Mar 2026 18:06:47 +0100
Subject: [PATCH 12/15] Fix tests
---
.../src/lib/ensdb-client/ensdb-client.mock.ts | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts b/apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts
index 4b7054aa6..05dbfa397 100644
--- a/apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts
+++ b/apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts
@@ -39,8 +39,14 @@ export const publicConfig = {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbow: "0.32.0",
- ensRainbowSchema: 2,
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
},
} satisfies EnsIndexerPublicConfig;
From 51df93bb952104ab228a18a8e2e09c0a62ac20e5 Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Tue, 3 Mar 2026 20:51:33 +0100
Subject: [PATCH 13/15] Move `ensRainbowPublicConfig` field to top-level of
`EnsIndexerPublicConfig` data model
---
apps/ensadmin/src/app/mock/config-api.mock.ts | 16 ++--
.../src/app/mock/config-info/data.json | 90 +++++++++----------
.../src/app/mock/config-info/page.tsx | 2 +-
.../connection/cards/ensnode-info.tsx | 11 +--
apps/ensapi/src/config/config.schema.test.ts | 10 +--
apps/ensapi/src/config/validations.ts | 8 +-
apps/ensindexer/src/config/public.ts | 21 +++--
.../src/lib/ensdb-client/ensdb-client.mock.ts | 16 ++--
apps/ensindexer/src/lib/version-info.ts | 6 --
.../ensnode-sdk/src/ensapi/client.test.ts | 10 +--
.../src/ensapi/config/conversions.test.ts | 23 ++---
.../ensnode-sdk/src/ensindexer/client.mock.ts | 16 ++--
.../src/ensindexer/config/compatibility.ts | 2 +-
.../src/ensindexer/config/conversions.test.ts | 20 ++---
.../src/ensindexer/config/serialize.ts | 10 ++-
.../src/ensindexer/config/types.ts | 12 +--
.../src/ensindexer/config/zod-schemas.test.ts | 73 ++++-----------
.../src/ensindexer/config/zod-schemas.ts | 21 +++--
18 files changed, 168 insertions(+), 199 deletions(-)
diff --git a/apps/ensadmin/src/app/mock/config-api.mock.ts b/apps/ensadmin/src/app/mock/config-api.mock.ts
index 9893115ed..54d0244f9 100644
--- a/apps/ensadmin/src/app/mock/config-api.mock.ts
+++ b/apps/ensadmin/src/app/mock/config-api.mock.ts
@@ -7,6 +7,14 @@ export const ensIndexerPublicConfig = deserializeENSIndexerPublicConfig({
},
indexedChainIds: [1, 8453, 59144, 10, 42161, 534352, 567],
databaseSchemaName: "alphaSchema0.34.0",
+ ensRainbowPublicConfig: {
+ version: "0.34.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
isSubgraphCompatible: false,
namespace: "mainnet",
plugins: [
@@ -23,14 +31,6 @@ export const ensIndexerPublicConfig = deserializeENSIndexerPublicConfig({
ponder: "0.11.43",
ensIndexer: "0.35.0",
ensDb: "0.35.0",
- ensRainbowPublicConfig: {
- version: "0.34.0",
- labelSet: {
- labelSetId: "subgraph",
- highestLabelSetVersion: 0,
- },
- recordsCount: 100,
- },
ensNormalize: "1.11.1",
},
});
diff --git a/apps/ensadmin/src/app/mock/config-info/data.json b/apps/ensadmin/src/app/mock/config-info/data.json
index 1f97daa8f..fd9319ecb 100644
--- a/apps/ensadmin/src/app/mock/config-info/data.json
+++ b/apps/ensadmin/src/app/mock/config-info/data.json
@@ -12,6 +12,14 @@
},
"indexedChainIds": [1, 8453, 59144, 10, 42161, 534352, 567],
"databaseSchemaName": "alphaSchema0.34.0",
+ "ensRainbowPublicConfig": {
+ "version": "0.34.0",
+ "labelSet": {
+ "labelSetId": "subgraph",
+ "highestLabelSetVersion": 0
+ },
+ "recordsCount": 100
+ },
"isSubgraphCompatible": false,
"namespace": "mainnet",
"plugins": [
@@ -28,15 +36,7 @@
"ponder": "0.11.43",
"ensDb": "0.35.0",
"ensIndexer": "0.35.0",
- "ensNormalize": "1.11.1",
- "ensRainbowPublicConfig": {
- "version": "0.34.0",
- "labelSet": {
- "labelSetId": "subgraph",
- "highestLabelSetVersion": 0
- },
- "recordsCount": 100
- }
+ "ensNormalize": "1.11.1"
}
}
},
@@ -56,15 +56,7 @@
"ponder": "0.11.43",
"ensDb": "0.35.0",
"ensIndexer": "0.35.0",
- "ensNormalize": "1.11.1",
- "ensRainbowPublicConfig": {
- "version": "0.34.0",
- "labelSet": {
- "labelSetId": "subgraph",
- "highestLabelSetVersion": 0
- },
- "recordsCount": 100
- }
+ "ensNormalize": "1.11.1"
},
"indexedChainIds": [11155111, 84532, 59141, 11155420, 421614, 534351],
"namespace": "sepolia",
@@ -77,6 +69,14 @@
"registrars"
],
"databaseSchemaName": "alphaSepoliaSchema0.34.0",
+ "ensRainbowPublicConfig": {
+ "version": "0.34.0",
+ "labelSet": {
+ "labelSetId": "subgraph",
+ "highestLabelSetVersion": 0
+ },
+ "recordsCount": 100
+ },
"isSubgraphCompatible": false
}
},
@@ -96,20 +96,20 @@
"ponder": "0.11.43",
"ensDb": "0.35.0",
"ensIndexer": "0.35.0",
- "ensNormalize": "1.11.1",
- "ensRainbowPublicConfig": {
- "version": "0.34.0",
- "labelSet": {
- "labelSetId": "subgraph",
- "highestLabelSetVersion": 0
- },
- "recordsCount": 100
- }
+ "ensNormalize": "1.11.1"
},
"indexedChainIds": [1],
"namespace": "mainnet",
"plugins": ["subgraph"],
"databaseSchemaName": "mainnetSchema0.34.0",
+ "ensRainbowPublicConfig": {
+ "version": "0.34.0",
+ "labelSet": {
+ "labelSetId": "subgraph",
+ "highestLabelSetVersion": 0
+ },
+ "recordsCount": 100
+ },
"isSubgraphCompatible": true
}
},
@@ -129,20 +129,20 @@
"ponder": "0.11.43",
"ensDb": "0.35.0",
"ensIndexer": "0.35.0",
- "ensNormalize": "1.11.1",
- "ensRainbowPublicConfig": {
- "version": "0.34.0",
- "labelSet": {
- "labelSetId": "subgraph",
- "highestLabelSetVersion": 0
- },
- "recordsCount": 100
- }
+ "ensNormalize": "1.11.1"
},
"indexedChainIds": [11155111],
"namespace": "sepolia",
"plugins": ["subgraph"],
"databaseSchemaName": "sepoliaSchema0.34.0",
+ "ensRainbowPublicConfig": {
+ "version": "0.34.0",
+ "labelSet": {
+ "labelSetId": "subgraph",
+ "highestLabelSetVersion": 0
+ },
+ "recordsCount": 100
+ },
"isSubgraphCompatible": true
}
},
@@ -162,20 +162,20 @@
"ponder": "",
"ensDb": "",
"ensIndexer": "",
- "ensNormalize": "",
- "ensRainbowPublicConfig": {
- "version": "",
- "labelSet": {
- "labelSetId": "",
- "highestLabelSetVersion": -1
- },
- "recordsCount": -1
- }
+ "ensNormalize": ""
},
"indexedChainIds": [11155111],
"namespace": "sepolia",
"plugins": ["subgraph"],
"databaseSchemaName": "DeserializationSchema0.34.0",
+ "ensRainbowPublicConfig": {
+ "version": "",
+ "labelSet": {
+ "labelSetId": "",
+ "highestLabelSetVersion": -1
+ },
+ "recordsCount": -1
+ },
"isSubgraphCompatible": true
}
}
diff --git a/apps/ensadmin/src/app/mock/config-info/page.tsx b/apps/ensadmin/src/app/mock/config-info/page.tsx
index a5700d460..be3d5e14c 100644
--- a/apps/ensadmin/src/app/mock/config-info/page.tsx
+++ b/apps/ensadmin/src/app/mock/config-info/page.tsx
@@ -13,7 +13,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com
import mockDataJson from "./data.json" with { type: "json" };
-const mockConfigData = mockDataJson as Record;
+const mockConfigData = mockDataJson as unknown as Record;
type LoadingVariant = "Loading" | "Loading Error";
type ConfigVariant = keyof typeof mockConfigData | LoadingVariant;
diff --git a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx
index fcdae1d44..90a7574b7 100644
--- a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx
+++ b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx
@@ -561,7 +561,7 @@ function ENSNodeConfigCardContent({
icon={}
version={
- v{ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version}
+ v{ensIndexerPublicConfig.ensRainbowPublicConfig.version}
}
docsLink={new URL("https://ensnode.io/ensrainbow/")}
@@ -571,11 +571,8 @@ function ENSNodeConfigCardContent({
label="Server LabelSet"
value={
- {ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.labelSet.labelSetId}:
- {
- ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.labelSet
- .highestLabelSetVersion
- }
+ {ensIndexerPublicConfig.ensRainbowPublicConfig.labelSet.labelSetId}:
+ {ensIndexerPublicConfig.ensRainbowPublicConfig.labelSet.highestLabelSetVersion}
}
additionalInfo={
@@ -594,7 +591,7 @@ function ENSNodeConfigCardContent({
label="Records Count"
value={
- {ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.recordsCount}
+ {ensIndexerPublicConfig.ensRainbowPublicConfig.recordsCount}
}
additionalInfo={
diff --git a/apps/ensapi/src/config/config.schema.test.ts b/apps/ensapi/src/config/config.schema.test.ts
index 6c5d0348f..407effcb2 100644
--- a/apps/ensapi/src/config/config.schema.test.ts
+++ b/apps/ensapi/src/config/config.schema.test.ts
@@ -32,6 +32,11 @@ const BASE_ENV = {
const ENSINDEXER_PUBLIC_CONFIG = {
namespace: "mainnet",
databaseSchemaName: "ensapi",
+ ensRainbowPublicConfig: {
+ version: packageJson.version,
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
indexedChainIds: new Set([1]),
isSubgraphCompatible: false,
labelSet: { labelSetId: "subgraph", labelSetVersion: 0 },
@@ -39,11 +44,6 @@ const ENSINDEXER_PUBLIC_CONFIG = {
versionInfo: {
ensDb: packageJson.version,
ensIndexer: packageJson.version,
- ensRainbowPublicConfig: {
- version: packageJson.version,
- labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
- recordsCount: 100,
- },
ensNormalize: "1.1.1",
nodejs: "1.1.1",
ponder: "1.1.1",
diff --git a/apps/ensapi/src/config/validations.ts b/apps/ensapi/src/config/validations.ts
index 62913bdb1..6705ef792 100644
--- a/apps/ensapi/src/config/validations.ts
+++ b/apps/ensapi/src/config/validations.ts
@@ -34,12 +34,12 @@ export function invariant_ensIndexerPublicConfigVersionInfo(
}
// Invariant: ENSApi & ENSRainbow must match version numbers
- if (ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version !== packageJson.version) {
+ if (ensIndexerPublicConfig.ensRainbowPublicConfig.version !== packageJson.version) {
ctx.issues.push({
code: "custom",
- path: ["ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version"],
- input: ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version,
- message: `Version Mismatch: ENSRainbow@${ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version} !== ENSApi@${packageJson.version}`,
+ path: ["ensIndexerPublicConfig.ensRainbowPublicConfig.version"],
+ input: ensIndexerPublicConfig.ensRainbowPublicConfig.version,
+ message: `Version Mismatch: ENSRainbow@${ensIndexerPublicConfig.ensRainbowPublicConfig.version} !== ENSApi@${packageJson.version}`,
});
}
}
diff --git a/apps/ensindexer/src/config/public.ts b/apps/ensindexer/src/config/public.ts
index 4e533f2e9..b80fa9f07 100644
--- a/apps/ensindexer/src/config/public.ts
+++ b/apps/ensindexer/src/config/public.ts
@@ -1,22 +1,29 @@
-import type { ENSIndexerPublicConfig } from "@ensnode/ensnode-sdk";
+import type { EnsIndexerPublicConfig } from "@ensnode/ensnode-sdk";
+import { getENSRainbowApiClient } from "@/lib/ensraibow-api-client";
import { getENSIndexerVersionInfo } from "@/lib/version-info";
-import type { ENSIndexerConfig } from "./types";
+import type { EnsIndexerConfig } from "./types";
+
+const ensRainbowApiClient = getENSRainbowApiClient();
/**
- * Build a public version of {@link ENSIndexerConfig}.
+ * Build a public version of {@link EnsIndexerConfig}.
*
- * Note: some values required to build an {@link ENSIndexerPublicConfig} object
+ * Note: some values required to build an {@link EnsIndexerPublicConfig} object
* have to fetched over the network.
*/
export async function buildENSIndexerPublicConfig(
- config: ENSIndexerConfig,
-): Promise {
- const versionInfo = await getENSIndexerVersionInfo();
+ config: EnsIndexerConfig,
+): Promise {
+ const [versionInfo, ensRainbowPublicConfig] = await Promise.all([
+ getENSIndexerVersionInfo(),
+ ensRainbowApiClient.config(),
+ ]);
return {
databaseSchemaName: config.databaseSchemaName,
+ ensRainbowPublicConfig,
labelSet: config.labelSet,
indexedChainIds: config.indexedChainIds,
isSubgraphCompatible: config.isSubgraphCompatible,
diff --git a/apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts b/apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts
index 05dbfa397..7387cc19f 100644
--- a/apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts
+++ b/apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts
@@ -25,6 +25,14 @@ export const databaseSchemaName = "public";
export const publicConfig = {
databaseSchemaName,
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
labelSet: {
labelSetId: "subgraph",
labelSetVersion: 0,
@@ -39,14 +47,6 @@ export const publicConfig = {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbowPublicConfig: {
- version: "0.32.0",
- labelSet: {
- labelSetId: "subgraph",
- highestLabelSetVersion: 0,
- },
- recordsCount: 100,
- },
},
} satisfies EnsIndexerPublicConfig;
diff --git a/apps/ensindexer/src/lib/version-info.ts b/apps/ensindexer/src/lib/version-info.ts
index 30c9624c6..55bd8b65f 100644
--- a/apps/ensindexer/src/lib/version-info.ts
+++ b/apps/ensindexer/src/lib/version-info.ts
@@ -9,8 +9,6 @@ import { prettifyError } from "zod/v4";
import type { ENSIndexerVersionInfo, SerializedENSIndexerVersionInfo } from "@ensnode/ensnode-sdk";
import { makeENSIndexerVersionInfoSchema } from "@ensnode/ensnode-sdk/internal";
-import { getENSRainbowApiClient } from "@/lib/ensraibow-api-client";
-
/**
* Get NPM package version.
*
@@ -109,9 +107,6 @@ function getPackageVersionFromPnpmStore(pnpmDir: string, packageName: string): s
* Get complete {@link ENSIndexerVersionInfo} for ENSIndexer app.
*/
export async function getENSIndexerVersionInfo(): Promise {
- const ensRainbowApiClient = getENSRainbowApiClient();
- const ensRainbowPublicConfig = await ensRainbowApiClient.config();
-
// ENSIndexer version
const ensIndexerVersion = packageJson.version;
@@ -122,7 +117,6 @@ export async function getENSIndexerVersionInfo(): Promise
// parse unvalidated version info
const schema = makeENSIndexerVersionInfoSchema();
const parsed = schema.safeParse({
- ensRainbowPublicConfig,
nodejs: process.versions.node,
ponder: getPackageVersion("ponder"),
ensDb: ensDbVersion,
diff --git a/packages/ensnode-sdk/src/ensapi/client.test.ts b/packages/ensnode-sdk/src/ensapi/client.test.ts
index 88baf4fbd..f53ea9ce0 100644
--- a/packages/ensnode-sdk/src/ensapi/client.test.ts
+++ b/packages/ensnode-sdk/src/ensapi/client.test.ts
@@ -64,6 +64,11 @@ const EXAMPLE_CONFIG_RESPONSE = {
reason: "no-api-key",
},
ensIndexerPublicConfig: {
+ ensRainbowPublicConfig: {
+ version: "0.31.0",
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
labelSet: {
labelSetId: "subgraph",
labelSetVersion: 0,
@@ -86,11 +91,6 @@ const EXAMPLE_CONFIG_RESPONSE = {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbowPublicConfig: {
- version: "0.31.0",
- labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
- recordsCount: 100,
- },
},
},
} satisfies SerializedEnsApiPublicConfig;
diff --git a/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts b/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts
index 44884ccbb..ae15afb0c 100644
--- a/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts
+++ b/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts
@@ -5,6 +5,7 @@ import { ENSNamespaceIds } from "@ensnode/datasources";
import { PluginName } from "../../ensindexer/config/types";
import { deserializeEnsApiPublicConfig } from "./deserialize";
import { serializeEnsApiPublicConfig } from "./serialize";
+import type { SerializedEnsApiPublicConfig } from "./serialized-types";
import type { EnsApiPublicConfig } from "./types";
const MOCK_ENSAPI_PUBLIC_CONFIG = {
@@ -16,6 +17,11 @@ const MOCK_ENSAPI_PUBLIC_CONFIG = {
ensIndexerPublicConfig: {
namespace: ENSNamespaceIds.Mainnet,
databaseSchemaName: "ensapi",
+ ensRainbowPublicConfig: {
+ version: "0.36.0",
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
indexedChainIds: new Set([1]),
isSubgraphCompatible: false,
labelSet: { labelSetId: "subgraph", labelSetVersion: 0 },
@@ -23,11 +29,6 @@ const MOCK_ENSAPI_PUBLIC_CONFIG = {
versionInfo: {
ensDb: "0.36.0",
ensIndexer: "0.36.0",
- ensRainbowPublicConfig: {
- version: "0.36.0",
- labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
- recordsCount: 100,
- },
ensNormalize: "1.1.1",
nodejs: "20.0.0",
ponder: "0.5.0",
@@ -51,6 +52,11 @@ describe("ENSApi Config Serialization/Deserialization", () => {
ensIndexerPublicConfig: {
namespace: ENSNamespaceIds.Mainnet,
databaseSchemaName: "ensapi",
+ ensRainbowPublicConfig: {
+ version: "0.36.0",
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
indexedChainIds: [1],
isSubgraphCompatible: false,
labelSet: { labelSetId: "subgraph", labelSetVersion: 0 },
@@ -58,17 +64,12 @@ describe("ENSApi Config Serialization/Deserialization", () => {
versionInfo: {
ensDb: "0.36.0",
ensIndexer: "0.36.0",
- ensRainbowPublicConfig: {
- version: "0.36.0",
- labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
- recordsCount: 100,
- },
ensNormalize: "1.1.1",
nodejs: "20.0.0",
ponder: "0.5.0",
},
},
- });
+ } satisfies SerializedEnsApiPublicConfig);
});
});
diff --git a/packages/ensnode-sdk/src/ensindexer/client.mock.ts b/packages/ensnode-sdk/src/ensindexer/client.mock.ts
index f7fffb84a..84d0ceaa2 100644
--- a/packages/ensnode-sdk/src/ensindexer/client.mock.ts
+++ b/packages/ensnode-sdk/src/ensindexer/client.mock.ts
@@ -14,6 +14,14 @@ export const configResponseMock = {
},
indexedChainIds: [1, 8453, 59144, 10, 42161, 534352],
databaseSchemaName: "alphaSchema0.31.0",
+ ensRainbowPublicConfig: {
+ version: "0.31.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
isSubgraphCompatible: false,
namespace: "mainnet",
plugins: [
@@ -30,14 +38,6 @@ export const configResponseMock = {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbowPublicConfig: {
- version: "0.31.0",
- labelSet: {
- labelSetId: "subgraph",
- highestLabelSetVersion: 0,
- },
- recordsCount: 100,
- },
},
} satisfies SerializedEnsIndexerConfigResponse;
diff --git a/packages/ensnode-sdk/src/ensindexer/config/compatibility.ts b/packages/ensnode-sdk/src/ensindexer/config/compatibility.ts
index 337af0909..2258e2b8d 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/compatibility.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/compatibility.ts
@@ -2,7 +2,7 @@ import type { EnsIndexerPublicConfig } from "./types";
export type EnsIndexerPublicConfigCompatibilityCheck = Omit<
EnsIndexerPublicConfig,
- "databaseSchemaName" | "versionInfo"
+ "databaseSchemaName" | "ensRainbowPublicConfig" | "versionInfo"
>;
/**
diff --git a/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts b/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts
index ae23548ff..79b1c82c0 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts
@@ -11,6 +11,11 @@ describe("ENSIndexer: Config", () => {
// arrange
const config = {
databaseSchemaName: "public",
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
labelSet: {
labelSetId: "subgraph",
labelSetVersion: 0,
@@ -25,11 +30,6 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbowPublicConfig: {
- version: "0.32.0",
- labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
- recordsCount: 100,
- },
},
} satisfies EnsIndexerPublicConfig;
@@ -54,6 +54,11 @@ describe("ENSIndexer: Config", () => {
describe("deserialization", () => {
const correctSerializedConfig = {
databaseSchemaName: "public",
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
+ recordsCount: 100,
+ },
labelSet: {
labelSetId: "subgraph",
labelSetVersion: 0,
@@ -68,11 +73,6 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbowPublicConfig: {
- version: "0.32.0",
- labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
- recordsCount: 100,
- },
},
} satisfies SerializedEnsIndexerPublicConfig;
diff --git a/packages/ensnode-sdk/src/ensindexer/config/serialize.ts b/packages/ensnode-sdk/src/ensindexer/config/serialize.ts
index a4e27c5e6..a24838803 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/serialize.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/serialize.ts
@@ -19,20 +19,22 @@ export function serializeEnsIndexerPublicConfig(
config: EnsIndexerPublicConfig,
): SerializedEnsIndexerPublicConfig {
const {
- labelSet,
- indexedChainIds,
databaseSchemaName,
+ ensRainbowPublicConfig,
+ indexedChainIds,
isSubgraphCompatible,
+ labelSet,
namespace,
plugins,
versionInfo,
} = config;
return {
- labelSet,
- indexedChainIds: serializeIndexedChainIds(indexedChainIds),
databaseSchemaName,
+ ensRainbowPublicConfig,
+ indexedChainIds: serializeIndexedChainIds(indexedChainIds),
isSubgraphCompatible,
+ labelSet,
namespace,
plugins,
versionInfo,
diff --git a/packages/ensnode-sdk/src/ensindexer/config/types.ts b/packages/ensnode-sdk/src/ensindexer/config/types.ts
index 1b4d71e41..0d37b0f5b 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/types.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/types.ts
@@ -50,11 +50,6 @@ export interface EnsIndexerVersionInfo {
**/
ensIndexer: string;
- /**
- * ENSRainbow public config
- */
- ensRainbowPublicConfig: EnsRainbowPublicConfig;
-
/**
* ENS Normalize package version
*
@@ -101,6 +96,13 @@ export interface EnsIndexerPublicConfig {
*/
databaseSchemaName: string;
+ /**
+ * ENSRainbow public config
+ *
+ * Represent the public config of connected ENSRainbow instance.
+ */
+ ensRainbowPublicConfig: EnsRainbowPublicConfig;
+
/**
* A set of strings referring to the names of plugins that are active.
*
diff --git a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
index f8ddd1cfa..182251613 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts
@@ -110,14 +110,6 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbowPublicConfig: {
- version: "0.32.0",
- labelSet: {
- labelSetId: "subgraph",
- highestLabelSetVersion: 0,
- },
- recordsCount: 100,
- },
} satisfies EnsIndexerVersionInfo),
).toStrictEqual({
nodejs: "v22.22.22",
@@ -125,14 +117,6 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbowPublicConfig: {
- version: "0.32.0",
- labelSet: {
- labelSetId: "subgraph",
- highestLabelSetVersion: 0,
- },
- recordsCount: 100,
- },
} satisfies EnsIndexerVersionInfo);
expect(
@@ -143,11 +127,6 @@ describe("ENSIndexer: Config", () => {
ensDb: "",
ensIndexer: "",
ensNormalize: "",
- ensRainbowPublicConfig: {
- version: "",
- labelSet: { labelSetId: "", highestLabelSetVersion: -1 },
- recordsCount: -1,
- },
} satisfies EnsIndexerVersionInfo),
),
).toStrictEqual(`✖ Value must be a non-empty string.
@@ -159,17 +138,7 @@ describe("ENSIndexer: Config", () => {
✖ Value must be a non-empty string.
→ at ensIndexer
✖ Value must be a non-empty string.
- → at ensNormalize
-✖ EnsRainbowPublicConfig.version must be a non-empty string.
- → at ensRainbowPublicConfig.version
-✖ EnsRainbowPublicConfig.recordsCount must be a non-negative integer (>=0).
- → at ensRainbowPublicConfig.recordsCount
-✖ EnsRainbowPublicConfig.labelSet.labelSetId must be 1-50 characters long
- → at ensRainbowPublicConfig.labelSet.labelSetId
-✖ EnsRainbowPublicConfig.labelSet.labelSetId can only contain lowercase letters (a-z) and hyphens (-)
- → at ensRainbowPublicConfig.labelSet.labelSetId
-✖ EnsRainbowPublicConfig.labelSet.highestLabelSetVersion must be a non-negative integer (>=0).
- → at ensRainbowPublicConfig.labelSet.highestLabelSetVersion`);
+ → at ensNormalize`);
});
it("validates ensDb and ensIndexer versions match", () => {
@@ -181,14 +150,6 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.33.0", // Different from ensDb
ensNormalize: "1.11.1",
- ensRainbowPublicConfig: {
- version: "0.32.0",
- labelSet: {
- labelSetId: "subgraph",
- highestLabelSetVersion: 0,
- },
- recordsCount: 100,
- },
} satisfies EnsIndexerVersionInfo),
),
).toContain("`ensDb` version must be same as `ensIndexer` version");
@@ -196,6 +157,14 @@ describe("ENSIndexer: Config", () => {
it("validates ENSRainbow label set and version compatibility", () => {
const baseConfig = {
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
indexedChainIds: [1], // Use array for serialized config
isSubgraphCompatible: false, // Set to false to bypass isSubgraphCompatible invariant
namespace: "mainnet" as const,
@@ -207,14 +176,6 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbowPublicConfig: {
- version: "0.32.0",
- labelSet: {
- labelSetId: "subgraph",
- highestLabelSetVersion: 0,
- },
- recordsCount: 100,
- },
},
};
@@ -247,6 +208,14 @@ describe("ENSIndexer: Config", () => {
it("can parse full ENSIndexerPublicConfig with label set", () => {
const validConfig = {
+ ensRainbowPublicConfig: {
+ version: "0.32.0",
+ labelSet: {
+ labelSetId: "subgraph",
+ highestLabelSetVersion: 0,
+ },
+ recordsCount: 100,
+ },
labelSet: {
labelSetId: "subgraph",
labelSetVersion: 0,
@@ -262,14 +231,6 @@ describe("ENSIndexer: Config", () => {
ensDb: "0.32.0",
ensIndexer: "0.32.0",
ensNormalize: "1.11.1",
- ensRainbowPublicConfig: {
- version: "0.32.0",
- labelSet: {
- labelSetId: "subgraph",
- highestLabelSetVersion: 0,
- },
- recordsCount: 100,
- },
},
} satisfies SerializedEnsIndexerPublicConfig;
diff --git a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
index 541b4f93a..c491b8844 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts
@@ -104,7 +104,6 @@ export const makeEnsIndexerVersionInfoSchema = (valueLabel: string = "Value") =>
ensDb: makeNonEmptyStringSchema(),
ensIndexer: makeNonEmptyStringSchema(),
ensNormalize: makeNonEmptyStringSchema(),
- ensRainbowPublicConfig: makeEnsRainbowPublicConfigSchema(),
},
{
error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`,
@@ -135,10 +134,10 @@ export function invariant_isSubgraphCompatibleRequirements(
}
export function invariant_ensRainbowSupportedLabelSetAndVersion(
- ctx: ZodCheckFnInput>,
+ ctx: ZodCheckFnInput>,
) {
const clientLabelSet = ctx.value.labelSet satisfies EnsRainbowClientLabelSet;
- const serverLabelSet = ctx.value.versionInfo.ensRainbowPublicConfig
+ const serverLabelSet = ctx.value.ensRainbowPublicConfig
.labelSet satisfies EnsRainbowServerLabelSet;
try {
@@ -149,7 +148,7 @@ export function invariant_ensRainbowSupportedLabelSetAndVersion(
ctx.issues.push({
code: "custom",
input: ctx.value,
- message: `The ENSRainbow label set and version specified in the config are not supported by the ENSRainbow version specified in versionInfo.ensRainbowPublicConfig. Cause: ${errorMessage}`,
+ message: `The ENSRainbow label set and version specified in the config are not supported by the ENSRainbow version specified in ensRainbowPublicConfig. Cause: ${errorMessage}`,
});
}
}
@@ -163,14 +162,17 @@ export function invariant_ensRainbowSupportedLabelSetAndVersion(
export const makeEnsIndexerPublicConfigSchema = (valueLabel: string = "ENSIndexerPublicConfig") =>
z
.object({
- labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
+ databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
+ ensRainbowPublicConfig: makeEnsRainbowPublicConfigSchema(
+ `${valueLabel}.ensRainbowPublicConfig`,
+ ),
indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
isSubgraphCompatible: z.boolean({
error: `${valueLabel}.isSubgraphCompatible must be a boolean value.`,
}),
+ labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
plugins: makePluginsListSchema(`${valueLabel}.plugins`),
- databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
versionInfo: makeEnsIndexerVersionInfoSchema(`${valueLabel}.versionInfo`),
})
/**
@@ -192,13 +194,16 @@ export const makeSerializedEnsIndexerPublicConfigSchema = (
valueLabel: string = "Serialized ENSIndexerPublicConfig",
) =>
z.object({
- labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
+ databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
+ ensRainbowPublicConfig: makeEnsRainbowPublicConfigSchema(
+ `${valueLabel}.ensRainbowPublicConfig`,
+ ),
indexedChainIds: makeSerializedIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
isSubgraphCompatible: z.boolean({
error: `${valueLabel}.isSubgraphCompatible must be a boolean value.`,
}),
+ labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
plugins: makePluginsListSchema(`${valueLabel}.plugins`),
- databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
versionInfo: makeEnsIndexerVersionInfoSchema(`${valueLabel}.versionInfo`),
});
From 5fd3bb30da9b9f1ccb9f3a77b039ac82ad042c10 Mon Sep 17 00:00:00 2001
From: Tomasz Kopacki
Date: Tue, 3 Mar 2026 21:03:10 +0100
Subject: [PATCH 14/15] Apply number formatter for presenting the total number
of Rainbow Records.
---
apps/ensadmin/src/components/connection/cards/ensnode-info.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx
index 90a7574b7..f33e928db 100644
--- a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx
+++ b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx
@@ -591,7 +591,7 @@ function ENSNodeConfigCardContent({
label="Records Count"
value={
- {ensIndexerPublicConfig.ensRainbowPublicConfig.recordsCount}
+ {ensIndexerPublicConfig.ensRainbowPublicConfig.recordsCount.toLocaleString()}
}
additionalInfo={
From ea1898b1b4eb804a03f20fd0eecd4a44e57a4855 Mon Sep 17 00:00:00 2001
From: Tomek Kopacki
Date: Tue, 3 Mar 2026 21:12:49 +0100
Subject: [PATCH 15/15] Update
packages/ensnode-sdk/src/ensindexer/config/types.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
packages/ensnode-sdk/src/ensindexer/config/types.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/ensnode-sdk/src/ensindexer/config/types.ts b/packages/ensnode-sdk/src/ensindexer/config/types.ts
index 0d37b0f5b..afc70c50d 100644
--- a/packages/ensnode-sdk/src/ensindexer/config/types.ts
+++ b/packages/ensnode-sdk/src/ensindexer/config/types.ts
@@ -99,7 +99,7 @@ export interface EnsIndexerPublicConfig {
/**
* ENSRainbow public config
*
- * Represent the public config of connected ENSRainbow instance.
+ * Represents the public config of the connected ENSRainbow instance.
*/
ensRainbowPublicConfig: EnsRainbowPublicConfig;