Skip to content

add contenthash interpretation#2285

Open
sevenzing wants to merge 4 commits into
mainfrom
ll/domain-profile-contenthash-02
Open

add contenthash interpretation#2285
sevenzing wants to merge 4 commits into
mainfrom
ll/domain-profile-contenthash-02

Conversation

@sevenzing

@sevenzing sevenzing commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary

  • Add Domain.resolve.profile.contenthash interpretation

decided to use simple structure for that:

type ProfileContenthash {
  decoded: String!
  httpUrl: String
  protocolType: String!
  uri: String!
}

Pre-Review Checklist (Blocking)

  • 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 June 11, 2026 13:33
@changeset-bot

changeset-bot Bot commented Jun 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: efee14f

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

@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
admin.ensnode.io Ready Ready Preview, Comment Jun 11, 2026 2:01pm
enskit-react-example.ensnode.io Ready Ready Preview, Comment Jun 11, 2026 2:01pm
ensnode.io Ready Ready Preview, Comment Jun 11, 2026 2:01pm
ensrainbow.io Ready Ready Preview, Comment Jun 11, 2026 2:01pm

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds complete support for interpreting and exposing ENSIP-7 contenthash data within ENS domain profiles. The implementation includes a new decoder-based interpreter that maps hex-encoded contenthash values to structured profile data (including protocol type, decoded payload, canonical URI, and optional HTTP gateway URLs), integrates the interpreter into the GraphQL schema, wires it into the resolution pipeline, and validates the functionality with integration tests.

Changes

ENS Domain Contenthash Profile Integration

Layer / File(s) Summary
Contenthash Interpreter Implementation
apps/ensapi/src/omnigraph-api/lib/resolution/profile/interpreters/contenthash.ts, apps/ensapi/src/omnigraph-api/lib/resolution/profile/interpreters/index.ts, apps/ensapi/src/omnigraph-api/lib/resolution/profile/profile-descriptions.ts
Adds ProfileContenthashModel and ProfileContenthashInterpreter that decode contenthash hex, detect protocol codecs (ipfs, ipns, swarm, arweave, onion, skynet), construct canonical URIs, and generate optional HTTP gateway URLs. Includes field description with ENSIP-7 documentation link.
GraphQL Schema Definition
apps/ensapi/src/omnigraph-api/schema/profile.ts
Introduces ProfileContenthashRef GraphQL object with interpreted protocolType, decoded, uri, and nullable httpUrl fields. Adds contenthash field to DomainProfileRef resolved via the new interpreter.
Resolution Pipeline Wiring
apps/ensapi/src/omnigraph-api/lib/resolution/profile/build-profile-selection.ts
Detects when contenthash is selected on the profile field and merges the interpreter's resolver records selection into the pipeline.
Integration Tests and Fixtures
apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts, packages/integration-test-env/src/devnet/fixtures.ts
Extends DomainProfile query to request contenthash { protocolType decoded uri httpUrl }. Updates test type definitions and assertions for test.eth. Replaces placeholder contenthash fixture with a real IPFS CID hex value.
Documentation and Release
apps/ensapi/src/omnigraph-api/lib/resolution/profile/README.md, packages/ensskills/skills/omnigraph/SKILL.md, .changeset/clean-insects-accept.md, apps/ensapi/package.json
Updates architecture README to list contenthash.ts interpreter and marks contenthash as completed in the roadmap. Adds ProfileContenthash to schema documentation. Adds patch-level Changeset entry. Adds @ensdomains/content-hash@^3.0.0 dependency.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

javascript

Poem

A contenthash now decoded bright,
Protocol gateways burning light,
IPFS and Arweave unified,
Profile data crystallized,
✨ No more mystery inside ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'add contenthash interpretation' accurately and specifically describes the main change—adding contenthash field interpretation to the Domain.resolve.profile GraphQL schema.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% 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.
Description check ✅ Passed The PR description follows the template structure with a clear summary, rationale (via the GraphQL structure shown), and pre-review checklist completion.

✏️ 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/domain-profile-contenthash-02

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

greptile-apps Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a contenthash field to DomainProfile by implementing a new ProfileContenthashInterpreter that decodes ENSIP-7 contenthash bytes into a structured { protocolType, decoded, uri, httpUrl } model. The GraphQL schema, introspection file, and SDK schema are updated accordingly.

  • New interpreter (contenthash.ts): decodes raw hex contenthash bytes using @ensdomains/content-hash@3.1.0-rc.1, maps known protocols (IPFS, IPNS, Swarm, Arweave, Onion, Skynet) to URI prefixes and optional HTTP gateway URLs, and silently returns null for unknown or malformed values.
  • Schema & profile wiring: ProfileContenthashRef is registered in Pothos, the resolver is wired in DomainProfile, and the selection is merged into the records round-trip in build-profile-selection.ts.
  • Test fixture updated: fixtures.contenthash is replaced with a real IPFS-encoded hex string whose decoded CIDv1 is asserted in the new integration test case.

Confidence Score: 5/5

Safe to merge — the change is purely additive with no modifications to existing resolvers or data paths.

All changed code is purely additive: a new interpreter module, a new GraphQL type, and generated schema files. The interpreter wraps the entire decode path in a try/catch and returns null for every failure mode (null raw, empty hex, unknown codec, malformed bytes), so it cannot break existing queries. The integration test covers the happy path with a real IPFS fixture. No existing behavior is altered.

No files require special attention.

Important Files Changed

Filename Overview
apps/ensapi/src/omnigraph-api/lib/resolution/profile/interpreters/contenthash.ts New interpreter: decodes hex contenthash via @ensdomains/content-hash, maps all Codec values to URI prefixes/gateway URLs, guards against null/empty/malformed input with try/catch; logic is sound.
apps/ensapi/src/omnigraph-api/schema/profile.ts Adds ProfileContenthashRef Pothos object type and wires the contenthash field into DomainProfile; follows existing patterns exactly.
apps/ensapi/src/omnigraph-api/lib/resolution/profile/build-profile-selection.ts Correctly adds a topLevelFields.has("contenthash") guard to merge the interpreter selection into the records round-trip.
packages/integration-test-env/src/devnet/fixtures.ts Replaces synthetic 0x04...04 fixture with a real IPFS-encoded contenthash hex taken from the library's own documentation; well-commented.
apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts Adds integration test assertions for the new contenthash field matching the updated fixture CIDv1 and expected gateway URL.
packages/enssdk/src/omnigraph/generated/schema.graphql Generated GraphQL schema updated with ProfileContenthash type and the new contenthash field on DomainProfile; consistent with implementation.
packages/enssdk/src/omnigraph/generated/introspection.ts Generated introspection file updated to reflect the new ProfileContenthash type and field; no manual changes needed.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[GraphQL Query: profile.contenthash] --> B[buildProfileSelectionFromResolveContainerInfo]
    B --> C{topLevelFields has contenthash?}
    C -- yes --> D[merge ProfileContenthashInterpreter.selection]
    C -- no --> E[skip]
    D --> F[resolveRecords round-trip]
    F --> G[ProfileContenthashInterpreter.interpret]
    G --> H{raw == null or 0x?}
    H -- yes --> I[return null]
    H -- no --> J[strip 0x prefix]
    J --> K[getCodec hex]
    K -- null --> I
    K -- Codec --> L[decode hex to CID string]
    L --> M{protocolType in PROTOCOL_CONFIG?}
    M -- yes --> N[use known uriPrefix + httpUrl builder]
    M -- no --> O[fallback prefix, httpUrl = null]
    N --> P[return ProfileContenthashModel]
    O --> P
    P --> Q[ProfileContenthash GraphQL type]
Loading

Reviews (2): Last reviewed commit: "fix AI comments" | Re-trigger Greptile

Comment thread apps/ensapi/package.json Outdated

@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 `@packages/integration-test-env/src/devnet/fixtures.ts`:
- Around line 97-99: The inline comment for the contenthash value (the property
named contenthash in the fixture object) is inconsistent with the actual decoded
CID — decode the hex string "0xe30101..." assigned to contenthash (or re-derive
the correct hex for the expected CID) and update either the comment to reflect
the true CID (e.g., bafybei... if that decodes correctly) or replace the hex
value so it encodes the commented CID (QmRAQ...). Locate the contenthash
property in fixtures.ts, validate the multicodec/multihash decoding result, and
make the comment and assigned hex consistent with each other. Ensure the chosen
fix preserves test expectations that rely on the decoded CID.
🪄 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: 94d69902-f372-4323-9abf-6fb60b9b98e8

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa2f2f and efee14f.

⛔ Files ignored due to path filters (3)
  • packages/enssdk/src/omnigraph/generated/introspection.ts is excluded by !**/generated/**
  • packages/enssdk/src/omnigraph/generated/schema.graphql is excluded by !**/generated/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • .changeset/clean-insects-accept.md
  • apps/ensapi/package.json
  • apps/ensapi/src/omnigraph-api/lib/resolution/profile/README.md
  • apps/ensapi/src/omnigraph-api/lib/resolution/profile/build-profile-selection.ts
  • apps/ensapi/src/omnigraph-api/lib/resolution/profile/interpreters/contenthash.ts
  • apps/ensapi/src/omnigraph-api/lib/resolution/profile/interpreters/index.ts
  • apps/ensapi/src/omnigraph-api/lib/resolution/profile/profile-descriptions.ts
  • apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts
  • apps/ensapi/src/omnigraph-api/schema/profile.ts
  • packages/ensskills/skills/omnigraph/SKILL.md
  • packages/integration-test-env/src/devnet/fixtures.ts

Comment thread packages/integration-test-env/src/devnet/fixtures.ts Outdated

@shrugs shrugs left a comment

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.

LGTM

const config = PROTOCOL_CONFIG[protocolType];
const prefix = config ? config.uriPrefix : `${protocolType}://`;
const uri = `${prefix}${decoded}`;
const httpUrl = config?.httpUrl ? config.httpUrl(decoded) : 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.

const httpUrl = config?.httpUrl?.(decoded) ?? null is better

@shrugs

shrugs commented Jun 11, 2026

Copy link
Copy Markdown
Member

i could see a schema improvement with either:

a) protocolType should become enum, or
b) ProfileContenthash should become an interface with concrete types for the known contenthash protocols, then you can drop protocolType entirely in favor of __typename differentiation. the ProfileContenthash interface implements all fields and the concrete implementation provide no specific fields

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