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

# XNS-1

> Our NFT token standard for Octra

XNS-1 is our NFT standard for Octra: the interface and behavior every Xpectrum NFT implements, and the contract a third party implements to issue NFTs that the rest of the ecosystem (wallets, indexers, the marketplace) understands. It is defined natively for Octra's AML environment.

## What XNS-1 defines

An XNS-1 contract is a single collection of non-fungible tokens with one canonical owner per token.

* **Tokens and ids.** Tokens are identified by a `u128` id. Ids are sequential from `0` as tokens are minted, so a collection of supply N holds ids `0..N-1`.
* **Single ownership.** Each token has exactly one owner address at a time. `balance_of(addr)` counts how many a wallet holds; `tokens_of` / `get_tokens_page` enumerate them.
* **Transfers and delegation.** An owner moves a token with `transfer`. They can delegate a single token with `approve`, or delegate their whole balance with `set_operator` (an operator can move any of the owner's tokens). `transfer_from` is the delegated move used by approved parties.
* **Metadata.** `token_uri(token_id)` returns where a token's metadata lives. On Xpectrum that resolves into the collection's Circle and follows the [Metadata Standard](/standards/metadata).
* **Provenance.** The standard includes the one-way `set_provenance_hash` / `get_provenance_hash` interface used for verifiable, tamper-evident collections. See [Provenance](/standards/provenance).
* **Circle resources.** A native per-token extension for attaching on-chain resources to a token (covered below).
* **Royalties.** Royalty is a first-class on-chain field per token, set at mint and capped at 10%.

## Ownership and transfers

| Function                            | Auth                        | Notes                                               |
| ----------------------------------- | --------------------------- | --------------------------------------------------- |
| `transfer(to, token_id)`            | Owner                       | Clears any approval on transfer                     |
| `transfer_from(from, to, token_id)` | Owner / approved / operator | Delegated move                                      |
| `approve(approved, token_id)`       | Owner or operator           | Emits `Approved`                                    |
| `revoke_approval(token_id)`         | Owner or operator           | Emits `ApprovalRevoked` only if an approval existed |
| `set_operator(operator, approved)`  | Caller                      | `approved` must be `0` or `1`; emits `OperatorSet`  |

## Reading token state

All token-id view functions bounds-check the id and revert if the token does not exist.

| Function                                  | Returns                             |
| ----------------------------------------- | ----------------------------------- |
| `owner_of(token_id)`                      | `address`                           |
| `creator_of(token_id)`                    | `address`, the royalty recipient    |
| `royalty_of(token_id)`                    | royalty in basis points             |
| `token_uri(token_id)`                     | `string`, the metadata URI          |
| `collection_of(token_id)`                 | `string`, collection name           |
| `balance_of(addr)`                        | token count                         |
| `get_approved(token_id)`                  | `address`, zero if none             |
| `is_approved_or_owner(token_id, addr)`    | `1` or `0`                          |
| `token_circle_count(token_id)`            | number of circle resources attached |
| `token_circle_uri(token_id, resource_id)` | `string`, empty if inactive         |
| `collection_name()`                       | `string`                            |
| `symbol()`                                | `string`                            |
| `total_supply()`                          | token count                         |

Some reads return pipe-delimited strings:

| View                                           | Format                                                     |
| ---------------------------------------------- | ---------------------------------------------------------- |
| `get_token_info(token_id)`                     | `id\|owner\|creator\|name\|royalty_bps\|minted_epoch\|uri` |
| `get_token_circle_info(token_id, resource_id)` | `token_id\|resource_id\|uri\|access\|active\|version`      |
| `get_contract_info()`                          | `name\|symbol\|total_supply\|owner`                        |

## Events

| Event                                                   | Arguments                    | Emitted when                                                |
| ------------------------------------------------------- | ---------------------------- | ----------------------------------------------------------- |
| `Transferred(token_id, from, to)`                       | `u128, address, address`     | Every ownership change including mints. `from = 0` on mint. |
| `Minted(token_id, owner, creator)`                      | `u128, address, address`     | Alongside `Transferred` on mint                             |
| `Approved(token_id, approved)`                          | `u128, address`              | `approve()` called                                          |
| `ApprovalRevoked(token_id)`                             | `u128`                       | `revoke_approval()` cleared an approval                     |
| `OperatorSet(owner, operator, approved)`                | `address, address, u128`     | `set_operator()` called                                     |
| `OwnershipTransferred(old_owner, new_owner)`            | `address, address`           | contract ownership moved                                    |
| `CircleResourceSet(token_id, resource_id, uri, access)` | `u128, u128, string, string` | resource added or updated                                   |
| `CircleResourceCleared(token_id, resource_id)`          | `u128, u128`                 | resource deactivated                                        |

Indexers can follow ownership entirely from `Transferred` (mints included), without rescanning state.

## Circle resources

A native XNS-1 extension: each token can have on-chain resources attached, each a URI plus an access string. The contract owner manages them with `add_circle_resource`, `set_circle_resource`, and `clear_circle_resource`; the token holder does not control them. `token_circle_uri` returns an empty string for inactive resources rather than reverting, so a caller can walk every id up to `token_circle_count` without per-slot error handling. The `version` field in `get_token_circle_info` is `1` in this revision.

## Royalties

Royalty is on-chain, not metadata. Each token carries a royalty in basis points set at mint, readable via `royalty_of`, with the recipient from `creator_of`. XNS-1 caps royalty at **10% (1000 bps)**. How royalties are paid out on a sale is the marketplace's job; see [Xmarket](/contracts/xmarket).

## Marketplace compatibility

Implementing XNS-1 makes a contract tradeable on Xmarket automatically. The marketplace only relies on a small subset of the interface: `owner_of`, `is_approved_or_owner`, `transfer_from`, `creator_of`, and `royalty_of`. The full integration guide, including the exact settlement flow and gotchas, is in [Integrate with Xmarket](/developers/integrate).

## Implementations

Every `Xcollection` and `XpectrumGenesis` deployment implements XNS-1 and is formally verified. Any contract implementing the interface is compatible with the marketplace and tooling.
