The Code

Under the hood of crustacean democracy. Every line of code that makes 5 lobsters trade memecoins.

🟢

Node.js

Bot runtime

Next.js

Dashboard

🧠

Claude AI

Council brain

Supabase

Database + Realtime

Solana

Blockchain

🔌

PumpPortal

Token data + Trading

🦅

Birdeye

Market data

🎨

Tailwind

Styling

Council Voting (Claude AI)

bot/src/lib/claude.js

Each lobster is simulated by Claude AI with unique personality traits. The prompt describes each lobster's bias and they vote independently.

00d4aa">"color:#4a6a7a">// Each lobster votes based on their personality
084fc">const LOBSTER_PROFILES = {
    chad:     { bias: 00d4aa">'bullish',  buyThreshold: 45 },  00d4aa">"color:#4a6a7a">// Always BUY
    nancy:    { bias: 00d4aa">'bearish',  buyThreshold: 75 },  00d4aa">"color:#4a6a7a">// Data only
    papaclaw: { bias: 00d4aa">'neutral',  buyThreshold: 60 },  00d4aa">"color:#4a6a7a">// Old school
    snappy:   { bias: 00d4aa">'chaotic',  buyThreshold: 24">null }, 00d4aa">"color:#4a6a7a">// Random
    coral:    { bias: 00d4aa">'vibes',    buyThreshold: 55 },   00d4aa">"color:#4a6a7a">// Feelings
};

00d4aa">"color:#4a6a7a">// Claude simulates all 5 voting independently
084fc">const result = 084fc">await analyzeWithCouncil(tokenInfo, tankState);
00d4aa">"color:#4a6a7a">// result.votes = { chad: {vote:00d4aa">'BUY'}, nancy: {vote:00d4aa">'SKIP'}, ... }
00d4aa">"color:#4a6a7a">// result.tally = 00d4aa">"3-2"
00d4aa">"color:#4a6a7a">// result.decision = 00d4aa">"BUY" or 00d4aa">"SKIP"

Tank State System

bot/src/lib/tank.js

Water level determines tank mood. Events raise or lower water level, which changes how lobsters trade.

00d4aa">"color:#4a6a7a">// Water level -> Tank State
084fc">function calculateTankState(waterLevel) {
    084fc">if (wl >= 80) 084fc">return 00d4aa">'REEF_PARADISE';    00d4aa">"color:#4a6a7a">// Harmony
    084fc">if (wl >= 60) 084fc">return 00d4aa">'STEADY_CURRENTS';  00d4aa">"color:#4a6a7a">// Normal
    084fc">if (wl >= 40) 084fc">return 00d4aa">'CHOPPY_WATERS';    00d4aa">"color:#4a6a7a">// Tense
    084fc">if (wl >= 20) 084fc">return 00d4aa">'RED_TIDE';         00d4aa">"color:#4a6a7a">// Crisis
    084fc">return 00d4aa">'TANK_BREACH';                    00d4aa">"color:#4a6a7a">// Chaos
}

00d4aa">"color:#4a6a7a">// Events affect water level
00d4aa">"color:#4a6a7a">// profit: +5  |  loss: -8  |  bigWin: +15
00d4aa">"color:#4a6a7a">// bigLoss: -20  |  unanimous: +5  |  escape: -10

00d4aa">"color:#4a6a7a">// Mood affects trading
REEF_PARADISE:  { riskMultiplier: 1.1 }  00d4aa">"color:#4a6a7a">// Confident
RED_TIDE:       { riskMultiplier: 1.3 }  00d4aa">"color:#4a6a7a">// Impulsive
TANK_BREACH:    { riskMultiplier: 1.5 }  00d4aa">"color:#4a6a7a">// YOLO

PumpPortal WebSocket

bot/src/lib/pumpportal.js

Real-time connection to PumpFun for new token detection. Auto-reconnects on disconnect.

00d4aa">"color:#4a6a7a">// Connect to PumpPortal for real-time token data
connectPumpPortal({
    onToken: (data) => {
        00d4aa">"color:#4a6a7a">// New token created on PumpFun
        processingQueue.push(data);
        processQueue(); 00d4aa">"color:#4a6a7a">// Council assembles
    },
    onConnect: () => {
        subscribeNewTokens();
        00d4aa">"color:#4a6a7a">// 00d4aa">"The tank hums to life..."
    },
    onDisconnect: () => {
        00d4aa">"color:#4a6a7a">// Auto-reconnect in 5 seconds
        setTimeout(() => connectPumpPortal(callbacks), 5000);
    }
});

Trade Execution

bot/src/index.js

When council approves, trade amount is calculated based on balance, mood modifiers, and risk level.

00d4aa">"color:#4a6a7a">// Council voted BUY — execute trade
084fc">if (analysis.decision === 00d4aa">'BUY' && analysis.score >= MIN_SCORE) {
    084fc">const modifier = getMoodModifier(tankState.state);
    084fc">const tradeAmount = balance * MAX_TRADE_PERCENT * modifier.riskMultiplier;
    084fc">const finalAmount = Math.min(tradeAmount, balance * 0.8);

    00d4aa">"color:#4a6a7a">// Execute via PumpPortal
    084fc">await buyToken(ca, finalAmount, SLIPPAGE);

    00d4aa">"color:#4a6a7a">// Record in Supabase with full vote breakdown
    084fc">await recordTrade({
        ca, symbol, type: 00d4aa">'buy',
        amount_sol: finalAmount,
        vote_breakdown: analysis.votes,
        deciding_lobster: analysis.swingVoter,
        council_commentary: analysis.tankNarration,
    });
}

Real-time Dashboard

site/app/page.tsx

Next.js site with Supabase real-time subscriptions. Data updates live without page refresh.

00d4aa">"color:#4a6a7a">// Subscribe to real-time tank status updates
useEffect(() => {
    084fc">const sb = getSupabase();
    084fc">const channel = sb.channel(00d4aa">'tank-status')
        .on(00d4aa">'postgres_changes', {
            event: 00d4aa">'*',
            schema: 00d4aa">'public',
            table: 00d4aa">'system_status',
            filter: 00d4aa">'id=eq.1'
        }, (payload) => {
            00d4aa">"color:#4a6a7a">// Tank visual updates in real-time
            setStatus(payload.new as SystemStatus);
        })
        .subscribe();

    084fc">return () => { sb.removeChannel(channel); };
}, []);

Lobster Chat Generator

site/components/LobsterChat.tsx

Each lobster speaks with unique slang and personality. Chat is generated from actual vote data or simulated for demo.

00d4aa">"color:#4a6a7a">// Chad always speaks in caps with ghetto slang
chad: {
    buyPhrases: [
        00d4aa">"YO THIS JOINT IS BUSSIN FR FR BUY THAT JAWN RN",
        00d4aa">"sheeeeesh look at that volume bruh we gotta cop NOW",
        00d4aa">"THIS IS IT CHIEF 084fc">if you aint buyin you tweakin",
    ],
}

00d4aa">"color:#4a6a7a">// Nancy is the skeptic
nancy: {
    skipPhrases: [
        00d4aa">"the data literally says this is a rug SKIP",
        00d4aa">"oh wow another 90% top 10 wallets how original",
    ],
}

00d4aa">"color:#4a6a7a">// Coral trades on vibes
coral: {
    buyPhrases: [
        00d4aa">"the universe says this one is blessed. my crystals agree.",
    ],
}

Project Structure

lobster-tank/
├── bot/                          # Trading bot (Node.js)
│   ├── src/
│   │   ├── index.js              # Main entry — orchestrates everything
│   │   ├── config.js             # Environment variables + trading config
│   │   └── lib/
│   │       ├── claude.js         # Council AI — 5 lobsters vote via Claude
│   │       ├── tank.js           # Tank state machine + mood modifiers
│   │       ├── pumpportal.js     # WebSocket + buy/sell execution
│   │       ├── birdeye.js        # Market data (MC, liquidity, holders)
│   │       ├── supabase.js       # Database CRUD operations
│   │       ├── logger.js         # Colorful terminal logs
│   │       └── utils.js          # Retry logic, formatters, helpers
│   └── .env                      # API keys (never committed)
│
├── site/                         # Dashboard (Next.js + Tailwind)
│   ├── app/
│   │   ├── page.tsx              # Main dashboard — tank visual + chat
│   │   ├── terminal/page.tsx     # Live terminal feed
│   │   ├── docs/page.tsx         # Documentation
│   │   ├── how-it-works/page.tsx # Visual pipeline explanation
│   │   └── code/page.tsx         # This page — code walkthrough
│   ├── components/
│   │   ├── TankVisual.tsx        # Animated aquarium with 5 lobsters
│   │   ├── LobsterChat.tsx       # Live chat — lobsters discuss tickers
│   │   ├── CouncilRoster.tsx     # Meet the council members
│   │   └── StatsGrid.tsx         # Trading statistics
│   └── lib/
│       ├── supabase.ts           # Lazy-init Supabase client
│       └── types.ts              # TypeScript interfaces
│
└── supabase/
    ├── schema.sql                # Database schema
    └── fix_realtime.sql          # Enable realtime subscriptions