A read-only observatory and security scanner for Robinhood Chain, built so that a failed request never turns into the word “safe”, and an unknown never reads as a pass.
Solo: product, design, frontend, backend and deploy.




One launchpad on this chain emits more than 300 tokens an hour, a rate the observatory measures live and prints on its own front page. Someone looking at a fresh token has minutes to decide, and the tools that help them hand back a green badge reading SAFE.
That word is a promise about the future, and reading a chain cannot keep it. I wanted a tool that says what it measured, names what it could not see, and never rounds the gap in the reassuring direction.
Paste an address and four measurements run against a public RPC and Blockscout. No API key, no wallet, no execution.
Every axis can come back unknown, and one unknown blocks the pass. The verdict reads PARTIAL with a line under it that the whole tool exists to say:
Nothing red was found, but part of the picture could not be seen. Structure, not price. A token with nothing red here can still go to zero.
In one scan the liquidity positions covered 40% of the pool. Showing the biggest holder and calling it locked would have looked better. It reported unknown instead.
The observatory counted new tokens by listening for the launchpad's event. That misses anything deployed without one.
A canary against the live chain measured the gap: 278 contracts creating supply against 27 the counter could see, from eight different creators in thirteen minutes.
So I added a second counter that counts supply appearing on the chain, with no launchpad involved. It cannot share the first one's blind spot, and the distance between the two is the measurement of what the first one misses.
Every source is public: an RPC node, Blockscout, DexScreener. No key is needed to run the project, so infrastructure costs nothing and anyone who clones it gets the same numbers I do.
Rate limits are the price. Public endpoints throttle per IP, and Cloudflare Workers leaves through an address shared with the platform, so code that answered on my machine came back HTTP 429 in production. The keys I added do not buy quota. They buy a path that does not depend on our address.
Nothing is cached, so a scan takes about a minute. When a source fails, that axis reports NOT MEASURED and the verdict drops toPARTIAL. A failed request can never round into a pass.
NOT MEASUREDand never as a guess.Next 16, TypeScript, Cloudflare Workers. One accent colour drives the theme from a registry of 18, each checked for contrast on a page that makes zero network calls.