Updated: 2026-02-19
ENSIP-X: Node Classification Metadata
Abstract
This ENSIP proposes a standard method for using text records to declare the role of an ENS name/subname (node). Two types of standardized text records are introduced, which provide for labeling the role of node against a larger organizational structure, and for defining the structure of additional, context-dependent attributes that may be appended to that node.
Motivation
In practice, ENS subnames are often used to represent organizational structures. For example, an ENS name belonging to an individual might have a subname which points to the individual's cold wallet, and another which points to a hot wallet that they use for voting in on-chain governance. DAOs or other on-chain organizations might have a top-level ENS name that represents the group as a whole, with subnames created to represent treasuries, smart contracts, working groups, committees, and other entities within the organization. This ENSIP offers a way to add metadata to each of those nodes to declare its role in the larger organizational structure, and to append context-specific metadata which is machine-readable and standardized, allowing dynamic discovery and recognition of the role each subname is meant to fulfill.
Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Metadata Records
This ENSIP builds on ENSIP-5 and ENSIP-24, and uses text records stored in each node's resolver to provide additional metadata for that node. We define two new unqualified, global key names (class and schema) which are hereby reserved for use in accordance with this ENSIP. Additional metadata attributes can also be added to a node and stored as text or data records, with their key names declared by the schema entry (explained below).
It is expected that each node will be configured to resolve to one or more on-chain addresses, and the metadata attributes attached to a node are understood to apply to the entity or entities represented by those addresses.
class Text Record
Nodes can specify a text record with the key name of class, the value of which serves to label the general role or purpose of that node. These values are largely intended to be useful to humans who wish to understand what importance to give to each node, but can also be used programmatically in filtering and recognizing categories of node for automated systems.
The value of this record MUST be pascal case, using only alphabet characters. Values SHOULD be limited to those outlined in the following table to maximize compatability across the ecosystem, however other values MAY be used for specialized use cases.
class Value | Meaning |
|---|---|
| Agent | This node represents an autonomous software-controlled entity |
| Application | This node represents a software application, service, or product |
| Committee | This node represents a formal group with delegated authority to make decisions or provide oversight within a defined scope |
| Contract | This node represents, and resolves to, a smart contract |
| Council | This node represents a high-level governance body with broad strategic authority and stewardship responsibilities |
| Delegate | This node represents a voter in on-chain governance, who may or may not have been delegated voting power from others |
| Group | This node represents a logical grouping of multiple child nodes |
| Org | This node represents an organization or sub-organization within a larger entity |
| Person | This node represents an individual human |
| Treasury | This node represents an account for funds that are collectively owned and/or managed |
| Wallet | This node's main purpose is to send, receive, and/or store funds |
| Workgroup | This node represents an operational team focused on executing tasks or work within a specific domain |
It is understood that all on-chain addresses could have the ability to perform a base set of actions, including:
- sending and receiving funds
- calling smart contracts
- publishing new smart contracts
- providing signatures
Therefore, class designations like contract and wallet should only be interpreted as declaring that node's main purpose in the context of the organizational structure; nodes that do not use one of these classes can still point to addresses which are smart contracts and/or hold funds. The same address can be pointed to by multiple nodes, each with a different class designation and metadata describing a different aspect of that address/account.
schema Text Record
Nodes can specify a text record with the key name of schema, the value of which points to a JSON schema which declares which metadata attributes can be added to the node as text or data records, in addition to the global text records already specified in existing ENSIPs. The value of schema MUST start with one of the following prefixes, followed by the appropriate value:
ipfs://- followed by the ipfs URI pointing to the JSON payloadhttps://- followed by the http(s) URI pointing to the JSON payloadcbor:- followed by the schema encoded in CBOR format
Schema Payload
If a schema is provided for a node, it specifies which additional metadata attributes are expected to be provided for that node, stored as text or data records. Schemas MUST follow the JSON Schema specification, version 2020-12, and describe a single-level object in which property names match the text or data record key names. Attribute key names MUST use camel case.
Clients that facilitate storing metadata records SHOULD reject values that fail validation according to the provided schema.
Clients that facilitate retrieving metadata records MAY ignore values that fail validation according to the provided schema.
Additional details
- The schema's
$idfield SHOULD be used to identify the schema's creator and/or version. - The schema's
titlefield identifies what entity is described in the data structure. If the schema is intended to be used with a specificclass, the value oftitleSHOULD be the same as the class it is meant to represent. - If a node has a
schemapresent but noclassrecord set, the value of the schema'stitleSHOULD be used as the class identifier for the node. - Schema authors are encouraged to populate the
descriptionfield with an explanation of the organizational role fulfilled by nodes which use this schema, in line with theclassdescriptions listed above. - Schemas MAY include definitions for key names which are declared as global in other ENSIPs, however if present, the descriptions of these keys MUST NOT be in direct conflict of their original definition provided by existing ENSIPs.
- Attributes can include an optional
recordType("text" | "data") keyword which indicates if the record is stored astext(ENSIP-5) ordata(ENSIP-24) (default:text)
Basic schema example
{
"$id": "v1.0",
"title": "Person",
"description": "This node represents an individual human",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "The person's first name.",
},
"lastName": {
"type": "string",
"description": "The person's last name."
},
"proofOfHumanity": {
"type": "string",
"description": "A signed attestation of proof of humanity.",
"recordType": "data"
},
"avatar": {
"type": "string",
"description": "a URL to an image used as an avatar or logo"
}
}
}Parameterized Key Names
Schemas can support parameterized properties, which allow a single property to have multiple variant-specific values. Parameters are specified using bracket notation appended to the property when used as a key name:
keyName[parameter]Schemas MAY simultaneously support both the base form (keyName) and parameterized form (keyName[parameter]). The parameterized form with empty brackets (keyName[]) SHALL NOT be allowed.
When both base and parameterized forms exist, clients SHOULD treat them as independent records, with the base form serving as a default when no specific parameter is requested.
To add a parameterized key to a JSON schema, add a regex pattern which enforces the use of brackets to the patternProperties object. The following example regex value will accept either the base form or the parameterized form, while rejected empty brackets: ^keyName(\[[^\]]+\])?$
When parsing key names, the following regex can be used to isolate the base form (group 1) and the parameter (group 3, if provided): ^(keyName)(\[([^\]]+)\])?$
Note: Defining which values are allowed to be passed inside of the brackets when setting and retrieving records is up to schema publishers and is outside the scope of this ENSIP.
Basic schema example including parameterized properties
{
"$id": "v1.0",
"title": "Person",
"description": "This node represents an individual human",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "The person's first name.",
},
"lastName": {
"type": "string",
"description": "The person's last name."
},
"avatar": {
"type": "string",
"description": "a URL to an image used as an avatar or logo"
}
},
"patternProperties": {
"^proofOfHumanity(\[[^\]]+\])?quot;: {
"type": "string",
"description": "A signed proof of humanity attestation. The name of a specific provider can be passed as a parameter.",
"recordType": "data"
}
}
}In this example, the owner of the node could use the key proofOfHumanity[provider] to store a proof of humanity attestation from a specific provider, and they could use proofOfHumanity to publish a default attestation to be retrieved if no provider is specified.
Backwards Compatibility
This proposal is built upon existing ENSIPs and does not affect existing ENS functionality. It introduces no breaking changes.
Security Considerations
None.
Copyright
Copyright and related rights waived via CC0.