ens-elixir

Changelog

ens_elixir helps an Elixir app work with ENS names when the job is to:

It is a library package. It reads ENS state, explains what is missing, and prepares the next request to send. Your app, wallet, or signer still decides whether to approve and send that request.

This package ports the core ENSIP-25 helpers from qntx/ensip25 and adds the higher-level tools needed by CLI tools and Phoenix apps.

Installation

Add ens_elixir to your list of dependencies in mix.exs:

def deps do
  [
    {:ens_elixir, "~> 0.1.0"}
  ]
end

Start Here

Most apps only need one of these entry points:

If you are building a custom flow, use AgentEns.Tx for one-off ENS and subname changes.

Quick Examples

Build the ENSIP-25 record key for an EVM registry entry:

iex> AgentEns.evm_record_key(1, "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432", 42)
{:ok, "agent-registration[0x000100000101148004a169fb4a3325136eb29fa0ceb6d2e539a432][42]"}

Check whether an ENS name already proves the link:

iex> AgentEns.verify(
...>   "https://eth.llamarpc.com",
...>   "vitalik.eth",
...>   1,
...>   "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
...>   42
...> )
{:ok, :verified}

Read the current state of a name:

iex> AgentEns.read_name(%{
...>   ens_name: "vitalik.eth",
...>   chain_id: 1,
...>   rpc_url: "https://eth.llamarpc.com",
...>   text_keys: ["avatar", "url"]
...> })
{:ok, %AgentEns.Read.NameDetails{}}

Plan what needs to change before prompting a signer:

iex> AgentEns.plan_link(%{
...>   ens_name: "vitalik.eth",
...>   chain_id: 1,
...>   registry_address: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
...>   agent_id: 42,
...>   rpc_url: "https://eth.llamarpc.com",
...>   signer_address: "0x1234..."
...> })
{:ok, %AgentEns.Plan.LinkPlan{}}

Prepare the next unsigned requests for both sides of the link:

iex> AgentEns.prepare_bidirectional_link(%{
...>   ens_name: "vitalik.eth",
...>   chain_id: 1,
...>   registry_address: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
...>   agent_id: 42,
...>   rpc_url: "https://eth.llamarpc.com",
...>   signer_address: "0x1234..."
...> })
{:ok,
 %{
   plan: %AgentEns.Plan.LinkPlan{},
   ensip25: %{tx: %AgentEns.TxRequest{}},
   erc8004: %{tx: %AgentEns.TxRequest{}},
   reverse: :skipped
 }}

Prepare an unsigned request to create or update a subname:

iex> AgentEns.Tx.build_create_subname_tx(%{
...>   parent_name: "vitalik.eth",
...>   chain_id: 1,
...>   label: "agent",
...>   owner_address: "0x1234...",
...>   resolver_address: "0x226159d592e2b063810a10ebf6dcbada94ed68b8",
...>   ttl: 0
...> })
{:ok, %AgentEns.TxRequest{}}

What You Get Back

The package always returns one of two shapes:

When the package prepares a change, it returns %AgentEns.TxRequest{}. That is a wallet-ready request with:

The package does not send that request for you.

Common Jobs

1. Check an existing link

Use AgentEns.verify/6 when you already know the chain, registry, and agent ID and only want a yes-or-no answer.

Use AgentEns.verify_agent/5 when the registry is one of the built-in ERC-8004 defaults for Ethereum mainnet or Sepolia.

2. Inspect a name before showing UI

Use AgentEns.read_name/1 when you want to show a person who controls a name, which resolver it uses, whether it has an ETH address, whether it has a content hash, and which text records are present.

3. Decide what should happen next

Use AgentEns.plan_link/1 when you want to know:

This is the safest starting point for a UI that wants to explain the situation before asking for approval.

4. Prepare updates

Use AgentEns.prepare_ensip25_update/1 when you only need the ENS proof record.

Use AgentEns.prepare_erc8004_update/1 when you only need to patch the agent registration.

Use AgentEns.prepare_bidirectional_link/1 when you want the full answer in one call.

Use AgentEns.Tx when you want to prepare other ENS changes such as:

Built-In Network Defaults

The package ships with default ENS and ERC-8004 addresses for:

You can still pass explicit addresses whenever you want to override those defaults.

What This Package Does Not Do

Full Guide

For a fuller walkthrough of the package, see USAGE.md.

Publishing

Build the package locally with:

mix hex.build

Publish it with:

mix hex.publish