> ## Documentation Index
> Fetch the complete documentation index at: https://docs.soran.domains/llms.txt
> Use this file to discover all available pages before exploring further.

# Native username claim API

> Registrar methods for owner policy, user-authorized claims, receipts, reservations, transfer and renewal.

<Note>
  This interface is deployed in the **6 September 2026 native-claim release**.
  Use the matching [verified addresses](/reference/release-status). Older deployments
  do not gain these methods automatically. SDK publication and hosted-service
  cutovers are tracked separately on that page.
</Note>

Usernames such as `alice.acme` belong to the namespace Registrar. Universal Lookup
remains the shared read entry point. A username claim does not call the top-level
namespace Allocator and does not enter its objection or refund process.

Network execution and storage fees apply separately from any username fee,
including when the username fee is zero. The Owner 0.7.0 and Holder 0.5.0 SDKs
default `maxNativeFeeStroops` to `50_000_000n` (5 XLM) for native operations and
reject a higher estimate before signing. Initial storage rent can exceed that
limit. An application must review the estimate and explicitly choose any higher
limit; the limit does not change the on-chain username price.

The [Owner and Holder SDK walkthrough](/owner/automatic-claiming) shows application
integration. The [native claim storage reference](/reference/successor-claim-storage)
defines every new stored value and canonical request type.

## Capability and bindings

| Contract  | Method                      | Result                                                                  |
| --------- | --------------------------- | ----------------------------------------------------------------------- |
| Registrar | `claim_version()`           | `u32`, exactly `1`                                                      |
| Registry  | `owner_epoch(ns_node)`      | `u64` ownership epoch                                                   |
| Registry  | `template_hashes()`         | `(Registrar Wasm hash, Resolver Wasm hash)`                             |
| Registry  | `native_contracts(ns_node)` | `(Registrar Address, Resolver Address)` after the native binding checks |
| Resolver  | `initialization_version()`  | `u32`, exactly `1`                                                      |

`native_contracts` checks the required namespace record, Registry-deployed
attestations, clean provenance, selected Resolver pointer and current Wasm hashes
against the Registry's immutable templates. It does not call the Registrar or
Resolver. This permits its use while either contract is already executing.

A namespace owner's ownership epoch changes on every completed ownership
transition. Returning the namespace to a former owner does not restore old claim
settings. Epoch numbers increase but are not necessarily consecutive for one
namespace.

An unsupported version or failed read never means Open registration. Installing
a new SDK does not add native claims to an existing contract. Verify code and
provenance as well as version answers before relying on the interface.

## Owner controls

Unless shown otherwise, these methods return `Result<result, Error>`.

| Registrar method                  | Arguments                            | Result                                                                |
| --------------------------------- | ------------------------------------ | --------------------------------------------------------------------- |
| `native_fee_token`                | none                                 | `Address`, the network's native XLM asset contract; no Result wrapper |
| `claim_config`                    | none                                 | `Option<ClaimConfig>`                                                 |
| `configure_claims`                | `settings: ClaimSettings`            | `ClaimConfig`                                                         |
| `set_claim_enabled`               | `enabled: bool`                      | `ClaimConfig`                                                         |
| `set_reserved`                    | `labels: Vec<Bytes>, reserved: bool` | `u32` labels updated                                                  |
| `is_reserved`                     | `label: Bytes`                       | `bool`                                                                |
| `issue_reserved`                  | `label: Bytes, holder: Address`      | `BytesN<32>` name node                                                |
| `issue_reserved_with_destination` | `intent: ReservedIntent`             | `ClaimResult`                                                         |
| `claim_usage`                     | `holder: Address`                    | `ClaimUsage`                                                          |
| `approval_usage`                  | none                                 | `ApprovalUsage`                                                       |

Administrative writes require the current Registry owner. Console roles are not
substitutes for that authorization. Initial configuration is absent: legacy
manual owner issuance remains available, while public claiming is unavailable.

Configuration chooses Manual or Public mode, enablement, admission, exact fee,
G treasury and usage limits. It records the current ownership epoch and advances
both policy and approval-grant epochs. Enabling stale-owner settings is rejected;
a new owner must explicitly configure them. Pause and re-enable each advance the
policy and grant epochs. Reservation changes advance the policy version.

Public mode blocks the legacy `issue` and `issue_batch` routes even while paused.
A public label must use public rules. The explicit reserved path is the
administrative exception to public username prices and quotas. It still rejects
an active name and records separate reserved-issuance usage.

Reservation batches are atomic, contain 1–23 distinct canonical labels and reject
active names when reserving them. Releasing a reservation leaves any holder
unchanged. An issued reserved name stays reserved until its owner releases the
reservation, including after the name expires.

`issue_reserved` uses owner authorization and the holder's default address. The
atomic custom-destination variant requires both owner and holder authorization.
Its first SDK release exposes simple assignment; a separate co-signing integration
is needed to call the raw atomic reserved method for different owner/holder accounts.

## Claim and recovery

| Registrar method    | Arguments                                                           | Result                         |
| ------------------- | ------------------------------------------------------------------- | ------------------------------ |
| `claim_quote`       | `label: Bytes, claimant: Address`                                   | `ClaimQuote`                   |
| `allowlist_leaf`    | `claimant: Address`                                                 | `BytesN<32>`                   |
| `claim`             | `intent: ClaimIntent, proof: Vec<BytesN<32>>`                       | `ClaimResult`                  |
| `claim_receipt`     | `claimant: Address, request_id: BytesN<32>`                         | `Option<ClaimReceipt>`         |
| `touch_claim_state` | `holder: Address, request_ids: Vec<BytesN<32>>, labels: Vec<Bytes>` | `u32` existing entries touched |

A quote reports availability, reservation, current configuration, ownership epoch,
record generation/expiry and lifetime usage. It does not reserve the label.
`available: true` alone does not mean claiming is enabled or that the wallet is
eligible. Inspect all relevant fields and the current policy.

The first public claim flow uses a **G claimant as holder and fee payer**. The
receiving destination can independently be G without a memo, G with ID/Text/Hash
memo, M with its muxed ID, or C without a memo. The transaction records future
receiving instructions; it does not make a payment to that destination.

A fresh claim checks the complete signed context, current policy and owner epochs,
fixed namespace term, exact fee, expected name generation/expiry, availability,
reservation, wallet limit and admission rule. It then issues the name, transfers
any fee directly to the treasury, initializes the destination and writes usage
and a receipt in one transaction. Any failure rolls back those business effects.
Network fees are separate.

A matching existing receipt returns `Replayed` before fresh deadline, policy and
authorization checks. It does not charge, increment usage, issue another name or
rewrite a later destination. Reusing a request ID with a different operation or
intent returns `RequestIdConflict`. Keep request IDs stable only for the same
immutable intent. Credential nonce/signature renewal does not change that intent.

History is not current ownership. After recovering a receipt, verify the current
holder and generation through Lookup before associating a name with an app account.
A missing receipt or interrupted RPC read does not prove that a transaction failed.
Reconcile the original transaction before replacing it.

## Exact authorization

For `claim`, claimant and optional approver each authorize the single argument
`[intent]` with native Soroban authorization. The Merkle proof is not part of the
signed intent; it can only demonstrate membership in the already committed root.

The claimant's authorization has these children, in order:

1. Native asset contract `transfer(claimant, fee_recipient, fee_amount)` when the
   fee is nonzero.
2. Resolver `initialize_destination(label, claimant, fresh_generation, destination)`.

The optional G approver's claim authorization has no children. The approver does
not authorize a fee transfer or substitute for claimant authorization. Native
account signer/threshold rules apply. The backend signs an authorization entry,
while the claimant independently signs the transaction.

An intent binds network, Registry, Registrar, namespace, request ID, execution
window, label, claimant, complete destination, Resolver, existing generation/expiry,
term, policy/owner/grant epochs and exact fee token/amount/recipient. See the
[type definitions](/reference/successor-claim-storage#request-types).

The business execution window is inclusive: `valid_after <= now <= deadline`.
Its positive span must be at most `3600` seconds. Approval mode may configure a
shorter maximum. Native credential expiration is a separate ledger-based limit;
an expired or rotated credential is not proof that a previous request never completed.

## Admission rules

Open admission accepts an empty proof and no approver. Allowlist admission verifies
at most 32 sibling hashes against the configured root. Approval admission requires
the configured separate G approver and an empty proof.

The leaf is SHA-256 of this Soroban XDR tuple:

```text theme={null}
(Symbol("allow_v1"), network_id, registry, namespace_node, registrar, claimant)
```

For each sibling, order the two 32-byte hashes lexicographically and compute
`SHA256(0x01 || smaller || larger)`. Use the final value as the root. This username
allowlist is separate from the Allocator's top-level namespace reservation proof.

Wallet limits count cumulative public claims, including expiry/reissue claims.
`wallet_limit = 0` means unlimited. They do not count current holdings or prove
one person. Reserved assignments have their own count.

Approval requires a nonzero cumulative allowance, rate limit, window and lifetime.
The owner chooses these numbers. The window is at most `31536000` seconds; approval
lifetime is at most `3600` seconds. Counts survive mode, key, policy and owner
changes. An active window cannot be reset or shortened by reconfiguration; a longer
window may extend its end. The next approved claim starts a new window after expiry.
The lifetime allowance is an absolute ceiling; only an explicit owner increase
provides more headroom.

## Transfer and renewal

| Contract / method                            | Arguments                                                                         | Result               |
| -------------------------------------------- | --------------------------------------------------------------------------------- | -------------------- |
| Registrar `accept_transfer_with_destination` | `intent: TransferIntent`                                                          | `ClaimResult`        |
| Registrar `renew_holder`                     | `intent: RenewIntent`                                                             | `ClaimResult`        |
| Resolver `preview_destination`               | `name: String, expected_generation: u64`                                          | `DestinationPreview` |
| Resolver `initialize_destination`            | `label: Bytes, holder: Address, generation: u64, destination: PaymentDestination` | `()`                 |

Transfer acceptance requires the intended recipient. It checks the exact current
holder, generation, name expiry and pending proposal expiry. It preserves the
name's expiry, advances the generation and initializes the selected destination
atomically. A failed destination write leaves the existing holder and proposal
unchanged. Claim pause, app admission and claim quotas do not gate this operation.

Holder renewal uses the immutable positive default term. It checks the recorded
holder, generation and expiry, then extends from `max(now, old_expiry)`. It preserves
the generation and existing records. It is available within the shorter of 30 days
or one policy term before expiry, subject to the resulting expiry being no more
than 100 years from execution and within the signed result bounds. Zero-expiry or
permanent names cannot use it. The legacy owner renewal method also rejects zero
extension and leases beyond the same 100-year bound.

An expired holder may renew only before reissue wins. There is no guaranteed grace
period. `preview_destination` returns the exact-generation receiving instructions,
including when inactive. It rejects mismatched generations and invalid configured
payment records. Ordinary payment resolution still rejects expired names. Preview
is not a new payment destination or a bypass of live resolution.

The initializer is restricted to the bound native Registrar and exact holder
consent. It accepts only a destination for a generation freshly created by claim,
reserved assignment or accepted transfer. It derives the node from its bound
namespace, checks native bindings, rejects already initialized/same-or-newer data,
and makes no callback into the active Registrar. It is not a general owner record
setter, and renewal does not call it.

## Errors and compatibility

Existing Registrar error codes `1–20` retain their values. New codes are:

| Code | Error                             |
| ---- | --------------------------------- |
| 21   | `InvalidClaimConfig`              |
| 22   | `ClaimsNotConfigured`             |
| 23   | `ClaimsPaused`                    |
| 24   | `StaleClaimPolicy`                |
| 25   | `ClaimIntentMismatch`             |
| 26   | `ClaimIntentExpired`              |
| 27   | `ReservedName`                    |
| 28   | `NameNotReserved`                 |
| 29   | `PublicIssuanceRequired`          |
| 30   | `WalletClaimLimit`                |
| 31   | `InvalidEligibility`              |
| 32   | `ApprovalAllowanceReached`        |
| 33   | `ApprovalRateReached`             |
| 34   | `RequestIdConflict`               |
| 35   | `CounterOverflow`                 |
| 36   | `InvalidNativeBinding`            |
| 37   | `UnsupportedClaimant`             |
| 38   | `DuplicateLabel`                  |
| 39   | `RenewalTooEarly`                 |
| 40   | `RenewalLeaseLimit`               |
| 41   | `DestinationInitializationFailed` |
| 42   | `FeeSettlementFailed`             |

Registry additionally reports `OwnershipEpochUnavailable` (`29`) and
`OwnershipEpochOverflow` (`30`). Resolver adds `InitializationContextMismatch`
(`22`), `DestinationAlreadyInitialized` (`23`) and `GenerationMismatch` (`24`).
An atomic Registrar call maps a failed initializer to Registrar error `41` and
aborts the whole operation.

A contract rejection does not authorize changing the destination, dropping a memo,
opening admission or charging different terms on a retry. Namespace template
changes require a successor deployment; this reference does not migrate existing
Registry records or make old contracts permanent.
