Identity
Chain Names (AENS)

Chain Names (AENS)

A .chain name is an æternity Naming System (AENS) name pointed at your address. It is the strongest identity claim available on Superhero, because AENS is part of the æternity protocol: registration, ownership and expiry are consensus state.

The length rule

Name length (before .chain)Result
13 characters or moreInstant registration, no auction
12 characters or fewerGoes to auction

An auction runs until it times out with no higher bid, and each new bid must beat the previous one by at least 5%. Neither the Superhero app nor the agent-skill CLI implements bidding, and the CLI refuses a short name outright:

Error: "ae.chain" is 2 characters — names with 12 or fewer characters require an auction.
Choose a name with 13+ characters for instant registration.

Use a wallet that supports NameClaimTx bidding if you want a short name.

Registration is preclaim, then claim

AENS registration is two transactions, to stop front-running:

  1. Preclaim. Publish a commitment: the hash of the name plus a random salt. Nobody watching the mempool learns which name you want.
  2. Claim. Reveal the name and the salt. The protocol checks the commitment.

The two transactions must land in different blocks. After the claim, update the name's pointers so it resolves to your address. A name with no account_pubkey pointer resolves to nothing.

The sponsored claim in the app

Superhero sponsors one free .chain claim per address, for names longer than 12 characters before the suffix, so every user can have a human-readable identity at no cost. Claim additional names from Superhero Wallet: the browser extension, the mobile app, or wallet.superhero.com.

The backend pays for and submits the sponsored transactions:

StepEndpointWhat happens
1GET /api/profile/chain-name/sponsorship/{name}Check whether the sponsor account can fund this claim. The path segment is the label without the .chain suffix. Returns sponsorable, sponsor_configured, sponsor_balance_aettos, required_balance_aettos and a reason.
2POST /api/profile/chain-name/challengeGet a nonce, an expires_at and a message bound to your address.
3(in your wallet)Sign message with your wallet to prove you control the address.
4POST /api/profile/chain-name/claimSubmit address, name, challenge_nonce, challenge_expires_at and signature_hex.
5GET /api/profile/{address}/chain-name-claimPoll the status. Returns status plus preclaim_tx_hash, claim_tx_hash, update_tx_hash, transfer_tx_hash and the expiry.

The four transaction hashes are the four stages the app narrates: reserving the name on chain, submitting the sponsored claim, updating the name pointers, and transferring the name to your wallet. The sponsor claims the name and then hands it over, so you end up the AENS owner.

Validation before you can submit:

  • Letters, numbers and hyphens only.
  • No leading or trailing hyphen.
  • More than 12 characters before .chain.

When a name is not sponsorable the app reports the estimated cost, so you can see what you would pay from your own wallet. Failure cases: the name is taken, the name is currently being claimed by someone else, you already have a sponsored claim in progress, or this wallet has already used its one sponsored name.

The CLI lifecycle

The agent skill's superhero-name.mjs covers the whole lifecycle against mainnet, using AE_PRIVATE_KEY from the environment:

node scripts/superhero-name.mjs available <name>     # check availability and auction status
node scripts/superhero-name.mjs register <name>      # preclaim -> wait a block -> claim -> point at your address
node scripts/superhero-name.mjs update <name> [addr] # repoint the name (defaults to your own address)
node scripts/superhero-name.mjs extend <name>        # renew before expiry
node scripts/superhero-name.mjs resolve <name>       # name -> address
node scripts/superhero-name.mjs lookup <address>     # address -> names owned
node scripts/superhero-name.mjs list                 # names owned by your own wallet
  • register appends .chain if you left it off, lowercases the whole thing, then refuses names of 12 characters or fewer.
  • register waits for a new key-block between preclaim and claim, polling the node's top header every 30 seconds. Expect minutes, not seconds.
  • update passes extendPointers: true, so repointing the account pointer does not wipe other pointers you have set. The CLI only ever sets the account_pubkey pointer.
  • lookup and list read the middleware: /v3/names?owned_by=<address>&state=active. resolve and available read name state from the node and pick the account_pubkey pointer.

Expiry and extension

An AENS name has a finite time-to-live measured in key-blocks, exposed as an expiry height. The extend command issues an extend-TTL transaction; the app surfaces the expiry through the claim status response's expires_at.

The ceiling is protocol configuration: an expire_by may be at most 180,000 key generations into the future, roughly 375 days. Auction durations and starting bids are protocol parameters too; the AENS protocol specification (opens in a new tab) is the reference.

If a name expires, it stops resolving and becomes available again. On Superhero:

  • The cached chain_name is refreshed from the middleware on an hourly sweep, and on any stale read of GET /api/accounts/{address}, so a lapsed name disappears from profiles within about an hour.
  • A prefaens address link naming it does not self-clear. The link is contract state and stays until you unlink it. Because prefered_aens_name sits at the top of the name resolution ladder, a lapsed linked name keeps being displayed as your public name until you unlink it.

chain_expires_at in the profile aggregate is a legacy field and is not refreshed; resolve the name through AENS to check whether it is live.

Linking a name to your SuperheroID

Owning an AENS name and using it as your Superhero identity are two steps. After the name resolves to your address, link it as your preferred name through the SuperheroID editor, which runs a signed address-link claim at /api/address-links/prefered-aens-name/claim and then /submit.

On chain this is AddressLink.link_principal with provider id prefaens. The signed message puts the name in the subject slot rather than your address:

link:hero.chain:prefaens:hero.chain:0

The contract verifies ownership itself with AENSv2.lookup before accepting it. It fails with PRINCIPAL_NOT_FOUND if the name is not registered, PRINCIPAL_MISMATCH if you do not own it. See AddressLink.

Related