Adapt ensjs for Electroneum ENS#1
Merged
Merged
Conversation
Port the library to work against the Electroneum ENS deployment from electroneum/ens-contracts (ABI-identical to upstream; only TLD constants differ): - Define the registrar TLD once as REGISTRAR_TLD = 'etn' in utils/consts and use it at the seven ground-truth 'eth' comparisons (getNameType, validation, getOwner, createSubname, getSubnames, filters). All 'eth-2ld'-gated functions adapt automatically; the specifier strings are kept as opaque tags to avoid public API churn. Template-literal name types now derive from typeof REGISTRAR_TLD. - Replace mainnet/sepolia in contracts/consts with electroneumTestnet (5201420), addresses sourced from ens-contracts deployment records, including canonical multicall3 (viem's Electroneum chain definitions ship no contracts). Drop the legacy/wrapped contract entries, which don't exist on Electroneum and were never consumed by function code. - Replace the subgraphApiKey option of addEnsContracts with a direct subgraphUrl override; no ENS subgraph exists for Electroneum yet, so the default is a localhost placeholder. - Add scripts/smokeElectroneumTestnet.mjs, a read-only smoke test that passes against the live testnet (availability, pricing, ownership, expiry, records via UniversalResolver, multicall3 batching, reverse). Electroneum mainnet (52014) addresses will be added once its contracts are deployed. The vitest suite still targets the upstream .eth local test env and is adapted separately.
Add the published Electroneum ens-contracts package as a devDependency and a verification script that checks the addresses in src/contracts/consts.ts against the package's shipped deployment records (pnpm verify:addresses, after pnpm build). Multicall3 is compared against a deployment record when one exists, falling back to the canonical singleton address, matching the deploy pipeline's semantics. When Electroneum mainnet is deployed, its addresses arrive via a version bump of the package and its records are the source for the mainnet entry in consts.ts. Also add pnpm script entries for the two .mjs scripts (smoke:testnet, verify:addresses) and apply Biome formatting to the smoke script, which was committed unformatted. @ensdomains/ens-contracts stays as a devDependency for now because hardhat.config.cts still points the local test environment at it; that machinery is replaced when the test env is adapted to the Electroneum contracts.
…flow The local test environment now deploys the real Electroneum ENS stack (from @etn-sc/ens-contracts) instead of the upstream .eth contracts: - scripts/testEnv.mjs replaces the @ensdomains/ens-test-env CLI: it starts a local foundry anvil (chain 1337, same timestamp/snapshot choreography as before), runs the deploy, then vitest. Docker is no longer needed. Anvil runs with --odyssey to enable the EIP-7951 P256VERIFY precompile that the fork's DNSSEC algorithm-13 contract calls — note the real Electroneum chains do NOT have that precompile (verified by probing 0x100 on testnet and mainnet with a valid P-256 signature), so P256-signed DNSSEC verification works locally but is silently broken on the live chains; fixing that belongs in ens-contracts (restore the pure-Solidity P256 implementation) or in etn-sc (adopt the precompile). - scripts/deployTestEnv.mjs runs the package's precompiled rocketh deploy pipeline in-process with electroneumTestnet-like tags (no legacy/wrapped contracts), registers the test fixtures, and writes DEPLOYMENT_ADDRESSES to .env.local. scripts/rockethAliasHook.mjs makes the precompiled scripts runnable under plain node (resolves the '@rocketh' alias, retries bare imports across pnpm's isolated layout, injects JSON import attributes, shims tsx and hardhat). - scripts/fixtures.mjs ports all the old hardhat-deploy fixture scripts to plain viem, registering the same ~95 names under .etn. Legacy/wrapped fixture states are recreated the way they arise on the real chain: modern-controller registration plus NameWrapper.wrapETH2LD (the retired legacy/wrapped controllers do not exist on Electroneum). ABI records encode through the library's own encodeAbi (the standalone cbor package miscompiles under node >= 26). Accounts are topped up because OwnedUsdOracle pricing makes multi-century durations unaffordable at default balances. - All hardhat machinery is removed: deploy/, utils/ name generators, hardhat.config.cts, the wrapped-controller artifacts, the hh script, and the hardhat/hardhat-deploy/@ensdomains/ens-contracts/ @ensdomains/ens-test-env devDependencies with their pnpm patches. NoMulticallResolver/OldResolver artifacts stay (deployed by the fixtures for resolver edge-case tests). - CI installs foundry instead of relying on docker anvil.
- Sweep every .eth fixture/test name to .etn and update namehash,
labelhash, and DNS-encoded-name constants and inline snapshots to
their .etn values (including namehash('etn') as the registrar node).
- Remove the live-Ethereum-network tests (CCIP against mainnet/sepolia
ENS, getDnsOffchainData, ENSv2 forward-compat, jessesum.eth/
taytems.xyz records): they target Ethereum ENS infrastructure that
this fork intentionally no longer supports. Local CCIP coverage via
ccipRequest/ccipBatchRequest utils remains; ccipRequest unit tests
now build their chain from electroneumTestnet.
- addTestContracts.ts: read Multicall3 (rocketh deployment name) and
drop the legacy/wrapped contract entries, which don't exist in the
Electroneum deployment; tests that asserted the legacy resolver
address now assert the PublicResolver.
- vitest: switch environment from happy-dom to node (nothing under
test touches DOM APIs, and happy-dom's AbortController breaks
node >= 26's fetch); a localStorage stub for the labels cache lives
in setup.ts. Subgraph tests are excluded until an Electroneum ENS
subgraph exists.
- getPrice expectations updated for OwnedUsdOracle pricing ($5/yr at
the default $0.00086/ETN test value).
Full suite: 62 files, 382 tests, all passing via
pnpm tenv start --extra-time 11368000.
CI installs the latest foundry, whose anvil (1.7.x) broke the test environment in two ways, both reproduced locally against the 1.7.1 binary: - anvil 1.7.x dropped the --odyssey flag (exit code 2 at startup); its default hardfork already includes the Osaka P256VERIFY precompile that the flag was providing. testEnv.mjs now retries without the flag when anvil rejects it (older anvils still need it), and prints anvil's stderr when startup genuinely fails instead of swallowing it. - anvil 1.7.x slightly underestimates gas for the timestamp-sensitive controller registrations, so fixture transactions died out-of-gas (gasUsed == gasLimit). The fixture writer now pads the node's estimate by 1.5x. Verified: full run (382/382) against anvil 1.7.1 via the fallback path, and the deploy against anvil 1.2.3 via --odyssey.
The pkg-pr-new GitHub App (upstream's continuous preview-release service) is not installed on this fork, so the step failed on every push after the tests had already passed. Preview builds of upstream's package from an Electroneum fork aren't wanted anyway.
- @ensdomains/ensjs -> @etn-sc/ensjs and @ensdomains/ensjs-react -> @etn-sc/ensjs-react across package manifests, source doc-comments, the error version string (getVersion), tests, examples, workflows, and the changesets changelog repo. repository fields now point at electroneum/ensjs, and both packages carry publishConfig.access=public (scoped packages default to restricted). - README rewritten for the fork: @etn-sc/ensjs install, Electroneum testnet example, .etn TLD, links to electroneum/ens-contracts, and a note that /subgraph functions need a not-yet-existing subgraph. - The release workflow's repository_owner guard now matches electroneum, so the changesets flow can run on this repo. Publishing uses npm OIDC trusted publishing (id-token: write, no NPM_TOKEN): the @etn-sc npm org must have trusted publishing configured for the electroneum/ensjs repo's publish.yml workflow before the first release. Verified: pnpm publish --dry-run resolves @etn-sc/ensjs@4.3.1 to registry.npmjs.org with a clean tarball (dist/ + src/, no tests), both packages build, and the full test suite passes (382/382).
Both automated publish paths (the changesets flow on main pushes and the prerelease flow on GitHub releases) are guarded off. Publishing to npm is done manually with pnpm publish from packages/ensjs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ports ensjs to Electroneum ENS: registrar TLD
.etn, Electroneum testnet (chain 5201420), publishable as@etn-sc/ensjs. Contracts come from@etn-sc/ens-contracts(ABI-identical to upstream; only TLD constants differ).Library
REGISTRAR_TLD = 'etn') and drives both runtime comparisons and the`${string}.etn`template-literal types. The'eth-2ld'specifier strings are kept as opaque tags to avoid churning the public API.contracts/consts.tssupportselectroneumTestnetonly, with addresses sourced from the testnet deployment records — including canonicalmulticall3, which viem's Electroneum chain definitions don't ship. Legacy/wrapped contract entries are removed (they don't exist on Electroneum and were never consumed). Mainnet (52014) gets added once deployed;pnpm verify:addresseschecksconsts.tsagainst the package's deployment records.addEnsContractstakes asubgraphUrloverride, and/subgraphfunctions are unusable until one is deployed.Test environment (docker-free)
pnpm tenv startnow runs a local foundry anvil, executes the@etn-sc/ens-contractsrocketh deploy pipeline in-process (no legacy/wrapped contracts, matching the real chain), registers all ~95.etnfixtures via plain viem, and runs vitest. All hardhat machinery and the docker-based ens-test-env are removed.pnpm smoke:testnet).--odyssey) and current anvil releases; CI installs foundry.Packaging
@etn-sc/ensjs(@etn-sc/ensjs-reactfor the hooks package), repository/README updated for the fork. npm publishing is manual only — both CI auto-publish workflows are guarded off.Known caveat
@etn-sc/ens-contracts' DNSSEC algorithm-13 contract (P256SHA256Algorithm) relies on the EIP-7951 P256VERIFY precompile, which the live Electroneum chains don't have — P256-signed DNSSEC verification silently fails on-chain (probed testnet + mainnet directly). The local test env enables the precompile in anvil, so DNS tests pass; the real fix belongs in ens-contracts (restore the pure-Solidity P256 implementation) or etn-sc (adopt the precompile). Low severity while DNSSEC is inert on Electroneum.