Solana wallet PnL tracker and token-gated chat
Paste any wallet address for FIFO cost-basis analytics, or sign in to join holder-only chat rooms.
Built with Next.js 16, Solana wallet-adapter, Helius, Jupiter Price API, and Supabase.
| Repository | github.com/mukulcodezz/onchain-solana |
| Live app | onchain-solana.vercel.app |
| License | MIT |
Solana wallet PnL tracker and token-gated chat — decode any Solana wallet's cost basis, realized/unrealized PnL, and allocation across 8 chart types. Connect your wallet to enter token-gated chat rooms verified by on-chain balances.
Tech stack: Next.js 16 · React 19 · TypeScript · Tailwind CSS 4 · Solana wallet-adapter · Helius · Jupiter · Supabase · D3 · Framer Motion
Topics: solana · pnl · portfolio-tracker · nextjs · crypto · web3 · supabase · token-gated
- Portfolio PnL — FIFO cost basis, realized/unrealized gains, holdings table, flex card export
- 8 chart types — net worth, allocation ring/treemap, PnL bars, OHLC candles, PnL calendar heatmap, sparklines
- Token-gated chat — Sign-In With Solana (SIWS), balance-verified room access, live messaging
- Demo mode — runs without Supabase or Helius using mock data
git clone https://github.com/mukulcodezz/onchain-solana.git
cd onchain-solana
npm install
cp .env.example .env.local # fill in keys (see below)
npm run devOpen http://localhost:3000.
Copy .env.example to .env.local for local dev. Add the same keys in Vercel → Project → Settings → Environment Variables.
| Variable | Required | Where to get it | Used for |
|---|---|---|---|
SESSION_SECRET |
Yes (prod) | Generate: openssl rand -base64 32 |
Signs auth session cookies after SIWS |
HELIUS_API_KEY |
Recommended | helius.dev → Dashboard → API Keys | Token balances, parsed swap history, PnL |
NEXT_PUBLIC_RPC_URL |
Optional | Helius RPC URL or any Solana RPC | Wallet connection (defaults to public mainnet RPC) |
NEXT_PUBLIC_SUPABASE_URL |
For chat DB | supabase.com → Project Settings → API | Chat rooms, memberships, messages |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
For chat DB | Supabase → Project Settings → API → anon key |
Client-side Supabase (if used) |
SUPABASE_SERVICE_ROLE_KEY |
For chat DB | Supabase → Project Settings → API → service_role key |
Server-side room/message writes (keep secret) |
| Feature | No keys | Helius only | Full stack |
|---|---|---|---|
| Landing page | ✅ | ✅ | ✅ |
| PnL dashboard | Mock data | Live PnL | Live PnL |
| Token chat | Mock rooms | Mock rooms | Live chat + gating |
openssl rand -base64 32Paste into .env.local and Vercel env vars. Without this, auth routes fail in production.
- Create account at helius.dev
- Create a project → copy API Key
- Set
HELIUS_API_KEY=your-key - Optional: set
NEXT_PUBLIC_RPC_URL=https://mainnet.helius-rpc.com/?api-key=your-key
Helius powers:
/api/pnl— wallet balances + transaction history- Room join — verifies token gate balances
- Create project at supabase.com
- Run this SQL in SQL Editor:
create table rooms (
id uuid primary key default gen_random_uuid(),
name text not null unique,
gate_mint text not null,
gate_min numeric not null,
gate_symbol text,
created_at timestamptz default now()
);
create table memberships (
room_id uuid references rooms(id) on delete cascade,
wallet text not null,
verified_at timestamptz default now(),
primary key (room_id, wallet)
);
create table messages (
id bigserial primary key,
room_id uuid references rooms(id) on delete cascade,
wallet text not null,
content text not null,
type text default 'text',
created_at timestamptz default now()
);
create index messages_room_created on messages(room_id, created_at);- Copy from Project Settings → API:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEY(server only — never expose to client)
Price data uses public endpoints automatically:
- Jupiter Price API v2 — current token prices
- CoinGecko — historical SOL prices for cost basis
- Push this repo to GitHub
- Import in vercel.com/new
- Add environment variables from the table above
- Deploy
Or via CLI:
npm i -g vercel
vercel login
vercel --prodSet env vars in the Vercel dashboard before the first production deploy.
src/
├── app/
│ ├── api/ # Route handlers (auth, pnl, rooms, prices, flex)
│ ├── chat/ # Token-gated chat UI
│ ├── pnl/ # Portfolio dashboard
│ └── page.tsx # Landing page
├── components/ # Nav, charts, wallet providers, UI primitives
└── lib/ # Helius, Supabase, PnL engine, SIWS, session
| Command | Description |
|---|---|
npm run dev |
Start dev server |
npm run build |
Production build |
npm run lint |
ESLint |
node qa-screenshot.mjs |
Capture QA screenshots (requires dev server + Playwright) |
- Never commit
.env.localor service role keys SESSION_SECRETmust be set in production (app throws without it)- Session cookies are
httpOnly,sameSite=strict, andsecurein production - Chat messages are capped at 2,000 characters; membership is verified before POST
| Name | Role | GitHub | |
|---|---|---|---|
| 👤 | mukulcodezz (0xmukul) | Author & maintainer | @mukulcodezz |
| 🤖 | cursoragent (Cursor Agent) | AI pair programming | @cursoragent |
Version history is published on GitHub Releases.
| Version | Notes |
|---|---|
| v0.1.0 | Initial public release — PnL dashboard, token-gated chat, demo mode |
MIT — see LICENSE.