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;