Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f3475d3
docs: add M3 dashboard design spec and implementation plan (v2)
mduthey May 7, 2026
521cab2
chore: remove M1 backend scaffold and its CI; v2 reads tracker SQLite…
mduthey May 7, 2026
7f54149
feat: vendor ticketing-2026 TII and tracker.toml for the M3 demo
mduthey May 7, 2026
112abd6
fix(tracker.toml): use preview ticket_policy for mints_policy_id
mduthey May 7, 2026
f77b0b8
feat(frontend): add kysely + better-sqlite3 for SSR data access
mduthey May 7, 2026
3678d7e
feat(frontend): Kysely-backed read-only connection to tracker.db
mduthey May 7, 2026
ced9f4d
refactor(frontend/db): readonly row interfaces + complete test schema
mduthey May 7, 2026
cd58b5a
feat(frontend): lifted JSON parser + bytes-to-hex helpers
mduthey May 7, 2026
67c5d0d
refactor(frontend/lifted): tighten parseLifted typing + edge-boundary…
mduthey May 7, 2026
91f2829
feat(frontend): listMatches + getMatch queries
mduthey May 7, 2026
29614a9
refactor(frontend/queries): use Selectable<MatchesRow>; drop dead Uin…
mduthey May 7, 2026
633f8b3
feat(frontend): PartyChip + TxNamePill display components
mduthey May 7, 2026
3e38959
style(frontend/PartyChip): explicit aria-hidden="true" on decorative dot
mduthey May 7, 2026
8e86a86
feat(frontend): matches list view at /
mduthey May 7, 2026
86cdc56
fix(frontend/queries): source txName from the column, not the lifted …
mduthey May 7, 2026
f751b5c
feat(frontend): match detail view; remove /txs index
mduthey May 7, 2026
3011220
refactor(frontend/match-detail): guard JSON re-parse in raw-lifted view
mduthey May 7, 2026
fc8b18b
feat(frontend): slim header to brand + theme toggle
mduthey May 7, 2026
25d9f2d
docs: refresh M3 documentation (architecture, access patterns, running)
mduthey May 7, 2026
ee8dd59
docs(M3): clarify C4 system label and align prod-build cwd
mduthey May 7, 2026
baf2056
fix(M3): final review cleanup — CI tests + doc accuracy + tracker commit
mduthey May 7, 2026
cc3318f
feat(frontend): show protocol column in matches list
mduthey May 8, 2026
863e562
feat(frontend/match-detail): syntax-highlighted + collapsible JSON vi…
mduthey May 8, 2026
e5b3612
style(frontend/match-detail): theme JSON viewer to match site palette
mduthey May 8, 2026
a06f6ac
fix(frontend/match-detail): restore expand/collapse chevrons in JSON …
mduthey May 8, 2026
6fbfb82
style(frontend/match-detail): bump JSON viewer chevrons to text-base …
mduthey May 8, 2026
1314088
feat(frontend): drop protocol column from list; add cexplorer link in…
mduthey May 8, 2026
6d147d1
feat(frontend): make every cell of a match row clickable to detail
mduthey May 8, 2026
c5fcba9
docs: add tracker example
mduthey May 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 0 additions & 43 deletions .github/workflows/backend-ci.yml

This file was deleted.

8 changes: 7 additions & 1 deletion .github/workflows/frontend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,14 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Rebuild native deps (better-sqlite3)
run: pnpm rebuild better-sqlite3

- name: Run typecheck
run: pnpm run typecheck

- name: Run check
run: pnpm run check
run: pnpm run check

- name: Run tests
run: pnpm test --run
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ Thumbs.db

# Logs
*.log

# Tracker SQLite artifacts (tx3-lift sidecar)
tracker.db
tracker.db-wal
tracker.db-shm
218 changes: 52 additions & 166 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,188 +1,74 @@
# tx3 Dashboard

This project provides a backend service that ingests Cardano transactions via the utxorpc service and exposes a read API for a web dashboard.
The dashboard consumes the backend API to present transaction activity, UTxOs, and asset movements in a structured, queryable view.

## How it works

1. **Load protocol**: The backend fetches protocol definitions and parameters from the tx3 registry.
2. **Ingest transactions**: utxorpc streams new transactions to the backend.
3. **Persist state**: The backend normalizes transaction data into SQLite tables.
4. **Serve the dashboard**: The dashboard queries the API for aggregated transaction and UTxO views.

## Project structure (conceptual)

```
dashboard/
├── backend/ # API + ingestion service
└── frontend/ # Frontend UI
```

## Architecture at a glance

- **Frontend dashboard**: Browser UI that queries the backend API.
- **Backend API**: Axum-based service that serves transaction data and aggregates UTxO state.
- **UTxO RPC ingestion**: Real-time transaction stream feeding the backend.
- **Tx3 Registry integration**: Fetches protocol definitions and parameters.
- **SQLite data store**: Persists transactions, UTXOs, and asset amounts.
A monitoring dashboard for [Tx3](https://github.com/tx3-lang)-described dApps. Builders and operators run it alongside `tx3-lift`'s tracker to see their protocol's matched on-chain transactions in real time, with parties and transaction names lifted from the TII. The dashboard is a pure TypeScript app (TanStack Start + Nitro SSR) that observes the SQLite file the tracker writes — no custom backend, no API tier in the middle.

## System context

```mermaid
flowchart LR
Dashboard[Dashboard UI]
API[Backend API]
Utxorpc[UTxO RPC Service]
Registry[Tx3 Registry]
DB[(SQLite)]

Dashboard -->|HTTP| API
Utxorpc -->|Tx stream| API
Registry -->|Protocol definitions| API
API --> DB
```
C4Context
title System Context — tx3 Dashboard

## Data flow
Person(operator, "Builder / Operator", "Runs the dashboard for their own dApp")
System(dashboard, "tx3 Dashboard", "Tracker (sidecar) + SSR app that monitor a Tx3-described dApp")
System_Ext(utxorpc, "utxorpc Provider", "Cardano chain stream (v1beta WatchTx)")
System_Ext(registry, "Tx3 Registry", "Source of TII files (queried at vendor time, not runtime)")

```mermaid
sequenceDiagram
participant D as Dashboard UI
participant A as Backend API
participant U as UTxO RPC Service
participant R as Tx3 Registry
participant S as SQLite

R->>A: Protocol definitions
U->>A: Transaction events
A->>S: Persist txs, utxos, amounts
D->>A: GET /txs, /txs/:hash
A->>S: Query txs + UTXO state
A-->>D: Aggregated transaction view
Rel(operator, dashboard, "Views matched transactions", "HTTPS")
Rel(dashboard, utxorpc, "Subscribes to tx stream", "gRPC / TLS")
Rel(operator, registry, "Pulls TII once at vendor time", "GraphQL")
```

## Data model
## Quick start

```mermaid
erDiagram
TXS {
text hash PK
text tx_name
datetime created_at
}

UTXOS {
text tx_hash PK
int output_index PK
text address
text consumed_by_tx
text datum
}

UTXO_AMOUNT {
text tx_hash PK
int output_index PK
text unit PK
text quantity
}

TXS ||--o{ UTXOS : "by tx_hash"
UTXOS ||--o{ UTXO_AMOUNT : "by (tx_hash, output_index)"
You need a clone of [`tx3-lang/tx3-lift`](https://github.com/tx3-lang/tx3-lift) as a sibling directory and a Demeter `utxorpc` API key.

```bash
# Once: clone tx3-lift sibling
git clone https://github.com/tx3-lang/tx3-lift ../tx3-lift
```

## API surface

### `GET /txs`

Returns a list of recent transactions ordered by `created_at` (newest first). Each item includes the protocol transaction name, inputs, outputs, and asset amounts.

Example response:

```json
[
{
"hash": "d03abcb194238e97b78fde2ad23965150fdf72b156731759b60f7d493836adbc",
"tx_name": "buy_ticket",
"inputs": [
{
"address": "addr1wy8ccvgzslpjf9yhrprvmqulpmjpkpxf8c0hvtjwvw8n6pqdcrnp0",
"tx_hash": "31596ecbdcf102c8e5c17e75c65cf9780996285879d18903f035964f3a7499a8",
"output_index": 0,
"amount": [
{ "unit": "lovelace", "quantity": "12507620" }
],
"datum": null,
"consumed_by_tx": "d03abcb194238e97b78fde2ad23965150fdf72b156731759b60f7d493836adbc"
}
],
"outputs": [
{
"address": "addr1wywecz65rtwrqrqemhrtn7mrczl7x2c4pqc9hfjmsa3dc7cr5pvqw",
"tx_hash": "d03abcb194238e97b78fde2ad23965150fdf72b156731759b60f7d493836adbc",
"output_index": 1,
"amount": [
{ "unit": "lovelace", "quantity": "1124910" },
{ "unit": "e1ddde8138579e255482791d9fba0778cb1f5c7b435be7b3e42069de425549444c45524645535432303236", "quantity": "1" }
],
"datum": "d87981184b",
"consumed_by_tx": null
}
]
}
]
```bash
# Terminal A — tracker (sidecar that writes tracker.db)
cd ../tx3-lift
DMTR_API_KEY=dmtr_... cargo run -p tracker -- ../dashboard/tracker.toml
```

### `GET /txs/:hash`

Returns a single transaction in the same expanded shape as `/txs`.

Example response:

```json
{
"hash": "d03abcb194238e97b78fde2ad23965150fdf72b156731759b60f7d493836adbc",
"tx_name": "buy_ticket",
"inputs": [
{
"address": "addr1wy8ccvgzslpjf9yhrprvmqulpmjpkpxf8c0hvtjwvw8n6pqdcrnp0",
"tx_hash": "31596ecbdcf102c8e5c17e75c65cf9780996285879d18903f035964f3a7499a8",
"output_index": 0,
"amount": [
{ "unit": "lovelace", "quantity": "12507620" }
],
"datum": null,
"consumed_by_tx": "d03abcb194238e97b78fde2ad23965150fdf72b156731759b60f7d493836adbc"
}
],
"outputs": [
{
"address": "addr1wywecz65rtwrqrqemhrtn7mrczl7x2c4pqc9hfjmsa3dc7cr5pvqw",
"tx_hash": "d03abcb194238e97b78fde2ad23965150fdf72b156731759b60f7d493836adbc",
"output_index": 1,
"amount": [
{ "unit": "lovelace", "quantity": "1124910" },
{ "unit": "e1ddde8138579e255482791d9fba0778cb1f5c7b435be7b3e42069de425549444c45524645535432303236", "quantity": "1" }
],
"datum": "d87981184b",
"consumed_by_tx": null
}
]
}
```bash
# Terminal B — dashboard (TanStack Start SSR app)
cd dashboard/frontend
pnpm install
pnpm dev
```

## Runtime configuration
Open <http://localhost:3000>. See [`docs/running.md`](docs/running.md) for prerequisites, env vars, and troubleshooting.

The backend uses environment variables for configuration (server address, database path, registry URL, and utxorpc connection details). The frontend dashboard only requires the backend base URL to query the API.
## What the demo shows

## Component responsibilities
The committed configuration tracks the [`buidler-fest/ticketing-2026`](protocols/buidler-fest/ticketing-2026.tii) protocol on Cardano preview. It defines a single transaction name (`buy_ticket`) with three parties (`buyer`, `treasury`, `issuer`) and roughly 80 real on-chain matches. The matches list at `/` shows every `buy_ticket` the tracker has seen, newest first; clicking through to `/txs/<hash>` shows the parties and their addresses for that transaction.

- **Backend API**: Aggregates transaction data and exposes `/txs` endpoints.
- **UTxO RPC ingestion**: Streams new transactions into the backend.
- **Registry integration**: Supplies protocol definitions and parameters.
- **Dashboard UI**: Presents transaction activity and UTXO state to users.
## Documentation

## Main concepts
- [`docs/architecture.md`](docs/architecture.md) — two-process topology, data flow per page load, why the shape, Postgres outlook.
- [`docs/access-patterns.md`](docs/access-patterns.md) — AP-1 (list) and AP-2 (detail), with type signatures and SQL.
- [`docs/running.md`](docs/running.md) — prerequisites, env vars, first run, troubleshooting, deployment notes.

- **Transaction**: Identified by `hash` and labeled by `tx_name`.
- **UTxO**: A specific output index associated with a transaction hash.
- **Asset amount**: Unit/quantity pairs attached to a UTXO.
- **Protocol tx name**: The protocol-level transaction identifier used for grouping.
## Project structure

```
dashboard/
├── README.md # this file
├── tracker.toml # config consumed by the external tracker
├── docs/
│ ├── architecture.md
│ ├── access-patterns.md
│ └── running.md
├── protocols/
│ └── buidler-fest/
│ └── ticketing-2026.tii # vendored TII for the demo protocol
└── frontend/ # TanStack Start SSR app
├── package.json
└── src/
├── lib/ # db.ts, queries.ts, lifted.ts
├── components/ # PartyChip, TxNamePill, Header, ...
└── routes/ # / (matches list), /txs/$hash (detail)
```
16 changes: 0 additions & 16 deletions backend/.env.example

This file was deleted.

6 changes: 0 additions & 6 deletions backend/.gitignore

This file was deleted.

Loading
Loading