Identity
SuperheroID

SuperheroID

SuperheroID is Superhero's identity layer: an æternity address with a set of independently signed, independently revocable links attached to it. The links live in the AddressLink contract. You authorise every link with your wallet signature, and only you can remove one.

What it links

LinkProvider idOn-chain callProof required
X handlexlinkAn OAuth session the backend observes, sealed into a 5-minute HMAC token
Nostr keynostrlinkA kind-22242 event signed by the npub, under 5 minutes old
Preferred .chain nameprefaenslink_principalAENS ownership, checked on chain with AENSv2.lookup
BiobiolinkOwnership of the address only
WebsitesitelinkOwnership of the address only

Every link also needs your æternity signature over the claim message; the proof column is what the provider checks on top of that. Each link is removed by its own unlink, which needs nothing but your signature.

The transaction itself is submitted and paid for by Superhero's provider wallet, which is the only account permitted to write the x, nostr, bio, site and prefaens namespaces. See AddressLink for the provider-ownership model.

What is on chain and what is not

DataAuthority
Every provider link, its value, and the per-address nonceAddressLink contract state
The reverse index: which address owns a given provider valueAddressLink contract state
Which account may write a provider namespaceAddressLink providers map
AENS name registration, pointers, expiryæternity AENS; the prefaens link references it but does not own it
Posts, comments, tip totalsTipping v3 plus the API index
Avatar, fullname, legacy username, follow counts, leaderboard statsSuperhero API
Chain name shown on a profileResolved hourly from the middleware, not from a contract link

Reading an identity

GET /api/profile/{address} returns the merged aggregate: address, a profile object (fullname, bio, site, avatarurl, username, prefered_aens_name, x_username, chain_name, chain_expires_at, plus follow counts when the social-graph feature is on) and a resolved public_name. Profiles are served entirely from indexed data; the includeOnChain query flag is deprecated.

public_name is the first non-empty value of:

prefered_aens_name   (links.prefaens — the AENS name you explicitly linked)
chain_name           (from the middleware, refreshed hourly)
username             (the legacy profile field)
address              (the ak_… itself)

GET /api/accounts/{address} returns the raw side of the same data, including a links object keyed by provider id. That is the authoritative view; the client reads it first and treats the flat profile fields as fallbacks for older records.

How a third party verifies a link

In order of how much can be checked independently:

  1. Preferred .chain name. link_principal calls AENSv2.lookup inside the contract and aborts with PRINCIPAL_MISMATCH if the signer does not own the name. You can independently resolve the name through AENS on any node and compare its account_pubkey pointer. Both checks are protocol state.
  2. Nostr key. The backend verifies a Schnorr signature from the npub over the exact claim message before submitting, but only the æternity signature is recorded on chain. A reader of the chain sees the address's consent to an npub string.
  3. X handle. The chain records that the address consented to a handle string and that the provider owner submitted it. The OAuth evidence lives only inside the backend. See Verifying Your X Account.
  4. Bio and website. Nothing to verify beyond ownership of the address.
  5. Posts. Independent of the identity layer. A post's sender is whichever address signed the transaction, recorded by the Tipping contract.

The verified badge on a profile means an x link exists for that account.

Where you manage it

Open your own profile at https://superhero.com/users/ plus your address and choose Edit SuperheroID. The editor covers the .chain name selection and preferred-name link, the bio, the website and the X connection. Each change is a separate claim-sign-submit round trip, and the editor reloads its state after each one.

Fullname, avatar and the legacy username are read-only.

Related