Detect Token Bundles, Sniper Wallets and Connected Holders
Spot bundled launches, sniper wallets and clusters of connected holders on Robinhood Chain with the Crius bundles, bubble map and wallet connections APIs.
Crius 8 min read
A launch is “bundled” when a group of wallets controlled by the same party buys a large share of supply in the first blocks, usually splitting the buy across fresh wallets funded from one source so the holder list looks distributed. Crius detects this from on-chain evidence (wallets in the same transaction, same-block buys from a shared funder, funding links and token transfers between wallets) and reports it in one request per token.
This guide is about the launch: bundles, snipers, where the early buyers’ money came from, and how to follow it. For holder concentration and drawing bubble maps of a token’s current holders, see the companion guide on holder analysis and bubble maps.
What counts as a bundle, a sniper and a cluster
The /bundles endpoint analyzes every buy in the first 300 blocks of trading, about 30 seconds on Robinhood Chain, plus the token’s creator:
| Finding | Rule |
|---|---|
| Sniper | Bought within the first window_blocks blocks (default 10, about one second) after trading opened |
Bundle: launch_tx_buy |
Tokens bought inside the launch transaction itself, typically the creator’s initial buy |
Bundle: multi_recipient_tx |
One transaction buying for two or more wallets |
Bundle: same_block_shared_funder |
Two or more wallets buying in the same block, all funded by the same address |
| Cluster | Wallets joined by a shared funder, ETH funding between them, or token transfers between them |
One rule prevents a flood of false positives: funders that paid more than 500 distinct wallets are treated as hubs (exchanges, bridges, faucets) and never link wallets together. Thousands of unrelated traders withdraw from the same bridge every day; that isn’t a bundle.
A bundled launch and a clean one
curl "https://api.crius.sh/v1/robinhood/token/$TOKEN/bundles" \ -H "x-api-key: $CRIUS_API_KEY"Here is a real response, trimmed, for a launchpad token from the 24-hour top 20 by volume at time of writing (Oct 2026). The address is withheld because the point is the pattern, not the project:
{ "bundled": true, "bundle_supply_pct": 40.3713, "bundle_supply_pct_now": 0, "snipers": { "count": 3, "supply_pct": 62.3858, "still_holding_pct": 0, "window_blocks": 10 }, "dev": { "bought_in_launch_tx": true, "first_buy_pct": 36.6038, "holding_pct": 0, "funded_by": { "address": "0xa3c6…7051", "amount_eth": 1.0177 } }, "bundles": [ { "id": "b_1", "type": "launch_tx_buy", "block": 92738009, "supply_pct": 36.6038, "cost_eth": 1 }, { "id": "b_2", "type": "same_block_shared_funder", "block": 92738039, "wallets": ["0xb6fa…9781", "0x922a…d570"], "supply_pct": 3.01863, "cost_eth": 0.555143, "funder": { "address": "0x7f08…1ee5", "funded_wallets": 404 } } ], "clusters": [ { "id": "c_36d7cf", "wallets": 10, "root_funder": "0xa3a4…5dbb", "supply_pct_now": 0, "includes_dev": false } ], "trader_funding": { "bridge": 36, "dev_linked": 8, "unlabeled_hub": 49, "other_wallets": 92 }, "early_buyers_analyzed": 185}How to read it:
launch_tx_buy. The creator bought 36.6% of supply inside the launch transaction. On launchpads this is a normal feature (a “dev buy”), but its size matters, and here the creator has since sold everything.- Repeated identical bundles. There were eight
same_block_shared_funderbundles, and four of them bought exactly 3.01863% of supply for exactly 0.555143 ETH in four different blocks. Identical sizes from wallets sharing a funder are a strong sign of one script. still_holding_pctandbundle_supply_pct_nowanswer the question that matters most after launch: is the bundled supply still waiting to be sold? Here it’s 0%, so it has already been distributed.trader_fundingclassifies where every early buyer’s first ETH came from: a bridge, a wallet linked to the creator (dev_linked), a busy unlabelled hub, or an ordinary wallet. Eight dev-linked early buyers is itself a finding.
Compare a clean launch, the GIGATENEV memecoin at the same time:
{ "bundled": false, "bundle_supply_pct": 0, "snipers": { "count": 1, "supply_pct": 0.582572, "still_holding_pct": 0.569045, "window_blocks": 10 }, "dev": { "bought_in_launch_tx": false, "first_buy_pct": 0, "holding_pct": 0.768673 }, "bundles": [], "clusters": [], "trader_funding": { "bridge": 9, "other_wallets": 1 }}One sniper with half a percent of supply, no bundles, no clusters, and early buyers funded overwhelmingly from bridges, which is what independent traders arriving from other chains look like.
A launch risk report in TypeScript
This script turns /bundles and the bubble map into a short list of plain-language flags. It runs directly on Node 24 (which executes TypeScript natively), or with any TS runner:
// launch_risk.ts: bundles, snipers, funding clusters and the holder graph for one token.const API = "https://api.crius.sh/v1/robinhood";const KEY = process.env.CRIUS_API_KEY!;const TOKEN = process.argv[2];
async function get<T = any>(path: string): Promise<T> { const res = await fetch(`${API}${path}`, { headers: { "x-api-key": KEY } }); const body = await res.json(); if (!res.ok) throw new Error(`${res.status} ${body.error?.code}: ${body.error?.message}`); return body.data as T;}
const b = await get(`/token/${TOKEN}/bundles?window_blocks=10`);const map = await get(`/token/${TOKEN}/bubblemap?top=100&exclude=infra`);
const flags: string[] = [];if (b.bundled) flags.push(`bundled: ${b.bundles.length} bundles bought ${b.bundle_supply_pct.toFixed(1)}% of supply (${b.bundle_supply_pct_now.toFixed(1)}% still held)`);if (b.snipers.supply_pct > 20) flags.push(`${b.snipers.count} snipers took ${b.snipers.supply_pct.toFixed(1)}% in the first ${b.snipers.window_blocks} blocks`);if (b.dev?.bought_in_launch_tx) flags.push(`creator bought ${b.dev.first_buy_pct.toFixed(1)}% in the launch transaction (holds ${b.dev.holding_pct.toFixed(1)}% now)`);for (const c of map.clusters ?? []) { if (c.pct >= 10) flags.push(`a cluster of ${c.wallets} connected top holders holds ${c.pct.toFixed(1)}% (risk: ${c.risk})`);}
console.log(`early buyers analyzed: ${b.early_buyers_analyzed}; how they were funded:`, b.trader_funding);const byType = Object.groupBy(b.bundles as any[], (x) => x.type);console.log("bundles by type:", Object.fromEntries(Object.entries(byType).map(([k, v]) => [k, v!.length])));console.log(flags.length ? flags.map((f) => `- ${f}`).join("\n") : "no launch red flags");On the bundled launch:
early buyers analyzed: 185; how they were funded: { bridge: 36, dev_linked: 8, other_wallets: 92, unlabeled_hub: 49 }bundles by type: { launch_tx_buy: 1, same_block_shared_funder: 8 }- bundled: 9 bundles bought 40.4% of supply (0.0% still held)- 3 snipers took 62.4% in the first 10 blocks- creator bought 36.6% in the launch transaction (holds 0.0% now)- a cluster of 14 connected top holders holds 35.9% (risk: high)On GIGATENEV it prints no launch red flags.
Note exclude=infra on the bubble map. Without it, the Uniswap v4 PoolManager (which custodies every v4 pool’s tokens) sits among the top holders, and token transfers through it can link otherwise unrelated wallets into one large cluster. Excluding infrastructure keeps the graph to real holders.
Follow the money: who funded the bundle?
A bundle’s funder is where the investigation usually continues. /wallet/{address}/connections returns who funded a wallet, who it funded, wallets sharing its funder, token transfers, and linked_devs (token creators connected to it). Its ETH funding covers both top-level transfers and internal transfers made by contracts, recovered from call traces, so money routed through a disperse contract is still followed:
"""funders.py: follow the money behind a bundle - who funded the funder?"""import os, sys, requests
API = "https://api.crius.sh/v1/robinhood"s = requests.Session()s.headers["x-api-key"] = os.environ["CRIUS_API_KEY"]TOKEN = sys.argv[1]
bundles = s.get(f"{API}/token/{TOKEN}/bundles", timeout=120).json()["data"]["bundles"]funded = [b for b in bundles if b["type"] == "same_block_shared_funder"]seen = set()for b in funded: if b["funder"]["address"] in seen: continue seen.add(b["funder"]["address"]) f = b["funder"] print(f"block {b['block']}: {len(b['wallets'])} wallets bought {b['supply_pct']:.2f}% of supply, " f"funder {f['address'][:10]}… has funded {f['funded_wallets']} wallets") c = s.get(f"{API}/wallet/{f['address']}/connections", params={"limit": 10}, timeout=60).json()["data"] up = c["funded_by"][0] if c["funded_by"] else None print(f" funder was itself funded by {up['address'][:10] + '…' if up else 'unknown'}" f"{' (' + up['label'] + ')' if up and up['label'] else ''}; linked devs: {len(c['linked_devs'])}")block 92738039: 2 wallets bought 3.02% of supply, funder 0x7f08779b… has funded 404 wallets funder was itself funded by 0x1764cd41…; linked devs: 2block 92738103: 2 wallets bought 0.00% of supply, funder 0xa3a428d9… has funded 28 wallets funder was itself funded by 0x56daf69e…; linked devs: 1block 92738150: 2 wallets bought 0.29% of supply, funder 0x17d9d1f4… has funded 28 wallets funder was itself funded by 0x62e991ba…; linked devs: 3block 92738150: 3 wallets bought 0.45% of supply, funder 0x62e991ba… has funded 305 wallets funder was itself funded by 0x53091256…; linked devs: 7Two things stand out. Every funder is connected to token creators (linked devs from 1 to 7), and the last two funders are linked to each other: 0x62e9… funded a bundle directly and funded the funder of another one. Funding chains like this are how one operator’s wallets show up across many launches. Funders that have paid hundreds of wallets (404 and 305 here) sit just under the hub threshold, so judge them by what else they funded.
Turning findings into a score
A practical scoring scheme for new launches, applied in your own code:
- Snipers’ share. Above about 20% of supply in the first 10 blocks is a warning; check
still_holding_pctto see whether it’s still a risk. - Bundled supply still held.
bundle_supply_pct_nowmatters more thanbundle_supply_pct. Bundled supply that has already been sold can’t be dumped again. - Creator behaviour. A large
launch_tx_buyfollowed byholding_pct: 0means the creator has exited. - Dev-linked early buyers. Any non-zero
trader_funding.dev_linkeddeserves a look. - Clusters among current holders. A bubble-map cluster holding 10%+ of supply is the same person, or the same group, controlling a block of supply today.
Combine this with a honeypot and tax check before trading anything fresh.
Limits and good practice
- Evidence, not intent. A shared funder can be an innocent payroll or airdrop distributor. Treat findings as signals to investigate, and avoid labelling individuals publicly on the basis of one pattern.
- Window.
/bundleslooks at the first 300 blocks of trading. Later accumulation by connected wallets is the bubble map’s job (passblockfor a historical map). - Plan and cost. Bundles and bubble maps are analytics endpoints (Starter plan and up, 10 credits each); wallet connections cost 10 credits. They’re computed on demand, so keep concurrency low and cache results; a launch’s bundle report doesn’t change once its first 300 blocks are past.
Frequently asked questions
What is a bundled token launch?
A launch where one party buys a large share of supply in the first blocks through several wallets, typically funded from one address, so that ownership looks more distributed than it is.
How does Crius detect sniper wallets?
A sniper is any wallet that bought within the first 10 blocks after trading opened (configurable with window_blocks). On Robinhood Chain that is roughly the first second.
Why aren’t wallets funded from the same exchange or bridge grouped together?
Funders that paid more than 500 distinct wallets are treated as hubs (exchanges, bridges, faucets) and don’t link wallets, otherwise every bridge user would be one “cluster”.
Can I see bundles and clusters at a past block?
/bundles always analyzes the first 300 blocks of trading. For connected holders at any past point, call /bubblemap?block=<number>.
Does wallet funding include internal ETH transfers?
Yes. Wallet connections count top-level ETH transfers and internal transfers made by contracts, recovered from call traces, so funding routed through a contract (a disperse tool, for example) is still followed.
Related
- Product overview: bundle detection API, token security API, token holders API
- Reference: snipers, bundles and clusters, bubble map, wallet connections
- Guides: holder analysis and bubble maps, smart money and top traders, Pons launchpad tokens
Build with Crius
Robinhood Chain data in one API
Free plan with 1M credits a month. Your key in under a minute.
Related APIs
More from the blog
- Uniswap v4Real-time
How to Detect New Uniswap v4 Pools on Robinhood Chain
Detect every new Uniswap v4 pool on Robinhood Chain as it is created: the pools:new stream, raw PoolManager Initialize logs, and hook checks before you trade.
- GuideRobinhood Chain
Robinhood Chain API: The Complete Developer Guide for 2026
How to get Robinhood Chain prices, OHLCV candles, trades, holders, launches and live streams from one API, with tested code in cURL, Node.js and Python.
- HoldersSnapshots
Robinhood Chain Token Holders API: Live and Historical Snapshots
Get the holders of any Robinhood Chain token, live or at any past block or market cap, with cohorts and holder-count history. Code in Node.js and Python.