Skip to content

Repository files navigation

Tessera

A browser app to create, browse, respond to, and tally on-chain surveys and polls on Cardano, implementing CIP-179 (transaction metadata label 17).

Surveys live entirely in transaction metadata — no smart contracts, no custom backend required to read them. Responses can be public or sealed (timelock-encrypted with drand for delayed reveal), eligibility is scoped by on-chain role (DRep, SPO, CC, Stakeholder, Keyholder), and tallies are computed client-side directly from chain data.

Status: active development, end to end. The app covers the whole survey lifecycle, and the Tier-1 serving backend validates responses, snapshots stake/voting-power weights at each survey's end epoch, and finalizes closed surveys into content-addressed result artifacts that anyone can re-derive from chain data with packages/verifier. See backend/ARCHITECTURE.md for the design and backend/TALLY-SPEC.md for the counting rules.

Governance linkage

A survey can be advertised by a Conway governance Info Action (CIP-179 Action → Survey linkage): the action's anchor metadata carries the survey's ref, and Tessera surfaces the link on the explore and survey pages once the action's voting deadline matches the survey's end epoch.

The app ships a small helper page at /propose-info-action to build, sign, and submit that Info Action from a CIP-30 wallet: load a CIP-108 anchor document, and the page validates its shape, extracts the linked survey, and checks the epoch alignment before letting you submit. You can pin the exact anchor bytes to your configured IPFS providers (or host them yourself) so the served document matches the on-chain hash.

Repository layout

Path What it is
frontend/app The browser app — SolidJS + Vite + TypeScript.
packages/cip179 The reusable cip-179 package: label-17 codec plus the cross-implementation domain / tally / txproof / tlock surface.
packages/core Tessera app core (cardano-tessera-core): the DataSource seam, Explore list/health payloads, keyset paging, the survey-list aggregation adapter, and config. The reusable domain/tally surface lives in cip-179.
packages/koios The Koios read path (KoiosDataSource, tally inputs), shared by direct mode, backend, and verifier.
packages/respond-core cardano-tessera-respond-core: the pure, framework-free answering core (drafting, responder eligibility, i18n factory, lazy sealed wrapper) shared by the app and the widget.
packages/respond-ui cardano-tessera-respond-ui: the shared SolidJS per-question body components, so the app and the widget cannot drift in answering behavior.
packages/respond-widget cardano-tessera-respond: the embeddable <tessera-respond> custom element — answer a survey anywhere, emitting a ready-to-attach label-17 payload. Framework-agnostic; wallets/chain stay host-side.
packages/respond-react cardano-tessera-respond-react: React 18/19 bindings for the widget — typed props synced as DOM properties, tessera:* events as callbacks.
packages/verifier Standalone CLI that re-derives a survey's result artifact from chain data and checks its content hash.
examples/ Minimal React and Svelte host apps for the widget, built in CI so framework compatibility regressions fail a build.
backend/server Tier-1 serving backend: cached chain reads, response validation, weight snapshots, artifact finalization. Node or CF+D1.
backend/deps Indexer submodules (Adder / Yaci Store / Oura) for a future Tier-2; design notes in backend/*.md.

Quick start

Requires Node ≥ 22.5 and pnpm ≥ 10 (install pnpm). This is a pnpm workspace — install once at the repository root:

pnpm install
pnpm --filter cardano-tessera-backend dev   # terminal 1
pnpm --filter tessera-app dev               # terminal 2

The app serves at http://127.0.0.1:3000, reading chain data through the local backend — no Koios token needed, for reads or for building transactions (they are signed and submitted by your CIP-30 wallet). The dev server points at http://localhost:8787 by default; set TESSERA_BACKEND_URL to use another address.

Both halves default to Preview. To run the same pair against preprod, pin the network on each side — the app checks the backend's /health and refuses one serving a different network:

pnpm --filter cardano-tessera-backend dev:preprod   # terminal 1
pnpm --filter tessera-app dev:preprod               # terminal 2

Each backend network caches into its own tessera-cache-$NETWORK.sqlite, so switching costs a re-scan but never mixes two chains' records.

Alternatively, skip the backend and let the browser scan Koios directly (the power-user/offline path): a dev server does this with an empty TESSERA_BACKEND_URL= pnpm --filter tessera-app dev, a deployed build when its backend URL is configured empty. That path requires an authenticated Koios token (tier 1 is free): the anonymous tier does not send CORS headers, so browser requests need one. Paste it in the app's Settings; it is stored in the browser and never built into the bundle.

Configuration

One deployment serves one network, on both halves and with no runtime switch: the app is built for a network and refuses a backend whose /health reports a different one. Frontend build configuration is public — it ships in the bundle — but deployment-specific, so it comes from build-time environment variables (the git-ignored frontend/app/.env.deploy) rather than committed code; the backend's Cloudflare bindings likewise live in a git-ignored wrangler.toml. Both have a committed .example to copy. The variables and their rules are in each half's README.

IPFS reads race a built-in list of public gateways (no config); IPFS pinning (for authoring external content / rationales) uses per-provider API tokens entered in Settings, stored only in the browser.

Development

The repo is a pnpm workspace over the paths above, plus the examples/ host apps. Packages are consumed from TypeScript source (Vite aliases / exports pointing at src), so cross-package edits are live with no build step.

From the repository root:

Command What it does
pnpm -r type-check Type-check every package.
pnpm -r test Run every package's unit tests (Vitest).
pnpm --filter cardano-tessera-backend dev Run the Tier-1 backend locally (see its README).
pnpm --filter cardano-tessera-backend dev:preprod Same, pinned to preprod (dev:preview / dev:mainnet likewise).
pnpm --filter tessera-app dev Start the app's Vite dev server.
pnpm --filter tessera-app dev:preprod Start the app's dev server in preprod mode.
pnpm --filter tessera-app build Production build of the app (the preview target).
pnpm --filter cardano-tessera-verifier verify -- --backend <url> --survey <tx>:<i> Re-verify a survey's final result artifact from chain data.

Formatting is Prettier over the whole repo: pnpm format / pnpm format:check at the root.

Both halves deploy to Cloudflare with wrangler, one deployment per network: the backend as a Worker + D1 + Cron (pnpm --filter cardano-tessera-backend deploy:preview / deploy:preprod / deploy:mainnet, after the one-time wrangler.toml and D1 setup in backend/server/OPERATIONS.md), the app as static Workers assets (pnpm --filter tessera-app deploy:preview / deploy:preprod / deploy:mainnet — each bakes the values from frontend/app/.env.deploy and uploads dist/; see frontend/app/wrangler.toml). The backend/deps submodules are not needed for any of this; to fetch them anyway: git submodule update --init --recursive.

Contributing

Contributions are welcome. Until a CONTRIBUTING.md lands, the basics:

  • Open an issue to discuss substantial changes before investing in a PR.
  • Keep the build green — CI runs these on every PR, in this order: pnpm -r test, pnpm test:operator-scripts, pnpm -r type-check, pnpm format:check. Tests come before type-check because the widget's test script builds the rolled-up d.ts its typed tests need. CI then runs pnpm -r build, which needs a frontend/app/.env.deploy to exist.
  • Match the existing code style — Prettier is the source of truth for formatting.

License

The code in this repository is licensed under the Apache License 2.0.

About

On-chain surveys and polls on Cardano (CIP-179)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages