DID method · specification v0.1 · 23 September 2026

The did:namid DID method.

Every NamID name is a W3C Decentralized Identifier. This page is the method specification: the identifier syntax, the DID document a name resolves to, the four operations, and the security and privacy considerations. Resolve one now: https://namid.net/api/did/resolve?did=did:namid:testnet11:alice.mojo

Status: Draft, 2026-09-23 · Owner: Web3UTXOs Technologies (NamID Protocol) Method name: namid · Ledger: Chia blockchain (singleton coins) · Licence: CC0 Registry entry: to be submitted to the W3C DID Extensions "DID Methods" registry (w3c/did-extensions, methods.json) once this document is published at https://namid.net/did-namid.html. Reference implementation: apps/NalandaX/registry-Backend-artefacts/did_namid.py and tld_uri.py in github.com/DIPMR/Codex-Namid-Protocol-V0; tests in tests/test_did_namid.py.

This document follows the requirements for DID method specifications in DID Core §8: method name, method-specific identifier syntax, the four operations, security and privacy considerations.


1. Why a method of its own

NamID is a naming protocol on Chia in which every name is an identity: a root (mojo, xch, chia) is a soulbound singleton coin, and a name beneath it (alice.mojo) is a Chia coin bound to its holder. Chia wallets already print DIDs as did:chia:1…, but did:chia is not a registered DID method and has no method specification; the only Chia-singleton method in the W3C registry is did:julia. A NamID identifier presented to the wider DID ecosystem therefore needs a method that is specified, resolvable and registered. did:namid is that method.

Nothing older changes. The same 32 launcher bytes remain spellable as did:chia:1… (Chia-ecosystem interop), tld:1… (protocol-internal) and namid:1… (the protocol's own URI); the did:namid document lists all of them under alsoKnownAs.

2. Method name

The method name is namid. A DID that uses this method MUST begin with did:namid:.

3. Method-specific identifier

did-namid   = "did:namid:" [ network ":" ] id
network     = 1*16( %x61-7A / DIGIT )   ; lowercase; OMITTED on mainnet
id          = launcher-id / name
launcher-id = "1" 1*bech32-char         ; bech32m, checksum computed over the hrp "namid:"
name        = label *( "." label )
label       = ( %x61-7A / DIGIT ) *61( %x61-7A / DIGIT / "-" )
  • Launcher formdid:namid:1<bech32m> (mainnet) or did:namid:testnet11:1<bech32m>. The bech32m string after did: is exactly the protocol URI namid:1…: the human-readable part of the checksum is namid:, so did:namid:1… and namid:1… share one checksum and one 32-byte payload, the launcher id of the name's singleton coin. This form is the canonical DID of a name once its coin exists on chain; it never changes for the life of the coin lineage.
  • Name formdid:namid:alice.mojo / did:namid:testnet11:alice.mojo. A valid DID (DID Core allows . and - in the method-specific id) that resolves to the same document. It is the DID of a name before its coin is minted, and an equivalentId of the launcher form afterwards.
  • Network — omitted for the Chia mainnet; any other network names itself (testnet11). did:namid:mainnet:… is invalid. A resolver serves one network and answers notFound for another.
  • Case — a did:namid identifier is lowercase; uppercase is invalid, not normalised.
  • Payment addresses are not identifiers — an id matching ^t?xch1[bech32]{20,}$ is invalid by grammar, because an xch1… string is a Chia address and an identifier that looks like one will be pasted into a Send box.

Examples:

did:namid:14w46h2at4w46h2at4w46h2at4w46h2at4w46h2at4w46h2at4w4snsj9a4
did:namid:testnet11:14w46h2at4w46h2at4w46h2at4w46h2at4w46h2at4w46h2at4w4snsj9a4
did:namid:testnet11:alice.mojo

4. DID document

{
  "@context": ["https://www.w3.org/ns/did/v1", "https://namid.net/ns/did/v1"],
  "id": "did:namid:testnet11:1…",
  "alsoKnownAs": ["namid:alice.mojo", "did:namid:testnet11:alice.mojo",
                  "did:chia:1…", "tld:1…", "namid:1…"],
  "controller": "did:key:z6Mk…",
  "verificationMethod": [{
    "id": "did:namid:testnet11:1…#owner", "type": "Bls12381G1Key2020",
    "controller": "did:namid:testnet11:1…", "publicKeyMultibase": "z…" }],
  "authentication": ["did:namid:testnet11:1…#owner"],
  "capabilityInvocation": ["did:namid:testnet11:1…#owner"],
  "service": [
    { "id": "…#namid", "type": "NamIDName",
      "serviceEndpoint": "https://namid.net/api/names/resolve?name=alice.mojo" },
    { "id": "…#xch", "type": "ChiaPaymentAddress",
      "serviceEndpoint": { "address": "txch1…", "network": "testnet11" } },
    { "id": "…#website", "type": "LinkedDomains", "serviceEndpoint": "https://alice.example" },
    { "id": "…#dns", "type": "NamIDDNSRecords", "serviceEndpoint": { "records": [] } }
  ]
}
  • controller is the holder's DID when the name is bound to one (a soulbound name is issued to a did:key or did:chia and never moves). It is absent when the name is controlled only by its owner key.
  • verificationMethod carries the name's BLS12-381 G1 owner key when the name has one (transferable names); the key authorises record updates and, for transferable names, transfer. Soulbound names issued to a DID carry no key of their own.
  • service entries are derived from the name's on-chain record set: the resolver endpoint, the XCH payment address, a linked website and DNS records. Nothing in the document is written by hand; it is a projection of the coin and its records.

DID document metadata (returned by resolution, not part of the document):

key meaning
canonicalId the launcher form, once the coin exists
equivalentId [the name form]
versionId the current coin id of the singleton
created / updated registry timestamps
deactivated true after lapse or a spend to nil; always false for renewal: never
namid {name, root, lock_mode, renewal, issuer, namespace, mint_status, launcher_id, coin_id, record_sequence, expiry_block} — the protocol's own view (standards/ROOT-PROFILES.md)

5. Operations

5.1 Create

A did:namid is created by creating the name:

  • a root is won at the sealed-bid auction and minted as a soulbound singleton (namid-protocol.md §5);
  • a name under a root is issued by the root's issuer through the signed issuer route (POST /api/names/issue, HMAC over the canonical body, ROOT-PROFILES.md), or registered by its owner where the root's issuance is open.

The name form of the DID exists from that moment; the launcher form exists once the coin is on chain (mint_status: minted). No separate "DID registration" step exists: a name that exists is a DID.

5.2 Read (resolve)

GET https://namid.net/api/did/resolve?did=<did>
GET https://namid.net/1.0/identifiers/<did>          ; Universal Resolver driver shape
GET https://namid.net/api/did/method                  ; the method descriptor

The response is a DID Resolution Result (@context: https://w3id.org/did-resolution/v1) with didDocument, didResolutionMetadata (contentType: application/did+ld+json, retrieved, did, kind) and didDocumentMetadata (§4). Errors use the registered names: invalidDid (400), notFound (404, including a network the resolver does not serve), methodNotSupported (400).

A resolver MUST answer only with a record it can tie to the chain (the NamID verify-or-refuse rule: /api/resolve carries the proof) or refuse; a client MAY verify the singleton lineage itself with the light client in chia-consensus-light-client.md against didDocumentMetadata.namid.launcher_id.

5.3 Update

Records (address, profile, DNS, services) are updated by the owner key through the registry's signed record routes; each update increments record_sequence and, when the coin is spent, changes versionId. For a soulbound name bound to a DID, the holder DID signs. Keys rotate through the two-phase rotation with a clawback window (tld-vault-design.md). The DID string never changes on update.

5.4 Deactivate

  • A term name that is not renewed lapses at expiry_block; the document resolves with deactivated: true until the label is re-issued, at which point a new coin and a new launcher-form DID exist (the name form resolves to the new one).
  • A soulbound, never-renewed name (renewal: never) has no lapse; it is deactivated only by its issuer re-issuing to the same holder DID (recovery) or by the singleton being spent to nil.
  • A root is never transferred; it is deactivated only by the DAO's threshold action in the cases the policy allows (TLD-POLICY.md).

6. Security considerations

  • Key compromise. The owner key authorises updates (and transfer, for transferable names). Rotation is two-phase with a clawback window; the Vault gives m-of-n recovery for roots. A soulbound name bound to a DID has no key to steal: the holder's DID controls it.
  • Issuer compromise. An issuer secret lets an attacker issue new names under that root; it cannot move or alter existing ones. Secrets are per issuer host and rotatable; every issuance is a coin creation visible on chain.
  • Resolver trust. The resolver is a projection of chain state and says so: the namid.launcher_id and versionId in the metadata let any client verify the lineage independently. A resolver that cannot produce chain evidence refuses rather than guesses.
  • Address confusion. did:namid:xch1… is invalid by grammar.
  • Network confusion. Mainnet omits the network segment; every other network names itself; a resolver answers only for the network it serves.
  • Sanctions. Registration refuses labels on the protocol's OFAC-derived list (blocked-ofac.tsv).
  • Denial of service. Resolution is a read of a local index plus optional chain verification; the registry rate-limits per client address behind nginx.

7. Privacy considerations

  • A DID document contains only what the holder chose to publish as records (address, profile display, website, DNS). Rich records marked sensitive by the kind taxonomy (/api/records/kinds) are anchored by hash and never served in a document.
  • The name form makes a DID human-readable by design; a holder who wants an unlinkable identifier should not use a NamID name as one. The launcher form is pseudonymous but stable, and links every update of the same coin.
  • The resolver does not log the caller beyond what rate limiting needs.
  • Holders can correlate across services by choice (alsoKnownAs), never by default.

8. Relationship to other identifiers

form what it is in the document
did:namid:… this method; canonical DID of a NamID id
namid:1… / namid:alice.mojo the protocol's URI scheme (not a DID) alsoKnownAs
did:chia:1… the Chia-ecosystem spelling of the same launcher; not a registered method alsoKnownAs
tld:1… protocol-internal view alsoKnownAs
did:key:… / did:chia:… of the holder who the name is bound to controller

9. Conformance

An implementation conforms if it produces documents and resolution results as in §4–§5 for every valid identifier in §3, refuses every invalid one with invalidDid, and never answers a resolution it cannot tie to the chain. The reference implementation's test suite (tests/test_did_namid.py, tests/test_namid_uri.py) is the conformance vector set.