ensdomains/ensjs

ENS JavaScript library for contract interaction

158

stars

1,667

commits

TypeScript

primary language

Sep 7, 2026

updated

README

ENSjs

The ultimate ENS JavaScript library, with viem under the hood.

ENSjs is a TypeScript library for interacting with the Ethereum Name Service. It provides tree-shakeable, composable actions on top of viem, with first-class support for both ENS v1 and ENS v2.

Features

  • Composable actions that extend any viem Client
  • Full tree-shaking — pay only for the actions you import
  • Multicall batching for read actions
  • TypeScript-first, with strict types for chain contracts
  • ENS v1 + ENS v2 support side by side
  • Subgraph and DNS helpers included
  • Standalone @ensdomains/ensjs-abi package for ABI snippets

Monorepo layout

PackageDescription
@ensdomains/ensjsMain library — actions, clients, utils
@ensdomains/ensjs-abiABI snippets for every ENS contract (v1 + v2)
@ensdomains/ensjs-reactReact hooks built on @wagmi/core
@ensdomains/ensjs-query-core@wagmi/core query integration

Supported chains: mainnet (1) and sepolia (11155111).

Installation

pnpm add @ensdomains/ensjs viem

You'll also need viem ≥ 2.9.2 as a peer dependency.

Getting started

addEnsL1Contracts extends a viem chain with all ENS contract addresses and subgraph URLs, so you can use it with any viem createPublicClient / createWalletClient.

import { http, createPublicClient } from 'viem'
import { mainnet } from 'viem/chains'
import { addEnsL1Contracts } from '@ensdomains/ensjs'
import { getAddressRecord, getRecords } from '@ensdomains/ensjs/public'

const client = createPublicClient({
  chain: addEnsL1Contracts(mainnet),
  transport: http(),
})

const eth = await getAddressRecord(client, { name: 'ens.eth' })
const records = await getRecords(client, {
  name: 'ens.eth',
  texts: ['com.twitter', 'avatar'],
  contentHash: true,
})

Entry points

The @ensdomains/ensjs package is split into subpath exports so bundlers can drop everything you don't import.

ImportContents
@ensdomains/ensjsaddEnsL1Contracts, error classes
@ensdomains/ensjs/publicShared read actions (resolution, records, reverse, price, availability)
@ensdomains/ensjs/public/v1v1-specific reads
@ensdomains/ensjs/public/v2v2-specific reads
@ensdomains/ensjs/walletShared write actions (register, renew, set records, wrap, transfer, …)
@ensdomains/ensjs/wallet/v2v2-specific writes
@ensdomains/ensjs/subgraphSubgraph client + queries (getSubnames, getNamesForAddress, history, …)
@ensdomains/ensjs/dnsDNS helpers (getDnsOwner, importDnsName, getDnsImportData, …)
@ensdomains/ensjs/utilsCoders (getAddress, getText, getAbi, getContentHash), name utils
@ensdomains/ensjs/utils/v2v2 utils (role encoding, resolver resources, canonical IDs)
@ensdomains/ensjs/contractsRe-exports of ABI snippets and getChainContractAddress
@ensdomains/ensjs/chainChain types and helpers (ChainWithEns, extendChainWithEns)

ABIs themselves are published as a standalone package and can be imported directly:

import { permissionedRegistryGetStateSnippet } from '@ensdomains/ensjs-abi/v2/permissionedRegistry'
import { ethRegistrarControllerRegisterSnippet } from '@ensdomains/ensjs-abi/v1/ethRegistrarController'

Action pattern

Every action is a plain function that takes the viem Client first and parameters second.

const result = await actionName(client, {
  /* params */
})

Read actions use getAction + readContract / multicall so they work with whatever batching configuration is on the client. Write actions return a transaction hash and accept the standard viem write parameters (account, chain, gas, etc.).

Development

# Install
pnpm install

# Build everything
pnpm -r build

# Build a single package
pnpm -F @ensdomains/ensjs build
pnpm -F @ensdomains/ensjs-abi build

# Lint (Biome)
pnpm lint

# Test the main package
pnpm -F @ensdomains/ensjs test
pnpm -F @ensdomains/ensjs test:watch
pnpm -F @ensdomains/ensjs test src/actions/public/getRecords.test.ts

# Local test environment with deployed ENS contracts
pnpm -F @ensdomains/ensjs denv

# Just the local anvil node (no contract deployment scripts)
pnpm -F @ensdomains/ensjs anvil

# Generate the markdown docs site
pnpm -F @ensdomains/ensjs generateDocs

# Versioning (changesets)
pnpm chgset:run
pnpm chgset:version

Node ≥ 22 is required for the main packages (≥ 18 for query-core). Tooling: pnpm 10, TypeScript strict mode, Biome for formatting and linting, Vitest for tests.

Contributing

See CONTRIBUTING.md for guidance on adding new actions, wiring up new ABI snippets, registering new contract addresses, and the test conventions used across the repo.

Docs

Per-action markdown docs live under docs/. A hosted docs site is in progress.

License

MIT

Contributors

TateB

583 commits

v1rtl

496 commits

storywithoutend

167 commits

LeonmanRolls

111 commits

ensdomains/ensjs

ENS JavaScript library for contract interaction

158

stars

1,667

commits

TypeScript

primary language

Sep 7, 2026

updated

README

ENSjs

The ultimate ENS JavaScript library, with viem under the hood.

ENSjs is a TypeScript library for interacting with the Ethereum Name Service. It provides tree-shakeable, composable actions on top of viem, with first-class support for both ENS v1 and ENS v2.

Features

  • Composable actions that extend any viem Client
  • Full tree-shaking — pay only for the actions you import
  • Multicall batching for read actions
  • TypeScript-first, with strict types for chain contracts
  • ENS v1 + ENS v2 support side by side
  • Subgraph and DNS helpers included
  • Standalone @ensdomains/ensjs-abi package for ABI snippets

Monorepo layout

PackageDescription
@ensdomains/ensjsMain library — actions, clients, utils
@ensdomains/ensjs-abiABI snippets for every ENS contract (v1 + v2)
@ensdomains/ensjs-reactReact hooks built on @wagmi/core
@ensdomains/ensjs-query-core@wagmi/core query integration

Supported chains: mainnet (1) and sepolia (11155111).

Installation

pnpm add @ensdomains/ensjs viem

You'll also need viem ≥ 2.9.2 as a peer dependency.

Getting started

addEnsL1Contracts extends a viem chain with all ENS contract addresses and subgraph URLs, so you can use it with any viem createPublicClient / createWalletClient.

import { http, createPublicClient } from 'viem'
import { mainnet } from 'viem/chains'
import { addEnsL1Contracts } from '@ensdomains/ensjs'
import { getAddressRecord, getRecords } from '@ensdomains/ensjs/public'

const client = createPublicClient({
  chain: addEnsL1Contracts(mainnet),
  transport: http(),
})

const eth = await getAddressRecord(client, { name: 'ens.eth' })
const records = await getRecords(client, {
  name: 'ens.eth',
  texts: ['com.twitter', 'avatar'],
  contentHash: true,
})

Entry points

The @ensdomains/ensjs package is split into subpath exports so bundlers can drop everything you don't import.

ImportContents
@ensdomains/ensjsaddEnsL1Contracts, error classes
@ensdomains/ensjs/publicShared read actions (resolution, records, reverse, price, availability)
@ensdomains/ensjs/public/v1v1-specific reads
@ensdomains/ensjs/public/v2v2-specific reads
@ensdomains/ensjs/walletShared write actions (register, renew, set records, wrap, transfer, …)
@ensdomains/ensjs/wallet/v2v2-specific writes
@ensdomains/ensjs/subgraphSubgraph client + queries (getSubnames, getNamesForAddress, history, …)
@ensdomains/ensjs/dnsDNS helpers (getDnsOwner, importDnsName, getDnsImportData, …)
@ensdomains/ensjs/utilsCoders (getAddress, getText, getAbi, getContentHash), name utils
@ensdomains/ensjs/utils/v2v2 utils (role encoding, resolver resources, canonical IDs)
@ensdomains/ensjs/contractsRe-exports of ABI snippets and getChainContractAddress
@ensdomains/ensjs/chainChain types and helpers (ChainWithEns, extendChainWithEns)

ABIs themselves are published as a standalone package and can be imported directly:

import { permissionedRegistryGetStateSnippet } from '@ensdomains/ensjs-abi/v2/permissionedRegistry'
import { ethRegistrarControllerRegisterSnippet } from '@ensdomains/ensjs-abi/v1/ethRegistrarController'

Action pattern

Every action is a plain function that takes the viem Client first and parameters second.

const result = await actionName(client, {
  /* params */
})

Read actions use getAction + readContract / multicall so they work with whatever batching configuration is on the client. Write actions return a transaction hash and accept the standard viem write parameters (account, chain, gas, etc.).

Development

# Install
pnpm install

# Build everything
pnpm -r build

# Build a single package
pnpm -F @ensdomains/ensjs build
pnpm -F @ensdomains/ensjs-abi build

# Lint (Biome)
pnpm lint

# Test the main package
pnpm -F @ensdomains/ensjs test
pnpm -F @ensdomains/ensjs test:watch
pnpm -F @ensdomains/ensjs test src/actions/public/getRecords.test.ts

# Local test environment with deployed ENS contracts
pnpm -F @ensdomains/ensjs denv

# Just the local anvil node (no contract deployment scripts)
pnpm -F @ensdomains/ensjs anvil

# Generate the markdown docs site
pnpm -F @ensdomains/ensjs generateDocs

# Versioning (changesets)
pnpm chgset:run
pnpm chgset:version

Node ≥ 22 is required for the main packages (≥ 18 for query-core). Tooling: pnpm 10, TypeScript strict mode, Biome for formatting and linting, Vitest for tests.

Contributing

See CONTRIBUTING.md for guidance on adding new actions, wiring up new ABI snippets, registering new contract addresses, and the test conventions used across the repo.

Docs

Per-action markdown docs live under docs/. A hosted docs site is in progress.

License

MIT

Contributors

TateB

583 commits

v1rtl

496 commits

storywithoutend

167 commits

LeonmanRolls

111 commits

Languages

TypeScript

100.0%