Skip to content

feat(ensapi): add Account.nameReferences Omnigraph field#2292

Open
shrugs wants to merge 7 commits into
mainfrom
feat/account-name-references
Open

feat(ensapi): add Account.nameReferences Omnigraph field#2292
shrugs wants to merge 7 commits into
mainfrom
feat/account-name-references

Conversation

@shrugs

@shrugs shrugs commented Jun 12, 2026

Copy link
Copy Markdown
Member

Resolves #1962.

Adds Account.nameReferences to the Omnigraph API: the Names whose indexed addr() record points at an Account ("names pointing to this address"), as a cursor-paginated Relay connection over a new NameReference type, optionally scoped to a single CoinType.

This replaces Portal's reliance on ensjs subgraph getResolvedNamesForAddress for /addr/$addr/resolution. Unblocked by the canonicalNode materialization.

API

type Account {
  nameReferences(
    where: AccountNameReferencesWhereInput   # optional → all coinTypes
    first: Int, last: Int, before: String, after: String
  ): AccountNameReferencesConnection
}

input AccountNameReferencesWhereInput { coinType: CoinType }

type NameReference {
  domain: Domain!        # canonical Domain whose addr(coinType) record points here
  coinType: CoinType!    # the matching addr() coinType
  resolver: Resolver!    # the Resolver holding the record
  match: Boolean!        # ENSIP-19 reverse resolution of (address, coinType) === this name
}

Design notes

  • Rich node, not flat strings. The issue's draft returned name: String! + flat resolverAddress/resolverChainId/normalized. Since domain.canonicalNode is now materialized, the node returns the real domain: Domain! (free interpreted/beautified names, ownership, navigation) and resolver: Resolver! (contract carries address + chainId). Dropped the redundant normalized (already first-class via CanonicalName).
  • Access path. resolver_address_records WHERE value = <addr> [AND coin_type = ?] INNER JOIN domain ON domain.canonicalNode = rar.node. Backed by a new (value, coinType) index on resolver_address_records; the join rides the existing byCanonicalNode hash index.
  • Canonical-only (inner join). Records whose node has no canonical Domain are omitted — correct for a "names pointing here" UI and consistent with the issue's literally-indexed framing. Documented on the field.
  • match resolves via full ENSIP-19 reverse resolution (resolveReverse) — covering both the legacy addr.reverse and StandaloneReverseRegistrar (default.reverse / [coinType].reverse) mechanisms, with forward verification. Accelerated from the index where supported; batched per (account, coinType) within a request via a dataloader.
  • Pagination: composite keyset cursor over the resolver_address_records PK.

v1 scope (per issue)

  • The records surfaced are literally-indexed: no Forward Resolution / CCIP-Read, no ENSIP-19 address record defaulting. (match is the exception — it performs reverse resolution.)
  • No active-resolver consistency enforcement (tracked separately) — records on resolvers no longer assigned to the Domain may surface.

Tests / validation

  • pnpm generate (idempotent), root typecheck, lint, and pnpm test --project ensapi (293) all green on main base.
  • Added Account.nameReferences integration tests (coinType scoping, isolation, all-coinTypes) using the seeded test.eth rootstock addr record. These require the devnet stack (pnpm test:integration:ci) and were not run locally.

Follow-ups

Surface the Names whose indexed addr() record points at an Account
("names pointing to this address") as a cursor-paginated connection over
a new NameReference type, optionally scoped to a single CoinType.

Each NameReference exposes the canonical domain, the matching coinType,
the resolver holding the record, and match (whether the indexed ENSIP-19
reverse shortcut resolves back to that exact name). Reflects literally-
indexed, canonical Domains only: records whose node has no canonical
Domain are omitted, and Forward Resolution / CCIP-Read and ENSIP-19
default-address-record expansion are not applied. Backed by a new
(value, coinType) index on resolver_address_records.

Resolves #1962
Copilot AI review requested due to automatic review settings June 12, 2026 16:32
@changeset-bot

changeset-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ff3844d

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

This PR includes changesets to release 24 packages
Name Type
ensapi Minor
@ensnode/ensdb-sdk Minor
ensindexer Minor
@ensnode/integration-test-env Minor
@ensnode/ensnode-sdk Minor
ensadmin Minor
ensrainbow Minor
fallback-ensapi Minor
enssdk Minor
enscli Minor
enskit Minor
ensskills Minor
@ensnode/datasources Minor
@ensnode/ensrainbow-sdk Minor
@ensnode/ponder-sdk Minor
@ensnode/ponder-subgraph Minor
@ensnode/shared-configs Minor
@docs/ensnode Minor
@docs/ensrainbow Minor
@namehash/ens-referrals Minor
@namehash/namehash-ui Minor
@ensnode/ensindexer-perf-testing Minor
@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

@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

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 12, 2026 10:32pm
3 Skipped Deployments
Project Deployment Actions Updated (UTC)
admin.ensnode.io Skipped Skipped Jun 12, 2026 10:32pm
ensnode.io Skipped Skipped Jun 12, 2026 10:32pm
ensrainbow.io Skipped Skipped Jun 12, 2026 10:32pm

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

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 45 minutes and 41 seconds. Learn how PR review limits work.

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

⌛ 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: fda297d1-769b-4e9e-abcd-004f6f9699f8

📥 Commits

Reviewing files that changed from the base of the PR and between 65282b8 and ff3844d.

📒 Files selected for processing (2)
  • apps/ensapi/src/omnigraph-api/context.ts
  • apps/ensapi/src/omnigraph-api/schema/resolver-records.ts
📝 Walkthrough

Walkthrough

Adds Account.nameReferences: a cursor-paginated GraphQL connection that returns canonical Domains whose indexed addr() records target an account, with optional coinType filtering; includes DB index, keyset resolver, GraphQL types/field, tests, context DataLoader, docs, and TODOs for coinType bigint migration.

Changes

Account.nameReferences GraphQL Feature

Layer / File(s) Summary
Database indexing and schema changes
packages/ensdb-sdk/src/ensindexer-abstract/protocol-acceleration.schema.ts, .changeset/name-references-ensdb-sdk.md
Adds (value, coinType) index on resolver_address_records and annotates TODOs for future coinType int8 migration.
Keyset pagination resolver
apps/ensapi/src/omnigraph-api/lib/find-name-references/find-name-references-resolver.ts
Exports NameReferenceModel and resolveAccountNameReferences: filters WHERE value = account (+ optional coinType), INNER JOINs node→canonical Domain, orders by (node, coinType, chainId, address), implements keyset pagination with opaque composite cursors, and maps rows into response models.
GraphQL types, field, and composition
apps/ensapi/src/omnigraph-api/schema/name-reference.ts, apps/ensapi/src/omnigraph-api/schema/account.ts, apps/ensapi/src/omnigraph-api/schema.ts
Adds NameReferenceRef object (fields: domain, coinType, resolver, async match) and Account.nameReferences connection with AccountNameReferencesWhereInput (optional coinType); wires schema import.
Reverse-resolution DataLoader and context wiring
apps/ensapi/src/omnigraph-api/context.ts
Adds createReverseResolutionLoader batching resolveReverse(account, coinType, ...) with acceleration flags and ${account}:${coinType} cache key; exposes loaders.reverseResolution in per-request context.
Integration tests
apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts
Adds tests for Account.nameReferences: canonical-domain lookup by address, coinType scoping excluding results, unscoped cross-coinType results, and match field ENSIP-19 reverse-equality checks.
Docs and changesets
packages/ensskills/skills/omnigraph/SKILL.md, .changeset/name-references-ensapi.md
Documents Account.nameReferences and NameReference in Omnigraph schema docs; adds changeset for ensapi minor release describing API semantics (canonical-only, no forward-resolution/ENSIP-19 defaults).
Technical debt notes and workflow guidance
apps/ensapi/src/lib/protocol-acceleration/get-primary-name-from-index.ts, apps/ensapi/src/omnigraph-api/schema/resolver-records.ts, apps/ensindexer/src/lib/protocol-acceleration/resolver-db-helpers.ts, apps/ensindexer/src/plugins/protocol-acceleration/handlers/StandaloneReverseRegistrar.ts, AGENTS.md
Scattered TODO comments about removing BigInt conversions once coinType becomes a number-backed int8 CoinType; adds guidance to prefer separate changesets per package.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant GraphQL
  participant AccountResolver
  participant Pagination
  participant DB
  participant Loader
  Client->>GraphQL: account.nameReferences(where?, first/last, before/after)
  GraphQL->>AccountResolver: resolveAccountNameReferences(account, coinType?, pagination args)
  AccountResolver->>Pagination: lazyConnection + resolveCursorConnection (decode cursors, build keyset bounds)
  Pagination->>DB: Query resolver_address_records WHERE value=account [AND coinType=filter] JOIN domain ON canonicalNode ORDER BY (node, coinType, chainId, address)
  DB->>Pagination: Rows + totalCount
  Pagination->>AccountResolver: Paginated rows
  AccountResolver->>Loader: context.loaders.reverseResolution.load(account, coinType) for each row when resolving `match`
  Loader->>AccountResolver: ReverseResolutionResult
  AccountResolver->>GraphQL: NameReferenceModel edges with encoded cursors
  GraphQL->>Client: NameReferenceConnection (edges, pageInfo)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • #2294: Requests ENSIP-19 default-record fallback logic for coinType filtering in Account.nameReferences; related because this PR implements exact-match coinType scoping without default/union semantics.

Possibly related PRs

  • namehash/ensnode#1974: Modifies Omnigraph context setup; both touch createOmnigraphContext area.
  • namehash/ensnode#2271: Changes Account parent/address handling in schema/account.ts which the new resolver relies on.

Poem

🐰 I nibble through indexes and cursors bright,
Hopping from value to canonical light,
Keyset tuples stitched in a tidy row,
Reverse lookups bloom where addr() flows,
A rabbit's cheer for names that point and show.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding an Account.nameReferences Omnigraph field, which is the primary objective of this PR.
Linked Issues check ✅ Passed All core requirements from issue #1962 are implemented: Account.nameReferences Relay connection with optional coinType filter, NameReference type with domain/coinType/resolver/match fields, canonical-only inner join semantics, indexed access via (value, coinType) index, and ENSIP-19 reverse-resolution match field.
Out of Scope Changes check ✅ Passed All changes directly support the Account.nameReferences feature: GraphQL schema additions, resolver implementation, integration tests, index definition, documentation, changesets, and contextual DataLoader for reverse resolution. Comments on technical debt (BigInt handling) are minimal and appropriate.
Description check ✅ Passed PR description comprehensively covers Summary, Why, Testing, and Notes for Reviewer with sufficient detail on API design and implementation strategy.

✏️ 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/account-name-references

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds Account.nameReferences to the ENSAPI Omnigraph GraphQL API, enabling cursor-paginated lookup of canonical ENS Domains whose indexed addr(coinType) record points to a given Account address (with optional coinType scoping). This supports Portal’s “names pointing to this address” view without relying on the subgraph.

Changes:

  • Introduces NameReference + AccountNameReferencesConnection and wires Account.nameReferences into the Omnigraph schema and runtime resolvers.
  • Implements a keyset-paginated DB resolver that filters resolver_address_records by value (+ optional coinType) and inner-joins to canonical Domain via domain.canonicalNode.
  • Adds a (value, coinType) index on resolver_address_records and integration tests covering coinType scoping and “all coinTypes” behavior.

Reviewed changes

Copilot reviewed 8 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/ensskills/skills/omnigraph/SKILL.md Documents the new Account.nameReferences field and adds NameReference to the schema type list.
packages/enssdk/src/omnigraph/generated/schema.graphql Regenerates the GraphQL schema to include nameReferences, connection/input types, and NameReference.
packages/enssdk/src/omnigraph/generated/introspection.ts Updates generated introspection data for the new field and types.
packages/ensdb-sdk/src/ensindexer-abstract/protocol-acceleration.schema.ts Adds (value, coinType) index to support reverse lookup queries on resolver_address_records.
apps/ensapi/src/omnigraph-api/schema/name-reference.ts Adds the NameReference GraphQL type (domain/coinType/resolver/match).
apps/ensapi/src/omnigraph-api/schema/account.ts Exposes Account.nameReferences connection field and defines AccountNameReferencesWhereInput.
apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts Adds integration tests validating scoping and omission behavior for nameReferences.
apps/ensapi/src/omnigraph-api/schema.ts Ensures the new schema module is registered.
apps/ensapi/src/omnigraph-api/lib/find-name-references/find-name-references-resolver.ts Implements the DB-backed, keyset-paginated resolver powering Account.nameReferences.
.changeset/account-name-references.md Adds Changeset entries bumping ensapi, enssdk, and @ensnode/ensdb-sdk.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/omnigraph-api/lib/find-name-references/find-name-references-resolver.ts`:
- Line 144: The current cast "canonicalName: row.canonicalName as
InterpretedName" in find-name-references-resolver.ts is relying on join
semantics; replace this implicit assertion with a small runtime guard: check
row.canonicalName for null/undefined and either throw a descriptive error or
handle the unexpected case (e.g., return/skip the row), then safely cast/assign
to InterpretedName; reference the 'row' object and the 'canonicalName' property
in your fix so the behavior is explicit and robust at runtime.
🪄 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: ec0c018f-6793-40e1-8212-2e8e89d65e49

📥 Commits

Reviewing files that changed from the base of the PR and between 4ecd8d9 and 9341508.

⛔ 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 (8)
  • .changeset/account-name-references.md
  • apps/ensapi/src/omnigraph-api/lib/find-name-references/find-name-references-resolver.ts
  • apps/ensapi/src/omnigraph-api/schema.ts
  • apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts
  • apps/ensapi/src/omnigraph-api/schema/account.ts
  • apps/ensapi/src/omnigraph-api/schema/name-reference.ts
  • packages/ensdb-sdk/src/ensindexer-abstract/protocol-acceleration.schema.ts
  • packages/ensskills/skills/omnigraph/SKILL.md

…Type bigint sites

- Document NameReference.match's indexed-shortcut limitation (no full ENSIP-19
  reverse walk; Primary Names set via legacy L1 addr.reverse may read match=false),
  keeping it consistent with the literally-indexed, exact-match nature of
  nameReferences.
- Split the nameReferences changeset into per-package changesets (ensdb-sdk /
  ensapi / enssdk) and document the per-service changeset convention in AGENTS.md.
- Add @todo(cointype-bigint) breadcrumbs at the indexed coinType bigint<->number
  round-trip sites (schema columns + indexer write sites + ENSApi read sites),
  tracked by #2293.
Comment thread .changeset/name-references-ensapi.md Outdated
Comment thread .changeset/name-references-enssdk.md Outdated
Comment thread apps/ensapi/src/omnigraph-api/schema/account.ts Outdated
Comment thread apps/ensapi/src/omnigraph-api/schema/name-reference.ts Outdated
- match: resolve via full ENSIP-19 reverse resolution (always accelerated,
  index-only, no memo/trace) instead of the StandaloneReverseRegistrar shortcut,
  covering legacy addr.reverse Primary Names.
- reframe "default-address-record expansion" -> "address record defaulting" in
  all PR prose/comments.
- rewrite the ensapi changeset copy; drop the enssdk changeset.
- clarify the cursor/keyset doc comments (`value` is the constant filter, not a
  primary-key column).
@shrugs

shrugs commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

@greptile review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 14 out of 16 changed files in this pull request and generated 3 comments.

Comment thread apps/ensapi/src/omnigraph-api/schema/name-reference.ts Outdated
Comment thread apps/ensapi/src/omnigraph-api/schema/name-reference.ts Outdated
Comment thread apps/ensapi/src/omnigraph-api/schema/name-reference.ts Outdated
@shrugs

shrugs commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

@greptile review

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/omnigraph-api/context.ts`:
- Around line 34-47: The reverse-resolution DataLoader currently hardcodes
canAccelerate: true which bypasses request-scoped gating; update
createReverseResolutionLoader to accept a canAccelerate boolean (thread
serverContext.canAccelerate into its caller) and pass that value into
resolveReverse instead of true so resolveReverse respects per-request
acceleration gating; locate createReverseResolutionLoader and its callers (and
NameReference.match usage) and propagate serverContext.canAccelerate through to
the DataLoader and then into resolveReverse.
🪄 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: 459a7152-e022-4a26-88b4-ad45ada5374e

📥 Commits

Reviewing files that changed from the base of the PR and between 5bb1de0 and 65282b8.

⛔ Files ignored due to path filters (1)
  • packages/enssdk/src/omnigraph/generated/schema.graphql is excluded by !**/generated/**
📒 Files selected for processing (2)
  • apps/ensapi/src/omnigraph-api/context.ts
  • apps/ensapi/src/omnigraph-api/schema/name-reference.ts

Comment thread apps/ensapi/src/omnigraph-api/context.ts Outdated
…on loader

Thread serverContext.canAccelerate into the NameReference.match reverse-resolution
DataLoader instead of hardcoding true — matching every other resolution call in
the codebase and avoiding stale/empty index reads when the indexer cannot safely
accelerate (non-realtime, no ProtocolAcceleration plugin).
Copilot AI review requested due to automatic review settings June 12, 2026 19:51
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io June 12, 2026 19:52 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io June 12, 2026 19:52 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io June 12, 2026 19:52 Inactive
@shrugs

shrugs commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

@greptile review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 15 out of 17 changed files in this pull request and generated 1 comment.

Comment thread apps/ensapi/src/omnigraph-api/schema/resolver-records.ts Outdated
resolveReverse's internal protocol-step tracing requires the trace context that
runWithTrace establishes; the captured trace is discarded here (match only needs
the resolved name).
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io June 12, 2026 22:20 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io June 12, 2026 22:20 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io June 12, 2026 22:20 Inactive
@shrugs shrugs marked this pull request as ready for review June 12, 2026 22:23
@shrugs shrugs requested a review from a team as a code owner June 12, 2026 22:23
Copilot AI review requested due to automatic review settings June 12, 2026 22:23
@shrugs

shrugs commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

@greptile review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 15 out of 17 changed files in this pull request and generated 2 comments.

Comment thread packages/ensskills/skills/omnigraph/SKILL.md
Comment thread apps/ensapi/src/omnigraph-api/schema/name-reference.ts
A bare toSorted() ordered CoinTypes (numbers) lexicographically (e.g. [137, 60]);
add a numeric comparator so they sort ascending ([60, 137]). Pre-existing issue
surfaced during review of the nameReferences change.
@shrugs

shrugs commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

@greptile review

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.

Omnigraph: names pointing to this address

2 participants