Formrus is a backendless, on-chain form platform on Sui.
Website: https://formrus.netlify.app
In-app Docs: https://formrus.netlify.app/docs
- Form definitions and control logic live in shared Move objects.
- Form schema and responses are stored as Walrus blobs.
- Private responses are encrypted with Seal and decrypted only by authorized wallets.
formrus/
├── web/ # React + Vite product app
│ ├── src/pages/BuilderPage.tsx
│ ├── src/pages/PublicViewPage.tsx
│ ├── src/pages/DashboardPage.tsx
│ └── src/pages/DashboardFormPage.tsx
└── contract/ # Move package: formrus::registry
└── sources/formrus.move
Main integrations:
- Sui: form lifecycle, role/auth, reward pool, eligibility, limits
- Walrus: schema + response blob storage
- Seal: private payload encryption/decryption authorization flow
- DNA-Uniqueness Per Form
- each form carries a DNA identity hash
- contract-level uniqueness is enforced in
Registry(registered_dnas) - prevents accidental identity collisions across forms
- Handler Model with Centralized Validation
- built-in handlers (
submit_and_act*) are the default execution path - all built-ins route through shared acceptance logic (
accept_response) - keeps validation, limits, expiry, and reward prechecks consistent across submit paths
- On-Chain Eligibility + Action + Embed Coupling
- same form object controls who can submit, what action runs on submit, and how the same runtime can be reused in embedded distribution
- supports anyone / min-SUI / coin-type / object-type gating
- public
/view/:formIdand embeddable/embed/:formIdstay aligned against the same on-chain schema and policy
- Walrus + Schema Versioning
- schema blob pointer is mutable (
update_schema_blob_id) - every update bumps
schema_version - each
ResponseAcceptedevent recordsschema_versionat submission time
- Private Response Flow with Seal Authorization
- private payloads stored encrypted in Walrus
- decryption requires creator/admin auth through
seal_approve - keeps decryption rights tied to on-chain roles
- Reward Pool Safety Model
- reward forms must remain funded at submission time
- reward amount becomes locked after first response
- protects submitters from mid-flight reward policy changes
- Operational Controls for Live Forms
- pause/resume, max submissions, expiry extension
- immediate drain or scheduled drain with cancellation path
- creator transfer workflow for team handoff
- No Backend Architecture
- static frontend + Sui + Walrus + Seal only
- no centralized API/service required for core workflow
- Builder
- multi-field form creation
- eligibility config (anyone / min SUI / coin type / object type)
- reward/non-reward form modes
- optional expiry and submission limits
- Public Form Runtime
/view/:formIdto collect submissions- public or private response modes
- file/screenshot/video upload fields supported
- Embed Runtime
/embed/:formIdfor iframe or host-page distribution- uses the same schema, eligibility, and submission pipeline as the public runtime
- supports host-wallet integration paths for controlled embedded flows
- Dashboard
- wallet-scoped discovery of forms (creator/admin/viewer)
- response queue, private decrypt, CSV export
- form operations: role changes, pool top-up, pause/resume, schema updates, reward/limit updates
- schema blob expiry warning and schema renew flow with selectable Walrus epochs
From contract/sources/formrus.move:
- register form with DNA uniqueness
- submit via built-in handlers with eligibility enforcement
- reward payout from pool (if configured)
- role management (creator/admin/viewer)
- expiry extension, submission caps, schema version updates
- drain flows (immediate drain or scheduled drain with delay)
- creator transfer flow (propose + accept)
See full contract reference: contract/README.md
Use web/.env.example as template.
Required variables:
VITE_SUI_NETWORKVITE_FORMRUS_PACKAGE_IDVITE_FORMRUS_REGISTRY_IDVITE_WALRUS_PUBLISHER_URLVITE_WALRUS_AGGREGATOR_URLVITE_WALRUS_EPOCHSVITE_SEAL_KEY_SERVER_IDSVITE_SEAL_THRESHOLD
Prerequisites:
- Node.js
>=22recommended (current Sui SDK targets modern Node) - npm
Commands:
npm install
npm run devBuild + typecheck:
npm run build
npm run typecheckBuild output: web/dist
Deploy web/dist to static hosting.
Netlify SPA routing is supported via:
web/public/_redirects
- Set Walrus epochs high enough for your launch horizon.
- Schema blob can be renewed because form stores a mutable
schema_blob_id. - Response blob IDs are immutable per submission event in current contract.
- Keep backup of important schema JSON versions used in production.