Overview
Slotwave turns the Solana slot cadence, roughly one block every 400 milliseconds, into music. Transactions become notes, compute load becomes brightness, fees become bass, and anomalous activity cuts through in violet. Slots stream in from live mainnet or from a recorded capture, a pure mutation engine maps chain activity to musical parameters, Tone.js plays them, and a flat canvas timeline pulses in sync.
What it demonstrates
- Deterministic mapping layer kept as pure modules in
lib/, with no React and no Tone.js imports - Server-side RPC proxying so the provider key never reaches the client
- Cache design that makes every listener request identical URLs, so each stretch of chain hits the origin once
- A player modeled as a tape: every ingested slot is mapped exactly once and retained in a session buffer
- One semantic expressed twice, in audio timbre and in UI color: green for normal flow, violet for anomalous events
Key features
- Pause, rewind 30s, click the tape to seek, and hover any tick to inspect that slot's data
- Shareable
/?slot=Nlinks that land on the exact moment you heard - Replay mode looping a JSONL fixture, with automatic fallback when no RPC key is configured
- Live mode that keeps recording into the buffer while you listen to the past
- Five mapping modules: density, pressure, bass, texture, and anomaly
- Per-voice volume sliders and room reverb behind
?debug=1, persisted in the browser - Ships as a Farcaster Mini App with manifest, embed tags, and the SDK handshake
Live mode needs a Solana RPC URL that includes your provider key. Without one the app falls back to replay automatically, so it runs with no setup.
Live demo
The mappings
Stats are exponentially weighted over a 64-slot window, so mappings react to relative change on any fixture or network condition.
- density: transaction count maps to 1 to 4 notes per slot on an E minor pentatonic ladder
- pressure: compute-unit utilization opens a lowpass filter, and fees drive velocity
- bass: total fees set the ground note under each slot
- texture: failed-transaction share produces deterministic noise grains
- anomaly: a skipped slot fires an FM thud, and a CU z-score above 2.5 fires a metallic burst
Architecture notes
- Route handlers proxy the RPC with closed, validated params:
GET /api/tipreturns the finalized tip slot,s-maxage=3GET /api/window/[start]returns 8 consecutiveSlotRecords,s-maxage=31536000, immutableGET /api/slot/[slot]returns one finalizedSlotRecordwith the same caching
- Window starts must be multiples of 8, which is what makes listener URLs identical and the cache effective. Windows that are not fully finalized return 404
no-store. - The player anchors the tip every 12 seconds and extrapolates locally in between. The 404 on non-finalized windows is what makes that optimism safe.
- While paused the buffer keeps recording about 2 minutes of tape, then the fetcher idles. It also idles in a hidden tab that is not playing, so an abandoned browser stops burning RPC quota.
- Every window fetched from the provider is archived to
.cache/slotwave/, so dev restarts and re-listens of the same slots never cost another call.
Quickstart
git clone https://github.com/casaisdev/slotwave.git
npm install
npm run devReplay mode works with no setup. For live mode, copy .env.example to .env.local and set SOLANA_RPC_URL to a JSON-RPC endpoint that includes your provider key. The app speaks raw JSON-RPC with no provider SDK, so any provider works.
Notes
- Tests are split between
npm testfor the purelib/unit tests under Vitest andnpm run e2efor a browser smoke test that needs the dev server running. npx tsx scripts/capture.ts --slots 600records a real mainnet fixture, andnpx tsx scripts/export-archive.tsturns the local archive into a replay tape.- On a custom domain,
NEXT_PUBLIC_SITE_URLhas to be set and redeployed: the domain is baked at build time and the Farcaster manifest signature must match it exactly.
Next steps
Work the repository still leaves open:
- Sign the
accountAssociationfor the production domain and add the generated header, payload, and signature to the manifest route - Verify the mini app with the Farcaster preview tool, checking that audio starts after the tap on a real phone
- Publish the mini app to the catalog