Description
Stellar Explain has no way to surface real usage numbers — transactions explained, accounts checked, total lookups. These numbers build trust and social proof on the landing page. This issue adds lightweight, fully anonymous counters to the backend and displays them on the landing page.
No personal data. No user tracking. No cookies. Just simple increment counters.
Part 1 — Backend
Option A — In-memory (start here)
Add atomic counters directly in the Axum app state. Resets on restart but good enough for early stage.
pub struct AppState {
// ... existing fields ...
pub stats: Arc<AppStats>,
}
pub struct AppStats {
pub transactions_explained: AtomicU64,
pub accounts_checked: AtomicU64,
}
Increment transactions_explained in the GET /tx/:hash handler on success.
Increment accounts_checked in the GET /account/:address handler on success.
New endpoint: GET /stats
Response:
{
"transactions_explained": 1284,
"accounts_checked": 743,
"total_lookups": 2027
}
total_lookups is just transactions_explained + accounts_checked computed at response time.
Key files (backend):
packages/core/src/main.rs (add AppStats to state)
packages/core/src/routes/stats.rs (new route)
packages/core/src/routes/mod.rs (register route)
packages/core/src/routes/tx.rs (increment counter on success)
packages/core/src/routes/account.rs (increment counter on success)
Part 2 — Frontend
Add fetchStats() to src/lib/api.ts
export interface StatsResponse {
transactions_explained: number;
accounts_checked: number;
total_lookups: number;
}
export async function fetchStats(): Promise<StatsResponse>
Add proxy route: src/app/api/stats/route.ts
Create src/components/landing/StatsSection.tsx
A clean section on the landing page showing 3 live numbers:
| Stat |
Label |
total_lookups |
Explanations generated |
transactions_explained |
Transactions decoded |
accounts_checked |
Accounts inspected |
- Numbers animate from 0 to their value on scroll into view (count-up effect)
- If the fetch fails, show placeholder dashes
— gracefully
- Non-blocking: page renders immediately, numbers fill in when ready
- Style consistent with the dark landing page aesthetic
Wire between HowItWorksSection and WhatWeDecodeSection in src/app/page.tsx
Key files (frontend):
src/lib/api.ts (add fetchStats)
src/types/index.ts (add StatsResponse)
src/app/api/stats/route.ts (proxy route)
src/components/landing/StatsSection.tsx (new component)
src/app/page.tsx (wire in)
Acceptance Criteria
Complexity: High · 200 pts
Stage: S10 — Power Features
Description
Stellar Explain has no way to surface real usage numbers — transactions explained, accounts checked, total lookups. These numbers build trust and social proof on the landing page. This issue adds lightweight, fully anonymous counters to the backend and displays them on the landing page.
No personal data. No user tracking. No cookies. Just simple increment counters.
Part 1 — Backend
Option A — In-memory (start here)
Add atomic counters directly in the Axum app state. Resets on restart but good enough for early stage.
Increment
transactions_explainedin theGET /tx/:hashhandler on success.Increment
accounts_checkedin theGET /account/:addresshandler on success.New endpoint:
GET /statsResponse:
{ "transactions_explained": 1284, "accounts_checked": 743, "total_lookups": 2027 }total_lookupsis justtransactions_explained + accounts_checkedcomputed at response time.Key files (backend):
packages/core/src/main.rs(add AppStats to state)packages/core/src/routes/stats.rs(new route)packages/core/src/routes/mod.rs(register route)packages/core/src/routes/tx.rs(increment counter on success)packages/core/src/routes/account.rs(increment counter on success)Part 2 — Frontend
Add
fetchStats()tosrc/lib/api.tsAdd proxy route:
src/app/api/stats/route.tsCreate
src/components/landing/StatsSection.tsxA clean section on the landing page showing 3 live numbers:
total_lookupstransactions_explainedaccounts_checked—gracefullyWire between
HowItWorksSectionandWhatWeDecodeSectioninsrc/app/page.tsxKey files (frontend):
src/lib/api.ts(add fetchStats)src/types/index.ts(add StatsResponse)src/app/api/stats/route.ts(proxy route)src/components/landing/StatsSection.tsx(new component)src/app/page.tsx(wire in)Acceptance Criteria
GET /statsreturns correct counts/tx/:hashand/account/:addressresponse—gracefully, no crashComplexity: High · 200 pts
Stage: S10 — Power Features