A permissionless event-ticketing platform on Sui. Anyone can host an event, sell tickets, check attendees in at the door, mint proof-of-attendance, run a ticket-gated chat, and open prediction markets on whether the event sells out — all on-chain, with gasless UX.
HostIt is a faithful Sui Move port of the HostIt EVM Diamond, paired with a Next.js dApp. It uses Walrus for event media, Seal for encrypted data, and Enoki for sponsored transactions and social login.
Status: live on Sui testnet. Move package
hostit_ticket, latest version0xb5c952…dffcc0f. See On-chain deployment.
- Events & tickets — permissionless
create_event; one sharedEventper event, genericCoin<T>payments, a 3% protocol fee, refunds, organizer payouts. - Check-in — at the door a staff device scans the ticket and signs an ed25519 voucher that gates an attendee-submitted on-chain check-in; optional self check-in within the event window. Multi-day attendance supported.
- POAP — checked-in holders mint a proof-of-attendance NFT (once per ticket).
- Ticket-gated forum — encrypted, on-chain-anchored event chat (Walrus + Seal), readable only by ticket holders.
- Prediction markets — native parimutuel "Sellout Clock" (binary) and "final tickets-sold" (range) markets that settle trustlessly on-chain by reading the event's mint counter.
- Gasless — transactions are sponsored server-side via Enoki; sign-in via wallet or Google (zkLogin).
- Trust signals, not gatekeeping — suiNS names + verification badges, consistent with the permissionless design.
graph TB
subgraph Client["Browser · Next.js 15 / React 19 / Tailwind v4"]
UI["Screens<br/>Discover · Event · Create · Manage<br/>Wallet · Forum · Check-in · Door"]
Kit["@mysten/dapp-kit<br/>wallet + zkLogin sign-in"]
end
subgraph Server["Next.js route handlers (server-only secrets)"]
Sponsor["/api/sponsor (+/execute)<br/>Enoki sponsored tx"]
Copilot["/api/copilot<br/>Claude AI assistant"]
end
subgraph Sui["Sui testnet"]
Pkg["hostit_ticket package<br/>hub · event · ticket · market · checkin<br/>access · poap · forum · predict"]
end
subgraph Infra["Decentralized services"]
Walrus["Walrus<br/>event metadata + cover images"]
Seal["Seal<br/>threshold encryption"]
Enoki["Enoki<br/>gas sponsor + zkLogin"]
end
UI --> Kit
UI --> Sponsor
UI --> Copilot
UI -->|store / read blobs| Walrus
UI -->|encrypt / decrypt| Seal
Kit -->|sign| Pkg
Sponsor --> Enoki --> Pkg
Seal -. seal_approve policy check .-> Pkg
A single Move package, hostit_ticket, with capability-based access control (capabilities replace EVM roles) and millisecond timestamps throughout.
graph LR
hub["hub<br/>shared Hub · config · 3% fee treasury"]
event["event<br/>Event + OrganizerCap · prices · escrow"]
ticket["ticket<br/>Ticket NFT (event_id field)"]
market["market<br/>buy · claim_free · refund · withdraw"]
checkin["checkin<br/>ed25519 voucher · self check-in"]
poap["poap<br/>proof-of-attendance NFT"]
forum["forum<br/>ticket-gated post anchor"]
access["access<br/>Seal seal_approve_* policies"]
predict["predict<br/>parimutuel Sellout + Range markets"]
market --> hub
market --> event
market --> ticket
checkin --> event
checkin --> ticket
poap --> event
poap --> ticket
forum --> event
forum --> ticket
access --> event
access --> ticket
predict --> event
| Module | Responsibility |
|---|---|
hub |
Shared Hub: protocol config + 3% platform-fee treasury. Touched by every paid sale. |
event |
create_event shares one Event per event and mints an OrganizerCap{event_id}; holds per-coin price + escrow via dynamic fields. |
ticket |
One global Ticket type with an event_id field (not a per-event type). |
market |
buy / buy_with_sui / claim_free / refund / withdraw_event_balance; splits the fee into Hub + event escrow. |
checkin |
Attendee-signed check-in gated by an ed25519 voucher over event_id ‖ ticket_id ‖ expiry; self_check_in fallback. |
access |
seal_approve_ticket / seal_approve_organizer / seal_approve_self decryption policies. |
poap |
Proof-of-attendance NFT via a shared registry, claimable after check-in (one per ticket). |
forum |
On-chain anchor (PostCreated) for ticket-gated Walrus + Seal messages. |
predict |
Native parimutuel markets settling on event::minted(). |
Sponsorship is server-side (the private Enoki key never reaches the browser); the user signs but pays no gas.
sequenceDiagram
actor U as User
participant FE as Frontend
participant API as /api/sponsor
participant E as Enoki
participant S as Sui
U->>FE: action (buy / claim / bet / check-in)
FE->>API: transaction-kind bytes + sender
API->>E: createSponsoredTransaction(allowlisted targets)
E-->>API: sponsored bytes + digest
API-->>FE: sponsored bytes
FE->>U: wallet signs (no gas dialog)
FE->>API: signature
API->>E: executeSponsoredTransaction
E->>S: submit — sponsor pays gas
S-->>FE: digest ✓
DeepBook Predict has no self-serve oracle on testnet, so HostIt ships its own parimutuel module that settles trustlessly against the event's verifiable on-chain mint counter — no oracle, no keeper, no fee.
graph LR
C["Create market<br/>snapshot strike (= max tickets)<br/>+ expiry (= start time)"] --> O["Open<br/>stake USDC on YES/NO<br/>or a tickets-sold bucket"]
O -->|now ≥ expiry| St["Settle (permissionless)<br/>reads event::minted on-chain"]
St --> Cl["Claim<br/>winners split the pool pro-rata"]
- Move 2024 (
hostit_ticket) on Sui ·suiCLI for build/test/upgrade. - Next.js 15 (App Router) · React 19 · Tailwind v4.
@mysten/suiv2 ·@mysten/dapp-kitv2 ·@mysten/enoki·@mysten/seal·@tanstack/react-query.- Walrus (HTTP publisher/aggregator) · Seal (committee key server) · Enoki (sponsored tx + zkLogin) · Anthropic Claude (in-app copilot).
- Package manager: bun (only).
Live on Sui testnet. web/lib/config.ts is the source of truth (all values are env-overridable).
| Object | ID |
|---|---|
| Package — original (type origin for core modules) | 0x423336143d4e5a810d24b97762bfa10be56b7d5dc86b75e831cb0897264b1e8d |
Package — latest (predict; all predict calls) |
0xb5c95242b1a2acc8a2561246f95f8de182b3cbc67d71a370ee413c9dcdffcc0f |
Shared Hub |
0xa2b9ceb63babc6897932c6f4cfdbbddc9d3493d36691e4520278fc58090efabd |
Shared PoapRegistry |
0x57e285538f99b6bcc4d42e6adca2d2bb305cfb0c8b292094677fb70963d6021f |
| Collateral coin (testnet USDC) | 0xa1ec7fc0…::usdc::USDC |
Package versioning (Sui upgrades): the package is upgraded in place, not re-published. Sui anchors a type's identity to the version that introduced it, so core modules keep the original id while
predicttypes live at the upgrade that added them. The frontend encodes this viaPACKAGE_ID,PACKAGE_ID_LATEST, andPREDICT_SELLOUT_PKG. SeeCLAUDE.mdfor the full model.
hostit-sui/
├── Move.toml · Move.lock · Published.toml # Sui Move package manifest + publish state
├── sources/ # Move modules: hub · event · ticket · market · checkin
│ # access · poap · forum · predict
├── tests/ # Move test_scenario suites (57 tests)
└── web/ # Next.js dApp
├── app/ # App Router routes (+ /api/sponsor, /api/copilot)
├── components/ (+ screens/) # UI
└── lib/ # config · ticketing · predict · hooks · walrus · seal · sponsor
sui move build # compile
sui move test # run all Move tests
sui move test predict # run a subset by namebun install
cp .env.local.example .env.local # then fill in your keys (see below)
bun run dev # http://localhost:3000
bunx tsc --noEmit # typecheck (the primary verification gate)
bun run lint
⚠️ Do not runbun run buildwhilebun run devis running — they share.next/and the prod build corrupts the dev bundle. Usebunx tsc --noEmitto verify instead.
Copy web/.env.local.example → web/.env.local. Notable variables:
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_ENOKI_API_KEY |
Public Enoki key — enables zkLogin sign-in (browser-safe). |
ENOKI_PRIVATE_API_KEY |
Server-only — used by /api/sponsor to sponsor gas. Never prefix with NEXT_PUBLIC_. |
NEXT_PUBLIC_GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET |
Google OAuth (secret is server-only). |
NEXT_PUBLIC_HOSTIT_* / NEXT_PUBLIC_USDC_COIN_TYPE |
Optional on-chain ID overrides; default to lib/config.ts. |
Without Enoki keys the app still runs — gasless UX is disabled and users pay their own gas. .env.local is git-ignored; the only env file in the repo is the all-blank .env.local.example template.
- Permissionless: no issuer/buyer role split — any wallet can host and hold. The UI signals quality via suiNS/verification, never access gates.
- Deploys are gated upgrades: shipping Move changes uses
sui client upgrade(not fresh publish), which requires explicit per-deploy authorization. - Gasless allowlist is server-authoritative in
web/app/api/sponsor/route.ts(mirrored as a hint inweb/lib/sponsor.ts).
For a deeper engineering guide, see CLAUDE.md.
MIT.