Stream live token launches and trades from the Solana blockchain to your browser or Node.js app.
- Node.js 18+
- A Solana RPC endpoint with WebSocket support
npm install ws express @solana/web3.jsThe Pump SDK includes a WebSocket relay server that bridges Solana RPC events to browser clients:
┌─────────────────┐ WebSocket ┌───────────────┐ WebSocket ┌─────────────┐
│ Solana RPC │ ◄───────────────► │ Relay Server │ ◄───────────────► │ Browser / │
│ (mainnet) │ (subscribe) │ (port 3099) │ (broadcast) │ Node.js │
└─────────────────┘ └───────────────┘ └─────────────┘
Message types flowing to clients:
token-launch— New token created on Pumpstatus— Server health and statisticsheartbeat— Keep-alive ping every 15s
Clone and run the built-in relay:
cd websocket-server
npm install
npm startOr configure with environment variables:
PORT=3099 \
SOLANA_RPC_WS=wss://api.mainnet-beta.solana.com \
npm startThe server exposes:
ws://localhost:3099/ws— WebSocket endpointhttp://localhost:3099/health— Health check (JSON)http://localhost:3099/— Built-in dashboard
<!DOCTYPE html>
<html>
<head><title>Pump Token Feed</title></head>
<body>
<h1>Live Token Launches</h1>
<div id="stats"></div>
<div id="feed"></div>
<script>
const feed = document.getElementById('feed');
const stats = document.getElementById('stats');
let ws;
function connect() {
ws = new WebSocket('ws://localhost:3099/ws');
ws.onopen = () => {
console.log('Connected to relay');
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
switch (msg.type) {
case 'token-launch':
handleLaunch(msg);
break;
case 'status':
handleStatus(msg);
break;
case 'heartbeat':
// Connection alive
break;
}
};
ws.onclose = () => {
console.log('Disconnected, reconnecting in 3s...');
setTimeout(connect, 3000);
};
}
function handleLaunch(launch) {
const el = document.createElement('div');
el.className = 'launch';
el.innerHTML = `
<strong>${launch.symbol || '???'}</strong> — ${launch.name || 'Unknown'}
<br>Mint: <code>${launch.mint}</code>
<br>Creator: <code>${launch.creator}</code>
${launch.hasGithub ? '<br>🔧 Has GitHub repo!' : ''}
${launch.marketCapSol ? `<br>Market Cap: ${launch.marketCapSol.toFixed(2)} SOL` : ''}
<br><small>${new Date(launch.time).toLocaleTimeString()}</small>
<hr>
`;
feed.prepend(el);
// Keep only last 100 launches in DOM
while (feed.children.length > 100) {
feed.removeChild(feed.lastChild);
}
}
function handleStatus(status) {
stats.innerHTML = `
Connected: ${status.connected} |
Uptime: ${Math.floor(status.uptime / 60)}m |
Total Launches: ${status.totalLaunches} |
GitHub Launches: ${status.githubLaunches} |
Clients: ${status.clients}
`;
}
connect();
</script>
</body>
</html>import WebSocket from "ws";
interface TokenLaunchEvent {
type: "token-launch";
signature: string;
time: string;
name: string | null;
symbol: string | null;
metadataUri: string | null;
mint: string | null;
creator: string | null;
isV2: boolean;
hasGithub: boolean;
githubUrls: string[];
imageUri: string | null;
description: string | null;
marketCapSol: number | null;
website: string | null;
twitter: string | null;
telegram: string | null;
}
interface ServerStatus {
type: "status";
connected: boolean;
uptime: number;
totalLaunches: number;
githubLaunches: number;
clients: number;
}
function connectToRelay(url: string = "ws://localhost:3099/ws") {
const ws = new WebSocket(url);
ws.on("open", () => {
console.log("Connected to Pump relay server");
});
ws.on("message", (data: WebSocket.Data) => {
const msg = JSON.parse(data.toString());
if (msg.type === "token-launch") {
const launch = msg as TokenLaunchEvent;
console.log(
`[LAUNCH] ${launch.symbol} (${launch.name}) — ${launch.mint}`
);
if (launch.hasGithub) {
console.log(` GitHub: ${launch.githubUrls.join(", ")}`);
}
if (launch.marketCapSol) {
console.log(` Market Cap: ${launch.marketCapSol.toFixed(4)} SOL`);
}
}
if (msg.type === "status") {
const status = msg as ServerStatus;
console.log(
`[STATUS] Launches: ${status.totalLaunches} | Clients: ${status.clients}`
);
}
});
ws.on("close", () => {
console.log("Disconnected, reconnecting in 3s...");
setTimeout(() => connectToRelay(url), 3000);
});
return ws;
}
connectToRelay();Build a filter pipeline to watch for specific patterns:
interface LaunchFilter {
minMarketCap?: number;
requireGithub?: boolean;
symbolPattern?: RegExp;
requireSocials?: boolean;
}
function matchesFilter(
launch: TokenLaunchEvent,
filter: LaunchFilter
): boolean {
if (filter.minMarketCap && (launch.marketCapSol ?? 0) < filter.minMarketCap) {
return false;
}
if (filter.requireGithub && !launch.hasGithub) {
return false;
}
if (filter.symbolPattern && launch.symbol && !filter.symbolPattern.test(launch.symbol)) {
return false;
}
if (filter.requireSocials && !launch.twitter && !launch.telegram && !launch.website) {
return false;
}
return true;
}
// Example: Only show tokens with GitHub repos and > 1 SOL market cap
const myFilter: LaunchFilter = {
minMarketCap: 1.0,
requireGithub: true,
};
ws.on("message", (data: WebSocket.Data) => {
const msg = JSON.parse(data.toString());
if (msg.type === "token-launch" && matchesFilter(msg, myFilter)) {
console.log(`[MATCH] ${msg.symbol} — ${msg.mint}`);
// Trigger your trading logic, alerts, etc.
}
});If you want to customize the relay or add new event types:
import { WebSocketServer, WebSocket } from "ws";
import http from "http";
import { Connection } from "@solana/web3.js";
const PORT = parseInt(process.env.PORT || "3099", 10);
const SOLANA_RPC_WS = process.env.SOLANA_RPC_WS || "wss://api.mainnet-beta.solana.com";
const HEARTBEAT_INTERVAL = 15_000;
const MAX_RECENT = 50;
// HTTP server for health checks
const httpServer = http.createServer((req, res) => {
if (req.url === "/health") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ status: "ok", clients: wss.clients.size }));
return;
}
res.writeHead(404);
res.end();
});
// WebSocket server
const wss = new WebSocketServer({ server: httpServer, path: "/ws" });
const recentLaunches: any[] = [];
wss.on("connection", (client) => {
// Send recent launches to new clients
for (const launch of recentLaunches) {
client.send(JSON.stringify(launch));
}
});
// Broadcast to all connected clients
function broadcast(message: object) {
const data = JSON.stringify(message);
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
}
// Heartbeat
setInterval(() => {
broadcast({ type: "heartbeat", ts: Date.now() });
}, HEARTBEAT_INTERVAL);
httpServer.listen(PORT, () => {
console.log(`Relay server running on port ${PORT}`);
});PORT=3099 SOLANA_RPC_WS=wss://api.devnet.solana.com npm startFROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3099
CMD ["node", "dist/index.js"]The websocket-server/ directory is deployment-ready. Set PORT and SOLANA_RPC_WS in your environment.
- Combine with Tutorial 11 to auto-trade on launch events
- Use Tutorial 22 to broadcast to Telegram
- Deploy the live dashboards for a visual feed