> For the complete documentation index, see [llms.txt](https://docs.omnisocial.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.omnisocial.dev/architecture-and-concepts/personanft-module.md).

# PersonaNFT Module

The `PersonaNFT` smart contract powers the **identity layer** of OmniSocial by enabling users to create and manage unique **personas**, each represented as an ERC-721-compliant NFT. These NFTs allow users to maintain separate, reputationally distinct identities (e.g., "DAO Mod", "Artist", "Anonymous Burner") all linked to a single `OmniWallet`.

🧬 Contract: `PersonaNFT.sol`

**✅ Standards:**

* Inherits from `ERC721`, `Ownable`, and optionally `ERC721Enumerable` if indexed querying is needed.

📦 Metadata Schema (on-chain or IPFS)

```json
{
  "name": "anonmod.omni",
  "description": "Anonymous Moderator Persona",
  "image": "ipfs://Qm...imagehash",
  "attributes": [
    { "trait_type": "Role", "value": "Moderator" },
    { "trait_type": "Visibility", "value": "Pseudonymous" },
    { "trait_type": "Created", "value": "2025-04-15" }
  ]
}
```

🔧 Key Functions

**`createPersona(string calldata handle, string calldata label, string calldata metadataURI) external returns (uint256)`**

* **Purpose:** Mints a new persona for the caller.
* **Validation:** Requires handle to be unique.
* **Effect:** Links the persona to caller’s `OmniWallet`, emits `PersonaCreated`.

**`linkPersona(uint256 personaId) external`**

* **Purpose:** Associates a minted persona with the sender’s active wallet.
* **Precondition:** Caller must own the `PersonaNFT`.

**`unlinkPersona(uint256 personaId) external`**

* **Purpose:** Detaches a persona from the wallet.
* **Notes:** Persona remains in the wallet but becomes inactive.

**`getActivePersona(address wallet) public view returns (uint256)`**

* **Purpose:** Returns the active persona ID for a given wallet address.

**`setMetadataURI(uint256 tokenId, string calldata newURI) external onlyOwner`**

* **Purpose:** Allows owner to update persona metadata.

🔁 Events

* `PersonaCreated(address indexed owner, uint256 indexed personaId, string handle)`
* `PersonaLinked(address indexed wallet, uint256 indexed personaId)`
* `PersonaUnlinked(address indexed wallet, uint256 indexed personaId)`

🔐 Identity Integrity

* **One active persona at a time** per wallet, but unlimited can be held.
* Persona changes update feed display name and `.omni` alias accordingly.
* `.omni` name is derived from the primary persona handle (e.g., `anonmod.omni`).
* Support for zk-based proof binding (e.g., PoH, BrightID) as optional metadata extensions.

🧭 Typical Flow

1. User signs up and mints first persona via `createPersona`.
2. `PersonaNFT` is linked automatically to their wallet.
3. User switches persona using the frontend, triggering `switchPersona(personaId)` via the wallet.
4. UI reflects new persona handle, avatar, and `.omni` domain in posts and actions.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.omnisocial.dev/architecture-and-concepts/personanft-module.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
