Skip to main content
One Xcollection is deployed per collection. It handles the full drop lifecycle: three-phase minting, whitelist enforcement, Genesis injection, reveal, royalty routing, holder enumeration, and XNS-1 compatible token ownership. The current version is Xcollection v3, formally verified before deployment.

Minting phases

Phases are time-gated by epoch ranges and resolved by get_current_phase(). Up to three sequential phases per collection. Durations are measured in epochs, the chain’s native time unit. MIN_PHASE_EPOCHS = 360, on the order of an hour at current epoch times. GTD and FCFS are bounded above by 259200 epochs (roughly a month). Set windows in epochs against the live chain rate rather than assuming a fixed seconds-per-epoch, since epoch wall-clock can drift. GTD and public both require a valid window; FCFS is the optional one. Phase ordering is enforced on-chain: fcfs_start >= gtd_end and pub_start >= fcfs_end.
Required here means the phase needs a valid time window. You can still make a phase mint nothing by setting its cap to 0 (closed). So a “no public sale” collection schedules a public window but leaves its cap at 0.
A phase cap of 0 means the phase is closed, not unlimited. To leave a phase open to the full supply, set its cap to the max supply. The global total_minted <= max_supply guard bounds everything regardless.
Force a specific phase via set_phase_override(); return to time-based resolution via clear_phase_override().

Genesis injection

Every Xcollection reserves an allocation for Xpectra holders, computed at deploy time as:
Xpectra holders mint via genesis_mint(genesis_id) during GTD. The contract verifies the caller currently owns that Xpectra token (owner_of(genesis_id) == caller). The injection reserve is additive on top of the creator’s GTD whitelist allocation, and genesis mints share the GTD minted counter. Xpectra holders pay the GTD price (no discount). A genesis mint is bound by every wallet limit a normal mint is: the GTD per-wallet cap and the collection’s global max_per_wallet. On top of that, each Xpectra token ID can be used only once per collection, recorded permanently, so the same NFT cannot claim multiple allocations across wallets (is_genesis_id_used, get_genesis_status). After GTD ends, unclaimed injection slots can be released via trigger_sweep(). The sweep is permissionless once GTD has ended, so no party can withhold it.

Whitelist

Xcollection calls its bound Xlist contract to verify GTD and FCFS access at mint time. See Xlist.

Payment splitting

Every mint splits payment at the contract level: Both collect via claim_proceeds(); balances are read with get_pending_proceeds(addr). Proceeds are never pushed alongside cross-contract calls. The pull model keeps funds isolated from AML atomicity risk.

Reveal

Collections deploy unrevealed. token_uri() returns the unrevealed_uri until reveal. The creator commits a provenance hash before mint opens, then calls reveal(base_uri) to publish the real metadata. Tokens then resolve as base_uri + token_id + .json. On Xpectrum the base URI is the collection’s Circle (oct://<circle_id>/), so revealed metadata and art are on-chain. Reveal is irreversible. See Provenance for how the held-back metadata is verified against the pre-committed hash.

Airdrop

The owner can airdrop up to 20 tokens per transaction via airdrop(). Airdrops bypass phase, price, and whitelist checks and count toward total_minted and max_supply.
Airdropped tokens consume max_supply but do not reduce phase caps. Plan your airdrop allocation before configuring phase caps to avoid overselling.

Holder enumeration

Xcollection v3 maintains a holder index, so the platform can page through current holders on-chain via get_holders_page(offset, limit) for distribution analytics, without scanning every token.