ENSIP 16 v2: Metadata API Improvements

Overview

While on-chain ENS interactions are straightforward, the off-chain environment is evolving to provide more flexibility and functionality. This document explores the improvements in the off-chain domain’s metadata retrieval and all available records, modifying the ENSIP-16 specification to enhance the developer experience and latency for user experience.

The Need for ENSIP-16

This contribution was developed during the implementation of a solution fully capable of reading and writing offchain domains which can be found on Blockful’s External Resolver repository.

While EIP-3668 (CCIP-Read) provides a standardized method for resolving domain records, it lacks comprehensive data retrieval capabilities. ENSIP-16 addresses this gap by offering a dynamic API that exposes all relevant data for externally resolved domains, including:

  • Text records
  • Address records
  • Subdomain information
  • Register date
  • Owner

Each resolver/subdomain issuer is responsible for indexing the relevant data of its domains, and not the ENS protocol.

Improved GraphQL Schema

Recent implementations have led to enhancements in the ENSIP-16 GraphQL schema. The updated schema provides a more complete and efficient structure for data retrieval:

type Text {
	key: String!
	value: String!
}

type Address {
	address: Bytes!
	coinType: BigInt!
}

type Resolver {
  id: ID!
  node: Bytes
  context: Bytes
  address: Bytes
  domain: Domain
  contentHash: Bytes
  texts: [Text!]
  addresses: [Address!]
}

type Domain {
  id: ID!
  context: Bytes
  owner: Bytes
  name: String
  node: Bytes
  label: String
  labelhash: Bytes
  resolvedAddress: Bytes
  parent: String
  parentNode: Bytes
  subdomains: [String] 
  subdomainCount: Int!
  resolver: Resolver!
  expiryDate: BigInt!
  registerDate: BigInt
}

Key Improvements

  1. Introduction of Text and Address types:
    • Provides both keys and values in a single query reducing the need for multiple queries
  2. Modification of subdomains in the Domain type:
    • Temporarly changed from a list of domains to a list of identifiers for preventing recursive query issues and potential infinite loops

Schema diff

The following is the git diff of the ENSIP-16 standard implementation and the improvements suggested by this document.

Implementation details

The latest version of a fully compliant Offchain Resolver is live on Sepolia. It implements:

  • Metadata API (ENSIP-16)
  • CCIP-Read (EIP-3668)
  • Cross-chain Writing Deferral (EIP-5559)

Metadata API

The Metadata API handles schema requests, returning comprehensive domain information for domains that use a resolver compliant to this standard.

Sample response

{
  "data": {
    "domain": {
      "id": "0x3a872f8FED4421E7d5BE5c98Ab5Ea0e0245169A0-0x2ba36aeb3375ac814e263100ad295d4af98c502343c6b3980e4d5e050636de77",
      "context": "0x3a872f8FED4421E7d5BE5c98Ab5Ea0e0245169A0",
      "name": "zuffo.eth",
      "namehash": "0x2ba36aeb3375ac814e263100ad295d4af98c502343c6b3980e4d5e050636de77",
      "labelName": "zuffo",
      "labelhash": "0xeb8c8cc4cbec6f48eb4b48a48ec473e66e719cd1a44f69509daf11416eb9fc97",
      "resolvedAddress": "0xfCfC138635e8c00BfDa78507C8abeD5013148150",
      "parent": "0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae",
      "subdomains": [
        "blockful.zuffo.eth"
      ],
      "subdomainCount": 1,
      "resolver": {
        "id": "0x3a872f8FED4421E7d5BE5c98Ab5Ea0e0245169A0-0x2ba36aeb3375ac814e263100ad295d4af98c502343c6b3980e4d5e050636de77",
        "node": "0x2ba36aeb3375ac814e263100ad295d4af98c502343c6b3980e4d5e050636de77",
        "context": "0x3a872f8FED4421E7d5BE5c98Ab5Ea0e0245169A0",
        "address": "0xfCfC138635e8c00BfDa78507C8abeD5013148150",
        "addr": "0x3a872f8FED4421E7d5BE5c98Ab5Ea0e0245169A0",
        "contentHash": null,
        "texts": [
          {
            "key": "com.linkedin",
            "value": "linkdedin.in/zuffo"
          },
          {
            "key": "olimpiadas",
            "value": "rebeca"
          },
          {
            "key": "com.twitter",
            "value": "@zuffo"
          }
        ],
        "addresses": [
          {
            "address": "0x3a872f8FED4421E7d5BE5c98Ab5Ea0e0245169A0",
            "coin": "60"
          }
        ]
      },
      "expiryDate": "1752358416"
    }
  }
}

Steps to reproduce

  1. Go to the ENS APP on Sepolia
  2. Create a domain or get one you have
  3. Set it’s resolver to the Blockful’s DatabaseResolver (0xfCfC138635e8c00BfDa78507C8abeD5013148150)
  4. Go to the nameful dapp*
  5. Connect you waller and find your domain in manage tab
  6. Set any records you’d like (it relies on the EIP-5559 to redirect to the Blockful’s Gateway)
  7. Go to the Metadata API Interface
  8. Change the name variable to your domain’s name
  • The subdomains page is still under development and will soon be released.

Conclusion

The improvements to the ENSIP-16 schema and the implementation of off-chain resolvers represent significant progress in ENS functionality. These enhancements provide a more robust, efficient, and flexible system for managing and resolving ENS domains, both on-chain and off-chain. As the ENS ecosystem continues to evolve, these developments will play a crucial role in expanding its utility and adoption across the Ethereum network and beyond.

Thanks for doing this! It’s much needed.

I don’t think this is a good idea. There are many ways to create an expensive graphql query to try and DoS a server, and closing off one way to do it at the cost of expressiveness is not the way to go about it.

Thanks a lot for the feedback!

This is one of the inputs we wanted to understand better how important it is to get these fields on subdomains, because having this recursive schema without barriers isn’t a good practice. We can have some approaches here to maintain expressiveness and also prevent complex and long queries:

  • Using depth limit for the query.
  • Creating another entity for a subdomain that doesn’t include the subdomain field. Seeing only the subdomains one level below the name being queried.

There is also the option of accepting the risk, but the cons are:

  • Leaves the system vulnerable to potential DoS attacks
  • May lead to performance issues even with legitimate complex queries