---
description: Contracts of SuiShadow
---

# Contracts

```
PackageId : 0x576ce6f9227b55f93844988881ecb53c74c8ffcbd5e7ecf6be8624d2ebd47f25
// This is the Package named nftverifier and has all of the contracts of SuiShadow . 

```

There are 3 main Contracts NFT , Allowlist and MarketPlace .&#x20;

***

The NFT contract handles minting and transferring NFTs, and stores each token’s Merkle root on-chain. Below are the key functions:

```rust
#[allow(lint(self_transfer))]
/// Create a new devnet_nft
public fun mint_to_sender(
    name: vector<u8>,
    metadata: vector<u8>,
    url: vector<u8>,    
    merkleroot: vector<u8>,
    ctx: &mut TxContext,
) {
    let sender = ctx.sender();
    let nft = NFT {
        id: object::new(ctx),
        name: string::utf8(name),
        metadata: string::utf8(metadata),
        url: url::new_unsafe_from_bytes(url),
        merkleroot: string::utf8(merkleroot),
    };

    event::emit(NFTMinted {
        object_id: object::id(&nft),
        creator: sender,
        name: nft.name,
    });

    transfer::public_transfer(nft, sender);
}

/// Transfer `nft` to `recipient`
public fun transfer(nft: NFT, recipient: address, _: &mut TxContext) {
    transfer::public_transfer(nft, recipient)
}
```

* **`mint_to_sender`**
  1. Reads four inputs:
     * `name`: the NFT’s name (as UTF-8 bytes)
     * `metadata`: arbitrary metadata (UTF-8)
     * `url`: a pointer to an off-chain preview or data blob (raw bytes)
     * `merkleroot`: the 32-byte SHA-256 Merkle root of all encrypted tiles (UTF-8)
  2. Calls `ctx.sender()` to identify the address minting the NFT.
  3. Constructs an `NFT` object with:
     * `id`: a fresh object created via `object::new(ctx)`
     * `name`: converted from `vector<u8>` to `string::String`
     * `metadata`: likewise converted
     * `url`: built from raw bytes (`url::new_unsafe_from_bytes`)
     * `merkleroot`: converted to `string::String` so it’s stored on-chain.
  4. Emits an `NFTMinted` event with:
     * `object_id`: the newly minted NFT’s object ID
     * `creator`: the minter’s address
     * `name`: the NFT’s human-readable name
  5. Transfers ownership of the `nft` object to the minter (`sender`) using `transfer::public_transfer`.
* **`transfer`**\
  A basic transfer function allowing the current owner to send the NFT to another address. It simply calls `transfer::public_transfer` to move the `NFT` object to `recipient`.

***

#### Allowlist Contract

The Allowlist contract tracks which addresses are permitted to decrypt encrypted data via Sui Seal. Once a buyer pays for an NFT, their address is added here, and they receive the encrypted blob IDs they can decrypt.

```rust
public fun create_allowlist(name: String, ctx: &mut TxContext): Cap {
    let allowlist = Allowlist {
        id: object::new(ctx),
        list: vector::empty(),
        name: name,
    };
    let cap = Cap {
        id: object::new(ctx),
        allowlist_id: object::id(&allowlist),
    };
    transfer::share_object(allowlist);
    cap
}

// convenience function to create a allowlist and send it back to sender (simpler ptb for cli)
entry fun create_allowlist_entry(name: String, ctx: &mut TxContext) {
    transfer::transfer(create_allowlist(name, ctx), ctx.sender());
}

public fun publish(allowlist: &mut Allowlist, cap: &Cap, blob_id: String) {
    assert!(cap.allowlist_id == object::id(allowlist), EInvalidCap);
    df::add(&mut allowlist.id, blob_id, MARKER);
}
```

* **`create_allowlist`**
  1. Takes a `name` (for identification) and the transaction context `ctx`.
  2. Creates a new `Allowlist` object with:
     * `id`: generated via `object::new(ctx)`
     * `list`: an initially empty `vector<string::String>` that will hold blob IDs
     * `name`: the provided identifier (e.g., “Summer 2025 Collection”)
  3. Creates a `Cap` object, which is a capability allowing only the holder to add entries to this allowlist:
     * `id`: its own fresh object ID (`object::new(ctx)`)
     * `allowlist_id`: the object ID of the new `Allowlist`.
  4. Calls `transfer::share_object(allowlist)` so the `Allowlist` object becomes globally accessible.
  5. Returns the `Cap`, which can be used to call `publish` later.
* **`create_allowlist_entry` (entry function)**\
  A convenience wrapper that calls `create_allowlist(name, ctx)` and then immediately transfers the resulting `Cap` to `ctx.sender()`. This is useful in CLI scripts: the caller ends up owning the `Cap` to manage that allowlist.
* **`publish`**
  1. Takes a mutable reference to an existing `Allowlist` (`&mut Allowlist`), a `Cap`, and a `blob_id` string.
  2. Asserts that `cap.allowlist_id` matches `object::id(allowlist)`—that is, the caller really holds the capability for that allowlist (otherwise it aborts with `EInvalidCap`).
  3. Calls `df::add(&mut allowlist.id, blob_id, MARKER)` to append `blob_id` into the `Allowlist.list`. Here, `df::add` is a helper that associates the new blob ID under a special “MARKER” field on the `allowlist.id` object. In practice, `blob_id` represents the Walrus content address that the allowed user can now decrypt via Sui Seal.

***

#### Marketplace Contract

The Marketplace contract maintains a shared list of all NFTs (by their Walrus blob IDs and metadata) so that anyone can browse the public collection without requiring centralized servers.

```rust
public struct Marketplace has key, store {
    id: UID,
    blobs: vector<string::String>,
}

// Initialize and share the marketplace
fun init(ctx: &mut TxContext) {
    let marketplace = Marketplace {
        id: object::new(ctx),
        blobs: empty()
    };
    transfer::share_object(marketplace);
}

// Create a new marketplace (if you need multiple instances)
public fun create_marketplace(ctx: &mut TxContext): Marketplace {
    Marketplace {
        id: object::new(ctx),
        blobs: empty()
    }
}

// Add a blob ID to the marketplace
public fun add_blob(registry: &mut Marketplace, new_blob: vector<u8>) {
    push_back<string::String>(&mut registry.blobs, string::utf8(new_blob));
}

// Get all blob IDs from the marketplace
public fun get_blobs(registry: &Marketplace): vector<string::String> {
    registry.blobs
}
```

* **`Marketplace` Struct**
  * `id: UID`\
    A unique object identifier for this marketplace instance.
  * `blobs: vector<string::String>`\
    A dynamic list of Walrus blob IDs (each pointing to an encrypted payload or metadata) that represent the entire collection visible in the storefront.
* **`init`**
  1. Creates a shared, singleton `Marketplace` object with:
     * `id`: new object created via `object::new(ctx)`
     * `blobs`: initialized as an empty `vector`.
  2. Calls `transfer::share_object(marketplace)` to make this shared marketplace accessible to all users on-chain.
* **`create_marketplace`**\
  If you want to run multiple, separate storefronts (e.g., per artist or per sub-collection), this function instantiates a fresh `Marketplace` (with its own `UID` and empty `blobs`). It does not automatically share it—caller can share or transfer as needed.
* **`add_blob`**
  1. Accepts a mutable reference to a `Marketplace` (`registry: &mut Marketplace`) and a new blob ID as raw bytes (`new_blob: vector<u8>`).
  2. Converts `new_blob` into `string::String` via `string::utf8(new_blob)`.
  3. Appends it to `registry.blobs` using `push_back`.\
     This is how each newly minted NFT’s Walrus blob ID (or metadata blob) becomes visible in the public marketplace.
* **`get_blobs`**\
  A read-only accessor that returns the full `vector<string::String>` of blob IDs stored in the given `Marketplace` object. Front-end applications call `get_blobs` to enumerate all available NFTs and render their previews/metadata.
