Qubit Orb · Docs

Measure who really holds a Solana token.

Twenty holders at the top of a token can be twenty people, or three people with a lot of wallets. Qubit Orb reads those twenty wallets, finds the ones that belong together and folds them into operators. Then it tells you how far the price falls if the biggest operator sells, and what the token's owner can still change.

Everything runs in your browser against public Solana nodes. There is no backend, no wallet connect and no account. The same code that powers the scanner is published as a small module, lib/qubitorb.js, which you can import from this site and run yourself.

NOTE

A measurement answers three questions: who really holds it, what happens if they sell, and what else can hurt you. Every number comes from the chain at the moment you measure. Measure again later and the answer can change.

01Quick start

On the site: paste a token address into the box on the scanner and press Measure. In code, import the module straight from this site:

import { measure } from 'https://qubitorb.vercel.app/lib/qubitorb.js';

const report = await measure('TokenMintAddress...', {
  onLog: l => console.log(l.t.toFixed(1), l.msg)
});

console.log(report.score, report.verdict);         // 62 'MIXED'
console.log(report.summary.wallets, '→', report.summary.operators);
<script type="module">
  import { measure } from 'https://qubitorb.vercel.app/lib/qubitorb.js';
  const r = await measure('TokenMintAddress...');
  document.body.insertAdjacentHTML('beforeend', `<b>${r.verdict}</b> ${r.score}/100`);
</script>
# the library is a plain ES module: read it, vendor it, pin it
curl -s https://qubitorb.vercel.app/lib/qubitorb.js -o qubitorb.js

# the one call that needs the holder node, if you want to see it raw
curl -s https://public.rpc.solanavibestation.com -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"getTokenLargestAccounts","params":["TokenMintAddress..."]}'

Node 20 and later work too: save the file as qubitorb.mjs and import it locally. It uses only fetch, atob and AbortController.

02Try it

This box runs the library from ../lib/qubitorb.js right here in the docs. Paste any token address.

Output appears here, line by line.

03The pipeline

One measurement is seven steps. Each step only reads; nothing is signed or sent.

#StepWhat is readCalls
1MintSupply, decimals, mint and freeze authority, Token-2022 extensions, name and symbolgetAccountInfo
2MarketPrice, market cap, the deepest pool and how many tokens sit in itDexScreener
3HoldersThe 20 biggest token accounts and who owns each onegetTokenLargestAccounts, getMultipleAccounts
4EntriesThe first move of each holder account: bought or received, and from whomgetSignaturesForAddress, getTransaction
5FundingHow many moves each wallet made before this token, where its first SOL came fromgetSignaturesForAddress, getTransaction
6LinksProofs that two wallets are one operatornone, computed
7Impact and scorePrice drop per operator, five parts, caps, verdictnone, computed

A fresh token is measured in about 10–20 seconds. Older tokens take longer, because their history is no longer on the fast node and has to come from the slower archive (see nodes and rate limits).

04Holders and float

Each of the top 20 token accounts has an owner. The orb looks at who owns that owner, and sorts every account into a role:

RoleHow it is recognisedCounted in float
walletOwner is a normal system accountyes
curveOwner belongs to the launch curve program 6EF8…F6P. Its reserves and creator are read from the account data.no
poolOwner belongs to PumpSwap, Raydium (v4, CPMM, CLMM, LaunchLab), Meteora (DLMM, DAMM v1/v2, DBC) or Orcano
lockerStreamflow or Jupiter Lockno
burnThe incinerator addressno
programAny other program-owned accountno

Float = supply minus everything in the curve, pools, lockers and burn addresses found in the top 20. Every share on the site is a share of the float, because that is what can actually be sold to you.

05Entries

For every wallet, the orb reads the history of its token account and opens the oldest transaction that increased its balance:

  • bought — the wallet signed and paid SOL (more than 0.003) or another token. Tokens that came out of a pool, curve or router also count as a buy.
  • received — the tokens arrived without a payment. The sender is the owner whose balance dropped the most in that transaction.
  • too old to read — the account has 1 000 or more moves, so its first one is out of reach.

The same transaction gives the entry slot and time. Entries within 30 seconds of creation mark a sniper.

06History and funding

The orb then reads each wallet's own history (up to 1 000 signatures):

  • Fresh — the full history is visible and the wallet made 3 moves or fewer before it entered this token.
  • Funder — for wallets with 150 moves or fewer, the oldest transaction is opened and the first incoming SOL transfer names the funder.
WARNING

Exchange hot wallets fund thousands of strangers. A funder from the known exchange list (Binance, Coinbase, OKX, Bybit, Kraken, MEXC, Gate, KuCoin, Bitget) never links two wallets.

08Price impact

Each operator sells everything at once into the market. The drop follows the constant-product rule:

Formula
drop = 1 − ( reserve / (reserve + sold) )²

// on the curve:   reserve = virtual token reserves, read from the curve account
// after a pool:   reserve = tokens in the deepest pool (DexScreener liquidity.base)

It is a scenario of what one operator could do right now, not a forecast. With no curve or pool yet, the biggest operator is judged by its share of the float instead.

09The score

A number from 0 to 100, where 100 is the cleanest distribution. Five parts, each linear between "full points at" and "zero at":

PartPointsFull atZero atMeasures

A part that cannot be read (for example snipers when creation time is unknown) gets half its points.

10Verdicts and caps

Caps cut the score down no matter how good the rest looks:

CapScore at mostWhen
VerdictScoreMeans

There is no score when fewer than 5 wallets are in the top 20, or when fewer than 60% of the wallets could be read.

11The orb

The sphere on the scanner is a Bloch sphere: the picture physicists use for a single qubit. The top pole, |0⟩, is one owner. The bottom, |1⟩, is many. Each top holder is a dot sized by its share of the float. When a link is proven, the two dots pull together into one operator, and the purple arrow |ψ⟩ points at the biggest one.

Until you measure something, the orb plays a replay of the example token. Drag it to turn it.

12Radar and the Gate

The Radar listens to a public stream of new launches. Every launch passes the Gate before it is shown:

RuleHeld when
Creator bought at launchThe creator bought 15% of the supply or more inside the launch transaction
Serial creatorThe same creator launched 3 tokens or more in the last 6 hours, as seen by this page

Held launches stay in the list in grey with the reason. The lattice shows the last 360 launches seen in your browser; gold cells reached a pool. Filters and the lattice are kept in local storage, so they survive a reload.

13Quick looks

The column next to the orb shows trending tokens with a quick look: two or three calls that read the top 20 and how much of the float the top wallets hold, without history or links. SPREAD is 30% or less, MIXED up to 50%, HEAVY above. Click one for a full measurement.

14measure()

Signature
measure(mint: string, options?: Options): Promise<Report>

Runs the whole pipeline. Throws on a bad address, a non-mint address or when the holder list cannot be fetched. Pass an AbortSignal to cancel.

const r = await measure(mint, {
  onStep:   (key, data) => ui.step(key),     // mint, market, holders, float, entries, history, links, impact, score, done
  onHolder: h => ui.dot(h),               // each wallet as soon as its entry is read
  onLog:    l => ui.log(l.msg, l.tag)      // tag: info, ok, warn, bad, dim
});
const ctl = new AbortController();
setTimeout(() => ctl.abort(), 30000);
try { await measure(mint, { signal: ctl.signal }); }
catch (e) { if (ctl.signal.aborted) console.log('cancelled'); }

15quickLook()

JS
import { quickLook } from 'https://qubitorb.vercel.app/lib/qubitorb.js';
const q = await quickLook(mint);
// { wallets: 18, top1: 0.027, topShare: 0.35, inCurveOrPool: 0.11, mintOpen: false, freezeOpen: false, look: 'MIXED' }

16Options

OptionDefaultWhat it does
rpcpublicnodeFast node for accounts, signatures and transactions (~2.5 days of history)
holdersRpcsolanavibestationNode for getTokenLargestAccounts and the full-history fallback
archive[]Extra full-history lanes { url, gap }, used together with holdersRpc
top20Holders read
concurrency6Parallel calls to rpc
holdersGap450Milliseconds between calls to the slow node
sniperWindow30Seconds after creation that count as sniping
freshTxs3Moves before entry that still count as fresh
packSlots150Window for a fresh-wallet pack
timeout15000Per-request timeout, ms
signal, onLog, onStep, onHolder—Cancel and progress hooks
NOTE

Running many measurements? Bring your own RPC: pass rpc and holdersRpc with your key and the slow lane disappears.

17Report format

Report
{
  mint, version, ms,
  score: 0..100 | null,
  verdict: 'COHERENT' | 'MIXED' | 'ENTANGLED' | 'UNMEASURED',
  unmeasured: string | null,           // why there is no score
  token:  { program, decimals, supply, mintAuthority, freezeAuthority, permanentDelegate,
            transferFee, transferHook, pausable, name, symbol },
  market: { priceUsd, marketCap, liquidityUsd, liquidityBase, dex, pair, url, createdAt } | null,
  curve:  { vToken, vSol, realToken, realSol, complete, creator, progress } | null,
  float, creator, devHolds, devShare, createdAt,
  holders: [{ rank, account, owner, role, amount, share, floatShare,
              entry: { kind, from, slot, time, sig }, moves, historyFull, fresh, sniper,
              funder: { from, lamports, time }, operator, opType }],
  edges:     [{ a, b, why }],
  operators: [{ id, members, size, amount, floatShare, type, why, drop }],
  parts:     [{ key, label, points, full, zero, value, got }],
  caps:      [{ key, cap, text }],
  summary:   { wallets, operators, entangled, freshShare, recvShare, sniperShare, biggestDrop, biggestShare, powers },
  notes:     [string]
}

18Constants

The module exports everything it decides with, so nothing is hidden:

ExportContents
RULESScore parts, caps and verdict thresholds, the same tables shown on this page
PROGRAMSProgram ids used to recognise curve, pools, lockers and token programs
EXCHANGESExchange hot wallets that never link wallets
DEFAULTSDefault options
priceDrop(sold, reserve)The impact formula
partPoints(value, part)Linear points for one score part
isAddress(s), short(a)Helpers

19Errors

MessageMeaningWhat to do
That is not a Solana address.The input is not base58, 32–44 charactersPaste the mint address, not a pair or a link
This address is not a token mint.It is a wallet, pool or programUse the token's contract address
The holder list is busy right now.The holder node kept answering 429Wait a minute, or pass your own holdersRpc
verdict UNMEASUREDToo little could be readRead report.unmeasured, measure again

20Nodes and rate limits

The free public nodes each answer some questions and refuse others, so the orb splits the work:

  • publicnode answers fast and in parallel, but keeps only about 2.5 days of history and caps getMultipleAccounts at 10 accounts.
  • solanavibestation answers getTokenLargestAccounts and keeps the full history, but only about two calls a second. All of its calls go through one spaced, retried queue.

When the fast node's history of an address ends near its oldest slot, the orb asks the archive for that address. That is why fresh tokens are fast and old ones are slow.

21What it cannot see

  • Wallets outside the top 20. A careful operator can spread below the line.
  • Exchange-funded clusters. Two wallets funded from one exchange account look independent, on purpose.
  • Third-party hops. A link through a wallet the orb never read stays invisible.
  • Very busy accounts. 1 000 moves or more hide the first entry and the funder.
  • The future. A good score today says nothing about tomorrow. Measure again.

It never asks for a wallet, a signature or a key, and stores only your own recent measurements and Radar filters in your browser.

22$QUBIT

$QUBIT is the token of this scanner. You can paste its own address into the orb: it will not go easy on itself.

CA soon

23FAQ

Is a COHERENT token safe?

It means the top holders look like different people right now. It does not mean the price will hold.

Why does an old token take a minute?

Its history is past the fast node's window, so every wallet goes through the slow archive queue. Fresh tokens finish in seconds.

Why is a wallet "too old to read"?

Its token account has 1 000 or more moves, so the first one is beyond a single page of history.

Can I run it on my own node?

Yes. Pass rpc and holdersRpc to measure(). With a paid node the whole measurement takes a few seconds.

Does the site store anything?

Only in your browser: your last measurements, quick looks, Radar filters and the launches it has seen. Nothing leaves your machine except the read calls to public nodes.