Documentation
ChainMind is an AI explorer for Robinhood Chain — the Arbitrum Orbit L2 (chain id 4663, ETH gas) where Robinhood issues tokenized equities. You type a question in any phrasing or language, it reads the chain and the indexer live, and it answers with the figures plus the bounds on them.
This page is the reference. For the three-step version of how a question becomes an answer, read the guide.
Capabilities
Twenty-six lookups, grouped the way a question arrives rather than the way the code is filed. Every example below is a phrasing the router was built against — you do not have to clean up your wording, name a tool, or know a ticker.
Which contract is the real one, who deployed it, and how many others are wearing the same ticker.
The bound: A safety check answers on one contract at a time and prints addresses in full so you can compare them character by character. Search is paginated: it reads at most 25 rows and, when there are more upstream, reports “at least N” — it can never list every impostor.
One token, two side by side, or the whole tokenized-equity market as it stands right now.
The bound: Only the equities the indexer published a figure for can be ranked; the rest come back counted as unmeasured, which is missing data and not zero activity. Aggregates say how many entries they cover.
Who owns it, how long they have held, whether they arrived together, and what else that crowd holds.
The bound: Hold times and bundle checks read the top addresses by balance, never the whole holder base. The pool, the burn address and the token contract itself are labelled and left out of the figures — none of them is a holder.
What moved, and separately, who actually bought or sold — at a price, for a fee.
The bound: A transfer says something moved; a swap says somebody bought or sold. Swaps are read over a block window, so the only negative that can be stated is “no sell was observed in the N blocks read”. Uniswap v3 and v4 are read over different windows and their counts are never added.
What one address holds, what it has done in one token, and who it deals with.
The bound: A trace walks at most 150 transfers over three pages, so “no sale in the transfers read” is the honest answer and “never sold” is not. A portfolio total covers the priced holdings only; an unpriced token is unquoted, never worthless.
One lookup for the question people actually ask about a token they were sent. A bare pasted address with no question attached is this one.
The bound: It produces observations, never a verdict and never intent. A launchpad deployment is an ordinary, cheap way to launch a token and is not evidence of dishonesty; being new, small, thinly traded or concentrated is not either. Links found in the launch calldata are self-declared by whoever launched the token and are not fetched or verified.
“Who is the main benefactor of this coin” can mean the largest holder, the deployer who minted it, or the address most in profit. Rather than silently picking one, ChainMind returns one short question and two to four pressable options, worded in your own voice and your own language. It will not do this when a sensible default exists, when both readings are cheap to answer, over spelling or phrasing, or twice in a row.
Fixed, explainable and published, so a finding can be argued with. An empty result is a real answer: the checks ran and flagged nothing, which is not a failed lookup.
| Check | Fires when |
|---|---|
| Near-identical amounts | 3 or more transfers within 1% of each other, inside a 30-minute window |
| Dominant holder | one address holding 50% or more of supply |
| One-way distribution | 5 or more receivers fed by 2 or fewer senders |
| Tight clustering | 5 or more transfers inside a 5-minute window |
Diligence
“Check this project out properly”, “full diligence on X”, “is this a larp — https://…” are asking for something a 24-second budget cannot produce: one page, one pass, and no way to decide what to look at next. Those questions can start a bounded investigation instead — the chain half answered now, the web half delivered as a sourced report minutes later.
A question is answered inside 24 seconds. An investigation runs for minutes: it reads a page, then decides what to look at next from what it found — a repository named in the markup, an API endpoint, the chain record — and keeps going until it has something to say or hits a cap. You get an id and a link; the report appears there when it is done. Nothing waits on it, and the chain half of your answer arrives immediately either way.
A URL you pasted, a link declared on chain in the launch transaction, a link found in the project's own marketing and a path the model guessed at are four different strengths of evidence, and the report prints which on every line. A finding resting only on the subject's own pages is labelled as the subject's account of itself, whatever its figures are.
Content decides what happens next, so a page that says “full audit at …” is proposing a target. Every discovered URL is re-screened exactly as if you had pasted it, and one named in the same text as instructions addressed at an automated reviewer is refused outright — with the attempt and the refusal both printed. Imperative text found in a page is a finding, never an instruction.
The subject is a URL or a 0x address and nothing else. There is no search engine and no “find this project's website”, permanently: reporting on a business that merely shares a name with a token would be reporting on the wrong people.
Steps, tool calls, bytes fetched, wall clock and model tokens all have ceilings, all are printed, and any figure that hit one is shown as a bound rather than a measurement. A repository search that did not read every file cannot be used to state an absence, and a commit count that ran out of pages reads “at least N”.
The report will not print scam, fraud, rug or LARP as a conclusion — the words are redacted from anything the model wrote, whatever the prompt said, and the redaction is listed so the edit is visible. Anonymous founders, a young domain, a small treasury and a launchpad deployment are facts a reader weighs. None of them is evidence of dishonesty and none is framed as such.
robots.txt is honoured for pages and for endpoint probes; a disallowed path is not fetched and the report says that was the operator's stated wish rather than a finding. Requests are rate-limited per host, reads are cached so one question costs a third party once, and the crawler identifies itself honestly so it can be blocked if it is not wanted.
A job is attached to a wallet: only the wallet that started one can read its report. Non-holders get one a day by default and verified holders five — capped rather than unlimited, because the cost of a runaway lands on somebody else's server and a token balance is not their consent. Where no research service is configured, the app says so plainly instead of offering a button that cannot work.
Findings grouped and each carrying its evidence, every source with the URL it came from and how that URL became a target; everything the run actually read; everything it refused to follow and which rule each one broke; what it did not check, stated as loudly as what it did; and what it cost, in model calls, tokens and bytes of somebody else's bandwidth. Anything quoted from the subject is marked as the subject's own words rather than set in the report's voice.
Interpretation
This chain punishes a figure read at face value. 94 tokenized equities were deployed by one issuer, byte-identical impostors circulate beside them, holder counts are airdrop-cheap and liquidity is rentable. Every rule below exists because of something measured on chain 4663.
A cap is supply times a quoted price. Realisable depth is capital actually sitting in the pool, read from the chain. On this chain they routinely differ by orders of magnitude.
A contract called “The Robinhood” carried 52,214 holders and a $3,855,217 notional cap with $1.03 of realisable depth behind it — about 3.7 million×. Of eighteen VLAD contracts surveyed, exactly one had more than $100 of realisable depth.
Where a read is paginated or sampled, the figure it produces is a lower bound and the wording says so. A floor is never quietly promoted to a total.
Search reads one page and says “at least N … never say these are all of them”. A hold time reads “at least 42 days”. A co-holdings row carries its denominator — “2 of the 3 probed holders” — rather than a percentage of holders.
Two different gaps travel with every answer and are never merged. `unavailable` names a source that was asked and did not answer. `budgetNotice` names one that was never asked, because the request would have been killed before it returned.
The notice is a finished sentence: “These reads were skipped to keep this answer inside its time limit: … They are UNKNOWN — not zero, not empty, and not a finding that there is nothing there.”
Balance-ranked lists contain the token's Uniswap pool, the burn address and often the token contract itself. The pool's balance is liquidity and the burn address's balance is supply that is gone.
Uniswap v4 keeps every pool on the chain inside one PoolManager (0x8366a39cc670b4001a1121b8f6a443a643e40951), so a single unlabelled row can be every v4 pool at once. Excluded addresses are listed with their role rather than dropped.
The address that called the pool is a router or aggregator in almost every swap, and one router fronts dozens of unrelated wallets. A row with no named wallet is unnamed — not anonymous, and not the router.
Measured on one token: a single router address was behind 212 of 213 swaps.
A name and a ticker are free. The one mark of an official token is that Robinhood's issuer deployed it, which is why a safety check prints both addresses in full.
Every genuine tokenized equity in the snapshot was deployed by 0x4783C67b63dE2B358Ac5951a7D41F47A38F3C046. Official names follow one convention — “NVIDIA • Robinhood Token” is NVDA. 229 distinct contracts on this chain use the symbol VLAD.
When several contracts wear one ticker, at most four get their pool measured, and four separate quantities travel with the result: attempted, measured, failed and dropped. A dropped candidate is unmeasured, which is not the same as shallow.
A live run: 4 measured of the 33 rows the explorer returned, verdict dominant, $1,324.23 of band depth against $0.31. The verdicts a reader can see are dominant, uncorroborated, shallow, partial and unmeasured.
A Uniswap v4 fee is charged per swap and a hook can set it, so it is quoted as charged and never rounded toward a familiar tier. A v4 pool has no contract address — only a 32-byte pool id.
Fees of 0%, 0.01%, 1%, 1.1%, 5.1%, 10.65% and 99.81% were all charged on real trades in one recent window.
Concentration, co-acquisition and repeated shapes are facts about the data. Wash trading, sniping and front-running are claims about intent, and nothing in a transfer or a swap log separates a market maker, a bot rebalancing, one desk filling an order in slices, and somebody trading with themselves.
An airdrop, a contract migration, a team allocation and a bought sniper bundle all leave exactly the same co-acquisition shape. Equally, finding nothing is not a clearing: a sole liquidity provider round-tripping its own pool pays the fee to itself, so the pattern is cheap to produce and cheap to avoid.
The platform kills a request at 30 seconds. Six of those are held back for everything outside the handler and seven more are reserved for writing the answer, which leaves lookups 17 seconds. That bound is not arbitrary: measured cold on this chain, a memecoin ticker took 49.0s end to end and a ticker collision 31.3s — both of which the platform answered with a bare 504 that discarded every second of work already done.
So a stage that cannot fit is not started, and the skip is reported in the answer rather than left to look like a finding. A degraded honest answer beats a gateway timeout. Depth probes are bounded the same way — at most four contracts in a ticker collision get their pool read, and four concurrent probes already cost 8.0 seconds, 16 HTTP requests and 211 JSON-RPC calls.
Scope
Some of these are choices and some are gaps. They are labelled, because dressing a gap as a principle is the same overclaiming this product exists to avoid.
By design
It will not tell you a token is a scam, that volume is wash traded, that somebody front-ran you or that a wallet sniped a launch. Those are claims about knowledge and intent that a transfer log cannot carry. You get the measurements and the denominators instead.
By design
It never recommends buying, selling or holding, gives no price targets, and does not compare a tokenized equity to the underlying stock as an investment case.
By design
Founders, teams, CEOs, company history, funding, investors and roadmaps are off-chain. They are not in the snapshot and not in any lookup, and the answer says so rather than substituting a market overview.
By design
A project profile reads the chain. It will examine a site only when you paste the URL, or when you ask it to look at a link the launch transaction itself declared — and a declared link stays labelled as self-declared. It never guesses a site from a token's name.
Gap
Every answer is a question you asked, in the moment you asked it. Nothing runs in the background and nothing is pushed to you.
Gap
Figures are current. There is no series to plot, no “price 30 days ago”, and no backtest.
Gap
This reads settled blocks on a sequencer-ordered L2. A transaction appearing earlier in a block proves it was ordered earlier and nothing about whether anyone saw another transaction — so ordering is reported as ordering, and never as front-running or sandwiching.
Gap
It never signs, sends or simulates a trade to see what would happen. It reads what already happened. A sell tax or a transfer restriction is not tested for.
Scope
Robinhood Chain only — mainnet 4663, with testnet 46630 selectable by the operator. No Solana, no Ethereum mainnet, no cross-chain view. An address is looked up here or not at all.
Gap
The explorer search is paginated and at most 25 rows come back, so a ticker with 229 contracts behind it can never be enumerated. That bound is stated in the answer rather than papered over.
And the standing caveat: answers are AI-generated from public on-chain data and can be incomplete or wrong. The evidence behind every answer is one click away so you can check it, and nothing here is financial advice.
Access
The explorer works with no account at all. Signing in exists for two things: lifting the daily limit if you hold the token, and keeping your questions.
You sign a plain text message. It is never a transaction, an approval, a permit or an EIP-712 typed-data blob — there is no code path in the flow that touches gas or an allowance, and the signed text says so itself. The challenge is single-use, expires in minutes, and is bound to your browser, so a signature captured elsewhere is not a login here. Recovery only proves control of an ordinary key: smart-contract wallets (ERC-1271) are rejected rather than half-supported.
Five questions per UTC calendar day by default, for everyone who is not a verified holder. A UTC day is used because the server cannot know your timezone, and “resets at 00:00 UTC” is a promise you can check against a clock. It is a speed bump rather than an anti-abuse system: an IP is shared behind a NAT and changes with a VPN hop, and a fresh wallet is free to create. What the server-side identity work buys is that the limit cannot be reset by setting a header.
A verified holder at or above the threshold asks without a daily limit. The balance is read by the server from its own RPC client, never taken from anything the browser sends, and re-read every few minutes because a holder can sell the block after signing in. There are three outcomes, not two: verified at the threshold, verified below it, and could not be read — and the last one keeps the free allowance rather than telling a holder they own nothing.
Saved only while signed in, and scoped to your address. The last 50 entries are kept: at the cap the oldest drops so the newest can be saved, so a save never silently fails. Entries age out after 90 days. You can delete one entry or all of them, immediately, and delete means delete — there is no soft-delete flag. Only the question, the answer, a label and a timestamp are stored: no IP, no user agent, no session id, no evidence blob.
Self-hosting
Everything above is the product. This part is only for running it, and it sits at the bottom of this page rather than on its own — it is short, it changes with the app, and the readers who arrive here from a link should not have to scroll past a table of environment variables to find out what the thing does.
npm install cp .env.example .env.local # fill in the values below npm run dev # http://localhost:3000 npm test # unit tests, no network npm run build && npm start # production
The full annotated list is in .env.example. What matters most is which way each one fails: nothing here degrades quietly into a weaker version of itself.
| Variable | Status | What it does, and what happens without it |
|---|---|---|
| GROQ_API_KEY | Required | Answers the questions. Nothing is answered without it. |
| NEXT_PUBLIC_APP_URL | Required for sign-in | The domain baked into the signed message. It is never read from a Host header — that would let a caller pick the domain a victim signs. Unset, /api/auth/nonce and /api/auth/verify return 503 and nobody can sign in. |
| SESSION_SECRET | Required for sign-in | Signs the session cookie. Minimum 32 characters, no development default. Rotating it invalidates every session. |
| UPSTASH_REDIS_REST_URL + _TOKEN | Required in production | Where nonces, quota counters and saved history live. With no store configured, production fails closed on every stateful feature; /api/health reports quota.enforced false. STORE_DATABASE_URL is the postgres alternative — the driver is not bundled, so it needs npm install pg and fails closed without it. |
| ROBINHOOD_NETWORK | Optional | mainnet (chain 4663, the default) or testnet (chain 46630). |
| ROBINHOOD_RPC_URL / ALCHEMY_* | Optional | A dedicated RPC for higher limits. Precedence is ROBINHOOD_RPC_URL, then ALCHEMY_RPC_URL, then template + key, then the public RPC. No hostname is ever guessed. |
| BLOCKSCOUT_API_URL / _API_KEY | Optional | Override the indexer host or add a Pro key to raise rate limits. |
| GATE_TOKEN_ADDRESS / GATE_TOKEN_MIN | Optional | The token and whole-token threshold that lift the daily limit. Unset means no gate: nobody can be verified as a holder, so every visitor gets the free allowance. |
| FREE_DAILY_QUESTIONS | Optional | Free questions per UTC day for everyone who is not a verified holder. Default 5; 0 makes the gate a hard paywall. |
| HISTORY_ENABLED / _MAX_ITEMS / _TTL_MS | Optional | Saved history on or off, how many entries one wallet keeps (default 50, store ceiling 500) and how long an entry survives (default 90 days). |
| RENDER_SERVICE_URL + RENDER_SHARED_SECRET | Optional, both or neither | The browser render service. With neither set, the client reports “not configured” and says in words that the absence is a fact about this deployment and not about any site. |
| RESEARCH_SERVICE_URL + RESEARCH_SHARED_SECRET | Optional, both or neither | The deep-research service. With neither set, deep investigations are not offered at all: /api/research answers configured false, the ask path says this deployment cannot run one, and no button appears that would fail when pressed. The secret is a different value from the render service's. |
| RESEARCH_DAILY_JOBS / RESEARCH_HOLDER_DAILY_JOBS | Optional | Deep investigations per UTC day for a signed-in caller and for a verified holder. Defaults 1 and 5. Metered separately from questions, and capped for holders too — a job is minutes of somebody else's bandwidth, and a token balance is not their consent to be crawled. 0 switches off one tier without switching off the other. |
| TRUSTED_PROXY_HOPS / TRUSTED_IP_HEADER | Optional | How the caller's IP is derived. X-Forwarded-For is a list each proxy appends to, so the entry that means anything is counted from the right. Default 1 hop, which is the truth on Vercel, Railway, Fly and Render. |
| Route | Role |
|---|---|
| POST /api/ask | The question. Guards, budget, lookups and the streamed answer. |
| GET /api/health | Liveness, plus which stateful features are actually configured. |
| GET /api/quota | What this caller has left today, and why. |
| POST /api/auth/nonce · /verify | Issue a single-use challenge; redeem a signature for a session. |
| GET /api/auth/session · POST /api/auth/logout | Read the current session; end it. |
| GET · POST · DELETE /api/history | A signed-in wallet's saved questions. Delete means delete. |
| GET · POST /api/research | Whether deep investigations are available here and what you have left; start one. |
| GET /api/research/[id] | Poll one investigation and collect its report. Readable only by the wallet that started it. |
A separate deployment that opens a URL in a headless browser and returns what a person would actually see. It exists because a plain HTTP read of a client-rendered site reads a different document than anybody looked at: measured through this repo, one site answered 200 with 5,782 bytes of HTML containing four characters of visible text; through the render service the same URL yielded 76,266 bytes and 343 characters in 2.2 seconds.
It holds one credential — the shared secret — and nothing else, on purpose: it runs a browser executing the investigated party's JavaScript, so it is built so that a full compromise of it yields only the ability to render pages. Never give it a chain key, a model key or a store credential. With it unconfigured, the app says the absence is a fact about this deployment and not about any site.