Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
d56b414
add legacy register name functions
storywithoutend Dec 16, 2024
db176b4
fix and add tests
storywithoutend Dec 18, 2024
0aef6bf
add export code
storywithoutend Dec 18, 2024
d548d95
add prelease changeset
storywithoutend Dec 19, 2024
00e52b0
add minor changeset
storywithoutend Dec 20, 2024
78211a9
revert to before changeset pre enter command
storywithoutend Jan 7, 2025
f63d308
Revert "revert to before changeset pre enter command"
storywithoutend Jan 7, 2025
bcbdd64
revert changeset changes
storywithoutend Jan 7, 2025
d5615f5
revert changeset changes
storywithoutend Jan 7, 2025
8890de9
fix typo in release.yml
storywithoutend Jan 7, 2025
a9c1192
update release.yml for prerelease
storywithoutend Jan 7, 2025
688e6f0
v4.0.3-alpha.0
github-actions[bot] Jan 7, 2025
f530c91
add more abi snippet for ethcontroller and legacyethcontroller
storywithoutend Jan 9, 2025
984d63a
refactor and split out legacyregistration and legacyregistraionwithco…
storywithoutend Jan 10, 2025
9fc9aba
update legacyRegisterHelpers test
storywithoutend Jan 10, 2025
9e63758
fix lint error
storywithoutend Jan 10, 2025
951874e
v4.0.3-alpha.11
github-actions[bot] Jan 10, 2025
930cf26
refactor legacyRegisterName
storywithoutend Jan 13, 2025
5e345df
Merge branch 'add-register-commit-without-namewrapper' of https://git…
storywithoutend Jan 13, 2025
28c004b
fix typo in legacyEthEthRegistrarControllerNameRegisteredEventSnippet
storywithoutend Jan 13, 2025
ae1199f
Merge branch 'main' into add-register-commit-without-namewrapper
storywithoutend Jan 13, 2025
5397a10
v4.0.3-alpha.12
github-actions[bot] Jan 13, 2025
e029b41
update address-encoder
storywithoutend Aug 14, 2025
b0d8ca3
add verbosity to ci logs
storywithoutend Aug 14, 2025
6e4327b
update the contracts
storywithoutend Aug 18, 2025
e330e76
Update pnpm-lock.yaml
storywithoutend Aug 18, 2025
ceb259b
Update prepack.ts
storywithoutend Aug 18, 2025
cb6c6db
update prepack command
storywithoutend Aug 18, 2025
2c017c0
Update test.yml
storywithoutend Aug 18, 2025
68e66ad
Merge branch 'main' into add-register-commit-without-namewrapper
storywithoutend Aug 18, 2025
edbdd41
Revert "Merge branch 'main' into add-register-commit-without-namewrap…
storywithoutend Aug 18, 2025
fcdb8cb
Reapply "Merge branch 'main' into add-register-commit-without-namewra…
storywithoutend Aug 18, 2025
cf7ce1a
Merge branch 'bump-address-encoder' into add-register-commit-without-…
storywithoutend Aug 18, 2025
a65ef18
Update test.yml
storywithoutend Aug 18, 2025
7180451
Update nonceManager.ts
storywithoutend Aug 18, 2025
96d80a7
add console log to check issues
storywithoutend Aug 18, 2025
4f1510c
Update wrappedNameGenerator.ts
storywithoutend Aug 18, 2025
4a0647d
test without nonceManager
storywithoutend Aug 18, 2025
7830265
swap pkg.pr.new order so i can test out build
storywithoutend Aug 18, 2025
3eb1193
Fix linting errors and CommonJS import issues
storywithoutend Aug 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Prerelease

on:
release:
types: [published]
jobs:
release:
name: Release
permissions:
id-token: write
contents: write
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.release.target_commitish }}

- uses: pnpm/action-setup@v4
with:
version: 9.4.0

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'

- run: pnpm install --frozen-lockfile

- name: Set up git
run: |
git config --local user.email '41898282+github-actions[bot]@users.noreply.github.com'
git config --local user.name 'github-actions[bot]'

- name: Bump version to ${{ github.event.release.tag_name }}
run: |
pnpm -F @ensdomains/ensjs ver ${{ github.event.release.tag_name }}
git add .
git commit -m "${{ github.event.release.tag_name }}"

- name: Publish
env:
NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true
run: |
pnpm config set //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}
pnpm -F @ensdomains/ensjs publish --tag next --no-git-checks

- name: Push changes
run: git push
env:
github-token: ${{ secrets.GITHUB_TOKEN }}
5 changes: 4 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ jobs:
- name: Build ensjs
run: pnpm -F @ensdomains/ensjs build

- name: Publish on pkg.pr.new
run: pnpm dlx pkg-pr-new publish './packages/ensjs'
- name: Run tests
run: pnpm -F @ensdomains/ensjs tenv start --extra-time 11368000
run: pnpm -F @ensdomains/ensjs tenv start --extra-time 11368000 --verbosity 1

lint:
name: Lint
runs-on: ubuntu-latest
Expand Down
75 changes: 75 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

### Development
```bash
# Install dependencies (from root)
pnpm install

# Build the main package
cd packages/ensjs && pnpm build

# Run tests
cd packages/ensjs && pnpm test

# Run tests in watch mode
cd packages/ensjs && pnpm test:watch

# Run a single test file
cd packages/ensjs && pnpm test path/to/file.test.ts

# Lint/format code (from root or package)
pnpm lint

# Start test environment
cd packages/ensjs && pnpm tenv
```

### Publishing
```bash
# Version packages with changesets
pnpm chgset:version

# Publish packages
pnpm release
```

## Architecture

ENSjs v3 is a monorepo containing the core ENS JavaScript library built on top of viem.

### Client Types
- **EnsPublicClient**: Read operations (getOwner, getResolver, getName, etc.)
- **EnsWalletClient**: Write operations (registerName, transferName, setRecords, etc.)
- **EnsSubgraphClient**: Subgraph queries for historical/aggregate data

### Function Organization
```
src/functions/
├── public/ # Read functions (e.g., getAddressRecord, getTextRecord)
├── wallet/ # Write functions (e.g., setResolver, setRecords)
├── subgraph/ # Subgraph queries (e.g., getNamesForAddress)
└── dns/ # DNS-related functions
```

### Key Patterns
- All functions are designed to be batchable using viem's multicall
- Extensive use of TypeScript generics for type safety
- Custom error types in `/errors/` for detailed error handling
- Utility functions in `/utils/` for common operations like name normalization

### Testing
- Uses Vitest with happy-dom environment
- Test files co-located with source (*.test.ts)
- ENS test environment available via `pnpm tenv` for integration testing
- Tests should not run in parallel due to shared blockchain state

### Code Style
- Biome for linting and formatting (2 spaces, single quotes)
- TypeScript strict mode enabled
- No explicit `any` types (warning)
- No non-null assertions allowed
- Imports are automatically organized
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"publish:local:ens-test-env": "yalc publish packages/ens-test-env --push --up",
"publish:local:ensjs": "yalc publish packages/ensjs --push --up",
"chgset:version": "changeset version && pnpm install",
"chgset:version:prerelease": "changeset pre enter next && pnpm chgset:version",
"chgset:run": "changeset",
"release": "pnpm publish -r --access public && changeset tag",
"chgset": "pnpm chgset:run && pnpm chgset:version",
Expand Down
27 changes: 27 additions & 0 deletions packages/ensjs/.claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"permissions": {
"allow": [
"Bash(node:*)",
"Bash(pnpm tenv start:*)",
"Bash(pnpm tenv:*)",
"Bash(pnpm -F @ensdomains/ensjs tenv start:*)",
"Bash(grep:*)",
"Bash(pnpm list:*)",
"Bash(pnpm add:*)",
"Bash(pnpm test:*)",
"Bash(pnpm prepack:*)",
"Bash(find:*)",
"Bash(ls:*)",
"WebFetch(domain:docs.anthropic.com)",
"Bash(claude mcp list:*)",
"mcp__github__list_workflow_runs",
"mcp__github__list_workflows",
"mcp__github__get_job_logs",
"Bash(pnpm lint:*)",
"Bash(pnpm build:*)",
"Bash(pnpm tsc:*)",
"Bash(git add:*)"
],
"deny": []
}
}
2 changes: 1 addition & 1 deletion packages/ensjs/deploy/00_register_concurrently.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { DeployFunction } from 'hardhat-deploy/dist/types.js'
import type { DeployFunction } from 'hardhat-deploy/dist/types.ts'
import { MAX_DATE_INT } from '../dist/utils/consts.js'
import { encodeFuses } from '../dist/utils/fuses.js'

Expand Down
6 changes: 3 additions & 3 deletions packages/ensjs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ensdomains/ensjs",
"version": "4.0.2",
"version": "4.0.3-alpha.12",
"description": "ENS javascript library for contract interaction",
"type": "module",
"types": "./dist/index.d.ts",
Expand Down Expand Up @@ -78,7 +78,7 @@
"clean": "rm -rf ./dist ./README.md ./LICENSE",
"lint": "eslint ./src/* --no-error-on-unmatched-pattern",
"build": "tsc --project tsconfig.build.json",
"tsn": "TS_NODE_PROJECT=tsconfig.node.json node --loader ts-node/esm",
"tsn": "node --loader ts-node/esm",
"prepublish": "pnpm build && cp ../../README.md ../../LICENSE ./",
"prepack": "pnpm tsn ./scripts/prepack.ts",
"ver": "pnpm tsn ./scripts/updateVersion.ts",
Expand All @@ -88,7 +88,7 @@
},
"dependencies": {
"@adraffy/ens-normalize": "1.10.1",
"@ensdomains/address-encoder": "1.1.1",
"@ensdomains/address-encoder": "1.1.3",
"@ensdomains/content-hash": "3.1.0-rc.1",
"@ensdomains/dnsprovejs": "^0.5.1",
"abitype": "^1.0.0",
Expand Down
12 changes: 8 additions & 4 deletions packages/ensjs/scripts/prepack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@

import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
/* eslint-disable no-continue */
import jsonFs from 'jsonfile'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

type Exports = {
[key: string]: string | { types?: string; import: string; default: string }
}

// Generates a package.json to be published to NPM with only the necessary fields.
function generatePackageJson() {
const packageJsonPath = path.join(import.meta.dirname, '../package.json')
const packageJsonPath = path.join(__dirname, '../package.json')
const tmpPackageJson = jsonFs.readFileSync(packageJsonPath)

jsonFs.writeFileSync(`${packageJsonPath}.tmp`, tmpPackageJson, { spaces: 2 })
Expand Down Expand Up @@ -42,10 +46,10 @@ function generatePackageJson() {
// Generate proxy packages for each export.
const files_ = [...files]
for (const [key, value] of Object.entries(exports_ as Exports)) {
console.log(key, value)
if (typeof value === 'string') continue
if (key === '.') continue
if (!value.default || !value.import)
throw new Error('`default` and `import` are required.')
if (!value.default) throw new Error('`default` is required.')
if (!fs.existsSync(key)) fs.mkdirSync(key)
if (!fs.existsSync(`${key}/package.json`))
fs.writeFileSync(
Expand All @@ -57,7 +61,7 @@ function generatePackageJson() {
if (k === 'import') return 'module'
if (k === 'default') return 'main'
if (k === 'types') return 'types'
throw new Error('Invalid key')
return k // Allow other keys to pass through
})()
return `"${key_}": "${v.replace('./', '../')}"`
})
Expand Down
38 changes: 35 additions & 3 deletions packages/ensjs/src/contracts/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export const supportedContracts = [
'ensRegistry',
'ensReverseRegistrar',
'ensUniversalResolver',
'legacyEthRegistrarController',
'legacyPublicResolver',
'ensDefaultReverseRegistrar',
] as const

export type SupportedChain = (typeof supportedChains)[number]
Expand Down Expand Up @@ -54,7 +57,16 @@ export const addresses = {
address: '0xa58E81fe9b61B5c3fE2AFD33CF304c454AbFc7Cb',
},
ensUniversalResolver: {
address: '0x5a9236e72a66d3e08b83dcf489b4d850792b6009',
address: '0xaBd80E8a13596fEeA40Fd26fD6a24c3fe76F05fB',
},
ensDefaultReverseRegistrar: {
address: '0x283F227c4Bd38ecE252C4Ae7ECE650B0e913f1f9',
},
legacyEthRegistrarController: {
address: '0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5',
},
legacyPublicResolver: {
address: '0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41',
},
},
[holesky.id]: {
Expand Down Expand Up @@ -88,6 +100,15 @@ export const addresses = {
ensUniversalResolver: {
address: '0xf606bc986635dab91b189aee8f565f45a0336f89',
},
legacyEthRegistrarController: {
address: '0xf13fC748601fDc5afA255e9D9166EB43f603a903',
},
legacyPublicResolver: {
address: '0xc5e43b622b5e6C379a984E9BdB34E9A545564fA5',
},
ensDefaultReverseRegistrar: {
address: '0x0000000000000000000000000000000000000000',
},
},
[sepolia.id]: {
ensBaseRegistrarImplementation: {
Expand Down Expand Up @@ -115,10 +136,19 @@ export const addresses = {
address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
},
ensReverseRegistrar: {
address: '0xCF75B92126B02C9811d8c632144288a3eb84afC8',
address: '0xA0a1AbcDAe1a2a4A2EF8e9113Ff0e02DD81DC0C6',
},
ensUniversalResolver: {
address: '0x49c9331501b37191d54f5e332b307df82d15e9cc',
address: '0xb7B7DAdF4D42a08B3eC1d3A1079959Dfbc8CFfCC',
},
ensDefaultReverseRegistrar: {
address: '0x4F382928805ba0e23B30cFB75fC9E848e82DFD47',
},
legacyEthRegistrarController: {
address: '0x7e02892cfc2Bfd53a75275451d73cF620e793fc0',
},
legacyPublicResolver: {
address: '0x0CeEC524b2807841739D3B5E161F5bf1430FFA48',
},
},
} as const satisfies Record<
Expand Down Expand Up @@ -159,6 +189,8 @@ type EnsChainContracts = {
ensReverseRegistrar: ChainContract
ensBulkRenewal: ChainContract
ensDnssecImpl: ChainContract
legacyEthRegistrarController: ChainContract
legacyPublicResolver: ChainContract
}

type BaseChainContracts = {
Expand Down
41 changes: 41 additions & 0 deletions packages/ensjs/src/contracts/ethRegistrarController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,44 @@ export const ethRegistrarControllerRenewSnippet = [
type: 'function',
},
] as const

export const ethRegistrarControllerNameRegisteredEventSnippet = [
{
anonymous: false,
inputs: [
{
indexed: false,
name: 'name',
type: 'string',
},
{
indexed: true,
name: 'label',
type: 'bytes32',
},
{
indexed: true,
internalType: 'address',
name: 'owner',
type: 'address',
},
{
indexed: false,
name: 'baseCost',
type: 'uint256',
},
{
indexed: false,
name: 'premium',
type: 'uint256',
},
{
indexed: false,
name: 'expires',
type: 'uint256',
},
],
name: 'NameRegistered',
type: 'event',
},
] as const
Loading
Loading