How to Stream Real-Time Solana DEX Trades with WebSockets
Build a real-time Solana DEX trade monitor using MadeOnSol's WebSocket streaming API. Filter trades by token, wallet, program, or size — covers Pump.fun, Raydium, Jupiter, and Orca.

Build a real-time Solana DEX trade monitor using MadeOnSol's WebSocket streaming API. Filter trades by token, wallet, program, or size — covers Pump.fun, Raydium, Jupiter, and Orca.

Disclosure: This article contains affiliate links. If you sign up through them, MadeOnSol may earn a commission at no extra cost to you. This never affects our rankings, ratings, or reviews.
Every Solana DEX trade — Pump.fun swaps, Raydium pools, Jupiter routes, Orca whirlpools — happens on-chain and is observable in real-time. But parsing raw Solana transactions to extract trade data is complex, expensive, and error-prone.
MadeOnSol's DEX Trade Stream gives you a clean WebSocket feed of parsed DEX trades, filterable by token, wallet, program, or trade size. No gRPC setup, no transaction parsing, no Yellowstone plugin — just connect and subscribe.
This tutorial shows you how to build a real-time trade monitor from scratch.
A TypeScript application that:
The stream covers 9 Solana DEX programs:
| DEX | What's covered |
|---|---|
| Pump.fun | Token launches, bonding curve swaps |
| PumpSwap | Post-bond AMM trades |
| Raydium AMM v4 | Legacy pool swaps |
| Raydium CPMM | Concentrated pools |
| Raydium CLMM | Concentrated liquidity |
| Jupiter (DCA) | Dollar-cost averaging orders |
| Orca Whirlpool | Concentrated liquidity trades |
| Moonshot | Token launch trades |
| Meteora DLMM | Dynamic liquidity trades |
The WebSocket URL requires a 24-hour token. Generate one via the REST API:
// src/get-token.ts
import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({
apiKey: process.env.MADEONSOL_API_KEY!,
});
async function getStreamToken() {
const token = await client.stream.getToken();
console.log("WebSocket URL:", token.ws_url);
console.log("DEX Stream URL:", token.dex_ws_url); // Ultra only
console.log("Expires:", token.expires_at);
return token;
}
Building a product on Solana data?
Skip the Geyser pipeline — embed KOL flow, deployer reputation, and the all-DEX firehose over REST, WebSocket, or webhooks. The Business tier (€400/mo) is the self-serve embed license at 500k calls/day — Enterprise adds white-label & redistribution.
Tools mentioned
Live health scores, average ratings, and direct links on MadeOnSol.

No-code Solana token minting with DEX swaps, a Telegram bot, and an API

AI-powered decentralized exchange and automated trading on Solana
Real-time DEX charts and trading data across all chains

Decentralized community crowdfunding for DEXScreener listings

Web3 data warehouse with Solana archival RPC and real-time streams
Build a deployer sniper bot
Access deployer alerts, bonding stats, and tier data via API. Free tier: 200 requests/day.
New customers try Pro free for 5 days — card, cancel anytime.
import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({ apiKey: "msk_your_key" });
// Elite deployer alerts with KOL buy enrichment
const { alerts } = await client.deployer.alerts({ limit: 5 });
// Top deployers by bonding rate
const { deployers } = await client.deployer.leaderboard({ tier: "elite" });Building a product on Solana data?
MadeOnSol isn't an RPC or another generic token API — it's Solana memecoin intelligence that's painful to build in-house, pulled from dual-region gRPC shred streams: sub-second from the on-chain event to your app.
Signals you'd otherwise build
KOL & smart-money flow from 1,000+ labeled wallets, deployer reputation, coordination clusters, linked-wallet entity resolution, and an all-DEX firehose.
Embed it in your product
The Business tier (€400/mo, self-serve) licenses you to display MadeOnSol data inside your own product — 500k calls/day, 10 WS + 5 firehose connections. Enterprise above adds white-label & redistribution rights and custom endpoints.
Evaluate first, commit later
Test everything on a free ULTRA key — no commitment. If it fits, we scope volume or white-label pricing.
Keep reading

DeFi
A practical guide to swapping crypto without KYC in 2026. Covers ChangeNOW for cross-chain instant swaps, on-chain DEXs like Jupiter and Raydium, THORChain, and when each option makes sense.

Developer Tools
Combine price dip webhooks, KOL coordination WebSocket streams, and wallet tracker events into a unified Solana alert system. TypeScript code for multi-signal trading decisions — sell when smart money exits, buy when they accumulate.

Analytics
Computing deployer reputation for ~27k real Pump.fun deployers means a validator gRPC feed, an indexing pipeline, terabytes of storage, and bond attribution — or a €99 file. Here's the honest cost breakdown, including where building your own still wins.

Developer Tools
Get a Discord embed the moment a proven Solana deployer — one with a real bonding track record on pump.fun or LaunchLab — launches a new token or one of their tokens bonds. This tutorial walks the open-source deployer-alert-discord-bot starter: zero dependencies, ~130 lines, a Discord webhook, and a free MadeOnSol API key.

Guides
A repeatable checklist for evaluating any new pump.fun launch before you buy. Five checks, under 60 seconds, that separate the 1.4% of tokens worth holding from the 98.6% that dump in the first hour.

Guides
Of the 7 million tokens launched on pump.fun, only 97,000 maintained over $1,000 in liquidity. The difference between the 1.4% that survive and the 98.6% that don't is readable on-chain before you buy.
Enjoyed this article?
Real-time KOL trades, Pump.fun deployer intel, and 1,200+ ranked Solana tools — free to explore.
Open the KOL TrackerThe response includes:
ws_url — KOL/deployer event stream (Pro/Ultra)dex_ws_url — all-DEX trade stream (Ultra only)token — JWT valid for 24 hours// src/stream.ts
import WebSocket from "ws";
import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({
apiKey: process.env.MADEONSOL_API_KEY!,
});
async function connectDexStream() {
const { dex_ws_url } = await client.stream.getToken();
if (!dex_ws_url) {
console.error("DEX stream requires Ultra subscription");
return;
}
const ws = new WebSocket(dex_ws_url);
ws.on("open", () => {
console.log("Connected to DEX stream");
// Subscribe with filters (at least one required)
ws.send(JSON.stringify({
type: "subscribe",
filters: {
program: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", // Pump.fun
min_sol: 0.5,
},
}));
});
ws.on("message", (data) => {
const trade = JSON.parse(data.toString());
if (trade.type === "dex:trade") {
console.log(
`[${trade.data.dex}] ${trade.data.action} ${trade.data.token_symbol || trade.data.token_mint.slice(0, 8)} — ` +
`${trade.data.sol_amount.toFixed(2)} SOL`
);
}
});
ws.on("close", () => {
console.log("Disconnected — reconnecting in 5s...");
setTimeout(connectDexStream, 5000);
});
ws.on("error", (err) => {
console.error("WebSocket error:", err.message);
});
}
connectDexStream();
The subscribe message requires at least one targeting filter:
// Track a specific token
ws.send(JSON.stringify({
type: "subscribe",
filters: {
token_mint: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", // BONK
},
}));
// Track multiple tokens (max 50)
ws.send(JSON.stringify({
type: "subscribe",
filters: {
token_mints: ["mint1...", "mint2...", "mint3..."],
min_sol: 1, // Only trades > 1 SOL
},
}));
// Track a specific wallet across all DEXes
ws.send(JSON.stringify({
type: "subscribe",
filters: {
wallet: "7xKXqmq...",
},
}));
// Track all Pump.fun trades above 2 SOL
ws.send(JSON.stringify({
type: "subscribe",
filters: {
program: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
min_sol: 2,
action: "buy", // Only buys
},
}));
| Filter | Type | Description |
|---|---|---|
token_mint | string | Single token mint address |
token_mints | string[] | Up to 50 token mints |
wallet | string | Single wallet address |
wallets | string[] | Up to 50 wallet addresses |
program | string | DEX program ID |
min_sol | number | Minimum trade size in SOL |
max_sol | number | Maximum trade size in SOL |
action | "buy" | "sell" | Filter by trade direction |
Each trade message looks like:
{
"type": "dex:trade",
"data": {
"signature": "5xYz...",
"wallet": "7xKX...",
"token_mint": "DezX...",
"token_symbol": null,
"action": "buy",
"sol_amount": 2.5,
"token_amount": 1500000,
"dex": "pumpfun",
"program_id": "6EF8...",
"slot": 312456789,
"timestamp": "2026-04-05T10:30:15Z"
}
}
Note: token_symbol and token_name are not included in the stream for performance. Resolve token metadata separately using a service like Helius DAS API or your own cache.
Here's a practical example — monitor all new Pump.fun trades and flag tokens with high buy volume:
// src/pumpfun-monitor.ts
import WebSocket from "ws";
import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({ apiKey: process.env.MADEONSOL_API_KEY! });
interface TokenStats {
buys: number;
sells: number;
totalSol: number;
uniqueBuyers: Set<string>;
firstSeen: number;
}
const tokens = new Map<string, TokenStats>();
async function monitor() {
const { dex_ws_url } = await client.stream.getToken();
if (!dex_ws_url) throw new Error("Ultra subscription required");
const ws = new WebSocket(dex_ws_url);
ws.on("open", () => {
ws.send(JSON.stringify({
type: "subscribe",
filters: {
program: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
min_sol: 0.1,
},
}));
console.log("Monitoring Pump.fun trades...");
});
ws.on("message", (raw) => {
const msg = JSON.parse(raw.toString());
if (msg.type !== "dex:trade") return;
const { token_mint, action, sol_amount, wallet } = msg.data;
if (!tokens.has(token_mint)) {
tokens.set(token_mint, {
buys: 0, sells: 0, totalSol: 0,
uniqueBuyers: new Set(),
firstSeen: Date.now(),
});
}
const stats = tokens.get(token_mint)!;
if (action === "buy") {
stats.buys++;
stats.uniqueBuyers.add(wallet);
} else {
stats.sells++;
}
stats.totalSol += sol_amount;
// Alert on tokens with 5+ unique buyers in the first 2 minutes
const age = (Date.now() - stats.firstSeen) / 1000;
if (stats.uniqueBuyers.size >= 5 && age < 120 && stats.buys === 5) {
console.log(
`[ALERT] ${token_mint.slice(0, 8)}... — ` +
`${stats.uniqueBuyers.size} buyers, ${stats.totalSol.toFixed(1)} SOL in ${age.toFixed(0)}s`
);
}
});
ws.on("close", () => setTimeout(monitor, 5000));
}
monitor();
The real power comes from combining the DEX stream with KOL intelligence. When a KOL buys a token you're monitoring:
// Periodically fetch KOL feed to cross-reference
setInterval(async () => {
const { trades } = await client.kol.feed({ limit: 20, action: "buy" });
for (const trade of trades) {
if (tokens.has(trade.mint)) {
const stats = tokens.get(trade.mint)!;
console.log(
`[KOL BUY] ${trade.kol_name} bought a token you're watching — ` +
`${stats.uniqueBuyers.size} unique buyers, ${stats.totalSol.toFixed(1)} SOL volume`
);
}
}
}, 30_000);
Instead of only checking the feed, use the momentum endpoint to find tokens where KOL buy interest is accelerating — before full coordination kicks in:
// Check momentum tokens every 2 minutes
setInterval(async () => {
const { hot_tokens } = await client.kol.hotTokens({
period: "1h",
min_kols: 2,
limit: 10,
});
for (const token of hot_tokens) {
if (token.acceleration > 2.0) {
const tracked = tokens.get(token.token_mint);
console.log(
`[MOMENTUM] ${token.token_symbol}: ${token.kols_total} KOLs, ` +
`${token.acceleration}x acceleration` +
(tracked ? `, ${tracked.uniqueBuyers.size} unique buyers on-chain` : "")
);
}
}
}, 120_000);
This combines two data sources: the raw DEX stream shows all trading activity, while the momentum endpoint tells you which tokens have smart money piling in.
When you spot a new Pump.fun token gaining traction, check the deployer's track record:
async function checkDeployer(deployerWallet: string) {
// Use the REST client for authenticated endpoints
const rest = new MadeOnSolREST({ apiKey: process.env.MADEONSOL_API_KEY! });
const { deployer, trajectory } = await rest.deployerTrajectory(deployerWallet);
console.log(`Deployer tier: ${deployer.tier}, bond rate: ${(deployer.bonding_rate * 100).toFixed(0)}%`);
console.log(`Current streak: ${trajectory.current_streak.count} ${trajectory.current_streak.type}s`);
console.log(`Trend: ${trajectory.trend}`);
// Only trade tokens from deployers on a winning streak
return trajectory.current_streak.type === "bond" && trajectory.trend !== "declining";
}
| Feature | Pro (€43/mo, ≈ $49) | Ultra (€131/mo, ≈ $149) |
|---|---|---|
| KOL/Deployer WebSocket | 1 connection | 3 connections |
| DEX Trade Stream | No | 2 connections |
| REST API | 10K req/day | 100K req/day |
| Webhooks | 3 | 10 |
The free tier (200 req/day) lets you test the REST API. Streaming and webhooks require Pro or Ultra.
See pricing at madeonsol.com/pricing.
Trades appear in the stream within 1-2 seconds of on-chain confirmation. The stream uses gRPC connections to Solana validator nodes for minimal latency.
Yes. You can combine filters in a single subscription — for example, track 50 token mints with a minimum SOL filter. You can also send multiple subscribe messages to layer filters.
MadeOnSol handles the infrastructure — gRPC connections to multiple validator nodes, transaction parsing across 14 DEX programs, reconnection logic, and data normalization. Running your own Yellowstone setup requires a dedicated server, validator relationships, and custom parsers for each DEX program.
No. For performance, the stream only includes mint addresses. Resolve metadata separately using Helius DAS API, Jupiter token list, or your own cache. This keeps the stream fast and lightweight.
Use the REST API alongside the stream. The /kol/tokens/hot endpoint shows tokens with accelerating KOL buy interest — cross-reference these with tokens you see volume spikes on in the stream. The /kol/pairs endpoint reveals which KOLs trade together, helping you weight signals from coordinated groups. And /deployer-hunter/{wallet}/trajectory lets you check a token creator's track record before trading.
The /kol/tokens/hot endpoint detects tokens where KOL buy interest is speeding up. An acceleration score of 2.0x means twice as many KOLs bought in the recent quarter of the time window compared to the baseline rate. This catches early momentum before the coordination threshold (3+ KOLs) triggers.