A monitoring dashboard for OpenZeppelin Guardian servers.
Guardian is a key-management service for Miden accounts — it holds Falcon-512 signing keys, validates state transitions, and cosigns transactions on behalf of accounts. This dashboard gives operators a real-time view of a running Guardian: liveness, account inventory, and per-account details.
| Page | Status | Data source |
|---|---|---|
| Overview — heartbeat, accounts / assets / activity stat cards, operator identity | ✅ Live | Guardian API + env vars |
| Accounts — paginated list with status, signers, assets, pending candidates | ✅ Live | Guardian API (listAccounts) |
| Account detail — fields, signers, vault snapshot, freeze / unfreeze | ✅ Live | Guardian API (getAccount, getAccountSnapshot, pauseAccount, unpauseAccount) |
| Account activity — per-account delta + proposal feed, paginated | ✅ Live | Guardian API (listAccountDeltas, listAccountProposals) |
| Transaction detail — balance changes, notes, storage diffs, proposal metadata | ✅ Live | Guardian API (getAccountDeltaDetail) |
| Activity feed — global delta + proposal feed, status filters, paginated | ✅ Live | Guardian API (listGlobalDeltas, listGlobalProposals) |
| Compliance — provider config, KYC/whitelist, policy rules | 🔶 Mock | Planned; no provider connected yet |
- Node.js 20+
- A running Guardian (local or remote)
- A Clerk application (for authentication)
- The operator's commitment and private key (Falcon-512, hex-encoded) — used to authenticate with the Guardian server
Copy .env.example to .env.local and fill in:
# Clerk — from dashboard.clerk.com
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...
# Guardian endpoints — JSON array, one entry per Guardian
# Each user's allowed endpoint IDs and role are set in Clerk user public metadata
GUARDIAN_ENDPOINTS=[{
"id": "testnet",
"label": "Guardian Testnet",
"url": "https://guardian.example.com",
"network": "MidenTestnet",
"commitment": "0x...",
"privateKey": "..."
}]
# PostHog analytics (optional)
NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN=phc_...
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.comOptional extras:
GUARDIAN_PRIVATE_KEY_{ID}(e.g.GUARDIAN_PRIVATE_KEY_TESTNET) — supply an endpoint'sprivateKeyseparately to keepGUARDIAN_ENDPOINTSunder Vercel's 4KB env var limitGUARDIAN_TOKEN_DECIMALS/GUARDIAN_TOKEN_DECIMALS_DEFAULT— JSON map of faucetId → display decimals and the fallback (default 6); these change displayed amounts
Users are managed via Clerk. Set publicMetadata on each user in the Clerk dashboard:
{
"role": "admin",
"endpointIds": ["testnet"]
}role:"admin"shows the User Management tab;"viewer"hides itendpointIds: which Guardian servers the user can connect to
npm install
npm run dev # → http://localhost:3000The dashboard authenticates to the Guardian server using a challenge-response protocol:
- Dashboard calls
GET /challengewith the operator commitment - Guardian returns a signing digest
- Dashboard signs the digest with the operator's Falcon-512 private key (via Miden WASM)
- Dashboard calls
POST /verifywith the commitment and signature - Guardian returns a session cookie used for all subsequent API calls
The private key never leaves the server process.
- Next.js 16 (App Router, TypeScript)
- Tailwind CSS v4
- Clerk — authentication and user management
- SWR — data fetching with polling
- Recharts — charts
- PostHog — product analytics
- Miden SDK (
@miden-sdk/miden-sdk) — Falcon-512 signing via WASM @openzeppelin/guardian-operator-client— typed Guardian API client