Skip to content

feat(ensapi): DomainResolver.effective (ENSv1 + ENSv2)#2265

Merged
shrugs merged 7 commits into
mainfrom
feat/domain-effective-resolver
Jun 5, 2026
Merged

feat(ensapi): DomainResolver.effective (ENSv1 + ENSv2)#2265
shrugs merged 7 commits into
mainfrom
feat/domain-effective-resolver

Conversation

@shrugs
Copy link
Copy Markdown
Member

@shrugs shrugs commented Jun 5, 2026

Summary

Adds DomainResolver.effective to the Omnigraph API — the Resolver that ENS Forward Resolution (ENSIP-10) lands on for a Domain, identified from indexed data. Complements the existing DomainResolver.assigned (the Domain's directly-assigned Resolver).

To make this work against ENSv2 data (where Domains are keyed by StorageId, not namehash), findResolverWithIndex is made ENSv2-aware.

Changes

Effective resolver

  • get-domain-resolver.ts — adds getDomainEffectiveResolver (resolves via findResolverWithIndex from the root registry); renames getDomainResolvergetDomainAssignedResolver. domain-resolver.ts exposes the nullable effective: Resolver field.

ENSv1/ENSv2 fork in findResolverWithIndex

  • ENSv1-only namespaces (no ENSv2Root datasource) keep the namehash + Domain-Resolver-Relation lookup, depending only on Protocol Acceleration data — so it still works when the Protocol Acceleration plugin runs in isolation.
  • ENSv2 namespaces walk the namegraph by labelHash (forwardWalkDisjointNamegraph) and return the deepest ancestor Domain with an assigned Resolver — which also yields ENSIP-10 fallback for free.
  • The ENSv2 walk reads the Unigraph-maintained domain table; the fork preserves the ENSv1 protocol-acceleration-only path until the plugins are folded. TODO(fold-protocol-acceleration) markers prep the codebase for that refactor (the ENSv1 path then deletes and the walk handles both).
  • Extracted the disjoint namegraph walk into a shared forward-walk-namegraph module, now reused by findResolverWithIndex and getDomainIdByInterpretedName (DRY).
  • ensnode-sdk: adds getRootRegistry (AccountId, ENSv2-preferring) and DRYs getRootRegistryId through it.

Test fixture + integration test

  • Seeds noresolver.parent.eth (no Resolver, under the Resolver-bearing parent.eth) to exercise effective-Resolver fallback.
  • Integration test covers assigned === effective and the fallback case.

Validation

  • pnpm generate, root pnpm typecheck, pnpm lint
  • pnpm test --project ensapi ✅ (288)
  • New integration test ✅ (2/2), validated end-to-end against the ENSv2 devnet — assigned === effective for resolver-bearing names, and noresolver.parent.ethassigned: null, effective = parent.eth's resolver.

Adds `DomainResolver.effective`, the Resolver that ENS Forward Resolution
(ENSIP-10) lands on for a Domain, identified from indexed data via
findResolverWithIndex. Renames getDomainResolver -> getDomainAssignedResolver
to disambiguate from the new effective-resolver lookup.
@shrugs shrugs requested a review from a team as a code owner June 5, 2026 15:24
Copilot AI review requested due to automatic review settings June 5, 2026 15:24
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Jun 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
enskit-react-example.ensnode.io Ready Ready Preview, Comment Jun 5, 2026 5:04pm
3 Skipped Deployments
Project Deployment Actions Updated (UTC)
admin.ensnode.io Skipped Skipped Jun 5, 2026 5:04pm
ensnode.io Skipped Skipped Jun 5, 2026 5:04pm
ensrainbow.io Skipped Skipped Jun 5, 2026 5:04pm

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 5, 2026

🦋 Changeset detected

Latest commit: 277717d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 24 packages
Name Type
ensapi Patch
ensindexer Patch
ensadmin Patch
ensrainbow Patch
fallback-ensapi Patch
enssdk Patch
enscli Patch
enskit Patch
ensskills Patch
@ensnode/datasources Patch
@ensnode/ensrainbow-sdk Patch
@ensnode/ensdb-sdk Patch
@ensnode/ensnode-sdk Patch
@ensnode/integration-test-env Patch
@ensnode/ponder-sdk Patch
@ensnode/ponder-subgraph Patch
@ensnode/shared-configs Patch
@docs/ensnode Patch
@docs/ensrainbow Patch
@namehash/ens-referrals Patch
@namehash/namehash-ui Patch
@ensnode/ensindexer-perf-testing Patch
@ensnode/enskit-react-example Patch
@ensnode/enssdk-example Patch

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

Warning

Review limit reached

@shrugs, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 31 minutes and 42 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: efd837e9-f0ac-40e6-abe6-d7edd5ac9bf9

📥 Commits

Reviewing files that changed from the base of the PR and between d68631e and 277717d.

📒 Files selected for processing (3)
  • apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts
  • apps/ensapi/src/lib/protocol-acceleration/forward-walk-disjoint-namegraph.ts
  • apps/ensapi/src/omnigraph-api/lib/get-domain-by-interpreted-name.ts
📝 Walkthrough

Walkthrough

Adds DomainResolver.effective via an exported resolver finder and ENSv2 namegraph walker, new getDomainAssignedResolver/getDomainEffectiveResolver helpers, GraphQL wiring, SKILL docs and changeset, integration tests, and devnet fixture/seed support.

Changes

DomainResolver.effective Implementation

Layer / File(s) Summary
Resolver finder and ENSv2 routing
apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts
Refactors and exports findResolverWithIndex, adds ENSv2-specific internal findResolverWithIndexENSv2, and preserves ENSv1 logic in an internal helper.
Shared forward-walk namegraph utility
apps/ensapi/src/lib/protocol-acceleration/forward-walk-namegraph.ts
New tracer, WalkResultRow shape, hasResolver guard, and forwardWalkDisjointNamegraph recursive SQL traversal returning ancestor rows with resolver data.
Integrate shared walker into name resolution flow
apps/ensapi/src/omnigraph-api/lib/get-domain-by-interpreted-name.ts
Replace local disjoint-walk with imports of forwardWalkDisjointNamegraph/hasResolver and adjust imports/termination behavior accordingly.
Assigned and effective resolver helpers
apps/ensapi/src/omnigraph-api/lib/get-domain-resolver.ts
Rename getDomainResolvergetDomainAssignedResolver; add getDomainEffectiveResolver that loads domain, uses the Root Registry and findResolverWithIndex to compute effective resolver id or null.
Root Registry selection helper
packages/ensnode-sdk/src/shared/root-registry.ts
Add getRootRegistry to pick preferred root contract (ENSv2 if available) and update getRootRegistryId to use makeConcreteRegistryId(getRootRegistry(namespace)).
GraphQL wiring and schema docs
apps/ensapi/src/omnigraph-api/schema/domain-resolver.ts, packages/ensskills/skills/omnigraph/SKILL.md, .changeset/domain-resolver-effective.md
Wire DomainResolverRef.assignedgetDomainAssignedResolver and effectivegetDomainEffectiveResolver; document effective in SKILL and release notes.
Integration test and devnet seeding/fixtures
apps/ensapi/src/omnigraph-api/schema/domain-resolver.integration.test.ts, packages/integration-test-env/src/devnet/fixtures.ts, packages/integration-test-env/src/seed/effective-resolver-fallback.ts, packages/integration-test-env/src/seed/index.ts
Add integration test asserting effective resolver behavior, add effectiveResolverFallback fixture, seed a subdomain without a resolver, and include the seed in devnet initialization.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • namehash/ensnode#1758: Touches root-registry selection logic related to ENSv2 root availability used when computing effective resolver.

Poem

🐰 I hop the namegraph, sniff each lair,
Assigned ones sit, the effective's found elsewhere.
From root to leaf I trace the trail,
A tiny hop, then wag my tail.
Resolver found — a carrot-scale!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding DomainResolver.effective support for both ENSv1 and ENSv2, which is the primary objective of this PR.
Description check ✅ Passed The description comprehensively covers all required template sections: Summary (clear bullet points), Why (ENSIP-10 and ENSv2 support rationale), Testing (validation results including tests and devnet verification), and includes helpful implementation notes.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/domain-effective-resolver

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Member Author

@shrugs shrugs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run pnpm generate

Comment thread .changeset/domain-resolver-effective.md Outdated
Comment thread apps/ensapi/src/omnigraph-api/schema/domain-resolver.ts Outdated
@shrugs
Copy link
Copy Markdown
Member Author

shrugs commented Jun 5, 2026

@greptile review

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 5, 2026

Greptile Summary

This PR adds DomainResolver.effective to the Omnigraph API — the Resolver that ENSIP-10 forward resolution lands on for a Domain — complementing the existing DomainResolver.assigned. To support ENSv2 namespaces (where Domains are keyed by StorageId rather than namehash), findResolverWithIndex is extended with an ENSv1/ENSv2 fork and the disjoint namegraph walk is extracted into a reusable shared module.

  • New effective field: getDomainEffectiveResolver reads domain.canonicalName, delegates to findResolverWithIndex starting from the Root Registry, and returns a ResolverId — or null when the domain is outside the canonical nametree or has no active resolver.
  • ENSv1/ENSv2 fork: The fork is driven by maybeGetDatasource(ENSv2Root): ENSv1-only namespaces keep the existing namehash-keyed DRR lookup (Protocol Acceleration only); ENSv2 namespaces use forwardWalkDisjointNamegraph to walk by labelHash and return the deepest ancestor with a resolver, naturally implementing ENSIP-10 fallback.
  • Shared namegraph walk + integration tests: The recursive CTE walk is extracted into forward-walk-disjoint-namegraph.ts and reused by both findResolverWithIndex (ENSv2 path) and getDomainIdByInterpretedName. Two integration tests validate assigned === effective for resolver-bearing names and the fallback case for the new noresolver.parent.eth fixture.

Confidence Score: 5/5

This PR is safe to merge. The changes are well-scoped, the ENSv1/ENSv2 fork is guarded by an existing datasource-presence check, and both the new namegraph walk and the effective-resolver lookup are covered by integration tests validated against the ENSv2 devnet.

The logic is cleanly decomposed: getDomainEffectiveResolver reads a typed InterpretedName from the DB schema, the ENSv1 path is strictly additive to existing Protocol Acceleration behavior, and the ENSv2 path reuses the same recursive CTE that already powers getDomainIdByInterpretedName. The forwardWalkDisjointNamegraph LEFT JOIN on domainResolverRelation is correct for ENSv2 (StorageId-keyed domains have at most one DRR entry per domain), and the depth-to-name mapping in findResolverWithIndexENSv2 is arithmetically correct. No pre-existing invariants are broken.

No files require special attention.

Important Files Changed

Filename Overview
apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts Adds ENSv1/ENSv2 fork in findResolverWithIndex: ENSv1-only namespaces keep the existing namehash-keyed DRR lookup; ENSv2 namespaces use the new namegraph walk. Fork decision via maybeGetDatasource(ENSv2Root) is clean and matches the existing pattern.
apps/ensapi/src/lib/protocol-acceleration/forward-walk-disjoint-namegraph.ts New shared module extracted from get-domain-by-interpreted-name.ts. Recursive CTE walks the namegraph by labelHash, LEFT JOINs each domain to its DRR, and returns rows depth-DESC. The hasResolver guard and over-depth guard are correct; Param usage follows the documented workaround for drizzle-orm array parameters.
apps/ensapi/src/omnigraph-api/lib/get-domain-resolver.ts Adds getDomainEffectiveResolver: reads domain.canonicalName (typed InterpretedName in the schema), delegates to findResolverWithIndex from the Root Registry, and constructs the ResolverId with the Root Registry's chainId. Logic is straightforward and the null-return paths are well-guarded.
apps/ensapi/src/omnigraph-api/schema/domain-resolver.ts Exposes the new effective: Resolver nullable field on DomainResolver, wired to getDomainEffectiveResolver. Schema description is accurate and distinguishes assigned vs effective correctly.
packages/ensnode-sdk/src/shared/root-registry.ts Adds getRootRegistry (AccountId) alongside getRootRegistryId (RegistryId), both returning ENSv2 Root when defined, ENSv1 Root otherwise. DRYs getRootRegistryId through getRootRegistry. Clean and consistent with existing helpers.
apps/ensapi/src/omnigraph-api/schema/domain-resolver.integration.test.ts Two integration tests cover both the assigned === effective case for a domain with its own resolver, and the ENSIP-10 fallback case for noresolver.parent.eth. Assertions are precise and correctly exercise the new field end-to-end.
apps/ensapi/src/omnigraph-api/lib/get-domain-by-interpreted-name.ts Refactored to consume the extracted forwardWalkDisjointNamegraph from the new shared module; logic is functionally unchanged. Clean DRY improvement.
packages/integration-test-env/src/seed/effective-resolver-fallback.ts Seeds noresolver.parent.eth with resolver=zeroAddress under parent.eth to exercise ENSIP-10 fallback. Guards against a missing parent subregistry and correctly reuses the devnet fixture constants.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[DomainResolver.effective] --> B[getDomainEffectiveResolver]
    B --> C{domain.canonicalName?}
    C -- null --> D[return null]
    C -- present --> E[getRootRegistry]
    E --> F[findResolverWithIndex]
    F --> G{ENSv2Root datasource present?}
    G -- No --> H[findResolverWithIndexENSv1\nnamehash-keyed DRR lookup]
    G -- Yes --> I[findResolverWithIndexENSv2\nnamegraph walk]
    H --> J{DRR found?}
    I --> K[forwardWalkDisjointNamegraph\nRecursive CTE by labelHash]
    K --> L{deepest ancestor\nwith resolver?}
    L -- none --> M[NULL_RESULT]
    L -- found --> N[activeResolver + activeName]
    J -- none --> M
    J -- found --> N
    N --> O[makeResolverId\nregistry.chainId + activeResolver]
    M --> D
Loading

Reviews (6): Last reviewed commit: "refactor(ensapi): rename forward-walk-na..." | Re-trigger Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 5, 2026

Greptile Summary

Adds DomainResolver.effective to the Omnigraph GraphQL API — the Resolver that ENS Forward Resolution (ENSIP-10) lands on for a Domain, found by walking the name hierarchy within the Domain's Registry via indexed data. This complements the existing DomainResolver.assigned field and makes findResolverWithIndex exported.

  • getDomainEffectiveResolver — new function that loads a Domain (with its Registry), guards against non-canonical domains (canonicalName null), delegates ENSIP-10 hierarchy walking to findResolverWithIndex, and returns the active resolver as a ResolverId for the ResolverRef dataloader.
  • findResolverWithIndex — made export; no logic change. Contains an existing TODO noting it is ENSv1-specific, so ENSv2 canonical domains will silently return null for effective until that work is done.
  • Generated files (schema.graphql, introspection.ts) and SKILL.md updated consistently via pnpm generate.

Confidence Score: 4/5

Safe to merge; the new field is additive and nullable, the rename is internal-only, and all generated artifacts are consistent.

The implementation is clean and well-guarded: the canonicalName null-check correctly short-circuits for non-canonical domains, findResolverWithIndex already handles the ENSIP-10 hierarchy walk correctly for ENSv1, and the ResolverId return flows naturally into the existing loadableObjectRef dataloader. The one thing worth noting is that findResolverWithIndex is documented (via its own TODO) as ENSv1-only — ENSv2 canonical domains will silently get null for effective, which is a silent false-negative rather than a crash, and is a known pre-existing limitation being tracked separately.

apps/ensapi/src/omnigraph-api/lib/get-domain-resolver.ts warrants a second look if/when ENSv2 resolver support is added, to ensure getDomainEffectiveResolver branches correctly by domain type.

Important Files Changed

Filename Overview
apps/ensapi/src/omnigraph-api/lib/get-domain-resolver.ts Core logic change: renames getDomainResolver → getDomainAssignedResolver (no logic change) and adds getDomainEffectiveResolver; fetches domain+registry, guards on canonicalName, delegates to findResolverWithIndex, returns a ResolverId.
apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts Single change: exports findResolverWithIndex (was module-private). No logic change.
apps/ensapi/src/omnigraph-api/schema/domain-resolver.ts Wires up the new effective field to getDomainEffectiveResolver; assigned field updated to use renamed getDomainAssignedResolver.
packages/enssdk/src/omnigraph/generated/schema.graphql Auto-generated: adds effective: Resolver to the DomainResolver type in the SDL.
packages/ensskills/skills/omnigraph/SKILL.md Documentation: adds effective: Resolver bullet to DomainResolver section of the Omnigraph skill guide.

Sequence Diagram

sequenceDiagram
    participant C as GraphQL Client
    participant DR as DomainResolver (Pothos)
    participant GER as getDomainEffectiveResolver
    participant GAR as getDomainAssignedResolver
    participant DB as ensDb
    participant FRI as findResolverWithIndex
    participant RL as ResolverRef Loader

    C->>DR: "query { domain { resolver { assigned effective } } }"

    DR->>GAR: getDomainAssignedResolver(domainId)
    GAR->>DB: domainResolverRelation.findFirst(domainId, with: resolver)
    DB-->>GAR: DRR with resolver object
    GAR-->>DR: "Resolver | undefined"

    DR->>GER: getDomainEffectiveResolver(domainId)
    GER->>DB: "domain.findFirst(id=domainId, with: registry)"
    DB-->>GER: "Domain { canonicalName, registry }"
    alt canonicalName is null
        GER-->>DR: null
    else canonicalName present
        GER->>FRI: findResolverWithIndex(registry, canonicalName)
        FRI->>DB: domainResolverRelation.findMany(registry + name hierarchy)
        DB-->>FRI: DRR records
        FRI-->>GER: "{ activeResolver: Address | null }"
        alt no active resolver
            GER-->>DR: null
        else resolver found
            GER-->>DR: ResolverId
        end
    end

    DR->>RL: load([ResolverId])
    RL->>DB: resolver.findMany(ids)
    DB-->>RL: Resolver[]
    RL-->>DR: "Resolver | null"

    DR-->>C: "{ assigned: Resolver, effective: Resolver | null }"
Loading

Reviews (2): Last reviewed commit: "docs: trim DomainResolver.effective desc..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the ENSAPI Omnigraph GraphQL surface to expose a Domain’s ENSIP-10 effective resolver (derived by walking the canonical name hierarchy within the domain’s registry using indexed Domain↔Resolver relationships), complementing the existing directly-assigned resolver field.

Changes:

  • Adds DomainResolver.effective: Resolver to the Omnigraph API and generated SDL.
  • Introduces getDomainEffectiveResolver(domainId) and renames the existing assigned-resolver helper to getDomainAssignedResolver.
  • Exports findResolverWithIndex for reuse by Omnigraph API logic, and adds a Changeset for an ensapi patch release.

Reviewed changes

Copilot reviewed 5 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/enssdk/src/omnigraph/generated/schema.graphql Generated SDL updated to include DomainResolver.effective.
apps/ensapi/src/omnigraph-api/schema/domain-resolver.ts Adds the new effective resolver field and wires it to the new lib helper.
apps/ensapi/src/omnigraph-api/lib/get-domain-resolver.ts Splits assigned vs effective resolver lookup into separate exported helpers.
apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts Exports findResolverWithIndex for external use by Omnigraph API.
.changeset/domain-resolver-effective.md Declares an ensapi patch release for the new API field.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts Outdated
Comment thread apps/ensapi/src/omnigraph-api/schema/domain-resolver.ts
shrugs added 2 commits June 5, 2026 10:38
Make findResolverWithIndex ENSv2-aware so DomainResolver.effective works
across both data models. It now forks by namespace: ENSv1-only namespaces
keep the namehash + Domain-Resolver-Relation lookup (Protocol Acceleration
data only), while ENSv2 namespaces walk the namegraph by labelHash and
return the deepest ancestor Domain with an assigned Resolver.

- Extract the disjoint namegraph walk into a shared
  forward-walk-namegraph module, reused by findResolverWithIndex and
  getDomainIdByInterpretedName.
- Add getRootRegistry (AccountId) and DRY getRootRegistryId through it.
- Seed noresolver.parent.eth (no Resolver under a Resolver-bearing parent)
  to exercise effective-Resolver fallback, plus an integration test
  covering assigned===effective and the fallback case.

The ENSv2 walk depends on the Unigraph-maintained domain table; the fork
preserves protocol-acceleration-in-isolation for ENSv1 until the plugins
are folded (TODO(fold-protocol-acceleration) markers added).
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
packages/ensskills/skills/omnigraph/SKILL.md (1)

142-142: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove implementation detail from the effective field description.

The description includes "identified by walking the name hierarchy within the Domain's Registry", but this phrase was requested to be dropped in a previous review and is inconsistent with the authoritative schema source in apps/ensapi/src/omnigraph-api/schema/domain-resolver.ts, which describes the field as simply "The Resolver that ENS Forward Resolution (ENSIP-10) lands on for this Domain — i.e. its effective Resolver."

📝 Align with schema source
-- effective: Resolver — The Resolver that ENS Forward Resolution (ENSIP-10) lands on for this Domain — i.e. its _effective_ Resolver, identified by walking the name hierarchy within the Domain's Registry. Null when no active Resolver exists or the Domain is not in the canonical nametree.
+- effective: Resolver — The Resolver that ENS Forward Resolution (ENSIP-10) lands on for this Domain — i.e. its _effective_ Resolver. Null when no active Resolver exists or the Domain is not in the Canonical Nametree.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ensskills/skills/omnigraph/SKILL.md` at line 142, Update the
"effective" field description in packages/ensskills/skills/omnigraph/SKILL.md to
match the authoritative schema in
apps/ensapi/src/omnigraph-api/schema/domain-resolver.ts by removing the
implementation detail phrase "identified by walking the name hierarchy within
the Domain's Registry" so the description reads only "The Resolver that ENS
Forward Resolution (ENSIP-10) lands on for this Domain — i.e. its effective
Resolver" and preserve the note about null when no active Resolver exists or the
Domain is not in the canonical nametree.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/ensapi/src/lib/protocol-acceleration/forward-walk-namegraph.ts`:
- Around line 34-35: The helper forwardWalkDisjointNamegraph currently accepts
paths longer than the CTE limit and can silently truncate them; add an explicit
guard at the start of forwardWalkDisjointNamegraph that checks if path.length >
MAX_SUPPORTED_NAME_DEPTH and rejects (throw an Error or return a clear failure)
instead of proceeding, and apply the same guard to the other related helper(s)
in this file (the block covering lines 42-75) so that findResolverWithIndexENSv2
cannot resolve with an over-depth path; reference the constant
MAX_SUPPORTED_NAME_DEPTH and the function name forwardWalkDisjointNamegraph (and
mirror this check in the sibling function(s) in the same file).

In `@apps/ensapi/src/omnigraph-api/lib/get-domain-resolver.ts`:
- Around line 34-51: The code currently uses getRootRegistry(namespace) and then
calls findResolverWithIndex(registry, domain.canonicalName) and makeResolverId({
chainId: registry.chainId, address: activeResolver }), which pins resolution to
the root registry; instead load the Domain's registry from the Domain record you
fetched (e.g., domain.registry or domain.registryId) and pass that domain
registry into findResolverWithIndex and makeResolverId so both the lookup and
the resulting resolver id use the Domain's own registry rather than the root
registry.

---

Duplicate comments:
In `@packages/ensskills/skills/omnigraph/SKILL.md`:
- Line 142: Update the "effective" field description in
packages/ensskills/skills/omnigraph/SKILL.md to match the authoritative schema
in apps/ensapi/src/omnigraph-api/schema/domain-resolver.ts by removing the
implementation detail phrase "identified by walking the name hierarchy within
the Domain's Registry" so the description reads only "The Resolver that ENS
Forward Resolution (ENSIP-10) lands on for this Domain — i.e. its effective
Resolver" and preserve the note about null when no active Resolver exists or the
Domain is not in the canonical nametree.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f1c8774f-25a8-4649-9dfd-75b1f648902a

📥 Commits

Reviewing files that changed from the base of the PR and between aee85b6 and d68631e.

⛔ Files ignored due to path filters (2)
  • packages/enssdk/src/omnigraph/generated/introspection.ts is excluded by !**/generated/**
  • packages/enssdk/src/omnigraph/generated/schema.graphql is excluded by !**/generated/**
📒 Files selected for processing (12)
  • .changeset/domain-resolver-effective.md
  • apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts
  • apps/ensapi/src/lib/protocol-acceleration/forward-walk-namegraph.ts
  • apps/ensapi/src/omnigraph-api/lib/get-domain-by-interpreted-name.ts
  • apps/ensapi/src/omnigraph-api/lib/get-domain-resolver.ts
  • apps/ensapi/src/omnigraph-api/schema/domain-resolver.integration.test.ts
  • apps/ensapi/src/omnigraph-api/schema/domain-resolver.ts
  • packages/ensnode-sdk/src/shared/root-registry.ts
  • packages/ensskills/skills/omnigraph/SKILL.md
  • packages/integration-test-env/src/devnet/fixtures.ts
  • packages/integration-test-env/src/seed/effective-resolver-fallback.ts
  • packages/integration-test-env/src/seed/index.ts

Comment thread apps/ensapi/src/omnigraph-api/lib/get-domain-resolver.ts
Copilot AI review requested due to automatic review settings June 5, 2026 16:48
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io June 5, 2026 16:48 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io June 5, 2026 16:48 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io June 5, 2026 16:48 Inactive
Comment thread apps/ensapi/src/omnigraph-api/lib/get-domain-resolver.ts
Guard against paths longer than MAX_SUPPORTED_NAME_DEPTH so an over-depth
name throws rather than resolving against a CTE-truncated ancestor path.
@shrugs
Copy link
Copy Markdown
Member Author

shrugs commented Jun 5, 2026

@greptile review

@vercel vercel Bot temporarily deployed to Preview – ensnode.io June 5, 2026 16:52 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io June 5, 2026 16:52 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io June 5, 2026 16:52 Inactive
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 14 changed files in this pull request and generated 1 comment.

…k-disjoint-namegraph

Match the file name to its contents (forwardWalkDisjointNamegraph + helpers).
Copilot AI review requested due to automatic review settings June 5, 2026 17:04
@vercel vercel Bot temporarily deployed to Preview – ensnode.io June 5, 2026 17:04 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io June 5, 2026 17:04 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io June 5, 2026 17:04 Inactive
@shrugs shrugs merged commit c6f9643 into main Jun 5, 2026
21 checks passed
@shrugs shrugs deleted the feat/domain-effective-resolver branch June 5, 2026 17:07
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 14 changed files in this pull request and generated 1 comment.

Comment on lines +32 to +37
effective: t.field({
description:
"The Resolver that ENS Forward Resolution (ENSIP-10) lands on for this Domain — i.e. its _effective_ Resolver. Null when no active Resolver exists or the Domain is not in the Canonical Nametree.",
type: ResolverRef,
nullable: true,
resolve: (domainId) => getDomainEffectiveResolver(domainId),
@github-actions github-actions Bot mentioned this pull request Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants