Finding Solana KOL Clusters: Pair Affinity & Co-Trading with `/v1/kol/pairs`
Which pairs of Solana KOLs buy the same tokens at nearly the same time? The `/kol/pairs` endpoint returns the affinity matrix — shared token count plus agreement rate — so you can spot coordinated clusters, bot groups, and genuinely independent alpha.
MadeOnSol·· 7 min read
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.
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 2,000+ labeled wallets, deployer reputation, coordination clusters, linked-wallet entity resolution, and an all-DEX firehose.
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.
You can embed a Solana data API in your app on a standard plan — but the moment you resell the data, expose it as your own feed, or strip the branding, you're in licensing territory most builders discover too late. This guide maps the three usage zones (internal use, user-facing display, redistribution), the questions to ask any data vendor before you build, and what an Enterprise data license actually covers: white-label, bulk export, extended caching, SLA, and dedicated limits.
The KOL leaderboard assumes every tracked wallet is an independent information source. That's almost never true. Run a copy-trade roster of 5 wallets and you'll quickly find that 2 of them are just copying a 3rd, one is a bot following the whole group, and the "5 diversified alpha sources" is actually 2 sources and 3 echoes.
GET /api/v1/kol/pairs is the endpoint that surfaces this structure. It returns the affinity matrix across all tracked KOLs — every pair, sorted by how often they buy the same tokens within tight timing windows. High-affinity pairs are either copy-trading each other, sharing a group chat, or part of a coordinated bot cluster. Either way, they're not independent.
The call
GET /api/v1/kol/pairs?period=7d&min_shared=3&limit=20
Authorization: Bearer msk_...
Parameters:
period — 7d or 30d. Default 7d. Short windows catch current clusters; 30d reveals durable relationships.
min_shared — minimum number of shared tokens to include a pair. Range 1–20, default 3. Lower values surface casual overlap; higher values only return tight pairs.
limit — 1–50 pairs returned. Default 20.
Responses are cached 5 minutes server-side so rapid polls are cheap.
shared_token_count — how many tokens both wallets bought in the period.
agreement_rate (%) — of those shared tokens, what fraction they bought within 2 hours of each other. This is the coordination signal.
shared_tokens[] — list of the actual mint addresses. ULTRA only — PRO and BASIC omit this array.
Reading agreement_rate
shared_token_count alone doesn't tell you much. Two KOLs who both trade heavily on pump.fun will overlap on many tokens just by pure coverage. What matters is how often they enter those shared tokens at the same time.
Calibration:
agreement_rate
Interpretation
90%+
Almost certainly coordinated. Either one is copy-trading the other, they're in the same group chat, or they share a bot.
60–90%
Tight cluster. Same information flow, same tooling. Treat as one signal source.
40–60%
Loose overlap. Partially correlated strategies.
20–40%
Coincidental overlap from both fishing the same pool (e.g. pump.fun).
< 20%
Independent wallets that happen to share coverage.
Combine with shared_token_count:
Low shared_token_count + high agreement_rate = small number of tokens, but they always trade them together. Could be a specific thesis group.
High shared_token_count + high agreement_rate = the strongest coordination signal. You've found a pod.
High shared_token_count + low agreement_rate = they trade the same pool but move independently. Two snipers on pump.fun, not coordination.
Use cases
De-duplicating a copy-trade roster
The most concrete use. You've shortlisted 5 wallets to copy-trade. Run /kol/pairs?period=30d&min_shared=5 and look for pairs from your shortlist with high agreement rates. (If you're still assembling that roster, our walkthrough on building a Solana copy-trading signal feed shows how to wire the Wallet Tracker API into a live feed.)
import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({ apiKey: process.env.MADEONSOL_API_KEY! });
async function deduplicateRoster(candidates: string[]) {
// Pull a big pair list for the period
const { pairs } = await client.kol.pairs({
period: "30d",
min_shared: 5,
limit: 50,
});
// Find cross-roster high-affinity pairs
const roster = new Set(candidates);
const coordinated = pairs.filter(
(p) =>
roster.has(p.kol_a.wallet) &&
roster.has(p.kol_b.wallet) &&
p.agreement_rate >= 70
);
// For each coordinated pair, drop the one with lower historical win rate
// (left as exercise — needs /kol/{wallet} lookups)
return coordinated;
}
If your shortlist has 5 wallets and 2 of them pair at 85% agreement, you're effectively copy-trading 4 wallets, not 5. Drop one, reclaim a slot on your rate limits.
Bot cluster detection
Pure bots frequently show up as pairs with 95%+ agreement_rate over 30-40 shared tokens. They're not information sources — they're algorithmic reactors. If your strategy is "follow where smart humans are buying first," you want to exclude bot clusters from your KOL feed.
Identify a bot-dominated pair once, and both wallets can be tagged as bot-suspect in your downstream pipeline.
Spotting new alpha cohorts
Periodic sweeps at ?period=7d surface which KOLs have recently started co-trading. If two wallets that didn't appear together in 30d data now pair at 70% agreement over 5 shared tokens in the last week, something changed — a new group formed, someone got added to a chat, a new tooling stack went live. Worth watching those pairs for the tokens they collectively signal. To find out which member of a cluster actually fires first on a given mint, cross-reference the KOL entry-order endpoint, which ranks every tracked wallet by buy timestamp.
Independence-check before a paid subscription
Before you subscribe to a KOL's signal service or copy-trade group, check their pair affinity against other KOLs you already follow. If they pair at 80%+ with someone you already track, you're paying for redundant signal.
Worked example: the "coordinated sell" trap
Suppose you've copy-traded a wallet that's been great on buys. You keep getting good entries. Then one day the wallet sells a position and you take a loss. You later discover the sell was triggered by 6 other KOLs dumping the same token within 5 minutes — a coordinated exit you didn't see coming.
A high agreement_rate pair on sells is just as meaningful as on buys. If your copy-trade target pairs at 85% with 4 other KOLs, every sell they make could be group-triggered. That doesn't make the signal bad — but it does mean you should either copy the whole cluster or none of them, never just one.
Tier considerations
Field
BASIC
PRO
ULTRA
pairs[] with names + agreement_rate
✓
✓
✓
shared_token_count
✓
✓
✓
shared_tokens[] (mint list per pair)
✗
✗
✓
Period + filter params
all
all
all
The ULTRA shared_tokens[] payload is the differentiator for backtests and what-trades-did-the-cluster-fire type analysis. Without it, you know a pair is coordinated but not on which tokens.
Practical tuning by intent
"Find me the tightest clusters."?period=30d&min_shared=10&limit=10 — forces durable overlap, returns the hardest-linked pairs.
"Which pairs are heating up this week?"?period=7d&min_shared=3&limit=30 — short window + low threshold to catch emerging coordination.
"Is my specific shortlist clean?"?period=30d&min_shared=5&limit=50 and filter client-side for your wallets.
"Is this specific wallet a bot?"?period=30d&min_shared=10 and check if it appears in 5+ high-agreement pairs.
Common mistakes
Equating shared_token_count with coordination. Two heavy pump.fun traders will each trade 200+ tokens in a week. Sharing 30 is mostly overlap-by-volume, not coordination. Always read agreement_rate first.
Setting min_shared too low.min_shared=1 returns pairs that overlap on a single token. That's a single coincidence, not a pattern. Stick to 3+ for signal.
Missing transitive clusters. If A and B pair at 80%, and B and C pair at 80%, A and C are probably in the same cluster even if their direct pair is lower. Build the full graph from /kol/pairs data, not just the top pair list.
Using 7d for structural decisions. A 7-day window can catch a single week where two wallets happened to take the same 3 trades. 30d is where durable relationships show.
Independent signal is the hardest thing to find. /kol/pairs is the endpoint that tells you which "independent" signals are actually the same signal wearing different wallet addresses.