Skip to content

add records resolution#1974

Draft
sevenzing wants to merge 1 commit intomainfrom
ll/omnigraph-resolution-api
Draft

add records resolution#1974
sevenzing wants to merge 1 commit intomainfrom
ll/omnigraph-resolution-api

Conversation

@sevenzing
Copy link
Copy Markdown
Member

Summary

  • Adds Domain.records field to the Omnigraph GraphQL API
  • Extracts getDomainInterpretedName as a shared local helper in domain.ts to avoid duplicating canonical path resolution logic
  • TODO:

Why

Closes #1802


Testing

  • Integration tests added to domain.integration.test.ts

Pre-Review Checklist (Blocking)

[x] This PR does not introduce significant changes and is low-risk to review quickly.
[ ] Relevant changesets are included (or are not required)

@sevenzing sevenzing requested a review from a team as a code owner April 21, 2026 17:03
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 21, 2026

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

Project Deployment Actions Updated (UTC)
admin.ensnode.io Ready Ready Preview, Comment Apr 21, 2026 5:03pm
ensnode.io Ready Ready Preview, Comment Apr 21, 2026 5:03pm
ensrainbow.io Ready Ready Preview, Comment Apr 21, 2026 5:03pm

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 21, 2026

⚠️ No Changeset found

Latest commit: eae25f6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@sevenzing sevenzing marked this pull request as draft April 21, 2026 17:03
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 21, 2026

📝 Walkthrough

Walkthrough

This PR integrates ENS record resolution into the Omnigraph GraphQL schema by introducing a new Domain.records field that accepts a selection argument and returns resolved text records and addresses. The implementation includes refactoring existing name resolution logic into a shared helper function and defining new GraphQL schema types for the resolution data structures.

Changes

Cohort / File(s) Summary
Schema Integration
apps/ensapi/src/omnigraph-api/schema.ts
Added import of schema/resolution module to register resolution-related GraphQL types in the schema.
Resolution Schema Types
apps/ensapi/src/omnigraph-api/schema/resolution.ts
New module defining GraphQL input type ResolveSelectionInput (specifies resolution scope via reverseName, texts, addresses), and object types ResolvedTextRecordRef, ResolvedAddressRecordRef, and ResolvedRecordsRef for resolved record structures.
Domain Resolver Refactoring
apps/ensapi/src/omnigraph-api/schema/domain.ts
Extracted Domain.name resolver logic into shared helper getDomainInterpretedName that loads canonical paths and maps to interpreted labels. Updated Domain.name to use the helper. Added new Domain.records field that accepts ResolveSelectionInput, computes canonical interpreted name, and calls resolveForward to resolve ENS records.
Integration Tests
apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts
New test suite for Domain.records with two test cases validating address resolution (ETH coin type 60) and text record resolution for test.eth and example.eth domains.

Sequence Diagram

sequenceDiagram
    actor Client
    participant GQL as GraphQL Resolver<br/>(Domain.records)
    participant DL as DataLoaders
    participant ENS as ENS Resolution
    
    Client->>GQL: Query Domain.records with selection
    GQL->>DL: Load canonical path for domain
    DL-->>GQL: Canonical path with domain IDs
    GQL->>GQL: Map to interpreted labels
    alt Canonical Path Exists
        GQL->>ENS: resolveForward(name, selection)
        ENS-->>GQL: Text & Address records
        GQL-->>Client: ResolvedRecordsResponse
    else Non-Canonical
        GQL-->>Client: null
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through the ENS garden so green,
Records now resolving, the clearest we've seen!
Addresses, text fields—all neatly arrayed,
With selection-based queries, no map-based trade!
One helper to share, one feature so bright,
Domain resolution GraphQL done right! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR partially implements issue #1802 objectives by adding Domain.records field with resolution capability, but does not implement Account.primaryNames, accelerate parameter, scoped filtering (texts/addresses with parameters), or canAccelerate context injection. Complete implementation of remaining objectives: add Account.primaryNames field, implement accelerate parameter on Domain.records, add scoped filtering for texts/addresses, and inject canAccelerate into context.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'add records resolution' is concise and clearly summarizes the main change: adding the Domain.records field to the Omnigraph GraphQL API.
Description check ✅ Passed The description covers main changes, links to issue #1802, mentions integration tests, and completes the pre-review checklist, though it contains an incomplete TODO section.
Out of Scope Changes check ✅ Passed All changes are in-scope: schema module import, new resolution.ts module with GraphQL types, domain.ts enhancements, and integration tests directly support the Domain.records addition specified in issue #1802.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ll/omnigraph-resolution-api

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.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 21, 2026

Greptile Summary

This PR adds a Domain.records field to the Omnigraph GraphQL API, enabling ENS record resolution (addresses, text records, reverse name) directly from a domain object via forward resolution. It also extracts getDomainInterpretedName as a shared helper to avoid duplicating canonical path logic.

  • P1: Canonical domains whose labels contain encoded labelhashes (e.g. [abc123].eth) will cause resolveForward to throw instead of returning null, breaking the documented contract. A pre-call isNormalizedName guard is needed.

Confidence Score: 4/5

Safe to merge after addressing the encoded-label guard; the throw surfaces as a GraphQL error for a valid subset of canonical domains.

One P1 defect: canonical domains with encoded labelhash labels trigger an unhandled throw from resolveForward instead of returning null, violating the documented API contract. The fix is a single-line isNormalizedName guard before the resolveForward call.

apps/ensapi/src/omnigraph-api/schema/domain.ts — the records resolver needs an isNormalizedName guard before calling resolveForward.

Important Files Changed

Filename Overview
apps/ensapi/src/omnigraph-api/schema/domain.ts Adds records field to Domain via getDomainInterpretedName helper; canonical names with encoded labelhash labels will throw instead of returning null.
apps/ensapi/src/omnigraph-api/schema/resolution.ts New file defining ResolveSelectionInput, ResolvedTextRecord, ResolvedAddressRecord, and ResolvedRecords GraphQL types; minor unclosed backtick in description.
apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts Integration tests for Domain.records added for ETH address and text record resolution; missing a test case for non-canonical domains returning null.
apps/ensapi/src/omnigraph-api/schema.ts Adds import for ./schema/resolution to register the new resolution schema module.
packages/enssdk/src/omnigraph/generated/schema.graphql Generated GraphQL schema updated to include records field on all Domain types and the new ResolveSelectionInput/ResolvedRecords types.

Sequence Diagram

sequenceDiagram
    participant Client
    participant GraphQL
    participant domain.ts
    participant resolution.ts
    participant forward-resolution.ts

    Client->>GraphQL: query { domain(by: {name}) { records(selection) { addresses texts } } }
    GraphQL->>domain.ts: resolve Domain.records
    domain.ts->>domain.ts: getDomainInterpretedName(domain, context)
    domain.ts->>domain.ts: load v1/v2CanonicalPath via DataLoader
    alt domain is not canonical
        domain.ts-->>GraphQL: null
    else domain has encoded label (e.g. [abc].eth)
        domain.ts->>forward-resolution.ts: resolveForward(name, selection)
        forward-resolution.ts-->>GraphQL: throws Error (not normalized)
    else domain is canonical and normalized
        domain.ts->>forward-resolution.ts: resolveForward(name, selection)
        forward-resolution.ts-->>domain.ts: ResolverRecordsResponseBase
        domain.ts->>resolution.ts: map to ResolvedRecords
        resolution.ts-->>GraphQL: { addresses, texts, reverseName }
        GraphQL-->>Client: records response
    end
Loading

Reviews (1): Last reviewed commit: "add records resolution" | Re-trigger Greptile

Comment on lines +236 to +253
resolve: async (domain, { selection }, context) => {
const name = await getDomainInterpretedName(domain, context);
if (!name) return null;

const { result } = await runWithTrace(() =>
resolveForward(
name,
{
name: selection.reverseName ?? undefined,
texts: selection.texts ?? undefined,
addresses: selection.addresses ?? undefined,
},
{ accelerate: false, canAccelerate: false },
),
);

return result as ResolverRecordsResponseBase;
},
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.

P1 Unhandled throw for canonical names with encoded labels

getDomainInterpretedName can return an InterpretedName that contains encoded labelhash segments (e.g. [abc123].eth). When that name is passed to resolveForward, it immediately throws "'[abc123].eth' must be normalized to be resolvable." (see forward-resolution.ts line 149). This error propagates as a GraphQL field error rather than returning null, violating the stated API contract: "Returns null if the domain is not canonical." Canonical domains with unknown labels would surface an unexpected 500-level error to the client instead of a clean null.

A simple guard before calling resolveForward would fix this:

import { isNormalizedName } from "enssdk";

resolve: async (domain, { selection }, context) => {
  const name = await getDomainInterpretedName(domain, context);
  if (!name) return null;
  if (!isNormalizedName(name)) return null;  // add this guard

  const { result } = await runWithTrace(() =>
    resolveForward(...)
  );
  ...
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hmmmm, make sense

required: false,
}),
texts: t.stringList({
description: "Text record keys to resolve (e.g. `avatar`, `description`, `com.).",
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.

P2 Unclosed backtick in description string

The description for the texts field has an unclosed backtick before com., which will render incorrectly in GraphQL API documentation.

Suggested change
description: "Text record keys to resolve (e.g. `avatar`, `description`, `com.).",
description: "Text record keys to resolve (e.g. `avatar`, `description`, `com.`).",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

oops, should be com.github

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

🤖 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/omnigraph-api/schema/domain.ts`:
- Around line 224-249: Domain.records currently lacks an accelerate arg and
always calls resolveForward with accelerate: false; add a GraphQL arg
"accelerate" to the Domain.records field (the field defined at records: t.field)
and forward its value along with context.canAccelerate into resolveForward
(i.e., call resolveForward(name, {...}, { accelerate: args.accelerate,
canAccelerate: context.canAccelerate })). Also wire up the acceleration
middleware chain to the omnigraph-api router by applying
makeIsRealtimeMiddleware, indexingStatusMiddleware and canAccelerateMiddleware
(same order used in resolution-api) and update the omnigraph-api context factory
to accept the initial context param that contains canAccelerate from the
middleware so context.canAccelerate is available in the resolver; keep
getDomainInterpretedName usage unchanged.

In `@apps/ensapi/src/omnigraph-api/schema/resolution.ts`:
- Around line 16-18: Update the description string for the texts field in
resolution.ts to fix the malformed example; locate the texts: t.stringList({ ...
}) declaration and replace the example snippet "Text record keys to resolve
(e.g. `avatar`, `description`, `com.)." with a correctly punctuated example such
as "Text record keys to resolve (e.g. `avatar`, `description`, `com`)." ensuring
matching backticks and proper parentheses/period placement.
🪄 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: 909769d3-67ea-4cf4-873d-e0d220e4bdd9

📥 Commits

Reviewing files that changed from the base of the PR and between d9ab6b0 and eae25f6.

⛔ Files ignored due to path filters (1)
  • packages/enssdk/src/omnigraph/generated/schema.graphql is excluded by !**/generated/**
📒 Files selected for processing (4)
  • apps/ensapi/src/omnigraph-api/schema.ts
  • apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts
  • apps/ensapi/src/omnigraph-api/schema/domain.ts
  • apps/ensapi/src/omnigraph-api/schema/resolution.ts

Comment on lines +224 to +249
records: t.field({
description:
"Resolve ENS records for this Domain via the ENS protocol. Only canonical domains can be resolved. Returns null if the domain is not canonical.",
type: ResolvedRecordsRef,
nullable: true,
args: {
selection: t.arg({
type: ResolveSelectionInput,
required: true,
description: "Which records to resolve.",
}),
},
resolve: async (domain, { selection }, context) => {
const name = await getDomainInterpretedName(domain, context);
if (!name) return null;

const { result } = await runWithTrace(() =>
resolveForward(
name,
{
name: selection.reverseName ?? undefined,
texts: selection.texts ?? undefined,
addresses: selection.addresses ?? undefined,
},
{ accelerate: false, canAccelerate: false },
),
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify context acceleration wiring and Domain.records schema args.
rg -nP -C3 '\bcanAccelerate\b|records:\s*t\.field|accelerate:\s*t\.arg' --iglob '*.ts'

Repository: namehash/ensnode

Length of output: 17937


🏁 Script executed:

# Check omnigraph context configuration and middleware wiring
cd apps/ensapi

# Find omnigraph context type definition
rg -nP 'type.*Context|interface.*Context' --iglob '*omnigraph*.ts' -B2 -A5

# Check if omnigraph routes/schema uses canAccelerateMiddleware
rg -nP 'canAccelerateMiddleware|omnigraph-api' --iglob '*.ts' -B2 -A2

Repository: namehash/ensnode

Length of output: 33798


🏁 Script executed:

# Check omnigraph context definition and yoga setup
cat -n apps/ensapi/src/omnigraph-api/context.ts

# Check omnigraph yoga handler
cat -n apps/ensapi/src/omnigraph-api/yoga.ts

Repository: namehash/ensnode

Length of output: 3243


🏁 Script executed:

# Check omnigraph router mounting and middleware setup
rg -nP 'omnigraph|canAccelerateMiddleware' apps/ensapi/src/handlers/api/router.ts -B3 -A3

# Check app.ts for middleware chain
rg -nP 'app\.use|middleware|canAccelerateMiddleware' apps/ensapi/src/app.ts -B2 -A2

Repository: namehash/ensnode

Length of output: 971


🏁 Script executed:

# Check omnigraph-api handler definition
cat -n apps/ensapi/src/handlers/api/omnigraph/omnigraph-api.ts

Repository: namehash/ensnode

Length of output: 1068


🏁 Script executed:

# Check if there's any middleware applied globally before omnigraph routes
cat -n apps/ensapi/src/app.ts | head -50

# Check if omnigraph has any acceleration-related code
rg -nP 'accelerate|canAccelerate' apps/ensapi/src/omnigraph-api/ --iglob '*.ts'

Repository: namehash/ensnode

Length of output: 1990


🏁 Script executed:

# Check how graphql-yoga context is supposed to work with Hono
# Look at yoga creation and how context parameter is passed
rg -nP 'createYoga|context' apps/ensapi/src/omnigraph-api/yoga.ts -B5 -A5

# Check if there are other GraphQL resolvers that access Hono context variables
rg -nP 'context\.' apps/ensapi/src/omnigraph-api/schema/ --iglob '*.ts' | head -20

Repository: namehash/ensnode

Length of output: 1604


🏁 Script executed:

# Check graphql-yoga documentation or types for context parameter
# Look for how yoga.fetch uses the second parameter (c.var)
rg -nP 'fetch.*c\.var|context.*function' apps/ensapi/ --iglob '*.ts' -B2 -A2

# Check if there are examples of graphql-yoga receiving context from request
rg -nP 'createYoga.*context|yoga.*context' apps/ensapi/ --iglob '*.ts' -B5 -A5

Repository: namehash/ensnode

Length of output: 2707


🏁 Script executed:

# Verify graphql-yoga context function signature and how it receives request context
# Check if context can be a function that receives request info
cat -n apps/ensapi/src/omnigraph-api/yoga.ts | grep -A20 "createYoga"

# Look at subgraph-api to see if it shows context wiring pattern
cat -n apps/ensapi/src/handlers/subgraph/subgraph-api.ts | grep -B5 -A10 "context"

Repository: namehash/ensnode

Length of output: 1883


🏁 Script executed:

# Check graphql-yoga version and context handling
# Look at package.json for graphql-yoga version
cd apps/ensapi && cat package.json | grep -A2 -B2 "graphql-yoga"

# Look at how subgraph or other yoga instances handle context from serverContext
rg -nP 'context.*serverContext|createYoga.*context' apps/ensapi/ --iglob '*.ts' -B3 -A10

Repository: namehash/ensnode

Length of output: 267


🏁 Script executed:

# Check graphql-yoga version and context patterns
grep -A2 -B2 "graphql-yoga" apps/ensapi/package.json

# Look for context function patterns with parameters in the codebase
rg -nP 'context\s*=.*\(\s*\w+\s*\)' apps/ensapi/src/omnigraph-api/ --iglob '*.ts' -B2 -A5

Repository: namehash/ensnode

Length of output: 197


🌐 Web query:

graphql-yoga 5.16 context function serverContext Hono variables fetch

💡 Result:

In GraphQL Yoga 5.16 (released around early 2026 per changelog), the context function and serverContext work with Hono via the WHATWG Fetch API compatibility, as Hono exposes c.req.raw (a standard Request) and app.fetch. Default context includes: request (Fetch Request), params, query (DocumentNode), operationName, variables (query variables object), extensions. For Hono integration (no official docs, but community examples from 2023+ still valid for v5): import { Hono } from 'hono' import { createYoga, createSchema } from 'graphql-yoga' import { serve } from '@hono/node-server' const schema = createSchema({...}) const yoga = createYoga({ schema }) const app = new Hono app.all('/graphql*', async (c) => yoga.fetch(c.req.raw, { /* serverContext if needed */ })) serve({ fetch: app.fetch, port: 3000 }) Or app.use('/graphql', async (c) => yoga.handle({ request: c.req.raw }, {}) ) // older handle In resolvers, access context.variables (object from client query), context.request (for headers/body), context.fetch (server fetch utility). To add Hono-specific serverContext (e.g., Hono c object), pass as second arg to handle/fetch: yoga.fetch(request, { honoC: c }) Then in user context factory: context: async (initialContext) => { const { honoC } = initialContext; return { honoVars: honoC.env?.VAR || c.req.param('id') } } For Cloudflare Workers/Deno (Hono common): serverContext auto-includes FetchEvent with request, waitUntil, etc. No explicit serverContext needed usually. Examples access context.request.headers.get('auth'), context.variables.userId in resolvers. Use context.fetch(url) for internal server calls.

Citations:


🏁 Script executed:

# Check if canAccelerateMiddleware could be applied to omnigraph
# Look at isRealtimeMiddleware to see if it's applied to omnigraph
rg -nP 'isRealtimeMiddleware|makeIsRealtimeMiddleware' apps/ensapi/src/ --iglob '*.ts' -B2 -A2

# Check omnigraph-api router to see all middlewares applied
cat -n apps/ensapi/src/handlers/api/omnigraph/omnigraph-api.ts

Repository: namehash/ensnode

Length of output: 5546


🏁 Script executed:

# Final verification: check if context function in yoga can be updated to receive serverContext
# Look at graphql-yoga documentation patterns in the code
rg -nP 'context.*async|context.*=>|serverContext' apps/ensapi/src/omnigraph-api/ --iglob '*.ts' -B3 -A3

Repository: namehash/ensnode

Length of output: 10109


🏁 Script executed:

# Check if omnigraph is expected to support acceleration or if it's REST-only
rg -nP 'omnigraph.*accelerat|accelerat.*omnigraph' apps/ensapi/src/ --iglob '*.ts'

# Check if there are any tests or documentation about Domain.records with accelerate
rg -nP 'Domain.*records|records.*accelerate' apps/ensapi/src/omnigraph-api/ --iglob '*.ts' -B2 -A2

Repository: namehash/ensnode

Length of output: 836


Expose and honor the accelerate argument.

Domain.records currently has no accelerate GraphQL arg and always passes { accelerate: false, canAccelerate: false }, so callers cannot use the default accelerated path required by the API contract.

To implement this, wire the acceleration middleware to the Omnigraph API router and update the context factory to receive canAccelerate from the middleware:

  1. Apply canAccelerateMiddleware and its prerequisite makeIsRealtimeMiddleware + indexingStatusMiddleware to the omnigraph-api router (similar to resolution-api)
  2. Update omnigraph-api/context.ts to accept an initial context parameter containing canAccelerate from the middleware
  3. Add the accelerate GraphQL arg to Domain.records and pass both accelerate and context.canAccelerate to resolveForward()
Proposed fix
     records: t.field({
       description:
         "Resolve ENS records for this Domain via the ENS protocol. Only canonical domains can be resolved. Returns null if the domain is not canonical.",
       type: ResolvedRecordsRef,
       nullable: true,
       args: {
+        accelerate: t.arg.boolean({
+          required: false,
+          defaultValue: true,
+          description: "Whether to use accelerated resolution when available.",
+        }),
         selection: t.arg({
           type: ResolveSelectionInput,
           required: true,
           description: "Which records to resolve.",
         }),
       },
-      resolve: async (domain, { selection }, context) => {
+      resolve: async (domain, { accelerate, selection }, context) => {
         const name = await getDomainInterpretedName(domain, context);
         if (!name) return null;
 
         const { result } = await runWithTrace(() =>
           resolveForward(
             name,
             {
               texts: selection.texts ?? undefined,
               addresses: selection.addresses ?? undefined,
             },
-            { accelerate: false, canAccelerate: false },
+            { accelerate: accelerate ?? true, canAccelerate: context.canAccelerate ?? false },
           ),
         );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ensapi/src/omnigraph-api/schema/domain.ts` around lines 224 - 249,
Domain.records currently lacks an accelerate arg and always calls resolveForward
with accelerate: false; add a GraphQL arg "accelerate" to the Domain.records
field (the field defined at records: t.field) and forward its value along with
context.canAccelerate into resolveForward (i.e., call resolveForward(name,
{...}, { accelerate: args.accelerate, canAccelerate: context.canAccelerate })).
Also wire up the acceleration middleware chain to the omnigraph-api router by
applying makeIsRealtimeMiddleware, indexingStatusMiddleware and
canAccelerateMiddleware (same order used in resolution-api) and update the
omnigraph-api context factory to accept the initial context param that contains
canAccelerate from the middleware so context.canAccelerate is available in the
resolver; keep getDomainInterpretedName usage unchanged.

Comment thread apps/ensapi/src/omnigraph-api/schema/resolution.ts
Copy link
Copy Markdown
Member

@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.

So i mentioned this in the original issue, which is that i'm not sure we want to allow people to query the trace and other meta information, like whether it was accelerated or not via the graphql api because i'm not convinced the ergonomics of it makes sense. but if you find a format that feels good, we can totally do so. For example, we could make the signature

query GetRecords {
  domain(by: { name: "eth" }) {
    resolve([accelerate: True]) {
      records { # equivalent to a ResolverRecordsSelection
        name
        texts(keys: ["description"]) { key value }
        addresses(coinType: [60]) { coinType address }
      }
      acceleration { requested attempted }
      trace
    }
  }
}

query GetPrimaryNames {
  account(by: { address: "0xabcd" }) {
    resolve(accelerate: False) {
      primaryNames(coinTypes: [60]) { coinType name }
      acceleration { requested attempted }
      trace
    }
  }
}

then that feels good; let's do that! then the pattern is clear; Domain.resolve.records and Account.resolve.primaryNames — feels good to me!


Note that within enskit, we need to update the cache client to mark these fields as EMBEDDED_DATA because they don't have a global key. Also, feel free to update the example app to render these records. So maybe add a new component that fetches a name's records by Domain.id or (name from the params, whatever) and then plug it into the name page.


Overall, this is definitely the correct direction and the data loader usage is correct. Let's move that helper into its own library.


to access the pothos context type, let's

  1. define a type Context = ReturnType<typeof createContext> in apps/ensapi/src/omnigraph-api/context.ts
  2. use that everywhere we currently use context: ReturnType<typeof createContext>
  3. make sure the helper you extracted here uses said type as well.

no need to alias it to graphqlContext; within the omnigraph graphql server module, "context" is always the graphql context

type DomainRecordsResult = {
domain: {
records: {
addresses: Array<{ coinType: number; address: string | null }>;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: you can use the enssdk#CoinType type here

const DomainRecords = gql`
query DomainRecords($name: InterpretedName!, $addresses: [CoinType!], $texts: [String!]) {
domain(by: { name: $name }) {
records(selection: { addresses: $addresses, texts: $texts }) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

in the future i want to move the addresses/texts selections into the fields themselves (which will require some gql query introspection, which we do elsewhere) but good call to not do that immediately

texts: [],
});

expect(result.domain.records?.addresses).toEqual([{ coinType: 60, address: DEVNET_OWNER }]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit:

await expect().resolves.toMatchObject({
  domain: { records: { texts: [], addresses: [{coinType: 60, address: DEVNET_OWNER }] } }
})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ditto below, consolidate into a single object match and use the await expect(...).resolves syntax. we should add that preference to our AGENT.md.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Actually, remove this case in favor of the below case which tests both at the same time.

///////////////////
records: t.field({
description:
"Resolve ENS records for this Domain via the ENS protocol. Only canonical domains can be resolved. Returns null if the domain is not canonical.",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

additional: only canonical, normalized names can be resolved; so names with unknown labels can't be resolved actually (which is crazy to me but that's what the contracts say)

// ResolvedRecords
////////////////////
export const ResolvedRecordsRef = builder
.objectRef<{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the types used here can likely be inferred (or already exist) within the resolution module likely using ResolverRecordsResponse or ResolverRecordsResponseBase, make sure to use that type instead of re-defining

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: Integrate Resolution APIs

2 participants