Problem
There's no public way to see how deep the anonymity set actually is (total commitments, deposit/withdraw volume over time) short of manually paging through get_commitments_page or reading raw chain events. Users deciding whether it's currently "safe" to withdraw (i.e. whether the pool has enough recent activity to blend into) have no signal to go on.
Why it matters
Anonymity-set size is the actual privacy guarantee a shielded pool provides — a pool with 3 deposits offers far less protection than one with 3,000, and today a user has no way to know which situation they're in without manually querying the contract.
Scope
- New
frontend/src/lib/analytics.ts: aggregate public, non-deanonymizing stats from pool events — total commitments (get_next_index), deposit/withdrawal counts over time, currently-known root history — with no linkage to which specific commitment belongs to which withdrawal (that link is exactly what the pool is designed not to reveal).
- New
frontend/src/app/stats/page.tsx: a public dashboard rendering pool depth over time, recent deposit/withdraw counts, and a simple "anonymity set size" figure.
frontend/src/lib/indexer.ts: expose the aggregate counts the dashboard needs without exposing per-note linkage.
- Tests confirming the aggregation logic never surfaces amount/recipient linkage between a specific deposit and a specific withdrawal.
README.md: link the new stats page.
Acceptance criteria
- A public page shows pool depth and activity trends over time.
- The dashboard's data model is verified (by test) to never expose a deposit-to-withdrawal linkage, only aggregate counts.
Problem
There's no public way to see how deep the anonymity set actually is (total commitments, deposit/withdraw volume over time) short of manually paging through
get_commitments_pageor reading raw chain events. Users deciding whether it's currently "safe" to withdraw (i.e. whether the pool has enough recent activity to blend into) have no signal to go on.Why it matters
Anonymity-set size is the actual privacy guarantee a shielded pool provides — a pool with 3 deposits offers far less protection than one with 3,000, and today a user has no way to know which situation they're in without manually querying the contract.
Scope
frontend/src/lib/analytics.ts: aggregate public, non-deanonymizing stats from pool events — total commitments (get_next_index), deposit/withdrawal counts over time, currently-known root history — with no linkage to which specific commitment belongs to which withdrawal (that link is exactly what the pool is designed not to reveal).frontend/src/app/stats/page.tsx: a public dashboard rendering pool depth over time, recent deposit/withdraw counts, and a simple "anonymity set size" figure.frontend/src/lib/indexer.ts: expose the aggregate counts the dashboard needs without exposing per-note linkage.README.md: link the new stats page.Acceptance criteria