Use ENSRainbow public config within ENSIndexer public config#1705
Use ENSRainbow public config within ENSIndexer public config#1705
Conversation
…onfig` Allows modifying ENSIndexer public config to include ENSRainbow public config.
Includes `ensRainbowPublicConfig: EnsRainbowPublicConfig` field.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
🦋 Changeset detectedLatest commit: ea1898b The changes in this PR will be included in the next version bump. This PR includes changesets to release 18 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR replaces the flat Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…EnsIndexerPublicConfig` data model.
| {ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.labelSet.labelSetId}: | ||
| { | ||
| ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.labelSet | ||
| .highestLabelSetVersion | ||
| } |
| <InfoCardItem | ||
| label="Records Count" | ||
| value={ | ||
| <p className={cardItemValueStyles}> | ||
| {ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.recordsCount} | ||
| </p> | ||
| } | ||
| additionalInfo={ | ||
| <p> | ||
| The total number of Rainbow Records.{" "} | ||
| <ExternalLinkWithIcon | ||
| href={`https://ensnode.io/ensrainbow/concepts/glossary/#rainbow-record`} | ||
| > | ||
| Learn more. | ||
| </ExternalLinkWithIcon> | ||
| </p> | ||
| } | ||
| /> |
There was a problem hiding this comment.
We present extra info now that we have access to it 👍
|
Self-review completed 👍 |
|
@greptile review |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/ensapi/src/config/config.schema.test.ts`:
- Around line 42-46: Add a unit test in the config.schema.test.ts suite that
asserts behavior when ensRainbowPublicConfig.version is different from
packageJson.version: create a test case where ensRainbowPublicConfig.version is
set to a different string than packageJson.version and validate the
schema/validation logic (the same assertions used for the existing
ensRainbowPublicConfig block) to ensure connected-service configs permit or
reject a mismatched version as intended; reference the existing
ensRainbowPublicConfig object and packageJson.version to locate where to add the
new case and mirror existing test patterns for consistency.
In `@apps/ensapi/src/config/validations.ts`:
- Around line 37-43: The current validation enforces exact equality between
ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version and
packageJson.version which wrongly treats ENSRainbow as an internal component;
remove or relax that strict check in validations.ts by deleting the equality
branch that pushes the custom issue (the block referencing
ensIndexerPublicConfig.versionInfo.ensRainbowPublicConfig.version and
packageJson.version) or replace it with a non-blocking compatibility/info-level
check; update any tests or callers expecting this issue to no longer fail when
ENSRainbow version differs from ENSApi.
In `@docs/ensnode.io/src/content/docs/docs/usage/api.mdx`:
- Around line 125-129: The docs use the new ensRainbowPublicConfig object but
the surrounding prose still says “ENSRainbow version and schema details”; update
the “Key Configuration Details” paragraph to reference ensRainbowPublicConfig
and its fields (version, labelSet with labelSetId/highestLabelSetVersion, and
recordsCount) so the wording aligns with the example. Specifically, replace the
ambiguous phrase “ENSRainbow version and schema details” with something like
“ensRainbowPublicConfig — contains version, labelSet (labelSetId and
highestLabelSetVersion), and recordsCount” and ensure any subsequent sentences
refer to those exact field names.
In `@packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts`:
- Around line 167-170: The nested ensRainbowPublicConfig schema is calling
makeLabelSetIdSchema() and makeLabelSetVersionSchema() without a valueLabel,
causing "undefined" in errors; update the calls to pass descriptive labels —
e.g., call makeLabelSetIdSchema("ensRainbowPublicConfig.labelSet.labelSetId")
and
makeLabelSetVersionSchema("ensRainbowPublicConfig.labelSet.highestLabelSetVersion")
where those functions are invoked so validation errors reference the correct
field paths.
In `@packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts`:
- Around line 108-115: The nested ensRainbowPublicConfig.labelSet schema uses
makeLabelSetIdSchema() and makeLabelSetVersionSchema() without explicit field
labels, which yields poor error messages; update the call sites inside the
ensRainbowPublicConfig object (labelSet) to pass descriptive labels (e.g.,
"labelSet.labelSetId" and "labelSet.highestLabelSetVersion") into
makeLabelSetIdSchema(...) and makeLabelSetVersionSchema(...) so Zod errors
report meaningful field names when validation fails.
In `@packages/ensnode-sdk/src/ensrainbow/zod-schemas/config.ts`:
- Around line 13-20: The validation error messages in makeLabelSetIdSchema (and
the similar factory at lines ~31-34) use the optional parameter valueLabel which
can be undefined, producing messages like "undefined must be..."; fix this by
giving valueLabel a sensible default (e.g., "value" or "label") in the function
signature or normalizing it at the start of the function, then use that fallback
when constructing the z.string/.min/.max/.regex error messages so all validation
output remains stable when no argument is passed.
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (19)
apps/ensadmin/src/app/mock/config-api.mock.tsapps/ensadmin/src/app/mock/config-info/data.jsonapps/ensadmin/src/components/connection/cards/ensnode-info.tsxapps/ensapi/src/config/config.schema.test.tsapps/ensapi/src/config/validations.tsapps/ensindexer/src/lib/version-info.tsdocs/ensnode.io/src/content/docs/docs/usage/api.mdxpackages/ensnode-sdk/src/ensapi/client.test.tspackages/ensnode-sdk/src/ensapi/config/conversions.test.tspackages/ensnode-sdk/src/ensindexer/client.mock.tspackages/ensnode-sdk/src/ensindexer/config/conversions.test.tspackages/ensnode-sdk/src/ensindexer/config/labelset-utils.tspackages/ensnode-sdk/src/ensindexer/config/types.tspackages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.tspackages/ensnode-sdk/src/ensindexer/config/zod-schemas.tspackages/ensnode-sdk/src/ensrainbow/config.tspackages/ensnode-sdk/src/ensrainbow/index.tspackages/ensnode-sdk/src/ensrainbow/zod-schemas/config.tspackages/ensrainbow-sdk/src/client.ts
There was a problem hiding this comment.
Pull request overview
This PR introduces EnsRainbowPublicConfig as a shared type in @ensnode/ensnode-sdk and embeds it in EnsIndexerVersionInfo as ensRainbowPublicConfig, replacing the previous flat ensRainbow (version string) and ensRainbowSchema (integer) fields. This allows ENSIndexer to expose richer ENSRainbow service configuration (version, label set, and records count) through its public config API, which ENSApi can then forward to ENSAdmin UI.
Changes:
EnsRainbowPublicConfigtype is extracted intopackages/ensnode-sdk/src/ensrainbow/config.tsand a corresponding Zod schema (makeEnsRainbowPublicConfigSchema) is added toensrainbow/zod-schemas/config.tsEnsIndexerVersionInfo.ensRainbow+ensRainbowSchemareplaced withensRainbowPublicConfig: EnsRainbowPublicConfig; all dependent schemas, types, and mocks updated- ENSAdmin UI updated to display the new
recordsCountfield fromensRainbowPublicConfig
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
packages/ensrainbow-sdk/src/client.ts |
EnsRainbow.ENSRainbowPublicConfig changed from interface to type alias re-exporting from ensnode-sdk |
packages/ensnode-sdk/src/ensrainbow/config.ts |
New file defining EnsRainbowPublicConfig interface |
packages/ensnode-sdk/src/ensrainbow/index.ts |
Exports the new config.ts |
packages/ensnode-sdk/src/ensrainbow/zod-schemas/config.ts |
New file with Zod schemas for EnsRainbowPublicConfig |
packages/ensnode-sdk/src/ensindexer/config/types.ts |
Replaces ensRainbow+ensRainbowSchema fields with ensRainbowPublicConfig: EnsRainbowPublicConfig |
packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts |
Updates makeEnsIndexerVersionInfoSchema and removes duplicate schema helpers |
packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts |
Updates tests for new field structure |
packages/ensnode-sdk/src/ensindexer/config/labelset-utils.ts |
Updates import of makeLabelSetIdSchema/makeLabelSetVersionSchema to new location |
packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts |
Updates mock data to new field structure |
packages/ensnode-sdk/src/ensindexer/client.mock.ts |
Updates mock config to new field structure |
packages/ensnode-sdk/src/ensapi/config/conversions.test.ts |
Updates mock data to new field structure |
packages/ensnode-sdk/src/ensapi/client.test.ts |
Updates example config response to new field structure |
apps/ensindexer/src/lib/version-info.ts |
Fetches ensRainbowPublicConfig via new config() API instead of version() |
apps/ensapi/src/config/validations.ts |
Updates version mismatch check to use ensRainbowPublicConfig.version |
apps/ensapi/src/config/config.schema.test.ts |
Updates test config to new field structure |
apps/ensadmin/src/components/connection/cards/ensnode-info.tsx |
Displays recordsCount and uses ensRainbowPublicConfig for version/label set display |
apps/ensadmin/src/app/mock/config-info/data.json |
Updates mock data to new field structure |
apps/ensadmin/src/app/mock/config-api.mock.ts |
Updates mock config to new field structure |
docs/ensnode.io/src/content/docs/docs/usage/api.mdx |
Updates API example response to reflect new ensRainbowPublicConfig structure |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@greptile review |
|
@greptile review |
Additional Comments (1)
If the ENSRainbow service returns a non-2xx response whose body is not valid JSON (e.g., a plain-text |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 22 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
apps/ensindexer/src/lib/version-info.ts:138
- The invariant check for label-set compatibility between ENSIndexer client and ENSRainbow server (
invariant_ensRainbowSupportedLabelSetAndVersion) was added tomakeEnsIndexerPublicConfigSchema, which runs at deserialization time in the consumer (ENSDb Writer Worker viaensIndexerClient.config()). However, the ENSIndexer's own/api/configendpoint inapps/ensindexer/ponder/src/api/handlers/ensnode-api.tsbuilds the config viabuildENSIndexerPublicConfig()and then directly serializes it without validating throughmakeEnsIndexerPublicConfigSchema. This means:
- ENSIndexer's
/api/configwill return HTTP 200 even when there's a label-set mismatch between the configured client label set and the ENSRainbow server's actual label set. - The failure only occurs on the consumer side (ENSDb Writer Worker), not at the source.
Issue #1166 (which this PR claims to resolve) explicitly requires: "if this invariant check fails then ENSIndexer should throw an error such that ultimately the API call to get the config of the ENSIndexer instance should trigger a HTTP 500 error."
To fulfill this requirement, buildENSIndexerPublicConfig (or the /api/config handler) should run the validation via makeEnsIndexerPublicConfigSchema and return HTTP 500 if the invariant fails. Note that deserializeEnsIndexerPublicConfig already performs this validation, so wrapping the built config through that schema would trigger the check and allow the handler to catch and return HTTP 500.
export async function getENSIndexerVersionInfo(): Promise<ENSIndexerVersionInfo> {
const ensRainbowApiClient = getENSRainbowApiClient();
const ensRainbowPublicConfig = await ensRainbowApiClient.config();
// ENSIndexer version
const ensIndexerVersion = packageJson.version;
// ENSDb version
// ENSDb version is always the same as the ENSIndexer version number
const ensDbVersion = ensIndexerVersion;
// parse unvalidated version info
const schema = makeENSIndexerVersionInfoSchema();
const parsed = schema.safeParse({
ensRainbowPublicConfig,
nodejs: process.versions.node,
ponder: getPackageVersion("ponder"),
ensDb: ensDbVersion,
ensIndexer: ensIndexerVersion,
ensNormalize: getPackageVersion("@adraffy/ens-normalize"),
} satisfies SerializedENSIndexerVersionInfo);
if (parsed.error) {
throw new Error(`Cannot deserialize ENSIndexerVersionInfo:\n${prettifyError(parsed.error)}\n`);
}
// return version info we have now validated
return parsed.data;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
lightwalker-eth
left a comment
There was a problem hiding this comment.
@tk-o Looks good! 1 question but appreciate your advice on how to proceed on it 👍
| ensRainbowSchema: number; | ||
| * ENSRainbow public config | ||
| */ | ||
| ensRainbowPublicConfig: EnsRainbowPublicConfig; |
There was a problem hiding this comment.
This field should be moved out of EnsIndexerVersionInfo and into EnsIndexerPublicConfig.
Goal: It's not a version number like all the other fields in EnsIndexerVersionInfo
…Config` data model
5a29a9d to
5fd3bb3
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
apps/ensindexer/src/config/public.ts:33
- The
buildENSIndexerPublicConfigfunction assembles the config and returns it without passing it throughmakeEnsIndexerPublicConfigSchema, so the newinvariant_ensRainbowSupportedLabelSetAndVersioncheck (which validates that the server labelSet from ENSRainbow is compatible with the client labelSet) is never triggered on the ENSIndexer server side. As a result, the/configHTTP endpoint will return a 200 response with mismatched label set data rather than a 500 error as required by issue #1166. The invariant check should be applied to the built config inbuildENSIndexerPublicConfig(or in the/configroute handler) so that a misconfiguration causes a server-side error.
export async function buildENSIndexerPublicConfig(
config: EnsIndexerConfig,
): Promise<EnsIndexerPublicConfig> {
const [versionInfo, ensRainbowPublicConfig] = await Promise.all([
getENSIndexerVersionInfo(),
ensRainbowApiClient.config(),
]);
return {
databaseSchemaName: config.databaseSchemaName,
ensRainbowPublicConfig,
labelSet: config.labelSet,
indexedChainIds: config.indexedChainIds,
isSubgraphCompatible: config.isSubgraphCompatible,
namespace: config.namespace,
plugins: config.plugins,
versionInfo,
};
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
apps/ensindexer/src/config/public.ts:34
- Issue #1166 requires that when ENSIndexer detects a label set mismatch between its configured client label set and the ENSRainbow server label set, the
/api/configendpoint must return an HTTP 500 error. This requirement is not met.
buildENSIndexerPublicConfig constructs the config object and returns it without running it through makeEnsIndexerPublicConfigSchema. The invariant invariant_ensRainbowSupportedLabelSetAndVersion is only applied during deserialization on the consuming side (e.g. in EnsIndexerClient.config()), not on the ENSIndexer server side when building and serving the response.
To meet the requirement, buildENSIndexerPublicConfig (or the /api/config handler) should validate the constructed config through makeEnsIndexerPublicConfigSchema, and if the validation fails due to label set mismatch, the error should propagate as an HTTP 500. For example, the built config can be passed through makeEnsIndexerPublicConfigSchema().parse(config) (with proper handling of the Set<ChainId> type), or validateSupportedLabelSetAndVersion can be called directly in buildENSIndexerPublicConfig.
export async function buildENSIndexerPublicConfig(
config: EnsIndexerConfig,
): Promise<EnsIndexerPublicConfig> {
const [versionInfo, ensRainbowPublicConfig] = await Promise.all([
getENSIndexerVersionInfo(),
ensRainbowApiClient.config(),
]);
return {
databaseSchemaName: config.databaseSchemaName,
ensRainbowPublicConfig,
labelSet: config.labelSet,
indexedChainIds: config.indexedChainIds,
isSubgraphCompatible: config.isSubgraphCompatible,
namespace: config.namespace,
plugins: config.plugins,
versionInfo,
};
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "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": 133856894 | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
The example JSON response in the documentation shows ensRainbowPublicConfig nested inside versionInfo, but according to the actual type definitions (EnsIndexerPublicConfig in packages/ensnode-sdk/src/ensindexer/config/types.ts), ensRainbowPublicConfig is a top-level field of the config, not a child of versionInfo. The versionInfo object only contains nodejs, ponder, ensDb, ensIndexer, and ensNormalize.
The example response should be corrected: ensRainbowPublicConfig should appear as a top-level sibling of versionInfo, labelSet, namespace, etc., and the versionInfo block should not contain ensRainbowPublicConfig.
Lite PR
Tip: Review docs on the ENSNode PR process
Summary
ensRainbowPublicConfig: EnsRainbowPublicConfigfield toEnsIndexerPublicConfigEnsIndexerPublicConfigdata modelEnsIndexerPublicConfigschema which ensures ENSRainbow labelset match between server labelset and client labelset.Why
ensRainbowfield to be added to the ENSIndexer version info object. I figured, that we could simply reference a fullEnsRainbowPublicConfigobject, so it was natural to useensRainbowPublicConfigto name the new field within the ENSIndexer version info object.Testing
Notes for Reviewer (Optional)
Pre-Review Checklist (Blocking)
Resolves #1166, #1168.