cw-cyber-passport
Passport is a soulbound-style NFT (CW721-based) that represents a citizen's identity in Cyber. Each passport has a unique nickname, an avatar, optional proved addresses from other chains, and metadata fields.
Contract version: 1.0.0
Core Concepts
Passport — a CW721 NFT token identified by an auto-incremented portid. Each passport belongs to one address (owner) and stores:
| Field | Type | Description |
|---|---|---|
nickname |
String |
Unique name, 3-32 chars, [a-z0-9-] only |
avatar |
String |
IPFS CID (particle) |
addresses |
Vec<LabeledAddress> |
Up to 8 cryptographically proved external addresses |
data |
Option<String> |
Arbitrary metadata, 3-256 chars |
particle |
Option<String> |
Optional IPFS CID |
Active Passport — each address can have multiple passports but only one is marked as active at a time.
Subgraphs — the contract writes cyberlinks to three subgraph contracts (name, avatar, proof) to make passport data discoverable through the Knowledge Graph.
Constitution — creating a passport requires signing the constitution CID (QmcHB9GKHAKCLQhmSj71qNJhENJJg8Gymd1PvvsCQBhG7M) with the sender's key, as an on-chain oath.
Name Pricing
Names shorter than 8 characters cost BOOT. Names 8+ characters are free.
Formula: price = 1_000_000 * 10^(8 - length) boot
| Length | Price (boot) | Price (BOOT) |
|---|---|---|
| 3 | 100,000,000,000 | 100,000 |
| 4 | 10,000,000,000 | 10,000 |
| 5 | 1,000,000,000 | 1,000 |
| 6 | 100,000,000 | 100 |
| 7 | 10,000,000 | 10 |
| 8+ | 0 | free |
Pricing is hardcoded — changing it requires a contract migration.
The same pricing applies to both CreatePassport and UpdateName (the price is based on the new name length).
Execute Messages
CreatePassport
Creates a new passport NFT. Requires signing the constitution.
- Nickname must be unique, 3-32 chars,
[a-z0-9-] - Must send exact BOOT amount if name < 8 chars
- Mints a new CW721 token with auto-incremented portid
- Creates cyberlinks:
nickname → address(name subgraph),nickname → avatar(avatar subgraph) - Sets as active passport if it's the first one for this address
UpdateName
Changes the nickname on an existing passport. Old name is released.
- Only the passport owner can call
- New name must be unique and follow naming rules
- Must send exact BOOT amount if new name < 8 chars
- Creates cyberlink:
new_nickname → address(name subgraph) - Old nickname→cyberhole link is NOT created (old links remain in the graph)
UpdateAvatar
- Creates cyberlink:
nickname → new_avatar(avatar subgraph)
UpdateData
- Data must be 3-256 chars, or
nullto clear
UpdateParticle
- Must be a valid particle (IPFS CID), or
nullto clear
ProofAddress
Cryptographically links an external address (Cosmos or Ethereum) to the passport.
- Supports Cosmos (ADR-36) and Ethereum (EIP-191) signatures
- Message to sign:
passport_owner_address:constitution_cid - Max 8 proved addresses per passport
- Creates cyberlink:
nickname → proved_address(proof subgraph)
RemoveAddress
SetActive
Sets which passport is the active one for the caller.
SetAddressLabel
Sets an optional label (max 16 chars) on a proved address.
TransferNft
Transfers passport to a new owner. Clears proved addresses, data, and particle. Remaps nickname to the new owner.
Burn
Destroys the passport. Nickname is released. Creates cyberlink: nickname → cyberhole.
Admin-only
| Message | Description |
|---|---|
Execute { msgs } |
Execute arbitrary Cyber messages (owner only) |
SetOwner { owner } |
Transfer contract ownership |
SetSubgraphs { name_subgraph, avatar_subgraph, proof_subgraph } |
Update subgraph contract addresses |
Disabled
| Message | Status |
|---|---|
Mint |
Disabled — passports can only be created through CreatePassport |
SendNft |
Disabled |
Query Messages
| Query | Returns | Description |
|---|---|---|
Config {} |
ConfigResponse |
Owner and subgraph addresses |
LastPortid {} |
PortidResponse |
Last issued portid (total passports created) |
PortidByNickname { nickname } |
PortidResponse |
Token ID for a nickname |
AddressByNickname { nickname } |
AddressResponse |
Owner address for a nickname |
PassportByNickname { nickname } |
TokenInfo<PassportMetadata> |
Full token info including owner |
MetadataByNickname { nickname } |
PassportMetadata |
Passport metadata only |
PassportSigned { nickname, address } |
SignatureResponse |
Check if address is proved for nickname |
ActivePassport { address } |
TokenInfo<PassportMetadata> |
Active passport for an address |
Standard CW721 queries (OwnerOf, NftInfo, AllNftInfo, Tokens, AllTokens, NumTokens, ContractInfo, Minter, Approval, Approvals, AllOperators) are also supported.
Interacting with the Contract
Contract is deployed on Bostrom mainnet. See deployments/bostrom-mainnet.toml for the address.
# Set contract address (from deployments/bostrom-mainnet.toml)
PASSPORT=bostrom1xut80d09q0tgtch8p0z4k5f88d3uvt8cvtzm5h3tu3tsy4jk9xlsfzhxel
NODE=https://rpc.bostrom.cybernode.ai:443
Query examples
# Get contract config (owner, subgraph addresses)
# How many passports exist
# Look up a passport by nickname
# Get only metadata (nickname, avatar, addresses)
# Resolve nickname → owner address
# Get active passport for an address
# Check if an address is proved for a nickname
# List all passports owned by an address (CW721)
# Total number of passport NFTs (CW721)
Execute examples
Requires cyber CLI with a funded wallet.
TX_FLAGS="--from <your-key> --chain-id bostrom --node --gas-prices 0boot --gas-adjustment 2.5 --gas auto -y"
# Update avatar
# Update name (free if new name >= 8 chars)
# Update name (paid — 5-char name costs 1000 BOOT)
# Set active passport
# Transfer passport to another address
Storage
| Key | Type | Description |
|---|---|---|
config |
Item<Config> |
Contract config |
portid |
Item<u64> |
Auto-increment counter for token IDs |
nicknames |
Map<&str, AddressPortID> |
Nickname → (owner address, portid) |
active |
Map<&Addr, String> |
Address → active portid |
| CW721 token storage | TokenInfo<PassportMetadata> |
Standard CW721 storage with passport extension |