Introduction to x1id
x1id resolves @handles and X1NS domain names to addresses on the X1 blockchain — a multi-chain name resolution layer that never silently picks between two namespaces with different owners.
Introduction to x1id
x1id resolves human-readable names to blockchain addresses on X1. It covers two distinct naming systems:
@handles— a flat, permanent, ASCII-only namespace (@jack), issued by the on-chain X1 Handle Registry program.- X1NS domains — the existing hierarchical, subdomain-capable namespace
(
jack.x1,jack.xnt,jack.xen), which x1id also resolves for compatibility.
Both are read directly from chain state — by the SDK via RPC, or by anyone deriving the accounts themselves. Neither namespace depends on an API being up.
The one invariant that matters
@jack and jack.x1 are different namespaces and can have different
owners. Nothing in x1id ever collapses that distinction into a single
address.
Every resolved result carries the namespace that matched, and there is no
response shape that returns a bare address without it. A query whose text
matches both namespace shapes at once — for example @jack.x1 — is refused
outright with an ambiguous error. It is never guessed, never resolved to
"whichever one exists," and never silently preferred one way. A caller
(wallet, dApp, payment form) is expected to show the namespace next to any
resolved address before letting a user send funds to it. See
Error reference for the full ambiguous contract.
Active constants
Handle resolution is testnet-only
The X1 Handle Registry program is deployed on X1 testnet. It has not been
deployed to X1 mainnet — that is gated on a decision about custody of the
registry's owner/upgrade authority. Do not assume @handle resolution is live
against mainnet RPC.
| Constant | Value | Network |
|---|---|---|
| X1 Handle Registry program ID | 8JgnNWi24bq9uzfnT9XmkWxvaWMVgoEs9bu8QsHhLe1P | X1 testnet |
| Handle resolution RPC endpoint | https://rpc.testnet.x1.xyz | X1 testnet |
X1NS .x1 root authority | 4NG35LXbtyamuoyjarMf5f78esyWxWhSDHxqbAU5yZTk | X1 mainnet |
X1NS .xnt root authority | 6sHoWK6ht73Pb4y6yA7Sw8iP7DxS45gGp1fH3zWYn56V | X1 mainnet |
X1NS .xen root authority | 3SUwpSz33AsyJwf6B48cKZuDTswuUEdUhcXszZrFWPqo | X1 mainnet |
| X1NS resolution RPC endpoint | https://rpc.mainnet.x1.xyz | X1 mainnet |
Yes, that means the two namespaces are currently on different networks:
@handle resolution only works against testnet, while .x1/.xnt/.xen
resolution only works against mainnet. This is a real, current constraint —
not a documentation error — and it will change once the registry's mainnet
deployment ships. The handleProgramId used by the SDK and REST API is
configurable, so it can be pointed at a different deployment (e.g. a future
mainnet program) without a client update.
What resolution returns today
A successful resolution returns an address for the requested chain, the namespace that matched, and a verification level:
- Address chains: resolution can return an X1 or SOL address
today — X1 shares Solana's ed25519 key format, so the same address material
works for both. Requesting an ETH or BTC record returns an honest
no-record-for-chainerror; per-chain records for those chains are on the roadmap and not read yet. x1id never fabricates or falls back to a wrong address for an unsupported chain. - Verification:
@handleresolution reads the registry account's owner directly — a proved control relationship, markedverified. X1NS domain resolution currently reports the domain's owner field, which is a strong signal but not a proved per-chain address record, so it is markedunverifieduntil per-chain profile records are read. - Subnames / hierarchical handles:
@handlesare deliberately flat — there is no subname system for handles, by design (the same way@jackdoesn't have subdomains on other platforms). This mirrors X1NS's own hierarchical domains only where domains are concerned, not handles. - Indexer: there is no indexer. Resolution is a direct point lookup — given a name, get an address (or given an address, get its primary name via reverse lookup). Enumerating all handles or all domains owned by an address is out of scope today.
Which integration path is right for you
| Path | Use it if | Page |
|---|---|---|
SDK (@x1id/resolve) | You control the client and can run a fetch-capable RPC call. This is the recommended path — it reads chain state directly and has no dependency on FortiBlox's own uptime. | SDK reference · Examples |
| REST API | Your service can't or won't embed an RPC client (e.g. a backend job, a curl-based integration test). It's a read-only convenience over the same on-chain data — never a source of truth, and never required. | REST API |
| On-chain, direct | You're integrating from a language without an x1id client, or want to verify results by deriving accounts yourself. | On-chain reference |
Why the SDK reads chain, not an API
Both the SDK and the REST API resolve by deriving accounts and reading them over RPC — neither calls a third-party resolution API. A resolver whose correctness depends on someone else's uptime eventually breaks when that service goes away.
Next steps
SDK Reference
Install @x1id/resolve, configure a resolver, and call resolve() / reverse().
Examples
Worked examples for wallets, payment forms, and reverse lookup.
REST API
The read-only HTTP resolution endpoint, for services that can't run an RPC client.
On-Chain Reference
Account layouts and PDA derivation for resolving without the SDK.
Error Reference
Every error code from the SDK and REST API, and what a UI should do about it.