sharing mygnoscan
2026-09-23 · #mygnoscan · #tooling · #explorer
mygnoscan is a BI tool I wrote to answer my own questions about gno.land. I have been adding to it since April and never announced it, because it is not finished and it will not be.
Then people found it, said they liked it, and asked when I would share it. So: here it is. Not a product, not official, and I add to it every time it fails to answer a new question.
what I actually open it for
Generic explorers are built around blocks and transactions. Those are table stakes. My questions were a different shape: what is deployed, who calls it, and what changed this week.
So the front page is a window, not a ledger. Pick a range, see it against the range before it, then five lists:
- hot realms, by calls, with the caller count beside them. 3,817 calls from 26 addresses and 4,998 from 461 are not the same event, and one number cannot tell you which you are looking at.
- hot assets: ugnot at 19,280 transfers from 980 senders, GNS at 6,324 from 141.
- hot developers, flagged when it is their first deploy ever. Three of the top four this week are first-timers.
- hot libraries, ranked by new importers rather than total.
p/nt/ufmttook 23 new importers this week against 113 all time. - notable transfers.
Under that: realm source, imports, dependents, callers, the MsgRun scripts
that use a realm without importing it, a dependency graph, and screenshots of
what each realm actually looks like.
two things the indexer taught me
Half of this is a frontend. The other half is learning how the tx-indexer actually behaves, which is where the interesting bugs live.
There is no pagination. getTransactions takes where and order, and
nothing else. The server caps a result set at 10,000 elements, and on reaching
it the resolver stops and returns the rows it has alongside a GraphQL error.
So a capped response is partial, not empty, and the only way to walk a larger
set is the block height filter:
1getTransactions(where: {
2 block_height: { gt: 250000, lte: 260000 }
3}) { hash block_height }
Read that wrong and you show a truncated history as if it were complete.
One unknown type kills every query. Message types are selected inside one shared fragment set:
1messages { value { __typename
2 ... on MsgCall { caller pkg_path func args }
3 ... on MsgAddPackage { creator package { name path } }
4 ... on MsgEnablePackage { approver pkg_path }
5} }
An indexer that does not define MsgEnablePackage rejects every transaction
query, not just the ones that would have matched it:
sync packages: indexer returned 422: Unknown type "MsgEnablePackage"
That took a whole chain's sync offline. And the types shipped separately, so
mainnet defines MsgEnablePackage and not MsgCreateSession: probing for one
and selecting the other fails every query while reporting support.
where I want to take it
A developer section, mostly. Realm state as a readable tree instead of a blob.
Code search across every .gno file on chain. A time machine, because the chain
overwrites state and the indexer is the only thing watching. And a read-only
endpoint so an agent can ask what I ask through the UI.
please break it
gnoverse/mygnoscan. One Go binary, the frontend embedded, SQLite for the graph analysis. The README says how to run your own against your own node, which I would like more people to do.
What I want most is an issue when it does not answer your question. Every feature in there came from a question I could not answer, and I only have mine. Second most: tell me when a number looks wrong. Some have been, and an explorer that is confidently wrong is worse than none.
I am not building the explorer for gno.land. gnoscan.io is the one to hand a stranger. I am building the one I want open in a tab while I work, and it turns out a few other people want that tab too.