If a wallet consistently buys the same memecoins within two seconds of another wallet, it is almost never a coincidence. Either the two are run by the same person, operated by the same trading group, or both subscribing to the same upstream signal source. For anyone trying to separate a genuine Solana alpha wallet from one node of a coordinated farm, co-buy timing is one of the sharpest signals available.
This post walks through the clustering approach MadeOnSol uses to flag linked wallets, why it's different from the funding-graph analysis most tools rely on, and how to query it through the /v1/alpha/[wallet]/linked endpoint.
Why funding-graph analysis alone isn't enough
The classic approach to wallet clustering is to trace SOL flows. If wallet A funded wallet B, and B funded C, cluster them. It's a good first pass, but it misses most of the wallets you actually care about:
- A trading group can fund 50 wallets from a central exchange withdrawal, then spread a few more hops through intermediary wallets. By the time you're three hops out, every analytics tool has given up.
- Wallets funded from the same CEX withdrawal can belong to 100 unrelated users who happened to use the same exchange that week.
- Sophisticated operators use chain-hopping and mixers to break the link entirely.
Funding graphs answer "were these wallets ever connected by a transfer?". That's historical and brittle. What you really want to know is "are these wallets currently behaving as if coordinated?". Behavior is harder to obfuscate than money flow.
The co-buy timing heuristic
Two independent humans trading the same token will never buy within two seconds of each other with matching sizes. There's latency in noticing the token, in clicking the UI, in signing the transaction, in finality. Even on the fastest sniper setup, you're looking at 5–10 seconds of variance between two unrelated people acting on the same signal.
But two wallets driven by the same script will land within a block or two of each other, consistently, on token after token. That regularity is the signal.
The specific query MadeOnSol uses:
- Take a target wallet's first-buy timestamps across every token it's ever touched.
- For every other wallet that also first-bought one of those tokens, compute
abs(time_diff) against the target's first buy.
- Keep only pairs where
time_diff <= 2 seconds.
- Group by candidate wallet, count how many tokens match, and require at least 3 shared tokens for a pair to be considered.
- Score the remaining candidates based on the shared-token count, the average time delta, and the average buy-size delta.
Running this against a first-buyer table gives you something money-flow analysis can't: a ranked list of wallets that act like they're linked, regardless of how their SOL got there.
The endpoint
GET /v1/alpha/{wallet}/linked returns up to 10 candidates for any wallet in the alpha leaderboard. The response looks like this:
{
"wallet": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
"linked": [
{
"wallet_address": "DezX...",
"shared_tokens": 27,
"avg_time_diff_secs": 0.413,
"avg_sol_diff": 0.002,
"similarity_score": 0.92
},
{
"wallet_address": "9vMJ...",
"shared_tokens": 11,
"avg_time_diff_secs": 1.207,
"avg_sol_diff": 0.018,
"similarity_score": 0.68
}
]
}
Each field tells a different part of the story:
shared_tokens — how many distinct tokens both wallets first-bought within 2 seconds of each other. Floor of 3; typical strong matches are 10+.
avg_time_diff_secs — mean absolute time delta on those shared buys. Under 0.5s is very tight coordination; 1–2s still unusual.
avg_sol_diff — mean absolute difference in buy size (SOL). Under 0.01 means they're buying roughly the same amount every time, a strong script signal.
similarity_score — composite 0–1 score. Starts at 1.0 with penalties for loose timing (-0.1 if avg > 0.5s), size divergence (-0.2 if avg > 0.01 SOL), and thin samples (-0.1 if < 5 shared tokens).
The endpoint is ULTRA-tier only, because the underlying SQL does a self-join on a first-buyers table and is expensive to run without tight row limits.
Calling it from Node.js
import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({ apiKey: process.env.MADEONSOL_API_KEY! });
async function findLinkedWallets(wallet: string) {
const { linked } = await client.alpha.linked(wallet);
const strong = linked.filter(
(l) => l.similarity_score >= 0.85 && l.shared_tokens >= 10
);
console.log(`Target: ${wallet}`);
console.log(`Strong links (score >= 0.85, 10+ shared):`);
for (const l of strong) {
console.log(
` ${l.wallet_address} shared=${l.shared_tokens} Δt=${l.avg_time_diff_secs}s score=${l.similarity_score}`
);
}
}
findLinkedWallets("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU");
The filter is the important part. The endpoint will return up to 10 candidates even if they're weak matches. If you're doing anything automated with the output — say, excluding linked wallets from a "top KOLs" feed to avoid double-counting — filter by score and shared-token count before acting.
What to do with the output
Three concrete use cases:
Deduplicate a KOL leaderboard. If your strategy is to copy-trade the top 10 KOL wallets by win rate, and three of those ten turn out to be strongly linked, you're actually only running three strategies, not ten. Collapse linked wallets into a single entry to avoid concentration you didn't intend.
Flag coordinated pump rings. When a new token gets first-bought by 15 wallets within a 1-second window, and half of those wallets are linked to each other, you're almost certainly looking at a coordinated launch where "organic KOL interest" was in fact one person running a farm. Downweight those tokens in your signal pipeline. This is also the on-chain test behind the curation in our best Solana Twitter/X accounts to follow for alpha — the accounts worth following are the ones whose wallets don't cluster into a single farm.
Build wallet family trees. Run /linked against a seed wallet, then run it against each strong match. Two or three levels of recursion usually surfaces the full cluster. Most farms we've looked at cap out at 20–50 wallets before the graph closes.
The same inflation risk applies to the coordination endpoint's kol_count field: three strategies for trading multi-KOL coordination signals are only as good as the wallet count behind them, so running a linked-wallet check before sizing an entry off a high kol_count is worth the extra call.
Limitations to keep in mind
- First-buy only. The current query uses first-buy timestamps per token, not every trade. Two wallets that happen to both re-enter a token later are not counted.
- 2-second window is a hard cutoff. A farm running with 3-second jitter between wallets will be missed. Tightening the window reduces false positives but misses loose coordination; MadeOnSol found 2s to be the practical sweet spot after testing against known farm clusters.