xlm-ns is a Rust workspace for a Stellar name service where names like
timmy.xlm behave as user-owned identifiers for accounts, apps, subdomains, and
cross-chain resolution targets.
The repository is organized as a multi-crate system so the core naming logic can be tested locally before it is wired into Soroban-specific storage, auth, and deployment flows.
The target user experience is straightforward:
- A user registers a base name such as
Rem.xlm. - That name resolves to a Stellar address or another delivery target.
- The owner can update resolver data, renew the registration, transfer ownership, create subdomains, or bridge the name to external resolver networks.
- Premium names can be sold through auctions instead of first-come-first-served issuance.
The workspace now contains real contract-domain logic instead of only placeholder stubs:
- Shared validation for labels, full names, registration periods, owners, and chain identifiers.
- Lifecycle-aware name records with registration, expiry, and grace-period data.
- Stateful registry, registrar, resolver, auction, subdomain, NFT, and bridge contract logic.
- Unit tests for all contract crates covering the main happy-path flows.
-
contracts/registryPurpose: canonical name ownership state. Responsibilities:- Stores
NameRecordownership and metadata. - Enforces active/grace/claimable lifecycle checks.
- Restricts mutation to the current owner.
- Supports transfer, resolver updates, target updates, metadata updates, and expiry extension.
- Stores
-
contracts/resolverPurpose: forward and reverse resolution. Responsibilities:- Maps
name -> resolution record. - Maps
address -> primary name. - Stores bounded text records such as social handles or app metadata.
- Enforces owner-controlled updates and deletion.
- Maps
-
contracts/registrarPurpose: registration issuance and renewal policy. Responsibilities:- Computes quotes from label length and registration duration.
- Tracks reserved names.
- Accepts registrations and renewals.
- Maintains treasury balance accounting in the domain model.
- Uses explicit expiry and grace-period rules.
-
contracts/auctionPurpose: premium-name sale flow. Responsibilities:- Creates auctions with a reserve price and bidding window.
- Records bids with timestamps.
- Settles using a Vickrey-style second-price outcome.
- Supports unsold outcomes when the reserve is not met.
-
contracts/subdomainPurpose: delegated namespace management. Responsibilities:- Registers parent domains for subdomain issuance.
- Supports parent owners and delegated controllers.
- Creates and transfers owned subdomains such as
pay.timmy.xlm.
-
contracts/nftPurpose: tokenized representation of name ownership. Responsibilities:- Mints ownership tokens.
- Tracks owner, approval, and metadata.
- Supports approval-based transfers.
-
contracts/bridgePurpose: cross-chain resolution payload construction. Responsibilities:- Registers supported destination chains.
- Maps chains to resolver and gateway targets.
- Builds deterministic Axelar-style payloads for resolution propagation.
-
packages/xlm-ns-commonShared constants, errors, types, and validation helpers used by the contract crates. -
packages/xlm-ns-sdkA lightweight Rust SDK surface for future wallet and dapp integration.
-
cli/Simple command-line entry points for register, resolve, renew, transfer, and auction flows. -
scripts/Shell helpers for deploy, invoke, and local setup tasks. -
tests/Placeholders for integration scenarios and test fixtures shared across crates.
NameRecord in packages/xlm-ns-common is the shared type used by the main
contract flows. It currently tracks:
labeltldownerresolvertarget_addressttl_secondsregistered_atexpires_atgrace_period_ends_at
This matters because the registry and registrar now reason about the same registration lifecycle:
- Active:
now <= expires_at - Grace period:
expires_at < now <= grace_period_ends_at - Claimable by a new owner:
now > grace_period_ends_at
The intended contract interaction order is:
- Ask the registrar for a quote using the requested label and registration duration.
- Submit payment and create a registration record.
- Materialize the name in the registry with the resulting ownership state.
- Set resolver records for forward and reverse lookups.
- Optionally mint an NFT and configure bridge routes or subdomains.
The current codebase models each of those steps, but not yet as a single integrated on-chain transaction graph.
Shared validation currently enforces:
- Minimum and maximum label length.
- Lowercase ASCII letters, digits, and hyphens only.
- No leading or trailing hyphen.
- Explicit
.xlmTLD parsing for base names. - Bounded registration durations.
- Non-empty owner and chain identifiers.
Format the workspace:
cargo fmt --allRun tests:
TMPDIR=/tmp cargo test --workspaceTMPDIR=/tmp is used here because the current sandbox environment does not allow
Rust to create temporary build directories in the default macOS temp location.